structure updates

This commit is contained in:
Mark Gregory
2026-08-26 12:38:12 +01:00
parent 66fd8b0e8a
commit 138a028537
14 changed files with 819 additions and 270 deletions
@@ -11,7 +11,8 @@
columns are configured in Helpdesk Settings.</p>
</div>
<div class="flex flex-wrap gap-2">
<div class="flex w-full flex-col gap-3 lg:w-auto lg:min-w-[420px]">
<div class="flex flex-wrap justify-start gap-2 lg:justify-end">
<a href="{{ route('helpdesk.index') }}" wire:navigate class="hd-btn hd-btn-blue">
<i class="fa-solid fa-gauge-high" aria-hidden="true"></i>
<span>Dashboard</span>
@@ -31,6 +32,39 @@
<i class="fa-solid fa-list" aria-hidden="true"></i>
<span>List view</span>
</a>
</div>
@if ($boards->isNotEmpty())
<div class="hd-kanban-active-board-card">
<div class="min-w-0">
<p class="hd-kanban-active-board-label">Active board</p>
<h2 class="hd-kanban-active-board-title">{{ $board?->name ?? 'None' }}</h2>
<p class="hd-kanban-active-board-description">
{{ $board?->description ?: 'Select the workflow board to display.' }}
</p>
@if ($board?->owner)
<p class="hd-kanban-active-board-owner">
<i class="fa-solid fa-user-shield" aria-hidden="true"></i>
{{ $board->owner->name }}
</p>
@endif
</div>
<div class="hd-select-wrap hd-kanban-board-selector">
<select
class="hd-select"
aria-label="Select Kanban board"
onchange="window.location.href = '{{ route('helpdesk.kanban') }}?board_id=' + encodeURIComponent(this.value)"
>
@foreach ($boards as $availableBoard)
<option value="{{ $availableBoard->id }}" @selected((int) $board_id === (int) $availableBoard->id)>
{{ $availableBoard->name }}{{ $availableBoard->owner ? ' · ' . $availableBoard->owner->name : '' }}
</option>
@endforeach
</select>
</div>
</div>
@endif
</div>
</div>
</div>
@@ -41,34 +75,6 @@
No Kanban boards exist yet. Open Helpdesk Settings and create a board with at least one status column.
</div>
@else
<div
class="flex flex-col gap-4 rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-700 dark:bg-zinc-900 md:flex-row md:items-center md:justify-between">
<div class="min-w-0">
<h2 class="text-sm font-semibold text-zinc-900 dark:text-zinc-100">Active board: {{ $board?->name ?? 'None' }}</h2>
<p class="text-xs text-zinc-500 dark:text-zinc-400">
{{ $board?->description ?: 'Use settings to configure which statuses appear as draggable columns.' }}
</p>
@if ($board?->owner)
<p class="mt-1 text-xs font-semibold text-emerald-600 dark:text-emerald-300">Owner:
{{ $board->owner->name }}</p>
@endif
</div>
<div class="hd-select-wrap shrink-0 md:w-72">
<select
class="hd-select"
aria-label="Select Kanban board"
onchange="window.location.href = '{{ route('helpdesk.kanban') }}?board_id=' + encodeURIComponent(this.value)"
>
@foreach ($boards as $availableBoard)
<option value="{{ $availableBoard->id }}" @selected((int) $board_id === (int) $availableBoard->id)>
{{ $availableBoard->name }}{{ $availableBoard->owner ? ' · ' . $availableBoard->owner->name : '' }}
</option>
@endforeach
</select>
</div>
</div>
@if ($statuses->isEmpty())
<div
class="rounded-2xl border border-amber-500/40 bg-amber-950/70 px-5 py-4 text-sm font-semibold text-amber-100">
@@ -111,12 +117,7 @@
draggable="true" data-helpdesk-kanban-ticket data-ticket-id="{{ $ticket->id }}"
wire:key="kanban-ticket-{{ $ticket->id }}-{{ $ticket->status_id }}-{{ $ticket->board_id }}-{{ optional($ticket->updated_at)->timestamp }}"
dusk="kanban-ticket-{{ $ticket->id }}">
<div class="mb-2 flex justify-end">
<span class="hd-kanban-drag-handle" draggable="true" data-kanban-drag-handle title="Drag ticket" aria-label="Drag {{ $ticket->reference }}">
<i class="fa-solid fa-grip-vertical"></i>
</span>
</div>
<div class="flex items-start justify-between gap-3">
<div class="flex items-start justify-between gap-3">
<div class="min-w-0">
<div
class="font-mono text-xs font-semibold text-blue-700 dark:text-blue-300">
@@ -122,7 +122,7 @@
class="hd-settings-modal w-full max-w-4xl"
@close="closeStatusModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--status">
<flux:heading size="lg">{{ filled($statusForm['id'] ?? null) ? 'Edit status' : 'Create status' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this status without leaving the settings list.</flux:subheading>
</div>
@@ -183,7 +183,7 @@
class="hd-settings-modal w-full max-w-4xl"
@close="closePriorityModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--priority">
<flux:heading size="lg">{{ filled($priorityForm['id'] ?? null) ? 'Edit priority' : 'Create priority' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this priority without leaving the settings list.</flux:subheading>
</div>
@@ -240,7 +240,7 @@
class="hd-settings-modal w-full max-w-4xl"
@close="closeCategoryModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--category">
<flux:heading size="lg">{{ filled($categoryForm['id'] ?? null) ? 'Edit category' : 'Create category' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this category without leaving the settings list.</flux:subheading>
</div>
@@ -300,7 +300,7 @@
@close="closeTeamModal"
>
<form wire:submit="saveTeam" class="space-y-5">
<div class="flex items-start justify-between gap-4 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--team flex items-start justify-between gap-4">
<div>
<flux:heading size="lg">
{{ filled($teamForm['id'] ?? null) ? 'Edit team' : 'Create team' }}
@@ -399,7 +399,7 @@
class="hd-settings-modal w-full max-w-5xl"
@close="closeProjectModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--project">
<flux:heading size="lg">{{ filled($projectForm['id'] ?? null) ? 'Edit project' : 'Create project' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this project without leaving the settings list.</flux:subheading>
</div>
@@ -467,7 +467,7 @@
class="hd-settings-modal w-full max-w-6xl"
@close="closeBoardModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--board">
<flux:heading size="lg">{{ filled($boardForm['id'] ?? null) ? 'Edit board' : 'Create board' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this board without leaving the settings list.</flux:subheading>
</div>
@@ -599,7 +599,7 @@
class="hd-settings-modal w-full max-w-5xl"
@close="closeRepositoryModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--git">
<flux:heading size="lg">{{ filled($repositoryForm['id'] ?? null) ? 'Edit repository' : 'Create repository' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this repository without leaving the settings list.</flux:subheading>
</div>
@@ -657,7 +657,7 @@
class="hd-settings-modal w-full max-w-6xl"
@close="closeWorkflowTemplateModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--workflow">
<flux:heading size="lg">{{ filled($workflowForm['id'] ?? null) ? 'Edit workflow message' : 'Create workflow message' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this workflow message without leaving the settings list.</flux:subheading>
</div>
@@ -777,7 +777,7 @@
class="hd-settings-modal w-full max-w-6xl"
@close="closeCannedResponseModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--canned">
<flux:heading size="lg">{{ filled($cannedForm['id'] ?? null) ? 'Edit canned response' : 'Create canned response' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this canned response without leaving the settings list.</flux:subheading>
</div>
@@ -875,7 +875,7 @@
class="hd-settings-modal w-full max-w-5xl"
@close="closeSlaPolicyModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--sla">
<flux:heading size="lg">{{ filled($slaForm['id'] ?? null) ? 'Edit SLA policy' : 'Create SLA policy' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this SLA policy without leaving the settings list.</flux:subheading>
</div>
@@ -984,7 +984,7 @@
class="hd-settings-modal w-full max-w-6xl"
@close="closeAutomationRuleModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--automation">
<flux:heading size="lg">{{ filled($automationForm['id'] ?? null) ? 'Edit automation rule' : 'Create automation rule' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this automation rule without leaving the settings list.</flux:subheading>
</div>
@@ -1087,7 +1087,7 @@
class="hd-settings-modal w-full max-w-5xl"
@close="closeChecklistTemplateModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--checklist">
<flux:heading size="lg">{{ filled($checklistTemplateForm['id'] ?? null) ? 'Edit checklist template' : 'Create checklist' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this checklist template without leaving the settings list.</flux:subheading>
</div>
@@ -1170,7 +1170,7 @@
class="hd-settings-modal w-full max-w-4xl"
@close="closeTagModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--tag">
<flux:heading size="lg">{{ filled($tagForm['id'] ?? null) ? 'Edit tag' : 'Create tag' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this tag without leaving the settings list.</flux:subheading>
</div>
@@ -1238,7 +1238,7 @@
class="hd-settings-modal w-full max-w-5xl"
@close="closeProductModal"
>
<div class="mb-5 border-b border-zinc-200 pb-4 dark:border-zinc-700">
<div class="hd-settings-modal-header hd-settings-modal-header--product">
<flux:heading size="lg">{{ filled($productForm['id'] ?? null) ? 'Edit product/service' : 'Create product' }}</flux:heading>
<flux:subheading class="mt-1">Create or edit this product/service without leaving the settings list.</flux:subheading>
</div>
@@ -25,28 +25,42 @@
<div class="rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-700 dark:bg-zinc-900">
<div class="grid gap-4 md:grid-cols-4">
<flux:input wire:model.live.debounce.350ms="search" icon="magnifying-glass"
placeholder="Search reference, subject or body" />
<div class="hd-ticket-search-wrap">
<i class="fa-solid fa-magnifying-glass hd-ticket-search-icon" aria-hidden="true"></i>
<input
type="search"
class="hd-ticket-search"
wire:model.live.debounce.350ms="search"
placeholder="Search reference, subject or body"
aria-label="Search tickets"
>
</div>
<flux:select wire:model.live="scope">
<option value="open">Open tickets</option>
<option value="closed">Closed tickets</option>
<option value="all">All tickets</option>
</flux:select>
<div class="hd-select-wrap">
<select class="hd-select" wire:model.live="scope" aria-label="Ticket scope">
<option value="open">Open tickets</option>
<option value="closed">Closed tickets</option>
<option value="all">All tickets</option>
</select>
</div>
<flux:select wire:model.live="status">
<option value="">All statuses</option>
@foreach ($statuses as $status)
<option value="{{ $status->id }}">{{ $status->name }}</option>
@endforeach
</flux:select>
<div class="hd-select-wrap">
<select class="hd-select" wire:model.live="status" aria-label="Ticket status">
<option value="">All statuses</option>
@foreach ($statuses as $status)
<option value="{{ $status->id }}">{{ $status->name }}</option>
@endforeach
</select>
</div>
<flux:select wire:model.live="priority">
<option value="">All priorities</option>
@foreach ($priorities as $priority)
<option value="{{ $priority->id }}">{{ $priority->name }}</option>
@endforeach
</flux:select>
<div class="hd-select-wrap">
<select class="hd-select" wire:model.live="priority" aria-label="Ticket priority">
<option value="">All priorities</option>
@foreach ($priorities as $priority)
<option value="{{ $priority->id }}">{{ $priority->name }}</option>
@endforeach
</select>
</div>
</div>
</div>
@@ -150,8 +164,23 @@
</table>
</div>
<div class="border-t border-zinc-200 p-4 dark:border-zinc-700">
{{ $tickets->links() }}
<div class="flex flex-col gap-3 border-t border-zinc-200 bg-zinc-50/70 px-4 py-4 dark:border-zinc-700 dark:bg-zinc-950/35 sm:flex-row sm:items-center sm:justify-between">
<div class="text-sm font-medium text-zinc-500 dark:text-zinc-400">
Showing
<span class="font-semibold text-zinc-800 dark:text-zinc-200">{{ $tickets->firstItem() ?? 0 }}</span>
–
<span class="font-semibold text-zinc-800 dark:text-zinc-200">{{ $tickets->lastItem() ?? 0 }}</span>
of
<span class="font-semibold text-zinc-800 dark:text-zinc-200">{{ $tickets->total() }}</span> tickets
</div>
<div class="min-w-0">
@if ($tickets->hasPages())
{{ $tickets->onEachSide(1)->links() }}
@else
<span class="inline-flex rounded-lg border border-zinc-200 bg-white px-3 py-1.5 text-xs font-semibold text-zinc-500 dark:border-zinc-700 dark:bg-zinc-900">Page 1 of 1</span>
@endif
</div>
</div>
</div>