Deploy Ladill Care / deploy (push) Successful in 40s
Move timeline into a workspace tab, surface Complete consultation and Call again in Actions, and make Call next end the current encounter then open the next called patient. Co-authored-by: Cursor <cursoragent@cursor.com>
145 lines
9.9 KiB
PHP
145 lines
9.9 KiB
PHP
<x-app-layout title="Appointment">
|
|
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
|
<div>
|
|
<p class="text-xs font-medium uppercase tracking-wide text-slate-500">{{ $statuses[$appointment->status] ?? $appointment->status }}</p>
|
|
<h1 class="text-2xl font-semibold text-slate-900">{{ $appointment->patient->fullName() }}</h1>
|
|
<p class="mt-1 text-sm text-slate-500">
|
|
{{ $appointment->scheduled_at?->format('d M Y H:i') ?? 'Walk-in' }}
|
|
@if ($appointment->practitioner) · {{ $appointment->practitioner->name }} @endif
|
|
</p>
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
@if ($canManage && $appointment->status === \App\Models\Appointment::STATUS_SCHEDULED)
|
|
<form method="POST" action="{{ route('care.appointments.check-in', $appointment) }}">
|
|
@csrf
|
|
<button type="submit" class="btn-primary">Check in</button>
|
|
</form>
|
|
<form method="POST" action="{{ route('care.appointments.no-show', $appointment) }}">
|
|
@csrf
|
|
<x-btn type="submit" variant="warning">No show</x-btn>
|
|
</form>
|
|
@endif
|
|
@if ($appointment->queue_ticket_status === 'called')
|
|
<form method="POST" action="{{ route('care.queue.recall', $appointment) }}">
|
|
@csrf
|
|
<button type="submit" class="rounded-lg border border-indigo-200 bg-indigo-50 px-4 py-2 text-sm font-medium text-indigo-700 hover:bg-indigo-100">Call again</button>
|
|
</form>
|
|
@endif
|
|
@if (($canStartConsultation ?? $canConsult) && in_array($appointment->status, [\App\Models\Appointment::STATUS_WAITING, \App\Models\Appointment::STATUS_CHECKED_IN], true))
|
|
<form method="POST" action="{{ route('care.queue.start', $appointment) }}">
|
|
@csrf
|
|
<button type="submit" class="btn-primary">Start consultation</button>
|
|
</form>
|
|
@endif
|
|
@if ($canConsult && in_array($appointment->status, [\App\Models\Appointment::STATUS_WAITING, \App\Models\Appointment::STATUS_CHECKED_IN, \App\Models\Appointment::STATUS_IN_CONSULTATION], true))
|
|
@if ($appointment->meet_join_url)
|
|
<a href="{{ $appointment->meet_join_url }}" target="_blank" rel="noopener" class="btn-primary">Join video visit</a>
|
|
@else
|
|
<form method="POST" action="{{ route('care.appointments.start-meet', $appointment) }}">
|
|
@csrf
|
|
<button type="submit" class="btn-primary">Start video visit</button>
|
|
</form>
|
|
@endif
|
|
@endif
|
|
@if ($canManage && $appointment->status === \App\Models\Appointment::STATUS_SCHEDULED && ! $appointment->meet_join_url)
|
|
<form method="POST" action="{{ route('care.appointments.schedule-meet', $appointment) }}">
|
|
@csrf
|
|
<button type="submit" class="rounded-lg border border-sky-200 px-4 py-2 text-sm text-sky-700 hover:bg-sky-50">Schedule video visit</button>
|
|
</form>
|
|
@endif
|
|
@if ($canManage && in_array($appointment->status, [\App\Models\Appointment::STATUS_WAITING, \App\Models\Appointment::STATUS_CHECKED_IN], true))
|
|
@if ($appointment->consultation)
|
|
<a href="{{ route('care.consultations.show', $appointment->consultation) }}" class="rounded-lg border border-sky-200 px-4 py-2 text-sm text-sky-700 hover:bg-sky-50">View consultation</a>
|
|
@endif
|
|
@endif
|
|
@if ($canManage && ! in_array($appointment->status, [\App\Models\Appointment::STATUS_COMPLETED, \App\Models\Appointment::STATUS_CANCELLED], true))
|
|
<x-confirm-dialog
|
|
:name="'cancel-appointment-'.$appointment->id"
|
|
title="Cancel this appointment?"
|
|
message="The appointment will be marked cancelled. Any linked video visit will also be cancelled."
|
|
:action="route('care.appointments.cancel', $appointment)"
|
|
confirm-label="Cancel appointment"
|
|
>
|
|
<x-slot:trigger>
|
|
<x-btn type="button" variant="danger">Cancel</x-btn>
|
|
</x-slot:trigger>
|
|
</x-confirm-dialog>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
@if ($workflowEnabled ?? false)
|
|
<section class="mt-6 rounded-2xl border border-slate-200 bg-white p-6">
|
|
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
|
|
<div>
|
|
<p class="text-xs font-medium uppercase tracking-wide text-slate-500">Patient journey</p>
|
|
<h2 class="mt-1 text-lg font-semibold text-slate-900">{{ $currentAdvance?->stage?->name ?? 'Workflow not started' }}</h2>
|
|
@if ($currentAdvance)
|
|
<p class="mt-1 text-sm {{ $currentAdvance->isBlocked() ? 'text-amber-700' : 'text-emerald-700' }}">
|
|
{{ $currentAdvance->isBlocked() ? 'Blocked — financial clearance required' : 'Ready for service' }}
|
|
</p>
|
|
@endif
|
|
@if ($currentObligation)
|
|
<p class="mt-2 text-sm text-slate-600">
|
|
{{ $currentObligation->label }} ·
|
|
{{ config('care.billing.currency') }} {{ number_format($currentObligation->amount_minor / 100, 2) }} ·
|
|
{{ ucfirst($currentObligation->status) }}
|
|
</p>
|
|
@endif
|
|
</div>
|
|
<div class="flex flex-wrap gap-2">
|
|
@if ($currentAdvance?->isBlocked() && ($canViewBills ?? false))
|
|
<a href="{{ route('care.obligations.index') }}" class="btn-primary">Open financial gates</a>
|
|
@endif
|
|
@if ($canAdvanceWorkflow ?? false)
|
|
<form method="POST" action="{{ route('care.visits.workflow.advance', $appointment->visit) }}">
|
|
@csrf
|
|
<button type="submit" class="btn-primary">Complete stage & continue</button>
|
|
</form>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
@if (($workflowHistory ?? collect())->isNotEmpty())
|
|
<ol class="mt-5 flex flex-wrap gap-2 border-t border-slate-100 pt-4">
|
|
@foreach ($workflowHistory as $step)
|
|
<li class="rounded-full px-3 py-1 text-xs {{ in_array($step->status, ['completed', 'skipped'], true) ? 'bg-emerald-50 text-emerald-700' : ($step->status === 'blocked' ? 'bg-amber-50 text-amber-800' : 'bg-sky-50 text-sky-700') }}">
|
|
{{ $step->stage?->name ?? $step->stage_code }} · {{ str_replace('_', ' ', $step->status) }}
|
|
</li>
|
|
@endforeach
|
|
</ol>
|
|
@endif
|
|
</section>
|
|
@endif
|
|
|
|
<div class="mt-6 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">Details</h2>
|
|
<dl class="mt-4 space-y-3 text-sm">
|
|
<div><dt class="text-slate-500">Patient</dt><dd class="font-medium"><a href="{{ route('care.patients.show', $appointment->patient) }}" class="text-sky-600">{{ $appointment->patient->fullName() }}</a></dd></div>
|
|
<div><dt class="text-slate-500">Branch</dt><dd class="font-medium">{{ $appointment->branch?->name ?? '—' }}</dd></div>
|
|
<div><dt class="text-slate-500">Department</dt><dd class="font-medium">{{ $appointment->department?->name ?? '—' }}</dd></div>
|
|
<div><dt class="text-slate-500">Type</dt><dd class="font-medium capitalize">{{ str_replace('_', ' ', $appointment->type) }}</dd></div>
|
|
@if ($appointment->meet_join_url)
|
|
<div><dt class="text-slate-500">Video visit</dt><dd class="font-medium flex flex-wrap items-center gap-2"><a href="{{ $appointment->meet_join_url }}" target="_blank" rel="noopener" class="text-sky-600">Join link</a><x-copy-button :text="$appointment->meet_join_url" icon copied-class="text-emerald-600" class="rounded p-1 text-slate-400 hover:bg-slate-100 hover:text-slate-600" /></dd></div>
|
|
@endif
|
|
<div><dt class="text-slate-500">Reason</dt><dd class="font-medium">{{ $appointment->reason ?? '—' }}</dd></div>
|
|
@if ($appointment->notes)
|
|
<div><dt class="text-slate-500">Notes</dt><dd class="font-medium">{{ $appointment->notes }}</dd></div>
|
|
@endif
|
|
</dl>
|
|
</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">Timeline</h2>
|
|
<dl class="mt-4 space-y-3 text-sm">
|
|
<div><dt class="text-slate-500">Checked in</dt><dd class="font-medium">{{ $appointment->checked_in_at?->format('d M Y H:i') ?? '—' }}</dd></div>
|
|
<div><dt class="text-slate-500">Waiting since</dt><dd class="font-medium">{{ $appointment->waiting_at?->format('d M Y H:i') ?? '—' }}</dd></div>
|
|
<div><dt class="text-slate-500">Queue position</dt><dd class="font-medium">{{ $appointment->queue_position ?? '—' }}</dd></div>
|
|
<div><dt class="text-slate-500">Started</dt><dd class="font-medium">{{ $appointment->started_at?->format('d M Y H:i') ?? '—' }}</dd></div>
|
|
<div><dt class="text-slate-500">Completed</dt><dd class="font-medium">{{ $appointment->completed_at?->format('d M Y H:i') ?? '—' }}</dd></div>
|
|
</dl>
|
|
</section>
|
|
</div>
|
|
</x-app-layout>
|