209 lines
8.9 KiB
PHP
209 lines
8.9 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
require_once __DIR__ . '/queue_bootstrap.php';
|
|
qh_boot();
|
|
|
|
$stats = qh_dashboard_stats();
|
|
$overview = qh_queue_overview();
|
|
$recentTickets = qh_fetch_tickets(['waiting_vitals', 'ready_for_doctor', 'called', 'in_progress'], null, 8);
|
|
$calledTickets = qh_fetch_tickets(['called', 'in_progress'], null, 4);
|
|
|
|
qh_page_start('home', 'Hospital queue operations', 'Bilingual hospital queue dashboard with queue status, staff entry points, and public display controls.');
|
|
?>
|
|
<div class="container-xxl px-3 px-lg-4">
|
|
<section class="hero-panel mb-4 mb-lg-5">
|
|
<div class="row g-4 align-items-center">
|
|
<div class="col-lg-7">
|
|
<span class="section-kicker">Hospital queue system / نظام الطوابير</span>
|
|
<h1 class="display-title mt-3 mb-3">One bilingual workflow for reception, nursing, doctors, and the public screen.</h1>
|
|
<p class="lead text-secondary mb-4">Issue one ticket, route it through optional vitals, call patients to the right room, and announce the latest calls with browser text-to-speech on the general display.</p>
|
|
<div class="d-flex flex-wrap gap-2">
|
|
<a class="btn btn-dark" href="reception.php">Issue ticket / إصدار تذكرة</a>
|
|
<a class="btn btn-outline-dark" href="display.php">Open TV display / فتح الشاشة العامة</a>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-5">
|
|
<div class="hero-card stack-card h-100">
|
|
<div class="small text-uppercase text-secondary fw-semibold mb-2">Today / اليوم</div>
|
|
<div class="row g-3">
|
|
<div class="col-6">
|
|
<div class="metric-card">
|
|
<div class="metric-value"><?= qh_h((string) $stats['issued_today']) ?></div>
|
|
<div class="metric-label">Issued / المُصدرة</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<div class="metric-card">
|
|
<div class="metric-value"><?= qh_h((string) $stats['waiting_vitals']) ?></div>
|
|
<div class="metric-label">Vitals / الحيوية</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<div class="metric-card">
|
|
<div class="metric-value"><?= qh_h((string) $stats['ready_for_doctor']) ?></div>
|
|
<div class="metric-label">Ready / جاهز</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<div class="metric-card">
|
|
<div class="metric-value"><?= qh_h((string) $stats['active_rooms']) ?></div>
|
|
<div class="metric-label">Active rooms / الغرف النشطة</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="row g-4 mb-4 mb-lg-5">
|
|
<div class="col-xl-8">
|
|
<div class="panel-card h-100">
|
|
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
|
|
<div>
|
|
<h2 class="section-title mb-1">Live queue overview / نظرة مباشرة على الطابور</h2>
|
|
<p class="section-copy mb-0">Clinic-level demand for vitals, doctor readiness, and active calls.</p>
|
|
</div>
|
|
<a class="btn btn-sm btn-outline-dark" href="admin.php">Manage clinics & doctors</a>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table align-middle mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th>Clinic / العيادة</th>
|
|
<th>Vitals wait</th>
|
|
<th>Doctor wait</th>
|
|
<th>Active calls</th>
|
|
<th>Total today</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($overview as $row): ?>
|
|
<tr>
|
|
<td>
|
|
<div class="fw-semibold"><?= qh_h($row['name_en']) ?></div>
|
|
<div class="small text-secondary" lang="ar" dir="rtl"><?= qh_h($row['name_ar']) ?></div>
|
|
</td>
|
|
<td><span class="table-pill warning"><?= qh_h((string) $row['vitals_waiting']) ?></span></td>
|
|
<td><span class="table-pill info"><?= qh_h((string) $row['doctor_waiting']) ?></span></td>
|
|
<td><span class="table-pill dark"><?= qh_h((string) $row['active_calls']) ?></span></td>
|
|
<td><?= qh_h((string) $row['total_today']) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-4">
|
|
<div class="panel-card h-100">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<div>
|
|
<h2 class="section-title mb-1">Current calls / النداءات الحالية</h2>
|
|
<p class="section-copy mb-0">Patients already called to a doctor room.</p>
|
|
</div>
|
|
</div>
|
|
<?php if ($calledTickets): ?>
|
|
<div class="vstack gap-3">
|
|
<?php foreach ($calledTickets as $ticket): ?>
|
|
<div class="call-strip">
|
|
<div>
|
|
<div class="ticket-code"><?= qh_h($ticket['ticket_number']) ?></div>
|
|
<div class="small text-secondary"><?= qh_h($ticket['doctor_name_en'] ?? 'Unassigned') ?> · Room <?= qh_h($ticket['doctor_room'] ?? '--') ?></div>
|
|
</div>
|
|
<?= qh_status_badge($ticket['status']) ?>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="empty-state compact">
|
|
<strong>No active calls yet.</strong>
|
|
<span>Use the doctor page to call the next patient.</span>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="row g-4 mb-4 mb-lg-5">
|
|
<div class="col-md-6 col-xl-3">
|
|
<a class="workflow-card h-100" href="admin.php">
|
|
<span class="workflow-step">01</span>
|
|
<h3>Admin config</h3>
|
|
<p>Manage clinics, vitals requirement, doctors, and room assignments.</p>
|
|
</a>
|
|
</div>
|
|
<div class="col-md-6 col-xl-3">
|
|
<a class="workflow-card h-100" href="reception.php">
|
|
<span class="workflow-step">02</span>
|
|
<h3>Reception issue</h3>
|
|
<p>Create a single bilingual ticket and route it to vitals or directly to the doctor.</p>
|
|
</a>
|
|
</div>
|
|
<div class="col-md-6 col-xl-3">
|
|
<a class="workflow-card h-100" href="nursing.php">
|
|
<span class="workflow-step">03</span>
|
|
<h3>Nursing handoff</h3>
|
|
<p>Capture vitals, note key measurements, and release the patient to the doctor queue.</p>
|
|
</a>
|
|
</div>
|
|
<div class="col-md-6 col-xl-3">
|
|
<a class="workflow-card h-100" href="doctor.php">
|
|
<span class="workflow-step">04</span>
|
|
<h3>Doctor call</h3>
|
|
<p>Call, start, and complete visits while the TV display announces the latest ticket.</p>
|
|
</a>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="panel-card">
|
|
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
|
|
<div>
|
|
<h2 class="section-title mb-1">Recent patient flow / آخر حركة للمرضى</h2>
|
|
<p class="section-copy mb-0">Each ticket is linked to a detail page showing its current stage.</p>
|
|
</div>
|
|
<a class="btn btn-sm btn-outline-dark" href="reception.php">Create new ticket</a>
|
|
</div>
|
|
<?php if ($recentTickets): ?>
|
|
<div class="table-responsive">
|
|
<table class="table align-middle mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th>Ticket</th>
|
|
<th>Patient</th>
|
|
<th>Clinic</th>
|
|
<th>Doctor / Room</th>
|
|
<th>Status</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($recentTickets as $ticket): ?>
|
|
<tr>
|
|
<td class="fw-semibold"><?= qh_h($ticket['ticket_number']) ?></td>
|
|
<td>
|
|
<div><?= qh_h($ticket['patient_name']) ?></div>
|
|
<div class="small text-secondary"><?= strtoupper(qh_h($ticket['language_pref'])) ?></div>
|
|
</td>
|
|
<td>
|
|
<div><?= qh_h($ticket['clinic_name_en'] ?? '—') ?></div>
|
|
<div class="small text-secondary" lang="ar" dir="rtl"><?= qh_h($ticket['clinic_name_ar'] ?? '') ?></div>
|
|
</td>
|
|
<td><?= qh_h($ticket['doctor_name_en'] ?? '—') ?> <span class="text-secondary">· <?= qh_h($ticket['doctor_room'] ?? '--') ?></span></td>
|
|
<td><?= qh_status_badge($ticket['status']) ?></td>
|
|
<td class="text-end"><a class="btn btn-sm btn-outline-dark" href="ticket.php?id=<?= qh_h((string) $ticket['id']) ?>">View detail</a></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="empty-state">
|
|
<strong>No active tickets yet.</strong>
|
|
<span>Start from the reception desk to issue the first patient ticket.</span>
|
|
</div>
|
|
<?php endif; ?>
|
|
</section>
|
|
</div>
|
|
<?php qh_page_end(); ?>
|