@extends('layouts.app') @section('title', 'ANC Profile | ' . ($registration->patient->full_name ?? '')) @section('content') @include('partials._encounter-styles') @php $r = $registration; $p = $r->patient; // ANC-level lock state — closed statuses are terminal ('delivered', 'closed', etc.) $ancLocked = app(\App\Services\VisitLockService::class)->isClosed($r); @endphp
{{-- Unified visit lock banner (read-only + reactivate for admins) --}} @include('partials._visit-lock-banner', ['entity' => $r, 'type' => 'anc']) {{-- ═══ PATIENT BALANCE SUMMARY (compact strip) ═══ --}} @include('partials._patient-balance-summary', ['patient' => $p])
{{ strtoupper(substr($p->first_name ?? '', 0, 1) . substr($p->last_name ?? '', 0, 1)) }}

{{ $p->full_name }}

{{ $p->mrn }} · {{ $p->phone ?? '' }}

@if($r->status === 'active' && !$ancLocked)
Record Delivery Admit to L&D
@endif
{{-- ═══ PATIENT / ANC SUMMARY BANNER (always visible) ═══ --}}
LMP
{{ $r->lmp?->format('d M Y') ?? '—' }}
EDD
{{ $r->edd?->format('d M Y') ?? '—' }}
GA
{{ $r->gestational_age ?? '—' }} wks
G / P
G{{ $r->gravida ?? '-' }}P{{ $r->parity ?? '-' }}
Blood Group
{{ trim(($r->blood_group ?? '') . ' ' . ($r->rhesus ?? '')) ?: '—' }}
Package
@php $pkgLabel = $coverage['package']['label'] ?? ($r->package_type ?? '—'); @endphp {{ $pkgLabel }} @if($coverage['mode'] === 'package') KES {{ number_format($coverage['paid']) }} / {{ number_format($coverage['package']['price'] ?? 0) }} @endif {{-- Convert / Change Package button — visible to staff who can manage billing. Labels differ based on current state. --}} @if($r->status === 'active' && auth()->user()->hasAnyRole('Super Admin','Hospital Admin','Receptionist','Finance User')) @endif
Risk
{{ ucfirst($r->risk_status ?? 'normal') }}
Status
{{ ucfirst($r->status) }}
Next Visit
{{ $r->next_visit_date?->format('d M Y') ?? 'Not set' }}
{{-- ═══ DRAWER BUTTONS (always visible) ═══ --}}
{{-- Full cross-module patient history (OPD visits, IPD admissions, past labs/imaging across encounters). Distinct from "View / Edit History" above which is the ANC HPI form. --}}
{{-- ═══ MAIN COLUMN ═══ --}}
@if($r->status === 'active') {{-- Risk banner above every encounter --}} @include('maternity.partials._risk-banner', [ 'registration' => $r, 'riskResult' => $riskResult, 'priorVisit' => $priorVisit ?? null, 'draftVisit' => $draftVisit, ]) {{-- ─── Close-visit soft warning (from flash session after ancVisitFinalize) ─── --}} @if(session('close_warning'))
⚠ Outstanding balance

{{ session('close_warning') }}

@csrf
@endif
@csrf @if($isBooking) {{-- ══════════════════════════════════════════════════════════════ BOOKING VISIT — first encounter. Three open accordions plus inline Orders and Billing. History and Labs are editable from the drawers (same underlying form fields). ══════════════════════════════════════════════════════════════ --}}
Booking Visit

First visit for this pregnancy. Capture history, book labs, record baseline vitals. On subsequent visits the form will be shorter — history and labs become drawers.

{{-- Clinical (vitals + symptoms + exam + assessment/plan + interventions + next visit) --}}

1 Vitals

