out new baseline

This commit is contained in:
Mark Gregory
2026-06-24 14:58:41 +01:00
parent 3737cf7ebc
commit a26129a383
10 changed files with 442 additions and 145 deletions
@@ -11,16 +11,16 @@
$currentLabel = \Modules\Helpdesk\Support\Color::label($currentValue);
@endphp
<div {{ $attributes->class('space-y-3') }}>
<label class="block text-sm font-semibold text-zinc-700 dark:text-zinc-200">
{{ $label }}
</label>
<div {{ $attributes->class('rounded-2xl border border-zinc-200 bg-white/70 p-4 shadow-sm dark:border-zinc-700 dark:bg-zinc-950/50') }}>
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
<div class="min-w-0 flex-1 space-y-3">
<label class="block text-sm font-semibold text-zinc-800 dark:text-zinc-100">
{{ $label }}
</label>
<div class="grid gap-3 md:grid-cols-[minmax(0,1fr)_auto] md:items-end">
<div class="space-y-2">
<select
wire:model.live="{{ $model }}"
class="block h-10 w-full rounded-xl border border-zinc-300 bg-white px-3 text-sm font-semibold text-zinc-900 shadow-sm outline-none transition-colors duration-150 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/30 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100"
class="h-11 w-full rounded-xl border border-zinc-300 bg-white px-3 text-sm font-semibold text-zinc-900 shadow-sm outline-none transition-colors duration-150 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/30 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100"
>
@foreach ($options as $key => $option)
<option value="{{ $key }}" style="color: {{ $option['hex'] }};">
@@ -29,13 +29,13 @@
@endforeach
</select>
<div class="flex flex-wrap gap-1.5" aria-label="Available Helpdesk colours">
<div class="flex flex-wrap items-center gap-2" aria-label="Available Helpdesk colours">
@foreach ($options as $key => $option)
<button
type="button"
wire:click="$set('{{ $model }}', '{{ $key }}')"
title="{{ $option['name'] }} {{ $option['hex'] }}"
class="inline-flex h-6 min-w-6 items-center justify-center rounded-full border border-white/80 shadow-sm ring-1 ring-zinc-900/10 transition hover:scale-105 focus:outline-none focus:ring-2 focus:ring-blue-500/40"
class="inline-flex h-7 w-7 items-center justify-center rounded-full border border-white/80 shadow-sm ring-1 ring-zinc-900/10 transition hover:scale-105 focus:outline-none focus:ring-2 focus:ring-blue-500/40 dark:ring-white/15"
style="background-color: {{ $option['hex'] }}"
>
<span class="sr-only">Use {{ $option['name'] }}</span>
@@ -44,28 +44,31 @@
</div>
</div>
<span
class="inline-flex min-w-28 items-center justify-center rounded-full px-3 py-2 text-xs font-bold shadow-sm ring-1 ring-zinc-900/10"
style="background-color: {{ $currentHex }}; color: {{ $currentText }};"
>
{{ $currentLabel }}
</span>
</div>
<div class="flex w-full flex-col gap-3 sm:w-44 sm:items-stretch">
<span
class="inline-flex h-11 items-center justify-center rounded-xl px-4 text-sm font-bold shadow-sm ring-1 ring-zinc-900/10 dark:ring-white/10"
style="background-color: {{ $currentHex }}; color: {{ $currentText }};"
>
{{ $currentLabel }}
</span>
<div class="grid gap-3 md:grid-cols-[auto_minmax(0,1fr)] md:items-center">
<input
type="color"
value="{{ $currentHex }}"
wire:change="$set('{{ $model }}', $event.target.value)"
class="h-10 w-16 cursor-pointer rounded-xl border border-zinc-300 bg-white p-1 shadow-sm dark:border-zinc-700 dark:bg-zinc-950"
aria-label="Choose a custom hex colour"
/>
<div class="grid grid-cols-[3.5rem_minmax(0,1fr)] items-center gap-2">
<input
type="color"
value="{{ $currentHex }}"
wire:change="$set('{{ $model }}', $event.target.value)"
class="h-10 w-14 cursor-pointer rounded-xl border border-zinc-300 bg-white p-1 shadow-sm dark:border-zinc-700 dark:bg-zinc-900"
aria-label="Choose a custom hex colour"
/>
<flux:input
wire:model.live.debounce.500ms="{{ $model }}"
label="Custom hex colour"
placeholder="#ffffff"
description="Use the standard palette where possible. Custom hex values must use six characters, for example #ffffff."
/>
<input
type="text"
wire:model.live.debounce.500ms="{{ $model }}"
class="h-10 w-full rounded-xl border border-zinc-300 bg-white px-3 text-sm text-zinc-900 placeholder:text-zinc-400 shadow-sm outline-none transition-colors duration-150 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/30 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-100 dark:placeholder:text-zinc-500"
placeholder="#ffffff"
aria-label="Custom hex colour"
/>
</div>
</div>
</div>
</div>
@@ -1,9 +1,32 @@
@props([
'title' => 'Settings',
'description' => '',
])
<section
class="overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-700 dark:bg-zinc-900">
<div class="border-b border-zinc-200 bg-zinc-50 px-5 py-4 dark:border-zinc-700 dark:bg-zinc-800/70">
<h2 class="text-lg font-semibold text-zinc-900 dark:text-white">{{ $title }}</h2>
<p class="mt-1 text-sm text-zinc-500 dark:text-zinc-400">{{ $description }}</p>
{{ $attributes->merge([
'class' => 'overflow-hidden rounded-3xl border border-zinc-700 bg-zinc-900 shadow-sm ring-1 ring-white/10',
]) }}>
<div class="border-b border-zinc-700 bg-gradient-to-r from-slate-950 via-blue-950 to-slate-900 px-5 py-4 text-white">
<div class="flex flex-col gap-2 sm:flex-row sm:items-start sm:justify-between">
<div class="min-w-0">
<p class="text-[10px] font-black uppercase tracking-[0.24em] text-blue-200">Configuration</p>
<h2 class="mt-1 text-lg font-extrabold tracking-tight text-white">{{ $title }}</h2>
<p class="mt-1 max-w-3xl text-sm font-medium leading-6 text-blue-100/90">{{ $description }}</p>
</div>
<span class="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl border border-white/10 bg-white/10 text-blue-100 shadow-inner">
<i class="fa-solid fa-sliders text-sm" aria-hidden="true"></i>
</span>
</div>
</div>
<div class="border-b border-zinc-800 bg-zinc-950/45 px-4 py-5 sm:px-5">
<div class="mx-auto max-w-7xl rounded-2xl border border-zinc-700 bg-zinc-900/90 p-4 shadow-sm sm:p-5 [&_input:not([type='checkbox']):not([type='radio']):not([type='color'])]:min-h-11 [&_textarea]:min-h-24 [&_textarea]:leading-6">
{{ $form }}
</div>
</div>
<div class="bg-zinc-900">
{{ $slot }}
</div>
<div class="border-b border-zinc-200 p-5 dark:border-zinc-700">{{ $form }}</div>
<div>{{ $slot }}</div>
</section>
@@ -140,21 +140,27 @@
<x-helpdesk::settings-section title="Statuses"
description="Control workflow stages and mark which statuses close tickets.">
<x-slot:form>
<form wire:submit.prevent="saveStatus" class="grid gap-4 md:grid-cols-5">
<flux:input wire:model="statusForm.name" label="Name" />
<flux:input wire:model="statusForm.slug" label="Slug" placeholder="auto-generated" />
<x-helpdesk::colour-select model="statusForm.color" label="Badge colour" :options="$colourOptions" />
<flux:input wire:model="statusForm.sort_order" label="Sort" type="number" min="0" />
<label class="flex items-end gap-2 pb-2 text-sm text-zinc-700 dark:text-zinc-200"><input
type="checkbox" wire:model="statusForm.is_closed" class="rounded border-zinc-300"> Closed
status</label>
<label
class="md:col-span-5 flex items-center gap-2 text-sm font-semibold text-zinc-700 dark:text-zinc-200">
<form wire:submit.prevent="saveStatus" class="grid gap-5 xl:grid-cols-12">
<div class="xl:col-span-3">
<flux:input wire:model="statusForm.name" label="Name" />
</div>
<div class="xl:col-span-3">
<flux:input wire:model="statusForm.slug" label="Slug" placeholder="auto-generated" />
</div>
<x-helpdesk::colour-select class="xl:col-span-4" model="statusForm.color" label="Badge colour" :options="$colourOptions" />
<div class="xl:col-span-2">
<flux:input wire:model="statusForm.sort_order" label="Sort" type="number" min="0" />
</div>
<label class="flex min-h-12 items-center gap-3 rounded-xl border border-zinc-200 bg-white/70 px-4 py-3 text-sm font-semibold text-zinc-700 shadow-sm dark:border-zinc-700 dark:bg-zinc-950/50 dark:text-zinc-200 xl:col-span-3">
<input type="checkbox" wire:model="statusForm.is_closed" class="rounded border-zinc-600 bg-zinc-950 text-blue-600 focus:ring-blue-500">
Closed status
</label>
<label class="flex min-h-12 items-center gap-3 rounded-xl border border-zinc-200 bg-white/70 px-4 py-3 text-sm font-semibold text-zinc-700 shadow-sm dark:border-zinc-700 dark:bg-zinc-950/50 dark:text-zinc-200 xl:col-span-4">
<input type="checkbox" wire:model="statusForm.is_default"
class="rounded border-zinc-300 bg-zinc-950 text-blue-600 focus:ring-blue-500">
Default status for new tickets
</label>
<div class="md:col-span-5 flex gap-2">
<div class="flex flex-wrap items-center gap-2 xl:col-span-12">
<flux:button type="submit" variant="primary"
class="!bg-green-600 !text-white hover:!bg-green-700 focus:!ring-green-400/60">Save status
</flux:button>
@@ -171,17 +177,23 @@
@if ($section === 'priorities')
<x-helpdesk::settings-section title="Priorities" description="Define ticket urgency levels and display order.">
<x-slot:form>
<form wire:submit.prevent="savePriority" class="grid gap-4 md:grid-cols-4">
<flux:input wire:model="priorityForm.name" label="Name" />
<flux:input wire:model="priorityForm.slug" label="Slug" placeholder="auto-generated" />
<x-helpdesk::colour-select model="priorityForm.color" label="Badge colour" :options="$colourOptions" />
<flux:input wire:model="priorityForm.sort_order" label="Sort" type="number" min="0" />
<label class="flex items-end gap-2 pb-2 text-sm font-semibold text-zinc-700 dark:text-zinc-200">
<form wire:submit.prevent="savePriority" class="grid gap-5 xl:grid-cols-12">
<div class="xl:col-span-3">
<flux:input wire:model="priorityForm.name" label="Name" />
</div>
<div class="xl:col-span-3">
<flux:input wire:model="priorityForm.slug" label="Slug" placeholder="auto-generated" />
</div>
<x-helpdesk::colour-select class="xl:col-span-4" model="priorityForm.color" label="Badge colour" :options="$colourOptions" />
<div class="xl:col-span-2">
<flux:input wire:model="priorityForm.sort_order" label="Sort" type="number" min="0" />
</div>
<label class="flex min-h-12 items-center gap-3 rounded-xl border border-zinc-200 bg-white/70 px-4 py-3 text-sm font-semibold text-zinc-700 shadow-sm dark:border-zinc-700 dark:bg-zinc-950/50 dark:text-zinc-200 xl:col-span-4">
<input type="checkbox" wire:model="priorityForm.is_default"
class="rounded border-zinc-300 bg-zinc-950 text-blue-600 focus:ring-blue-500">
Default for new tickets
</label>
<div class="md:col-span-4 flex gap-2">
<div class="flex flex-wrap items-center gap-2 xl:col-span-12">
<flux:button type="submit" variant="primary"
class="!bg-green-600 !text-white hover:!bg-green-700 focus:!ring-green-400/60">Save priority
</flux:button>
@@ -199,26 +211,31 @@
<x-helpdesk::settings-section title="Categories"
description="Group tickets by support area, optionally per company.">
<x-slot:form>
<form wire:submit.prevent="saveCategory" class="grid gap-4 md:grid-cols-4">
<flux:select wire:model="categoryForm.company_id" label="Company">
<option value="">Global</option>
@foreach ($companies as $company)
<option value="{{ $company->id }}">{{ $company->name }}</option>
@endforeach
</flux:select>
<flux:input wire:model="categoryForm.name" label="Name" />
<flux:input wire:model="categoryForm.slug" label="Slug" placeholder="auto-generated" />
<x-helpdesk::colour-select model="categoryForm.color" label="Badge colour" :options="$colourOptions" />
<div class="md:col-span-4">
<form wire:submit.prevent="saveCategory" class="grid gap-5 xl:grid-cols-12">
<div class="xl:col-span-3">
<flux:select wire:model="categoryForm.company_id" label="Company">
<option value="">Global</option>
@foreach ($companies as $company)
<option value="{{ $company->id }}">{{ $company->name }}</option>
@endforeach
</flux:select>
</div>
<div class="xl:col-span-3">
<flux:input wire:model="categoryForm.name" label="Name" />
</div>
<div class="xl:col-span-3">
<flux:input wire:model="categoryForm.slug" label="Slug" placeholder="auto-generated" />
</div>
<x-helpdesk::colour-select class="xl:col-span-3" model="categoryForm.color" label="Badge colour" :options="$colourOptions" />
<div class="xl:col-span-12">
<flux:textarea wire:model="categoryForm.description" label="Description" rows="3" />
</div>
<label
class="md:col-span-4 flex items-center gap-2 text-sm font-semibold text-zinc-700 dark:text-zinc-200">
<label class="flex min-h-12 items-center gap-3 rounded-xl border border-zinc-200 bg-white/70 px-4 py-3 text-sm font-semibold text-zinc-700 shadow-sm dark:border-zinc-700 dark:bg-zinc-950/50 dark:text-zinc-200 xl:col-span-4">
<input type="checkbox" wire:model="categoryForm.is_default"
class="rounded border-zinc-300 bg-zinc-950 text-blue-600 focus:ring-blue-500">
Default category for new tickets
</label>
<div class="md:col-span-4 flex gap-2">
<div class="flex flex-wrap items-center gap-2 xl:col-span-12">
<flux:button type="submit" variant="primary"
class="!bg-green-600 !text-white hover:!bg-green-700 focus:!ring-green-400/60">Save
category</flux:button>
@@ -236,26 +253,31 @@
<x-helpdesk::settings-section title="Teams"
description="Create support teams under each company and assign projects to them.">
<x-slot:form>
<form wire:submit.prevent="saveTeam" class="grid gap-4 md:grid-cols-4">
<flux:select wire:model="teamForm.company_id" label="Company">
<option value="">Global</option>
@foreach ($companies as $company)
<option value="{{ $company->id }}">{{ $company->name }}</option>
@endforeach
</flux:select>
<flux:input wire:model="teamForm.name" label="Name" />
<flux:input wire:model="teamForm.slug" label="Slug" placeholder="auto-generated" />
<x-helpdesk::colour-select model="teamForm.color" label="Badge colour" :options="$colourOptions" />
<div class="md:col-span-4">
<form wire:submit.prevent="saveTeam" class="grid gap-5 xl:grid-cols-12">
<div class="xl:col-span-3">
<flux:select wire:model="teamForm.company_id" label="Company">
<option value="">Global</option>
@foreach ($companies as $company)
<option value="{{ $company->id }}">{{ $company->name }}</option>
@endforeach
</flux:select>
</div>
<div class="xl:col-span-3">
<flux:input wire:model="teamForm.name" label="Name" />
</div>
<div class="xl:col-span-3">
<flux:input wire:model="teamForm.slug" label="Slug" placeholder="auto-generated" />
</div>
<x-helpdesk::colour-select class="xl:col-span-3" model="teamForm.color" label="Badge colour" :options="$colourOptions" />
<div class="xl:col-span-12">
<flux:textarea wire:model="teamForm.description" label="Description" rows="3" />
</div>
<label
class="md:col-span-4 flex items-center gap-2 text-sm font-semibold text-zinc-700 dark:text-zinc-200">
<label class="flex min-h-12 items-center gap-3 rounded-xl border border-zinc-200 bg-white/70 px-4 py-3 text-sm font-semibold text-zinc-700 shadow-sm dark:border-zinc-700 dark:bg-zinc-950/50 dark:text-zinc-200 xl:col-span-4">
<input type="checkbox" wire:model="teamForm.is_default"
class="rounded border-zinc-300 bg-zinc-950 text-blue-600 focus:ring-blue-500">
Default team for new tickets
</label>
<div class="md:col-span-4 flex gap-2">
<div class="flex flex-wrap items-center gap-2 xl:col-span-12">
<flux:button type="submit" variant="primary"
class="!bg-green-600 !text-white hover:!bg-green-700 focus:!ring-green-400/60">Save team
</flux:button>
@@ -273,32 +295,39 @@
<x-helpdesk::settings-section title="Projects"
description="Create company projects and optionally assign them to support teams.">
<x-slot:form>
<form wire:submit.prevent="saveProject" class="grid gap-4 md:grid-cols-5">
<flux:select wire:model="projectForm.company_id" label="Company">
<option value="">Global</option>
@foreach ($companies as $company)
<option value="{{ $company->id }}">{{ $company->name }}</option>
@endforeach
</flux:select>
<flux:select wire:model="projectForm.team_id" label="Team">
<option value="">No team</option>
@foreach ($teams as $team)
<option value="{{ $team->id }}">{{ $team->name }}</option>
@endforeach
</flux:select>
<flux:input wire:model="projectForm.title" label="Title" />
<flux:input wire:model="projectForm.slug" label="Slug" placeholder="auto-generated" />
<x-helpdesk::colour-select model="projectForm.color" label="Badge colour" :options="$colourOptions" />
<div class="md:col-span-5">
<form wire:submit.prevent="saveProject" class="grid gap-5 xl:grid-cols-12">
<div class="xl:col-span-2">
<flux:select wire:model="projectForm.company_id" label="Company">
<option value="">Global</option>
@foreach ($companies as $company)
<option value="{{ $company->id }}">{{ $company->name }}</option>
@endforeach
</flux:select>
</div>
<div class="xl:col-span-2">
<flux:select wire:model="projectForm.team_id" label="Team">
<option value="">No team</option>
@foreach ($teams as $team)
<option value="{{ $team->id }}">{{ $team->name }}</option>
@endforeach
</flux:select>
</div>
<div class="xl:col-span-2">
<flux:input wire:model="projectForm.title" label="Title" />
</div>
<div class="xl:col-span-2">
<flux:input wire:model="projectForm.slug" label="Slug" placeholder="auto-generated" />
</div>
<x-helpdesk::colour-select class="xl:col-span-4" model="projectForm.color" label="Badge colour" :options="$colourOptions" />
<div class="xl:col-span-12">
<flux:textarea wire:model="projectForm.description" label="Description" rows="3" />
</div>
<label
class="md:col-span-5 flex items-center gap-2 text-sm font-semibold text-zinc-700 dark:text-zinc-200">
<label class="flex min-h-12 items-center gap-3 rounded-xl border border-zinc-200 bg-white/70 px-4 py-3 text-sm font-semibold text-zinc-700 shadow-sm dark:border-zinc-700 dark:bg-zinc-950/50 dark:text-zinc-200 xl:col-span-4">
<input type="checkbox" wire:model="projectForm.is_default"
class="rounded border-zinc-300 bg-zinc-950 text-blue-600 focus:ring-blue-500">
Default project for new tickets
</label>
<div class="md:col-span-5 flex gap-2">
<div class="flex flex-wrap items-center gap-2 xl:col-span-12">
<flux:button type="submit" variant="primary"
class="!bg-green-600 !text-white hover:!bg-green-700 focus:!ring-green-400/60">Save project
</flux:button>
@@ -865,11 +894,15 @@
<x-helpdesk::settings-section title="Ticket tags"
description="Maintain visible ticket labels for search, triage and Kanban card context.">
<x-slot:form>
<form wire:submit.prevent="saveTag" class="grid gap-4 md:grid-cols-5">
<flux:input wire:model="tagForm.name" label="Name" />
<flux:input wire:model="tagForm.slug" label="Slug" />
<x-helpdesk::colour-select model="tagForm.color" label="Colour" :options="$colourOptions" />
<div class="md:col-span-5 flex gap-2">
<form wire:submit.prevent="saveTag" class="grid gap-5 xl:grid-cols-12">
<div class="xl:col-span-4">
<flux:input wire:model="tagForm.name" label="Name" />
</div>
<div class="xl:col-span-4">
<flux:input wire:model="tagForm.slug" label="Slug" />
</div>
<x-helpdesk::colour-select class="xl:col-span-4" model="tagForm.color" label="Colour" :options="$colourOptions" />
<div class="flex flex-wrap items-center gap-2 xl:col-span-12">
<flux:button type="submit" variant="primary"
class="!bg-green-600 !text-white hover:!bg-green-700 focus:!ring-green-400/60">Save tag
</flux:button>
@@ -527,7 +527,7 @@
class="prose prose-sm min-h-[12rem] max-w-none bg-white p-4 text-sm leading-6 text-zinc-900 outline-none dark:prose-invert dark:bg-zinc-950 dark:text-zinc-100"
data-placeholder="Write a public reply or internal note. Right-click or Ctrl-click underlined words for spelling suggestions.">{!! $oldCommentBody !!}</div>
<textarea id="ticket-comment-body" name="commentBody" required class="sr-only" tabindex="-1" aria-hidden="true">{{ $oldCommentBody }}</textarea>
<textarea id="ticket-comment-body" name="commentBody" required spellcheck="true" lang="en-GB" autocorrect="on" autocomplete="on" autocapitalize="sentences" inputmode="text" class="sr-only" tabindex="-1" aria-hidden="true">{{ $oldCommentBody }}</textarea>
</div>
<p class="mt-2 flex items-center gap-2 text-xs font-medium text-zinc-500 dark:text-zinc-400">
@@ -221,7 +221,7 @@
<button type="button" data-helpdesk-wrap="<code>" data-helpdesk-wrap-end="</code>"
class="rounded-lg border px-2 py-1 text-xs">Code</button>
</div>
<textarea spellcheck="true" lang="en-GB" id="reply-body-{{ $comment->id }}" dusk="reply-body-{{ $comment->id }}" name="commentBody" rows="4"
<textarea spellcheck="true" lang="en-GB" autocorrect="on" autocomplete="on" autocapitalize="sentences" inputmode="text" id="reply-body-{{ $comment->id }}" dusk="reply-body-{{ $comment->id }}" name="commentBody" rows="4"
required
class="block w-full rounded-xl border border-zinc-300 bg-white p-3 text-sm text-zinc-900 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100"
placeholder="Write a threaded Lotus Notes-style response..."></textarea>