Files
ladill-care/resources/views/care/partials/queue-board.blade.php
T
isaaccladandCursor 64e3f75159
Deploy Ladill Care / deploy (push) Successful in 51s
Let nurses open specialty visits from the queue list.
Open on waiting/called cards no longer requires consultations.manage so
view roles can re-enter Emergency and other specialty workspaces.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-19 13:52:28 +00:00

174 lines
8.2 KiB
PHP

{{--
Shared patient-flow board (GP Queue + specialty Queue homes).
Expected vars:
- $queue, $inConsultation (collections of Appointment)
- $done (optional completed today)
- $queueIntegration, $branchId
- $canConsult (bool)
- $queueCallNextRoute, $queueCallNextParams (optional if set, Call next renders above board)
- $startRouteName (default care.queue.start) route(name, $appointment)
- $openInCareUrl (callable Appointment $a): ?string workspace/form URL for Open
(waiting / called / in-care / done; not gated by canConsult)
- $inCareLabel (default "In care")
- $lockToPractitioner, $canSwitchBranch, $branches, $practitioners, $practitionerId (filter bar)
- $showFilters (default true)
--}}
@php
$canConsult = $canConsult ?? false;
$showFilters = $showFilters ?? true;
$inCareLabel = $inCareLabel ?? 'In care';
$startRouteName = $startRouteName ?? 'care.queue.start';
$openInCareUrl = $openInCareUrl ?? function ($appointment) {
return $appointment->consultation
? route('care.consultations.show', $appointment->consultation)
: null;
};
$queueCallNextRoute = $queueCallNextRoute ?? null;
$queueCallNextParams = $queueCallNextParams ?? [];
$done = $done ?? collect();
$calledStatuses = ['called', 'serving'];
$waitingList = $queue->reject(
fn ($a) => in_array($a->queue_ticket_status ?? '', $calledStatuses, true)
)->values();
$calledList = $queue->filter(
fn ($a) => in_array($a->queue_ticket_status ?? '', $calledStatuses, true)
)->values();
$stages = [
[
'key' => 'waiting',
'label' => 'Waiting',
'count' => $waitingList->count(),
'items' => $waitingList,
'empty' => 'No patients waiting.',
'accent' => 'text-slate-500',
'dot' => 'bg-slate-400',
],
[
'key' => 'called',
'label' => 'Called',
'count' => $calledList->count(),
'items' => $calledList,
'empty' => 'No one called yet.',
'accent' => 'text-indigo-600',
'dot' => 'bg-indigo-500',
],
[
'key' => 'in_care',
'label' => $inCareLabel,
'count' => $inConsultation->count(),
'items' => $inConsultation,
'empty' => 'No active encounters.',
'accent' => 'text-emerald-700',
'dot' => 'bg-emerald-500',
],
[
'key' => 'done',
'label' => 'Done',
'count' => $done->count(),
'items' => $done,
'empty' => 'None completed today.',
'accent' => 'text-slate-400',
'dot' => 'bg-slate-300',
],
];
@endphp
@if ($showFilters)
<form method="GET" class="flex flex-wrap items-center gap-3 rounded-xl border border-slate-200 bg-white px-4 py-3">
@if ($lockToPractitioner ?? false)
@if (($canSwitchBranch ?? false) && isset($branches) && $branches->count() > 1)
<select name="branch_id" class="rounded-lg border-slate-300 text-sm" onchange="this.form.submit()">
@foreach ($branches as $branch)
<option value="{{ $branch->id }}" @selected($branchId == $branch->id)>{{ $branch->name }}</option>
@endforeach
</select>
@elseif (isset($branches) && $branches->isNotEmpty())
<span class="text-sm font-medium text-slate-700">{{ $branches->first()->name }}</span>
@elseif (! empty($branchLabel))
<span class="text-sm font-medium text-slate-700">{{ $branchLabel }}</span>
@endif
<span class="text-sm text-slate-500">Assigned to you</span>
@elseif ($canSwitchBranch ?? false)
<select name="branch_id" class="rounded-lg border-slate-300 text-sm" onchange="this.form.submit()">
@foreach ($branches as $branch)
<option value="{{ $branch->id }}" @selected($branchId == $branch->id)>{{ $branch->name }}</option>
@endforeach
</select>
<select name="practitioner_id" class="rounded-lg border-slate-300 text-sm">
<option value="">All practitioners</option>
@foreach ($practitioners as $practitioner)
<option value="{{ $practitioner->id }}" @selected($practitionerId == $practitioner->id)>{{ $practitioner->name }}</option>
@endforeach
</select>
<button type="submit" class="btn-primary">Filter</button>
@else
@if (isset($branches) && $branches->isNotEmpty())
<input type="hidden" name="branch_id" value="{{ $branchId }}">
<span class="text-sm font-medium text-slate-700">{{ $branches->first()->name }}</span>
@elseif (! empty($branchLabel))
<span class="text-sm font-medium text-slate-700">{{ $branchLabel }}</span>
@endif
@if (isset($practitioners))
<select name="practitioner_id" class="rounded-lg border-slate-300 text-sm">
<option value="">All practitioners</option>
@foreach ($practitioners as $practitioner)
<option value="{{ $practitioner->id }}" @selected($practitionerId == $practitioner->id)>{{ $practitioner->name }}</option>
@endforeach
</select>
<button type="submit" class="btn-primary">Filter</button>
@endif
@endif
</form>
@endif
<div class="overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-sm shadow-slate-100/80">
@if ($queueCallNextRoute)
<div class="border-b border-slate-100 bg-gradient-to-r from-indigo-50/90 via-white to-slate-50 px-4 py-3 sm:px-5">
@include('care.partials.queue-ops', [
'queueIntegration' => $queueIntegration ?? null,
'queueCallNextRoute' => $queueCallNextRoute,
'queueCallNextParams' => $queueCallNextParams,
'branchId' => $branchId ?? null,
'variant' => 'bar',
])
@if (empty($queueIntegration['enabled']))
<p class="text-sm text-slate-500">Start patients from the waiting column when they arrive at your desk.</p>
@endif
</div>
@endif
<div class="flex snap-x snap-mandatory gap-0 overflow-x-auto lg:grid lg:grid-cols-4 lg:overflow-visible" style="-ms-overflow-style:none;scrollbar-width:none;">
@foreach ($stages as $index => $stage)
<section @class([
'flex w-[min(85vw,20rem)] shrink-0 snap-start flex-col border-slate-100 lg:w-auto',
'border-r' => $index < count($stages) - 1,
])>
<header class="sticky top-0 z-[1] flex items-center justify-between gap-2 border-b border-slate-100 bg-white/95 px-4 py-3 backdrop-blur-sm">
<div class="flex items-center gap-2">
<span class="h-2 w-2 rounded-full {{ $stage['dot'] }}"></span>
<h2 class="text-xs font-semibold uppercase tracking-wide {{ $stage['accent'] }}">{{ $stage['label'] }}</h2>
</div>
<span class="rounded-md bg-slate-100 px-2 py-0.5 text-xs font-semibold tabular-nums text-slate-700">{{ $stage['count'] }}</span>
</header>
<div class="flex-1 space-y-2 p-3 sm:min-h-[12rem]">
@forelse ($stage['items'] as $appointment)
@include('care.partials.queue-board-card', [
'appointment' => $appointment,
'stage' => $stage['key'],
'canConsult' => $canConsult,
'queueIntegration' => $queueIntegration ?? null,
'startRouteName' => $startRouteName,
'openInCareUrl' => $openInCareUrl,
])
@empty
<p class="rounded-xl border border-dashed border-slate-200 px-3 py-8 text-center text-xs text-slate-400">{{ $stage['empty'] }}</p>
@endforelse
</div>
</section>
@endforeach
</div>
</div>