@include('maternity.partials._fields.input', ['name'=>'bp_systolic', 'label'=>'BP Systolic', 'unit'=>'mmHg', 'type'=>'number', 'step'=>'0.1']) @include('maternity.partials._fields.input', ['name'=>'bp_diastolic', 'label'=>'BP Diastolic', 'unit'=>'mmHg', 'type'=>'number', 'step'=>'0.1']) @include('maternity.partials._fields.input', ['name'=>'pulse', 'label'=>'Pulse', 'unit'=>'bpm', 'type'=>'number']) @include('maternity.partials._fields.input', ['name'=>'temperature', 'label'=>'Temp', 'unit'=>'°C', 'type'=>'number', 'step'=>'0.1']) @include('maternity.partials._fields.input', ['name'=>'weight', 'label'=>'Weight', 'unit'=>'kg', 'type'=>'number', 'step'=>'0.01']) @include('maternity.partials._fields.input', ['name'=>'height_cm', 'label'=>'Height', 'unit'=>'cm', 'type'=>'number', 'step'=>'0.1']) @include('maternity.partials._fields.input', ['name'=>'bmi', 'label'=>'BMI', 'unit'=>'kg/m²','type'=>'number', 'step'=>'0.01', 'help'=>'Auto']) @include('maternity.partials._fields.input', ['name'=>'muac_cm', 'label'=>'MUAC', 'unit'=>'cm', 'type'=>'number', 'step'=>'0.1'])

2 Symptoms & Examination

@include('maternity.partials._fields.checkbox', ['name'=>'fetal_movements_felt', 'label'=>'Fetal movements felt']) @include('maternity.partials._fields.checkbox', ['name'=>'reduced_fetal_movement', 'label'=>'Reduced fetal movement']) @include('maternity.partials._fields.checkbox', ['name'=>'vaginal_bleeding', 'label'=>'Vaginal bleeding']) @include('maternity.partials._fields.checkbox', ['name'=>'vaginal_discharge', 'label'=>'Vaginal discharge']) @include('maternity.partials._fields.checkbox', ['name'=>'headache', 'label'=>'Headache']) @include('maternity.partials._fields.checkbox', ['name'=>'blurred_vision', 'label'=>'Blurred vision']) @include('maternity.partials._fields.checkbox', ['name'=>'epigastric_pain', 'label'=>'Epigastric pain']) @include('maternity.partials._fields.checkbox', ['name'=>'dysuria', 'label'=>'Dysuria']) @include('maternity.partials._fields.checkbox', ['name'=>'fever', 'label'=>'Fever']) @include('maternity.partials._fields.checkbox', ['name'=>'vomiting', 'label'=>'Vomiting']) @include('maternity.partials._fields.checkbox', ['name'=>'swelling_limbs_face', 'label'=>'Swelling'])
@include('maternity.partials._fields.input', ['name'=>'fundal_height', 'label'=>'Fundal height', 'unit'=>'cm', 'type'=>'number', 'step'=>'0.1']) @include('maternity.partials._fields.select', ['name'=>'presentation', 'label'=>'Presentation', 'options'=>['Cephalic'=>'Cephalic','Breech'=>'Breech','Transverse'=>'Transverse','Oblique'=>'Oblique']]) @include('maternity.partials._fields.input', ['name'=>'fetal_heart_rate', 'label'=>'FHR', 'unit'=>'bpm', 'type'=>'number']) @include('maternity.partials._fields.select', ['name'=>'fetal_heart_status', 'label'=>'Fetal heart', 'options'=>['present'=>'Present','absent'=>'Absent','not_checked'=>'Not checked']]) @include('maternity.partials._fields.select', ['name'=>'pallor', 'label'=>'Pallor', 'options'=>['none'=>'None','mild'=>'Mild','moderate'=>'Moderate','severe'=>'Severe']]) @include('maternity.partials._fields.select', ['name'=>'jaundice', 'label'=>'Jaundice', 'options'=>['none'=>'None','mild'=>'Mild','moderate'=>'Moderate','severe'=>'Severe']]) @include('maternity.partials._fields.select', ['name'=>'oedema', 'label'=>'Oedema', 'options'=>['none'=>'None','mild'=>'Mild','moderate'=>'Moderate','severe'=>'Severe']]) @include('maternity.partials._fields.input', ['name'=>'next_visit_date','label'=>'Next Visit', 'type'=>'date'])
@include('maternity.partials._fields.compact_input', ['name'=>'complaints', 'label'=>'Chief complaints']) @include('maternity.partials._fields.compact_input', ['name'=>'danger_signs','label'=>'Danger signs (comma-separated)']) @include('maternity.partials._fields.textarea', ['name'=>'assessment', 'label'=>'Assessment', 'rows'=>2]) @include('maternity.partials._fields.textarea', ['name'=>'plan', 'label'=>'Plan', 'rows'=>2])
@include('maternity.partials._fields.checkbox', ['name'=>'ifas_issued', 'label'=>'IFAS']) @include('maternity.partials._fields.checkbox', ['name'=>'tt_given', 'label'=>'TT']) @include('maternity.partials._fields.checkbox', ['name'=>'iptp_given', 'label'=>'IPTp-SP']) @include('maternity.partials._fields.checkbox', ['name'=>'deworming_given', 'label'=>'Deworming']) @include('maternity.partials._fields.checkbox', ['name'=>'itn_issued', 'label'=>'ITN'])
Next steps: capture patient history and booking labs using the drawer buttons at the top. Orders and billing below. Close the visit once everything is recorded.
@include('maternity.partials._anc-save-bar', ['section' => 'booking']) @else {{-- ══════════════════════════════════════════════════════════════ FOLLOW-UP VISIT — flat OPD-style page. Everything on one scroll. ══════════════════════════════════════════════════════════════ --}} {{-- ═══ 1. VITALS (+ collapsible Danger Signs) ═══ --}}

