@extends('layouts.app') @section('title', 'Dashboard') @section('content') @php // Format helpers used throughout the view $fmtKes = fn($n) => 'KES ' . number_format((float) $n, 0); $fmtKesNeg= function($n) use ($fmtKes) { $n = (float) $n; return $n < 0 ? '-' . $fmtKes(abs($n)) : $fmtKes($n); }; @endphp @php // Smart period label that adapts to the selected range. // Single-day-today → "Today" // Single-day-other → "Mon, 01 May 2026" // Multi-day → "01 May — 05 May 2026" (or with year prefix if cross-year) $periodLabel = (function() use ($rangeStart, $rangeEnd, $isSingleDay, $isToday) { if ($isToday) return 'Today (' . $rangeStart->format('d M Y') . ')'; if ($isSingleDay) return $rangeStart->format('D, d M Y'); $sameYear = $rangeStart->year === $rangeEnd->year; return $sameYear ? $rangeStart->format('d M') . ' — ' . $rangeEnd->format('d M Y') : $rangeStart->format('d M Y') . ' — ' . $rangeEnd->format('d M Y'); })(); // Preset URL helpers — generate ?from=X&to=Y links. $presetUrl = function($from, $to) { return route('dashboard') . '?from=' . $from . '&to=' . $to; }; $today = \Carbon\Carbon::today(); $yesterday = $today->copy()->subDay(); $sevenDaysAgo = $today->copy()->subDays(6); $thirtyDaysAgo = $today->copy()->subDays(29); $thisMonthStart = $today->copy()->startOfMonth(); $lastMonthStart = $today->copy()->subMonthNoOverflow()->startOfMonth(); $lastMonthEnd = $today->copy()->subMonthNoOverflow()->endOfMonth(); // Detect which preset is currently active (for visual highlight). $isPreset = function($from, $to) use ($rangeStart, $rangeEnd) { return $rangeStart->toDateString() === $from->toDateString() && $rangeEnd->toDateString() === $to->toDateString(); }; $activePreset = match(true) { $isPreset($today, $today) => 'today', $isPreset($yesterday, $yesterday) => 'yesterday', $isPreset($sevenDaysAgo, $today) => 'last7', $isPreset($thirtyDaysAgo, $today) => 'last30', $isPreset($thisMonthStart, $today) => 'thismonth', $isPreset($lastMonthStart, $lastMonthEnd) => 'lastmonth', default => 'custom', }; @endphp {{-- ══════════════ TOP BAR: Title + Date Range Filter ══════════════ --}}

Dashboard

Showing data for {{ $periodLabel }} @if(!$isToday) Historical @endif

{{-- From / To inputs --}}
@if(!$isToday) Reset @endif
{{-- Quick-preset chips --}}
Quick: @php $chip = function($label, $key, $url) use ($activePreset) { $active = $activePreset === $key; $cls = $active ? 'bg-purple-100 text-purple-700 border-purple-200 font-semibold' : 'bg-gray-50 text-gray-600 border-gray-200 hover:bg-gray-100'; return '' . $label . ''; }; @endphp {!! $chip('Today', 'today', $presetUrl($today->format('Y-m-d'), $today->format('Y-m-d'))) !!} {!! $chip('Yesterday', 'yesterday', $presetUrl($yesterday->format('Y-m-d'), $yesterday->format('Y-m-d'))) !!} {!! $chip('Last 7 days', 'last7', $presetUrl($sevenDaysAgo->format('Y-m-d'), $today->format('Y-m-d'))) !!} {!! $chip('Last 30 days','last30', $presetUrl($thirtyDaysAgo->format('Y-m-d'), $today->format('Y-m-d'))) !!} {!! $chip('This month', 'thismonth', $presetUrl($thisMonthStart->format('Y-m-d'), $today->format('Y-m-d'))) !!} {!! $chip('Last month', 'lastmonth', $presetUrl($lastMonthStart->format('Y-m-d'), $lastMonthEnd->format('Y-m-d'))) !!} @if($activePreset === 'custom') Custom range @endif
{{-- ══════════════ ROW 1A: TODAY — FINANCIAL ══════════════ --}}
{{-- Patients Today --}}

Patients{{ $isToday ? ' Today' : '' }}

{{ number_format($row1['patientsToday']) }}

{{-- Revenue Today (collections + insurance billed) --}}

Revenue{{ $isToday ? ' Today' : '' }}

{{ $fmtKes($row1['revenueToday']) }}

{{-- Collections Today (cash + mobile, incl. co-pay — what hit the till) --}}

Collections{{ $isToday ? ' Today' : '' }}

{{ $fmtKes($row1['collectionsToday'] ?? 0) }}

{{-- Cash (incl. co-pay paid in cash) --}}

Cash

{{ $fmtKes($row1['cashToday']) }}

