@extends('layouts.app') @section('title', $patient->fullName()) @php use App\Modules\Patients\Enums\ClinicalRecordStatus; $activeAllergies = $allergies->where('status', ClinicalRecordStatus::Active); $activeConditions = $conditions->where('status', ClinicalRecordStatus::Active); $activeMedications = $medications->where('status', ClinicalRecordStatus::Active); $severeAllergy = $activeAllergies->first(fn ($a) => $a->severity->isHigh()); $address = collect([ $patient->address_line_1, $patient->address_line_2, $patient->city, $patient->state, $patient->postal_code, ])->filter()->implode(', '); /* | The counts at the top. | | Every one is something this module owns and already has in memory, and | every one links to the panel that explains it — a number nobody can act | on is decoration. Appointments, invoices and an outstanding balance are | deliberately absent: they belong to other modules, and a record screen | that queried them directly would stop rendering on a clinic that has not | installed them. They are reachable from Quick links instead. */ $summaryCards = [ [ 'label' => __('patients::messages.clinical.allergies'), 'value' => $activeAllergies->count(), 'icon' => 'bi-shield-exclamation', 'tone' => $severeAllergy ? 'pink' : 'violet', 'note' => __('patients::messages.summary.allergies_note'), 'anchor' => '#allergies', ], [ 'label' => __('patients::messages.clinical.conditions'), 'value' => $activeConditions->count(), 'icon' => 'bi-clipboard2-pulse', 'tone' => 'amber', 'note' => __('patients::messages.summary.conditions_note'), 'anchor' => '#conditions', ], [ 'label' => __('patients::messages.clinical.medications'), 'value' => $activeMedications->count(), 'icon' => 'bi-capsule', 'tone' => 'green', 'note' => __('patients::messages.summary.medications_note'), 'anchor' => '#medications', ], [ 'label' => __('patients::messages.patients.documents'), 'value' => $documents->count(), 'icon' => 'bi-folder2-open', 'tone' => 'blue', 'note' => __('patients::messages.summary.documents_note'), 'anchor' => '#documents', ], ]; @endphp @section('content') {{-- ============================ IDENTITY ============================ --}} {{-- One card: who they are, the counts, and what you can do next. Three regions across a wide screen, stacked in the same order below it. --}}

{{ $patient->fullName() }}

{{-- Identity first, then the facts a clinician checks before anything else. Blood group and date of birth sit here rather than in the panel below because both are read at a glance: one before a transfusion, the other because age drives every reference range on the screen. --}}
{{ $patient->mrn }} {{ $patient->ageLabel() }} {{ $patient->gender->label() }} @if ($patient->date_of_birth) {{ $patient->date_of_birth->format('d M Y') }} @endif @if ($patient->blood_group) {{ $patient->blood_group }} @endif @if ($patient->phone) {{ $patient->phone }} @endif @if ($patient->email) {{ $patient->email }} @endif
{{-- An archived record is still readable, and must never be mistaken for a live one. The active state is stated too rather than left to be inferred from the absence of a warning. --}} {{ $patient->is_active ? __('common.active') : __('common.inactive') }}
@if ($canSeeClinical) {{-- The counts, in the header where the reference puts them. Each one jumps to the panel that explains it. --}}
@foreach ($summaryCards as $card) {{-- The qualifier rides on the link rather than under the number: a tile this size has no room for a third line, and "3 allergies" is ambiguous without knowing whether that means ever or still active. --}} {{ number_format($card['value']) }} {{ $card['label'] }} @endforeach
@endif {{-- Actions, each guarded by the route that serves it: a clinic without the appointments or laboratory module gets a shorter row, not a broken button. Ordered by how often reception reaches for them. --}}
@can('update', $patient) {{ __('patients::messages.patients.edit') }} @endcan @if (Route::has('appointments.create')) {{ __('common.new_appointment') }} @endif {{-- Carries the patient, so the wizard opens on choosing tests rather than asking who they are. --}} @if (Route::has('lab.new-test.patient') && $canSeeClinical) {{ __('patients::messages.patients.action_order_tests') }} @endif @can('delete', $patient) @endcan
@if ($canSeeClinical) {{-- The single most important thing on this screen, above everything else it might compete with. --}} @include('patients::partials.allergy-banner') @endif {{-- One flowing grid across the full width, not a main column and a sidebar. Panels sit side by side as many as fit and reflow as the window narrows — which is the only arrangement that can work here, because how many panels there are depends on which modules the clinic installed. Laboratory adds result trends; the upload portal adds another. This screen never learns their names. --}}

{{ __('patients::messages.patients.demographics') }}

@can('update', $patient) {{ __('patients::messages.patients.edit') }} @endcan
{{ __('patients::messages.fields.date_of_birth') }}
{{ $patient->date_of_birth?->format('d M Y') ?? '—' }} @if ($patient->date_of_birth_estimated) {{-- An estimated date drives age, and age drives lab reference ranges. Marked, never hidden. --}} ~ @endif
{{ __('patients::messages.fields.national_id') }}
{{ $patient->national_id ?: '—' }}
{{ __('patients::messages.fields.marital_status') }}
{{ $patient->marital_status ?: '—' }}
{{ __('patients::messages.fields.occupation') }}
{{ $patient->occupation ?: '—' }}
{{ __('patients::messages.fields.phone') }}
{{ $patient->phone ?: '—' }}
{{ __('patients::messages.fields.email') }}
{{ $patient->email ?: '—' }}
{{ __('patients::messages.patients.address') }}
{{ $address ?: '—' }}
{{ __('patients::messages.patients.registered_on') }}
{{ $patient->registered_at?->format('d M Y') ?? '—' }} {{ $patient->registeredBy?->name }}
@if ($patient->notes)

{{ $patient->notes }}

@endif
{{-- Panel order is deliberate and reads across, then down: Demographics · Allergies · Problem list · Go to Medications · Documents · Reports · Contacts Allergies sit next to the identity because they are the thing that changes what may safely be prescribed. Contacts come last of the eight: they are the only panel nobody reads unless something has gone wrong. It holds at the width that fits four across. Narrower, the grid reflows to three, two or one and the pairing goes with it — which is the trade for a layout that also works on a laptop. --}} @if ($canSeeClinical) @include('patients::partials.clinical-allergies') @include('patients::partials.clinical-conditions') @else {{-- Said plainly rather than shown as an empty screen: a blank panel reads as "this patient has no history". --}}
{{ __('patients::messages.clinical.restricted') }}
@endif {{-- Quick links, in the grid rather than in a column of their own. This was a sidebar, which earned its quarter of the screen when it also carried the patient's identity and the record history. With only these links left the column was a band of empty background down the whole page, so the links became another panel and the record took the width back. --}} {{-- ── Second row ─────────────────────────────────────────────── --}} @if ($canSeeClinical) @include('patients::partials.clinical-medications') @endif @include('patients::partials.documents') {{-- Contributed regions. The upload portal fills the administrative one with its "send us your reports" panel; Laboratory fills the clinical one with result trends. Patients learns about neither, which is what lets this screen render unchanged on a clinic that has installed neither. Administrative sits here, in the second row. Clinical comes last because result trends claims the whole width, and a full-width panel in the middle would cut the eight cards in half. --}} @include('patients::partials.contacts') {{-- Behind the same gate as the panels above: a trend line is clinical information, and a receptionist who may not read the problem list may not read it either. --}} @if ($canSeeClinical) @endif
@endsection