1 Vitals

Visit #{{ ($priorVisit?->visit_number ?? 0) + 1 }}
@include('maternity.partials._fields.input', ['name'=>'bp_systolic', 'label'=>'BP Sys', 'unit'=>'mmHg', 'type'=>'number', 'step'=>'0.1']) @include('maternity.partials._fields.input', ['name'=>'bp_diastolic', 'label'=>'BP Dias', 'unit'=>'mmHg', 'type'=>'number', 'step'=>'0.1']) @include('maternity.partials._fields.input', ['name'=>'pulse', 'label'=>'Pulse', 'unit'=>'bpm', 'type'=>'number']) @include('maternity.partials._fields.input', ['name'=>'temperature', 'label'=>'Temp', 'unit'=>'°C', 'type'=>'number', 'step'=>'0.1']) @include('maternity.partials._fields.input', ['name'=>'weight', 'label'=>'Weight', 'unit'=>'kg', 'type'=>'number', 'step'=>'0.01']) @include('maternity.partials._fields.input', ['name'=>'height_cm', 'label'=>'Height', 'unit'=>'cm', 'type'=>'number', 'step'=>'0.1']) @include('maternity.partials._fields.input', ['name'=>'bmi', 'label'=>'BMI', 'unit'=>'kg/m²','type'=>'number', 'step'=>'0.01', 'help'=>'Auto']) @include('maternity.partials._fields.input', ['name'=>'respiratory_rate','label'=>'Resp', 'unit'=>'/min', 'type'=>'number']) @include('maternity.partials._fields.input', ['name'=>'gestational_age_weeks', 'label'=>'GA', 'unit'=>'wks', 'type'=>'number']) @include('maternity.partials._fields.input', ['name'=>'next_visit_date', 'label'=>'Next Visit','type'=>'date'])
{{-- Danger signs — collapsed by default. Skip if nothing concerning. --}}
+ Record Danger Signs Only if any are present — skip otherwise
@include('maternity.partials._fields.checkbox', ['name'=>'headache', 'label'=>'Severe headache']) @include('maternity.partials._fields.checkbox', ['name'=>'blurred_vision', 'label'=>'Blurred vision']) @include('maternity.partials._fields.checkbox', ['name'=>'vaginal_bleeding', 'label'=>'Vaginal bleeding']) @include('maternity.partials._fields.checkbox', ['name'=>'epigastric_pain', 'label'=>'Epigastric pain']) @include('maternity.partials._fields.checkbox', ['name'=>'reduced_fetal_movement', 'label'=>'Reduced fetal movement']) @include('maternity.partials._fields.checkbox', ['name'=>'swelling_limbs_face', 'label'=>'Swelling of face/hands']) @include('maternity.partials._fields.checkbox', ['name'=>'fever', 'label'=>'Fever']) @include('maternity.partials._fields.checkbox', ['name'=>'vomiting', 'label'=>'Persistent vomiting']) @include('maternity.partials._fields.checkbox', ['name'=>'dysuria', 'label'=>'Dysuria']) @include('maternity.partials._fields.checkbox', ['name'=>'vaginal_discharge', 'label'=>'Abnormal discharge'])
{{-- ═══ 2. CLINICAL DETAILS (mirrors OPD format) ═══ --}}

