added correct SLA support

Awaiting Response

No qualifying response yet

Due Soon

SLA is approaching its deadline

MET

SLA target achieved on time

BREACHED

SLA target missed
This commit is contained in:
Mark Gregory
2026-06-23 10:46:32 +01:00
parent d449f01593
commit 373f78ea15
5 changed files with 314 additions and 25 deletions
@@ -886,28 +886,49 @@
</div>
<div class="space-y-3 text-xs">
<div
class="rounded-lg border {{ $ticket->sla_first_response_breached ? 'border-red-300 bg-red-50 text-red-900 dark:border-red-900 dark:bg-red-950 dark:text-red-100' : ($ticket->first_response_at ? 'border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-100' : 'border-amber-200 bg-amber-50 text-amber-950 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100') }} p-3">
<div class="text-[0.68rem] font-semibold uppercase tracking-wide">First response</div>
<div class="rounded-lg border {{ $this->firstResponseSlaClasses() }} p-3">
<div class="flex items-start justify-between gap-3">
<div>
<div class="text-[0.68rem] font-semibold uppercase tracking-wide">First response</div>
<div class="mt-1 text-sm font-black">{{ $this->firstResponseSlaHeadline() }}</div>
<div class="mt-1 text-[0.68rem] font-semibold opacity-80">{{ $this->firstResponseSlaDetail() }}</div>
</div>
@if ($ticket->first_response_at)
<span class="rounded-full bg-white/60 px-2 py-1 text-[0.6rem] font-black uppercase tracking-wide dark:bg-black/20">
Met
</span>
@endif
</div>
@if ($ticket->first_response_at)
<div class="mt-1 font-semibold">Responded</div>
<div class="mt-1 text-[0.68rem] opacity-75">
{{ $ticket->first_response_at->format('d M Y H:i') }}
</div>
@else
<div class="mt-1 font-semibold">Awaiting public reply</div>
<div class="mt-1 text-[0.68rem] opacity-75">Due
{{ $ticket->sla_first_response_due_at?->format('d M Y H:i') ?? 'Not set' }}</div>
<dl class="mt-3 grid gap-1 border-t border-current/15 pt-2 text-[0.65rem] font-semibold opacity-85">
<div class="flex justify-between gap-3">
<dt>Responder</dt>
<dd class="text-right">{{ $this->firstResponderName() }}</dd>
</div>
<div class="flex justify-between gap-3">
<dt>Responded at</dt>
<dd class="text-right">{{ $ticket->first_response_at->format('d M Y H:i') }}</dd>
</div>
</dl>
@endif
</div>
<div
class="rounded-lg border {{ $ticket->sla_resolution_breached ? 'border-red-300 bg-red-50 text-red-900 dark:border-red-900 dark:bg-red-950 dark:text-red-100' : 'border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-900 dark:bg-blue-950 dark:text-blue-100' }} p-3">
<div class="text-[0.68rem] font-semibold uppercase tracking-wide">Resolution</div>
<div class="mt-1">{{ $ticket->completed_at?->format('d M Y H:i') ?? 'Open' }}</div>
<div class="mt-1 text-[0.68rem] opacity-75">Due
{{ $ticket->sla_resolution_due_at?->format('d M Y H:i') ?? 'Not set' }}</div>
<div class="rounded-lg border {{ $this->resolutionSlaClasses() }} p-3">
<div class="flex items-start justify-between gap-3">
<div>
<div class="text-[0.68rem] font-semibold uppercase tracking-wide">Resolution</div>
<div class="mt-1 text-sm font-black">{{ $this->resolutionSlaHeadline() }}</div>
<div class="mt-1 text-[0.68rem] font-semibold opacity-80">{{ $this->resolutionSlaDetail() }}</div>
</div>
@if ($ticket->completed_at)
<span class="rounded-full bg-white/60 px-2 py-1 text-[0.6rem] font-black uppercase tracking-wide dark:bg-black/20">
Closed
</span>
@endif
</div>
</div>
<div class="grid grid-cols-2 gap-2 text-center">
@@ -938,6 +959,54 @@
</button>
</div>
</div>
<div class="rounded-lg border border-zinc-200 bg-zinc-50 p-3 text-zinc-800 shadow-sm dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100">
<div class="flex items-center justify-between gap-3">
<div class="text-[0.68rem] font-black uppercase tracking-wide">SLA audit trail</div>
<div class="text-[0.62rem] font-semibold text-zinc-500 dark:text-zinc-400">
{{ $ticket->slaEvents->count() }} events
</div>
</div>
<div class="mt-3 space-y-2">
@forelse ($ticket->slaEvents->take(5) as $event)
<div class="rounded-md border border-zinc-200 bg-white p-2 dark:border-zinc-700 dark:bg-zinc-900">
<div class="flex items-start justify-between gap-3">
<div>
<div class="font-bold">{{ $this->formatSlaEventName($event->event) }}</div>
<div class="mt-0.5 text-[0.62rem] text-zinc-500 dark:text-zinc-400">
{{ $event->occurred_at?->format('d M Y H:i') ?? 'Not timestamped' }}
</div>
</div>
<span class="rounded-full px-2 py-0.5 text-[0.58rem] font-black uppercase {{ $event->breached ? 'bg-red-100 text-red-800 dark:bg-red-950 dark:text-red-100' : 'bg-emerald-100 text-emerald-800 dark:bg-emerald-950 dark:text-emerald-100' }}">
{{ $event->breached ? 'Breached' : 'Met' }}
</span>
</div>
@if ($event->due_at || filled(data_get($event->meta, 'actor_name')))
<dl class="mt-2 grid gap-1 text-[0.6rem] text-zinc-600 dark:text-zinc-300">
@if ($event->due_at)
<div class="flex justify-between gap-2">
<dt>Due</dt>
<dd>{{ $event->due_at->format('d M Y H:i') }}</dd>
</div>
@endif
@if (filled(data_get($event->meta, 'actor_name')))
<div class="flex justify-between gap-2">
<dt>Actor</dt>
<dd>{{ data_get($event->meta, 'actor_name') }}</dd>
</div>
@endif
</dl>
@endif
</div>
@empty
<div class="rounded-md border border-dashed border-zinc-300 p-3 text-center text-[0.65rem] font-semibold text-zinc-500 dark:border-zinc-700 dark:text-zinc-400">
No SLA events have been recorded yet.
</div>
@endforelse
</div>
</div>
</div>
</div>