@extends('layouts.app') @section('title', __('appointments::messages.appointments.calendar')) @php use App\Modules\Appointments\Enums\AppointmentStatus; use App\Modules\Appointments\Models\Appointment; /* | The legend, and the source of truth for what a colour on this screen | means. Cancelled and did-not-attend are deliberately absent: the events | feed asks for occupying appointments only, because a cancelled booking | releases its slot. Listing them here would promise a colour that never | appears on the grid. */ $legend = [ AppointmentStatus::Scheduled, AppointmentStatus::Confirmed, AppointmentStatus::CheckedIn, AppointmentStatus::InProgress, AppointmentStatus::Completed, ]; /* | Four figures for today, counted in the browser from the same feed the | grid draws. Nothing here can show cancellations for the reason above, so | the fourth card is the day's remaining work rather than a cancelled | count that would sit on zero for ever. */ $cards = [ ['key' => 'total', 'label' => __('appointments::messages.appointments.card_total'), 'icon' => 'bi-calendar-week-fill', 'tone' => 'violet'], ['key' => 'completed', 'label' => __('appointments::messages.appointments.card_completed'), 'icon' => 'bi-check-circle-fill', 'tone' => 'green'], ['key' => 'in_progress', 'label' => __('appointments::messages.calendar.card_in_clinic'), 'icon' => 'bi-person-walking', 'tone' => 'amber'], ['key' => 'upcoming', 'label' => __('appointments::messages.calendar.card_upcoming'), 'icon' => 'bi-clock-fill', 'tone' => 'blue'], ]; $views = [ 'dayGridMonth' => __('appointments::messages.calendar.view_month'), 'timeGridWeek' => __('appointments::messages.calendar.view_week'), 'timeGridDay' => __('appointments::messages.calendar.view_day'), 'listWeek' => __('appointments::messages.calendar.view_agenda'), ]; @endphp @section('content') {{-- ── Page head ──────────────────────────────────────────────────────── --}}

{{ __('appointments::messages.calendar.title') }}

{{ __('appointments::messages.calendar.subtitle') }}

{{ __('appointments::messages.appointments.day_list') }} @can('create', Appointment::class) {{ __('appointments::messages.appointments.new') }} @endcan
{{-- ── Filters ────────────────────────────────────────────────────────── --}} {{-- The clinician filter is the only one the server knows about — it changes which appointments are fetched. Status and patient narrow what is drawn from the events already in hand, which is why this is not a GET form: submitting would reload the page and lose the month being looked at. --}}
{{-- ── Legend ─────────────────────────────────────────────────────── --}}
@foreach ($legend as $status) {{ $status->label() }} @endforeach {{-- Says why the two colours a clinic expects to find are not here. --}} {{ __('appointments::messages.calendar.legend_note') }}
{{-- ── Today at a glance ──────────────────────────────────────────────── --}}
@foreach ($cards as $card)

{{ $card['label'] }}

{{ __('common.loading') }}

@endforeach
{{-- ── Calendar ───────────────────────────────────────────────────────── --}}
{{-- The toolbar is markup rather than FullCalendar's own, so it can be built from the same buttons, segmented control and typography as the rest of the product. The library still owns the behaviour — these controls call its API and it writes the title back. --}}

@foreach ($views as $value => $label) @endforeach
{{-- Shown by the script when a fetch returns nothing for the range. --}}
{{-- ── Slide-over ─────────────────────────────────────────────────────── --}} {{-- One drawer, filled by the script from the event that was clicked. The status controls are not repeated in here: which transitions an appointment may make is decided by the status machine on the server, and a second copy of those rules in JavaScript is how the calendar starts offering a button the record refuses. --}} {{-- Thumb-reachable on a phone, where the header button has scrolled away. --}} @can('create', Appointment::class) @endcan @endsection