2 Clinical Details

{{-- Chief Complaint --}}
{{-- Clinical Notes / History --}}
{{-- Treatment Plan --}}
{{-- Diagnosis (optional, free-text ICD-10) --}}
{{-- ═══ 3. ANC EXAMINATION (WHO / MOH 405 — maternal + fetal) ═══ --}}

3 ANC Examination

WHO / MOH 405
{{-- Maternal --}}
Maternal Examination
@include('maternity.partials._fields.select', ['name'=>'pallor', 'label'=>'Pallor', 'options'=>['none'=>'None','mild'=>'Mild','moderate'=>'Moderate','severe'=>'Severe']]) @include('maternity.partials._fields.select', ['name'=>'jaundice', 'label'=>'Jaundice', 'options'=>['none'=>'None','mild'=>'Mild','moderate'=>'Moderate','severe'=>'Severe']]) @include('maternity.partials._fields.select', ['name'=>'oedema', 'label'=>'Oedema', 'options'=>['none'=>'None','mild'=>'Mild','moderate'=>'Moderate','severe'=>'Severe']]) @include('maternity.partials._fields.select', ['name'=>'breast_exam', 'label'=>'Breast Exam', 'options'=>['normal'=>'Normal','abnormal'=>'Abnormal','not_done'=>'Not done']])
{{-- Fetal / Obstetric --}}
Fetal / Obstetric Examination
@include('maternity.partials._fields.input', ['name'=>'fundal_height', 'label'=>'Fundal Height', 'unit'=>'cm', 'type'=>'number', 'step'=>'0.1']) @include('maternity.partials._fields.select', ['name'=>'fetal_lie', 'label'=>'Lie', 'options'=>['longitudinal'=>'Longitudinal','transverse'=>'Transverse','oblique'=>'Oblique']]) @include('maternity.partials._fields.select', ['name'=>'presentation', 'label'=>'Presentation', 'options'=>['Cephalic'=>'Cephalic','Breech'=>'Breech','Transverse'=>'Transverse','Oblique'=>'Oblique']]) @include('maternity.partials._fields.input', ['name'=>'fetal_heart_rate', 'label'=>'FHR', 'unit'=>'bpm', 'type'=>'number']) @include('maternity.partials._fields.select', ['name'=>'fetal_heart_status','label'=>'Fetal Heart', 'options'=>['present'=>'Present','absent'=>'Absent','not_checked'=>'Not checked']]) @include('maternity.partials._fields.select', ['name'=>'liquor_volume', 'label'=>'Liquor Volume', 'options'=>['adequate'=>'Adequate','reduced'=>'Reduced','polyhydramnios'=>'Polyhydramnios','not_assessed'=>'Not assessed']]) @include('maternity.partials._fields.select', ['name'=>'engagement', 'label'=>'Engagement', 'options'=>['not_applicable'=>'N/A (early)','not_engaged'=>'Not engaged','engaged'=>'Engaged','deeply_engaged'=>'Deeply engaged']])
@include('maternity.partials._fields.checkbox', ['name'=>'fetal_movements_felt', 'label'=>'Fetal movements felt']) @include('maternity.partials._fields.checkbox', ['name'=>'reduced_fetal_movement', 'label'=>'Reduced fetal movement'])
{{-- ═══ 4. WHO INTERVENTIONS + REFERRAL ═══ --}}

4 WHO Interventions

