173 lines
8.4 KiB
PHP
173 lines
8.4 KiB
PHP
<div class="hd-helpdesk-surface space-y-6" wire:key="helpdesk-kanban-{{ $refreshNonce }}">
|
|
<div class="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
|
|
<div>
|
|
<flux:heading size="xl">{{ __('Helpdesk Kanban') }}</flux:heading>
|
|
<flux:text class="mt-1">
|
|
{{ __('Move tickets through the workflow for the selected board.') }}
|
|
</flux:text>
|
|
</div>
|
|
|
|
<div class="flex flex-wrap items-end gap-3">
|
|
@if ($boards->isNotEmpty())
|
|
<div class="min-w-64">
|
|
<flux:select
|
|
wire:model.live="board_id"
|
|
:label="__('Board')"
|
|
>
|
|
@foreach ($boards as $boardOption)
|
|
<option value="{{ $boardOption->id }}">
|
|
{{ $boardOption->name }}
|
|
@if ($boardOption->is_default)
|
|
— {{ __('Default') }}
|
|
@endif
|
|
</option>
|
|
@endforeach
|
|
</flux:select>
|
|
</div>
|
|
@endif
|
|
|
|
<flux:button
|
|
:href="route('helpdesk.tickets.index')"
|
|
wire:navigate
|
|
>
|
|
{{ __('Ticket list') }}
|
|
</flux:button>
|
|
|
|
<flux:button
|
|
variant="primary"
|
|
:href="route('helpdesk.tickets.create')"
|
|
wire:navigate
|
|
>
|
|
{{ __('New ticket') }}
|
|
</flux:button>
|
|
</div>
|
|
</div>
|
|
|
|
@if (session('success'))
|
|
<div class="rounded-xl border border-emerald-300 bg-emerald-50 px-4 py-3 text-sm font-medium text-emerald-800 dark:border-emerald-800 dark:bg-emerald-950/40 dark:text-emerald-200">
|
|
{{ session('success') }}
|
|
</div>
|
|
@endif
|
|
|
|
@if ($board === null)
|
|
<div class="rounded-2xl border border-dashed border-zinc-300 bg-white p-10 text-center dark:border-zinc-700 dark:bg-zinc-900">
|
|
<flux:heading size="lg">{{ __('No Kanban board configured') }}</flux:heading>
|
|
<flux:text class="mt-2">
|
|
{{ __('Create a board in Helpdesk settings before using Kanban.') }}
|
|
</flux:text>
|
|
|
|
<flux:button
|
|
class="mt-5"
|
|
variant="primary"
|
|
:href="route('helpdesk.settings')"
|
|
wire:navigate
|
|
>
|
|
{{ __('Open settings') }}
|
|
</flux:button>
|
|
</div>
|
|
@else
|
|
<div class="flex gap-4 overflow-x-auto pb-4">
|
|
@foreach ($statuses as $status)
|
|
@php
|
|
$statusTickets = collect($ticketsByStatus[$status->id] ?? []);
|
|
@endphp
|
|
|
|
<section
|
|
class="w-[22rem] min-w-[22rem] rounded-2xl border border-zinc-200 bg-zinc-100/70 p-3 dark:border-zinc-700 dark:bg-zinc-900"
|
|
wire:key="kanban-status-{{ $status->id }}-{{ $refreshNonce }}"
|
|
>
|
|
<header class="mb-3 flex items-center justify-between gap-3 px-1">
|
|
<div class="min-w-0">
|
|
<flux:heading size="sm" class="truncate">
|
|
{{ $status->name }}
|
|
</flux:heading>
|
|
</div>
|
|
|
|
<span class="inline-flex min-w-7 items-center justify-center rounded-full bg-white px-2 py-1 text-xs font-semibold text-zinc-600 shadow-sm dark:bg-zinc-800 dark:text-zinc-300">
|
|
{{ $statusTickets->count() }}
|
|
</span>
|
|
</header>
|
|
|
|
<div class="space-y-3">
|
|
@forelse ($statusTickets as $ticket)
|
|
<article
|
|
class="rounded-xl border border-zinc-200 bg-white p-4 shadow-sm transition hover:shadow-md dark:border-zinc-700 dark:bg-zinc-800"
|
|
wire:key="kanban-ticket-{{ $ticket->id }}-{{ $ticket->status_id }}"
|
|
>
|
|
<div class="flex items-start justify-between gap-3">
|
|
<div class="min-w-0">
|
|
<a
|
|
href="{{ route('helpdesk.tickets.show', $ticket) }}"
|
|
wire:navigate
|
|
class="text-xs font-semibold text-blue-600 hover:underline dark:text-blue-400"
|
|
>
|
|
{{ $ticket->reference }}
|
|
</a>
|
|
|
|
<a
|
|
href="{{ route('helpdesk.tickets.show', $ticket) }}"
|
|
wire:navigate
|
|
class="mt-1 block font-semibold leading-snug text-zinc-900 hover:underline dark:text-zinc-100"
|
|
>
|
|
{{ $ticket->subject }}
|
|
</a>
|
|
</div>
|
|
|
|
@if ($ticket->priority)
|
|
<span class="shrink-0 rounded-full bg-zinc-100 px-2 py-1 text-[11px] font-semibold text-zinc-600 dark:bg-zinc-700 dark:text-zinc-200">
|
|
{{ $ticket->priority->name }}
|
|
</span>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="mt-3 space-y-1 text-xs text-zinc-500 dark:text-zinc-400">
|
|
@if ($ticket->agent)
|
|
<div>{{ __('Agent') }}: {{ $ticket->agent->name }}</div>
|
|
@endif
|
|
|
|
@if ($ticket->category)
|
|
<div>{{ __('Category') }}: {{ $ticket->category->name }}</div>
|
|
@endif
|
|
|
|
@if ($ticket->project)
|
|
<div>{{ __('Project') }}: {{ $ticket->project->name ?? $ticket->project->title ?? '—' }}</div>
|
|
@endif
|
|
</div>
|
|
|
|
@can('update', $ticket)
|
|
<div class="mt-4">
|
|
<label class="mb-1 block text-xs font-semibold text-zinc-500 dark:text-zinc-400">
|
|
{{ __('Move to') }}
|
|
</label>
|
|
|
|
<select
|
|
class="hd-select !min-h-0 !rounded-lg !px-3 !py-2 text-sm"
|
|
wire:change="moveTicket({{ $ticket->id }}, $event.target.value)"
|
|
wire:loading.attr="disabled"
|
|
wire:target="moveTicket"
|
|
>
|
|
<option value="{{ $status->id }}">{{ $status->name }}</option>
|
|
|
|
@foreach ($statuses as $targetStatus)
|
|
@if ($targetStatus->id !== $status->id)
|
|
<option value="{{ $targetStatus->id }}">
|
|
{{ $targetStatus->name }}
|
|
</option>
|
|
@endif
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
@endcan
|
|
</article>
|
|
@empty
|
|
<div class="rounded-xl border border-dashed border-zinc-300 bg-white/70 px-4 py-8 text-center text-sm text-zinc-500 dark:border-zinc-700 dark:bg-zinc-800/40 dark:text-zinc-400">
|
|
{{ __('No tickets') }}
|
|
</div>
|
|
@endforelse
|
|
</div>
|
|
</section>
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</div>
|