{{-- Mobile Money / Bank (incl. co-pay paid via M-Pesa or bank) --}}

Mobile / Bank

{{ $fmtKes($row1['mobileToday']) }}

{{-- Insurance --}}

Insurance

{{ $fmtKes($row1['insuranceToday']) }}

{{-- ══════════════ ROW 1B: TODAY — OPERATIONAL ══════════════ --}}
{{-- ARPP --}}

ARPP

{{ $fmtKes($row1['arpp']) }}

{{-- Average Revenue per Day (MTD) ─ added at Clara's request. Denominator = calendar days elapsed in the current month so a clinician can compare today's revenue against the running daily average for the month so far. --}}

Avg Revenue/Day

{{ $fmtKes($row2['avgRevenuePerDay'] ?? 0) }}

MTD average · {{ $row2['daysElapsed'] ?? 0 }} day{{ ($row2['daysElapsed'] ?? 0) === 1 ? '' : 's' }}

{{-- Follow-Ups Due Today. Live count of FollowUp::dueToday() — decrements as the receptionist records call outcomes and the rows flip to status=closed. Click-through goes to the CRM worklist so the receptionist can act immediately. --}}

Follow-Ups Due

{{ number_format($row1['followUpsDue'] ?? 0) }}

{{-- ══════════════ ROW 2: MTD FINANCIAL POSITION ══════════════ --}}

Month-to-date · {{ $rangeEnd->format('M Y') }}

{{-- MTD Revenue --}}

MTD Revenue

{{ $fmtKes($row2['mtdRevenue']) }}

{{-- MTD Expenses --}}

MTD Expenses

{{ $fmtKes($row2['mtdExpenses']) }}

{{-- MTD Net Position --}}

MTD Net Position

{{ $fmtKesNeg($row2['mtdNet']) }}

{{-- Cash in Bank (liquidity) --}}

Cash in Bank

{{ $fmtKesNeg($row2['cashInBank']) }}

{{-- Accounts Receivable (live total, not MTD) --}}

Accounts Receivable

{{ $fmtKes($row2['accountsReceivable']) }}

{{-- ══════════════ ROW 3: OPERATIONS ══════════════ --}}
{{-- Appointments --}}

Appointments

{{ number_format($row3['appointments']) }}

{{-- Bed Occupancy --}}

Bed Occupancy

{{ $row3['bedOccupancy'] }}%

{{ $row3['occupiedBeds'] }} / {{ $row3['totalBeds'] }} beds occupied

{{-- Active ANC --}}

Active ANC Clients

{{ number_format($row3['activeAnc']) }}

{{-- New vs Returning --}}

New vs Returning

{{ $row3['newCount'] }} NEW
·
{{ $row3['returningCount'] }} RET

@php $total = $row3['newCount'] + $row3['returningCount']; @endphp {{ $total > 0 ? round(($row3['newCount'] / $total) * 100) : 0 }}% new

{{-- ══════════════ CHARTS: 7-day trends ══════════════ --}}

Daily Revenue Trend (7 days ending {{ $rangeEnd->format('d M') }})

Daily Visits (7 days ending {{ $rangeEnd->format('d M') }})

{{-- ══════════════ BOTTOM: Dept revenue + Shifts ══════════════ --}}
{{-- Revenue by Clinical Service --}}

Revenue by Clinical Service

@if($revenueByDept->count()) @php $deptTotal = $revenueByDept->sum('total'); @endphp @foreach($revenueByDept as $dept) @php $pct = $deptTotal > 0 ? ($dept->total / $deptTotal) * 100 : 0; @endphp @endforeach
{{ $dept->department ?: 'Unassigned' }} {{ $fmtKes($dept->total) }}
@else

No revenue recorded for this date.

@endif
{{-- Shift Tables (Day + Night). For a multi-day range, these show the LAST date's shifts (most recent). The subtitle below the heading clarifies. --}} @foreach(['day' => ['label' => 'Day Shift', 'time' => '8:00 AM – 8:00 PM', 'icon' => 'M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z', 'bg' => 'amber'], 'night' => ['label' => 'Night Shift', 'time' => '8:00 PM – 8:00 AM', 'icon' => 'M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z', 'bg' => 'indigo']] as $shift => $meta) @php $s = $dashboardShifts[$shift]; @endphp

{{ $meta['label'] }} @if(!$isSingleDay) ({{ $rangeEnd->format('d M') }}) @endif

{{ $meta['time'] }}

Cash{{ $fmtKes($s['cash']) }}
M-Pesa / Mobile{{ $fmtKes($s['mpesa']) }}
Insurance{{ $fmtKes($s['insurance']) }}
Card / Bank{{ $fmtKes($s['card']) }}
Shift Total{{ $fmtKes($s['total']) }}
@endforeach
@endsection @section('scripts') @endsection