@include('maternity.partials._fields.checkbox', ['name'=>'ifas_issued', 'label'=>'IFAS']) @include('maternity.partials._fields.checkbox', ['name'=>'tt_given', 'label'=>'TT']) @include('maternity.partials._fields.checkbox', ['name'=>'iptp_given', 'label'=>'IPTp-SP']) @include('maternity.partials._fields.checkbox', ['name'=>'deworming_given', 'label'=>'Deworming']) @include('maternity.partials._fields.checkbox', ['name'=>'itn_issued', 'label'=>'ITN']) @include('maternity.partials._fields.checkbox', ['name'=>'referred', 'label'=>'Referred'])
@include('maternity.partials._anc-save-bar', ['section' => 'encounter']) @endif
{{-- ═══ ORDERS and BILLING live OUTSIDE the ANC form — they have their own forms. ═══ --}} @include('maternity.partials._anc-orders', ['backingVisit'=>$backingVisit, 'labOrders'=>$labOrders, 'imagingRequests'=>$imagingRequests, 'prescriptions'=>$prescriptions]) @include('maternity.partials._anc-billing', ['registration'=>$r, 'coverage'=>$coverage, 'backingVisit'=>$backingVisit, 'invoice'=>$invoice, 'packageInvoice'=>$packageInvoice ?? null]) {{-- ═══ CLOSE VISIT (sticky footer). Submits the main form above. ═══ --}} @php // "Has content" = anything worth finalizing is on the page. The // server-side ancVisitFinalize does the authoritative check; this // flag just keeps the button from being offered when there's // obviously nothing to close. $hasDraft = $draftVisit->exists; $hasOrders = ($labOrders->count() + $imagingRequests->count() + $prescriptions->count()) > 0; $hasExtraItems = $invoice && $invoice->items->filter(fn($it) => ! in_array($it->source_type ?? '', ['anc_consultation','anc_package','anc_package_carry'], true))->count() > 0; $canClose = $hasDraft || $hasOrders || $hasExtraItems; // Compute the close gate message. Round 10 single-invoice model: // the gate is enforced per-visit by AncPackage::canCloseVisit() // — 50% of THIS visit's package balance must be paid before // close. We replicate that calc here for UI feedback only. $closeMessage = null; if ($invoice) { $pkgLineTotal = (float) $invoice->items->whereIn('source_type', ['anc_package','anc_package_carry'])->sum('total'); $extrasTotal = (float) $invoice->items->whereNotIn('source_type', ['anc_package','anc_package_carry'])->sum('total'); $invTotal = (float) $invoice->total_amount; $invPaid = (float) $invoice->amount_paid; $paidToPkg = $invTotal > 0 ? $invPaid * ($pkgLineTotal / $invTotal) : 0; $paidToExtras = $invPaid - $paidToPkg; $extrasUnpaid = max(0, $extrasTotal - $paidToExtras); if ($extrasUnpaid > 0.01) { $closeMessage = sprintf('KES %s visit extras unpaid — close will be blocked.', number_format($extrasUnpaid)); } elseif ($pkgLineTotal > 0.01 && $paidToPkg + 0.01 < $pkgLineTotal * 0.5) { $owed = ($pkgLineTotal * 0.5) - $paidToPkg; $closeMessage = sprintf('Package minimum not met — collect at least KES %s more (50%% of the KES %s package balance) before closing.', number_format($owed), number_format($pkgLineTotal)); } } @endphp
Ready to close? Runs risk evaluation and locks the visit. @if($closeMessage) {{ $closeMessage }} @elseif(! $canClose) Record vitals, a complaint, a plan, or place an order before closing. @endif
@if(! $canClose)
@if($backingVisit && $backingVisit->status === 'in_consultation' && auth()->user()->hasAnyRole('Super Admin','Hospital Admin')) {{-- Cancel Visit — admin-only, mirrors the routes/web.php role gate on visits.cancel. Hidden when there's no backing visit, when the visit is already completed/cancelled, and for non-admin users. The handler cancels the visit, cascades cleanup of unpaid stub records, and preserves anything with real financial/clinical value. The redirect_to field sends the user to the ANC visits list afterwards — without it, back() would return to this same URL and immediately spawn a fresh in_consultation visit (ensureAncBackingVisit correctly skips cancelled visits and creates a new one), which would feel like the cancel didn't take. Confirmation prompt because the action discards draft work. --}}
@csrf
@endif
@else
@if($backingVisit && $backingVisit->status === 'in_consultation' && auth()->user()->hasAnyRole('Super Admin','Hospital Admin'))
@csrf
@endif
@endif
{{-- /#anc-wrap --}} @endif
{{-- /main column --}} {{-- ═══ DRAWER PARTIALS ═══ --}} @if($r->status === 'active') @include('maternity.partials._anc-drawer-history', ['registration'=>$r, 'priorVisit'=>$priorVisit, 'draftVisit'=>$draftVisit]) @include('maternity.partials._anc-drawer-labs', ['registration'=>$r, 'draftVisit'=>$draftVisit]) @include('maternity.partials._anc-drawer-visits', ['registration'=>$r]) @endif {{-- Cross-module patient history drawer. Always available regardless of registration status — a delivered patient's clinician may still want to look up prior OPD visits, IPD admissions, etc. --}} @include('patients.partials._patient-history-drawer', ['patient' => $r->patient]) {{-- ───── DELIVERY RECORD (unchanged from original) ───── --}} @if($r->delivery)

Delivery Record

Date: {{ $r->delivery->delivery_date?->format('d M Y') ?? '—' }}
Mode: {{ $r->delivery->mode_of_delivery ?? '—' }}
Mother: {{ ucfirst(str_replace('_',' ',$r->delivery->mother_outcome ?? '—')) }}
Baby: {{ ucfirst(str_replace('_',' ',$r->delivery->baby_outcome ?? '—')) }}
Blood Loss: {{ $r->delivery->blood_loss ?? '—' }}
@if($r->delivery->newborns && $r->delivery->newborns->count())
Weight: {{ $r->delivery->newborns->first()?->birth_weight }}kg
APGAR: {{ $r->delivery->newborns->first()?->apgar_1min }}/{{ $r->delivery->newborns->first()?->apgar_5min }}
Gender: {{ ucfirst($r->delivery->newborns->first()?->gender ?? '') }}
@endif
@endif {{-- ═══ BOOK NEXT APPOINTMENT ═══ Renders inside .enc-page so the .enc-section CSS scoping applies (border, padding, header strip). Quick link to the appointments form with this patient pre-selected, plus next_visit_date pre-filled if set. The appointments/create view reads ?patient_id=X&date=Y from the querystring. --}} @if($r->status === 'active')

Book Next Appointment

@if($r->next_visit_date) Suggested next visit: {{ $r->next_visit_date->format('d M Y') }} — click to schedule a confirmed appointment for {{ $p->full_name }}. @else No next-visit date suggested yet — you can still book an appointment for {{ $p->full_name }} from here. @endif
Book Next Appointment →
@endif
{{-- /.enc-page --}} {{-- BMI auto-calc + drawers + save infra --}} {{-- ═══ CONVERT TO PACKAGE MODAL ════════════════════════════════════════ --}} @if($r->status === 'active' && auth()->user()->hasAnyRole('Super Admin','Hospital Admin','Receptionist','Finance User')) @php // Credit preview for new single-invoice model. The credit applied to a // package upgrade = whatever's been paid against the existing package // (anc_package + anc_package_carry lines, pro-rata across all visits). // packagePaid() in the service does exactly this. $svc = \App\Services\AncPackage::class; $oldKeyForModal = $svc::keyFor($r->package_type); $oldPkgForModal = $oldKeyForModal ? $svc::forType($oldKeyForModal) : null; $oldPackagePrice = $oldPkgForModal ? (float) $oldPkgForModal['price'] : 0.0; $oldPackagePaid = $oldPkgForModal ? $svc::packagePaid($r) : 0.0; $totalCreditPreview = $oldPackagePaid; @endphp @endif {{-- ───────────────────────────────────────────────────────────────────── Live BMI calculation for the Vitals/Triage section. BMI = weight(kg) / (height(m))² Reacts to input on either Weight or Height. Marked read-only so it's clear the value is computed; the height_cm field accepts either a single decimal (e.g. 162.5 cm) or a whole number. Clears BMI when either input is empty or invalid. ───────────────────────────────────────────────────────────────────── --}} @endsection