Give specialty modules the same Queue UI as GPs.
Deploy Ladill Care / deploy (push) Successful in 36s

Specialty homes now use the shared Waiting/In care board with Call next, Start routes specialty tickets into specialty workspaces, and redundant Dentistry/Specialty module chrome is removed.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-18 15:52:00 +00:00
co-authored by Cursor
parent dd3e42ebf3
commit ec9135c59d
15 changed files with 429 additions and 246 deletions
@@ -0,0 +1,176 @@
{{--
Shared Waiting | In care board (GP Queue + specialty Queue homes).
Expected vars:
- $queue, $inConsultation (collections of Appointment)
- $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 link for in-care Open
- $inCareLabel (default "In consultation")
- $lockToPractitioner, $canSwitchBranch, $branches, $practitioners, $practitionerId (filter bar)
- $showFilters (default true)
--}}
@php
$canConsult = $canConsult ?? false;
$showFilters = $showFilters ?? true;
$inCareLabel = $inCareLabel ?? 'In consultation';
$startRouteName = $startRouteName ?? 'care.queue.start';
$openInCareUrl = $openInCareUrl ?? function ($appointment) {
return $appointment->consultation
? route('care.consultations.show', $appointment->consultation)
: null;
};
$queueCallNextRoute = $queueCallNextRoute ?? null;
$queueCallNextParams = $queueCallNextParams ?? [];
@endphp
@if ($showFilters)
<form method="GET" class="flex flex-wrap gap-3 rounded-2xl border border-slate-200 bg-white p-4">
@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="flex items-center text-sm font-medium text-slate-700">{{ $branches->first()->name }}</span>
@elseif (! empty($branchLabel))
<span class="flex items-center text-sm font-medium text-slate-700">{{ $branchLabel }}</span>
@endif
<span class="flex items-center text-sm text-slate-500">Showing patients 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="flex items-center text-sm font-medium text-slate-700">{{ $branches->first()->name }}</span>
@elseif (! empty($branchLabel))
<span class="flex items-center 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
@if ($queueCallNextRoute)
@include('care.partials.queue-ops', [
'queueIntegration' => $queueIntegration ?? null,
'queueCallNextRoute' => $queueCallNextRoute,
'queueCallNextParams' => $queueCallNextParams,
'branchId' => $branchId ?? null,
])
@endif
<div class="grid gap-6 lg:grid-cols-2">
<section class="rounded-2xl border border-slate-200 bg-white p-6">
<h2 class="text-sm font-semibold uppercase tracking-wide text-slate-500">Waiting ({{ $queue->count() }})</h2>
<div class="mt-4 space-y-3">
@forelse ($queue as $appointment)
<div @class([
'flex items-start justify-between gap-4 rounded-xl border p-4',
'border-indigo-200 bg-indigo-50/60' => ($appointment->queue_ticket_status ?? null) === 'called',
'border-emerald-200 bg-emerald-50' => ($appointment->queue_ticket_status ?? null) === 'serving',
'border-slate-100 bg-slate-50' => ! in_array($appointment->queue_ticket_status ?? null, ['called', 'serving'], true),
])>
<div class="min-w-0 flex-1 space-y-2">
@if (! empty($queueIntegration['enabled']) && $appointment->queue_ticket_number)
@include('care.partials.queue-ticket', [
'ticketNumber' => $appointment->queue_ticket_number,
'ticketStatus' => $appointment->queue_ticket_status,
'destination' => $appointment->queue_destination,
'staffDisplayName' => $appointment->queue_staff_display_name,
])
@elseif (! empty($queueIntegration['enabled']) && ($appointment->queue_routing_status ?? '') === 'unresolved')
<span class="inline-flex rounded-full bg-amber-100 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-amber-800">Unassigned</span>
@elseif ($appointment->queue_position)
<span class="inline-flex h-7 w-7 items-center justify-center rounded-full bg-sky-100 text-xs font-bold text-sky-700">{{ $appointment->queue_position }}</span>
@endif
<div class="min-w-0">
<p class="truncate text-base font-semibold text-slate-900">{{ $appointment->patient?->fullName() ?? 'Patient' }}</p>
<p class="mt-0.5 truncate text-xs text-slate-500">{{ $appointment->patient?->patient_number ?? '—' }} · {{ $appointment->reason ?? '—' }}</p>
</div>
</div>
<div class="flex shrink-0 flex-wrap items-center justify-end gap-2">
@if (! empty($queueIntegration['enabled']) && $appointment->queue_ticket_uuid && in_array($appointment->queue_ticket_status ?? '', ['called', 'serving'], true) && $canConsult)
<form method="POST" action="{{ route('care.queue.recall', $appointment) }}">
@csrf
<button type="submit" class="rounded-lg border border-indigo-200 bg-indigo-50 px-3 py-1.5 text-xs font-medium text-indigo-700 hover:bg-indigo-100">Call again</button>
</form>
@endif
@if ($canConsult)
<form method="POST" action="{{ route($startRouteName, $appointment) }}">
@csrf
<button type="submit" class="rounded-lg bg-sky-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-sky-700">
{{ ! empty($queueIntegration['enabled']) && ($appointment->queue_ticket_status ?? '') === 'called' ? 'Serve & start' : 'Start' }}
</button>
</form>
@endif
</div>
</div>
@empty
<p class="text-sm text-slate-500">No patients waiting.</p>
@endforelse
</div>
</section>
<section class="rounded-2xl border border-slate-200 bg-white p-6">
<h2 class="text-sm font-semibold uppercase tracking-wide text-slate-500">{{ $inCareLabel }} ({{ $inConsultation->count() }})</h2>
<div class="mt-4 space-y-3">
@forelse ($inConsultation as $appointment)
<div class="flex items-start justify-between gap-4 rounded-xl border border-emerald-100 bg-emerald-50 p-4">
<div class="min-w-0 flex-1 space-y-2">
@if (! empty($queueIntegration['enabled']) && $appointment->queue_ticket_number)
@include('care.partials.queue-ticket', [
'ticketNumber' => $appointment->queue_ticket_number,
'ticketStatus' => $appointment->queue_ticket_status,
'showAssignment' => false,
])
@endif
<div class="min-w-0">
<p class="truncate text-base font-semibold text-slate-900">{{ $appointment->patient?->fullName() ?? 'Patient' }}</p>
<p class="mt-0.5 truncate text-xs text-slate-500">{{ $appointment->practitioner?->name ?? 'Unassigned' }}</p>
</div>
</div>
<div class="flex shrink-0 flex-wrap items-center justify-end gap-2">
@if (! empty($queueIntegration['enabled']) && $appointment->queue_ticket_uuid && in_array($appointment->queue_ticket_status ?? '', ['called', 'serving'], true) && $canConsult)
<form method="POST" action="{{ route('care.queue.recall', $appointment) }}">
@csrf
<button type="submit" class="rounded-lg border border-indigo-200 bg-indigo-50 px-3 py-1.5 text-xs font-medium text-indigo-700 hover:bg-indigo-100">Call again</button>
</form>
@endif
@php $openUrl = $openInCareUrl($appointment); @endphp
@if ($openUrl)
<a href="{{ $openUrl }}" class="text-sm font-medium text-sky-600 hover:text-sky-700">Open</a>
@endif
</div>
</div>
@empty
<p class="text-sm text-slate-500">No active encounters.</p>
@endforelse
</div>
</section>
</div>
+12 -133
View File
@@ -16,142 +16,21 @@
@endif
</x-care.page-hero>
<form method="GET" class="flex flex-wrap gap-3 rounded-2xl border border-slate-200 bg-white p-4">
@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="flex items-center text-sm font-medium text-slate-700">{{ $branches->first()->name }}</span>
@endif
<span class="flex items-center text-sm text-slate-500">Showing patients 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="flex items-center text-sm font-medium text-slate-700">{{ $branches->first()->name }}</span>
@endif
<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
</form>
@include('care.partials.queue-ops', [
@include('care.partials.queue-board', [
'queue' => $queue,
'inConsultation' => $inConsultation,
'queueIntegration' => $queueIntegration ?? null,
'branchId' => $branchId,
'canConsult' => $canConsult,
'lockToPractitioner' => $lockToPractitioner ?? false,
'canSwitchBranch' => $canSwitchBranch ?? false,
'branches' => $branches ?? collect(),
'practitioners' => $practitioners ?? collect(),
'practitionerId' => $practitionerId ?? null,
'queueCallNextRoute' => 'care.queue.call-next',
'queueCallNextParams' => array_filter(['practitioner_id' => $practitionerId]),
'branchId' => $branchId,
'startRouteName' => 'care.queue.start',
'inCareLabel' => 'In consultation',
])
<div class="grid gap-6 lg:grid-cols-2">
<section class="rounded-2xl border border-slate-200 bg-white p-6">
<h2 class="text-sm font-semibold uppercase tracking-wide text-slate-500">Waiting ({{ $queue->count() }})</h2>
<div class="mt-4 space-y-3">
@forelse ($queue as $appointment)
<div @class([
'flex items-start justify-between gap-4 rounded-xl border p-4',
'border-indigo-200 bg-indigo-50/60' => ($appointment->queue_ticket_status ?? null) === 'called',
'border-emerald-200 bg-emerald-50' => ($appointment->queue_ticket_status ?? null) === 'serving',
'border-slate-100 bg-slate-50' => ! in_array($appointment->queue_ticket_status ?? null, ['called', 'serving'], true),
])>
<div class="min-w-0 flex-1 space-y-2">
@if (! empty($queueIntegration['enabled']) && $appointment->queue_ticket_number)
@include('care.partials.queue-ticket', [
'ticketNumber' => $appointment->queue_ticket_number,
'ticketStatus' => $appointment->queue_ticket_status,
'destination' => $appointment->queue_destination,
'staffDisplayName' => $appointment->queue_staff_display_name,
])
@elseif (! empty($queueIntegration['enabled']) && ($appointment->queue_routing_status ?? '') === 'unresolved')
<span class="inline-flex rounded-full bg-amber-100 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-amber-800">Unassigned</span>
@elseif ($appointment->queue_position)
<span class="inline-flex h-7 w-7 items-center justify-center rounded-full bg-sky-100 text-xs font-bold text-sky-700">{{ $appointment->queue_position }}</span>
@endif
<div class="min-w-0">
<p class="truncate text-base font-semibold text-slate-900">{{ $appointment->patient->fullName() }}</p>
<p class="mt-0.5 truncate text-xs text-slate-500">{{ $appointment->patient->patient_number }} · {{ $appointment->reason ?? '—' }}</p>
</div>
</div>
<div class="flex shrink-0 flex-wrap items-center justify-end gap-2">
@if (! empty($queueIntegration['enabled']) && $appointment->queue_ticket_uuid && in_array($appointment->queue_ticket_status ?? '', ['called', 'serving'], true) && $canConsult)
<form method="POST" action="{{ route('care.queue.recall', $appointment) }}">
@csrf
<button type="submit" class="rounded-lg border border-indigo-200 bg-indigo-50 px-3 py-1.5 text-xs font-medium text-indigo-700 hover:bg-indigo-100">Call again</button>
</form>
@endif
@if ($canConsult)
<form method="POST" action="{{ route('care.queue.start', $appointment) }}">
@csrf
<button type="submit" class="rounded-lg bg-sky-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-sky-700">
{{ ! empty($queueIntegration['enabled']) && ($appointment->queue_ticket_status ?? '') === 'called' ? 'Serve & start' : 'Start' }}
</button>
</form>
@endif
</div>
</div>
@empty
<p class="text-sm text-slate-500">No patients waiting.</p>
@endforelse
</div>
</section>
<section class="rounded-2xl border border-slate-200 bg-white p-6">
<h2 class="text-sm font-semibold uppercase tracking-wide text-slate-500">In consultation ({{ $inConsultation->count() }})</h2>
<div class="mt-4 space-y-3">
@forelse ($inConsultation as $appointment)
<div class="flex items-start justify-between gap-4 rounded-xl border border-emerald-100 bg-emerald-50 p-4">
<div class="min-w-0 flex-1 space-y-2">
@if (! empty($queueIntegration['enabled']) && $appointment->queue_ticket_number)
@include('care.partials.queue-ticket', [
'ticketNumber' => $appointment->queue_ticket_number,
'ticketStatus' => $appointment->queue_ticket_status,
'showAssignment' => false,
])
@endif
<div class="min-w-0">
<p class="truncate text-base font-semibold text-slate-900">{{ $appointment->patient->fullName() }}</p>
<p class="mt-0.5 truncate text-xs text-slate-500">{{ $appointment->practitioner?->name ?? 'Unassigned' }}</p>
</div>
</div>
<div class="flex shrink-0 flex-wrap items-center justify-end gap-2">
@if (! empty($queueIntegration['enabled']) && $appointment->queue_ticket_uuid && in_array($appointment->queue_ticket_status ?? '', ['called', 'serving'], true) && $canConsult)
<form method="POST" action="{{ route('care.queue.recall', $appointment) }}">
@csrf
<button type="submit" class="rounded-lg border border-indigo-200 bg-indigo-50 px-3 py-1.5 text-xs font-medium text-indigo-700 hover:bg-indigo-100">Call again</button>
</form>
@endif
@if ($appointment->consultation)
<a href="{{ route('care.consultations.show', $appointment->consultation) }}" class="text-sm font-medium text-sky-600 hover:text-sky-700">Open</a>
@endif
</div>
</div>
@empty
<p class="text-sm text-slate-500">No active consultations.</p>
@endforelse
</div>
</section>
</div>
</div>
</x-app-layout>
@@ -42,8 +42,7 @@
@endif
</div>
<p class="mt-3 text-[11px] uppercase tracking-wide text-slate-400">
Dept · {{ $module['department_name'] ?? $module['label'] }}
· Queue · {{ $module['queue_name'] ?? $module['label'] }}
{{ $module['department_name'] ?? $module['label'] }}
</p>
</label>
@endforeach
@@ -1,17 +1,20 @@
{{-- Specialty shell action buttons (desktop sticky + mobile sheet). --}}
{{-- Specialty action buttons (desktop sticky + mobile sheet). --}}
@php
$btn = 'flex w-full items-center justify-center rounded-xl px-3 py-2.5 text-sm font-semibold transition';
$btnPrimary = $btn.' bg-indigo-600 text-white hover:bg-indigo-700';
$btnSecondary = $btn.' border border-slate-200 bg-white text-slate-800 hover:bg-slate-50';
$btnAccent = $btn.' border border-indigo-200 bg-indigo-50 text-indigo-900 hover:bg-indigo-100';
$onWorkspace = ($section ?? '') === 'workspace';
@endphp
@include('care.partials.queue-ops', [
'queueIntegration' => $queueIntegration ?? null,
'queueCallNextRoute' => 'care.specialty.call-next',
'queueCallNextParams' => ['module' => $moduleKey],
'branchId' => $branchId ?? null,
])
@if ($onWorkspace)
@include('care.partials.queue-ops', [
'queueIntegration' => $queueIntegration ?? null,
'queueCallNextRoute' => 'care.specialty.call-next',
'queueCallNextParams' => ['module' => $moduleKey],
'branchId' => $branchId ?? null,
])
@endif
@if ($workspaceVisit)
@php
@@ -34,20 +37,16 @@
@if ($consultationInProgress)
<a href="{{ route('care.specialty.workspace', ['module' => $moduleKey, 'visit' => $workspaceVisit, 'tab' => $chartTab]) }}"
class="{{ $btnPrimary }}">
Open specialty chart
Open chart
</a>
@elseif ($canStartConsultation)
<form method="POST" action="{{ route('care.specialty.consultation.start', ['module' => $moduleKey, 'visit' => $workspaceVisit]) }}" class="w-full" @click.stop>
@csrf
<button type="submit" class="{{ $btnPrimary }}">
{{ $actions['start'] ?? 'Start specialty encounter' }}
{{ $actions['start'] ?? 'Start' }}
</button>
</form>
@endif
<a href="{{ route('care.specialty.workspace', ['module' => $moduleKey, 'visit' => $workspaceVisit]) }}"
class="{{ $btnSecondary }}">
Specialty workspace
</a>
@if ($workspaceVisit->patient)
<a href="{{ route('care.patients.show', $workspaceVisit->patient) }}" class="{{ $btnSecondary }}">
Patient chart
@@ -58,12 +57,12 @@
Appointment
</a>
@endif
@else
<a href="{{ route('care.specialty.workspace', ['module' => $moduleKey]) }}" class="{{ $btnPrimary }}">
Open workspace
</a>
@endif
<a href="{{ route('care.specialty.show', $moduleKey) }}" class="{{ $btnSecondary }}">
Back to queue
</a>
<a href="{{ route('care.appointments.create') }}" class="{{ $btnAccent }}">
Register / book
</a>
@@ -15,8 +15,8 @@
@if (! $workspaceVisit)
<section class="rounded-2xl border border-dashed border-slate-200 bg-white px-4 py-12 text-center">
<h2 class="text-sm font-semibold text-slate-900">No open visit selected</h2>
<p class="mt-1 text-sm text-slate-500">Open a visit from the Visits list, or call next from the waiting queue.</p>
<a href="{{ route('care.specialty.visits', $moduleKey) }}" class="mt-4 inline-flex text-sm font-medium text-indigo-600">Go to visits</a>
<p class="mt-1 text-sm text-slate-500">Open a visit from the queue, or call next from the waiting list.</p>
<a href="{{ route('care.specialty.show', $moduleKey) }}" class="mt-4 inline-flex text-sm font-medium text-indigo-600">Back to queue</a>
</section>
@else
{{-- Module tabs --}}
+106 -67
View File
@@ -1,77 +1,116 @@
<x-app-layout title="{{ $definition['label'] ?? $moduleKey }}">
@php
$pageTitle = match ($section) {
'workspace' => ($patientHeader['patient'] ?? null)?->fullName() ?: 'Workspace',
'history' => 'Visit history',
'billing' => 'Billing',
'visits' => 'Patient queue',
default => 'Patient queue',
};
@endphp
<x-app-layout :title="$pageTitle">
<div class="space-y-4">
<div class="flex flex-wrap items-start justify-between gap-4">
<div>
<p class="text-xs font-semibold uppercase tracking-wider text-indigo-600">Specialty module</p>
<h1 class="mt-1 text-xl font-semibold text-slate-900">{{ $definition['label'] ?? $moduleKey }}</h1>
<p class="mt-1 max-w-2xl text-sm text-slate-500">{{ $definition['description'] ?? '' }}</p>
@if ($section === 'workspace')
<div class="flex flex-wrap items-center justify-between gap-3">
<a href="{{ route('care.specialty.show', $moduleKey) }}" class="text-sm font-medium text-indigo-600 hover:text-indigo-800"> Back to queue</a>
<div class="flex flex-wrap gap-3 text-sm">
<a href="{{ route('care.specialty.history', $moduleKey) }}" class="text-slate-600 hover:text-slate-900">History</a>
<a href="{{ route('care.specialty.billing', $moduleKey) }}" class="text-slate-600 hover:text-slate-900">Billing</a>
</div>
</div>
<a href="{{ route('care.settings.modules') }}" class="text-sm font-medium text-indigo-600 hover:text-indigo-800">Manage modules</a>
</div>
<div class="grid gap-4 lg:grid-cols-[220px_minmax(0,1fr)_16rem]">
{{-- Left navigation --}}
<nav class="rounded-2xl border border-slate-200 bg-white p-3 lg:sticky lg:top-4 lg:self-start">
<p class="px-2 pb-2 text-[10px] font-semibold uppercase tracking-wider text-slate-400">Navigate</p>
<ul class="space-y-0.5">
@foreach ($navItems as $key => $item)
@php
$active = $section === $key;
$params = ['module' => $moduleKey];
if ($key === 'workspace' && $workspaceVisit) {
$params['visit'] = $workspaceVisit;
}
@endphp
<li>
<a href="{{ route($item['route'], $params) }}"
@class([
'block rounded-xl px-3 py-2 text-sm font-medium',
'bg-indigo-50 text-indigo-800' => $active,
'text-slate-600 hover:bg-slate-50 hover:text-slate-900' => ! $active,
])>
{{ $item['label'] }}
</a>
</li>
@endforeach
</ul>
@if (! empty($stages))
<p class="mt-4 px-2 pb-2 text-[10px] font-semibold uppercase tracking-wider text-slate-400">Stage map</p>
<ol class="space-y-1 px-1">
@foreach ($stages as $stage)
<li class="flex items-center gap-2 rounded-lg px-2 py-1.5 text-xs text-slate-600">
<span class="flex h-5 w-5 items-center justify-center rounded-full bg-slate-100 text-[10px] font-semibold text-slate-500">{{ $loop->iteration }}</span>
{{ $stage['label'] ?? $stage['code'] }}
</li>
@endforeach
</ol>
@endif
</nav>
{{-- Main workspace --}}
<div class="min-w-0 space-y-4">
@if ($section === 'overview')
@include('care.specialty.sections.overview')
@elseif ($section === 'visits')
@include('care.specialty.sections.visits')
@elseif ($section === 'history')
@include('care.specialty.sections.history')
@elseif ($section === 'billing')
@include('care.specialty.sections.billing')
@elseif ($section === 'workspace')
<div class="lg:grid lg:grid-cols-[minmax(0,1fr)_16rem] lg:items-start lg:gap-6">
<div class="min-w-0 space-y-4">
@include('care.specialty.sections.workspace')
@endif
</div>
@include('care.partials.clinical-actions-panel', [
'actionsView' => 'care.specialty.partials.actions-menu',
'title' => 'Actions',
])
</div>
@include('care.partials.clinical-actions-panel', [
@include('care.partials.clinical-actions-mobile', [
'actionsView' => 'care.specialty.partials.actions-menu',
'title' => 'Actions',
])
</div>
</div>
@elseif ($section === 'history')
<div class="flex flex-wrap items-center justify-between gap-3">
<div>
<h1 class="text-xl font-semibold text-slate-900">Visit history</h1>
<p class="mt-1 text-sm text-slate-500">Completed encounters for this service line.</p>
</div>
<a href="{{ route('care.specialty.show', $moduleKey) }}" class="text-sm font-medium text-indigo-600 hover:text-indigo-800"> Back to queue</a>
</div>
@include('care.specialty.sections.history')
@elseif ($section === 'billing')
<div class="flex flex-wrap items-center justify-between gap-3">
<div>
<h1 class="text-xl font-semibold text-slate-900">Billing</h1>
<p class="mt-1 text-sm text-slate-500">Service catalog for this module.</p>
</div>
<a href="{{ route('care.specialty.show', $moduleKey) }}" class="text-sm font-medium text-indigo-600 hover:text-indigo-800"> Back to queue</a>
</div>
@include('care.specialty.sections.billing')
@else
{{-- Queue home (overview / visits) same UI as GP Queue --}}
<div class="lg:grid lg:grid-cols-[minmax(0,1fr)_16rem] lg:items-start lg:gap-6">
<div class="min-w-0 space-y-6">
<x-care.page-hero
badge="Waiting · In care · Call next"
title="Patient queue"
description="See who is waiting, start encounters, and keep patient flow moving."
:stats="[
['value' => number_format($kpis['waiting'] ?? $queue->count()), 'label' => 'Waiting'],
['value' => number_format($kpis['in_progress'] ?? $inConsultation->count()), 'label' => 'In care'],
['value' => number_format($kpis['completed_today'] ?? 0), 'label' => 'Today'],
]">
@if ($canManageQueue ?? false)
<x-slot name="actions">
<a href="{{ route('care.appointments.walk-in.create') }}" class="btn-primary">Walk-in</a>
</x-slot>
@endif
</x-care.page-hero>
@include('care.partials.clinical-actions-mobile', [
'actionsView' => 'care.specialty.partials.actions-menu',
'title' => 'Actions',
])
<div class="flex flex-wrap gap-3 text-sm">
<a href="{{ route('care.specialty.history', $moduleKey) }}" class="rounded-lg border border-slate-200 bg-white px-3 py-1.5 font-medium text-slate-700 hover:bg-slate-50">History</a>
<a href="{{ route('care.specialty.billing', $moduleKey) }}" class="rounded-lg border border-slate-200 bg-white px-3 py-1.5 font-medium text-slate-700 hover:bg-slate-50">Billing</a>
</div>
@include('care.partials.queue-board', [
'queue' => $queue,
'inConsultation' => $inConsultation,
'queueIntegration' => $queueIntegration ?? null,
'branchId' => $branchId,
'branchLabel' => $branchLabel ?? null,
'canConsult' => $canConsult ?? false,
'lockToPractitioner' => $lockToPractitioner ?? false,
'showFilters' => true,
'queueCallNextRoute' => 'care.specialty.call-next',
'queueCallNextParams' => ['module' => $moduleKey],
'startRouteName' => 'care.queue.start',
'inCareLabel' => 'In care',
'openInCareUrl' => function ($appointment) use ($moduleKey) {
if ($appointment->visit) {
return route('care.specialty.workspace', [
'module' => $moduleKey,
'visit' => $appointment->visit,
]);
}
return $appointment->consultation
? route('care.consultations.show', $appointment->consultation)
: null;
},
])
</div>
@include('care.partials.clinical-actions-panel', [
'actionsView' => 'care.specialty.partials.actions-menu',
'title' => 'Actions',
])
</div>
@include('care.partials.clinical-actions-mobile', [
'actionsView' => 'care.specialty.partials.actions-menu',
'title' => 'Actions',
])
@endif
</div>
</x-app-layout>