166 lines
8.7 KiB
PHP
166 lines
8.7 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',
|
|
qh_t('Hospital queue operations', 'عمليات طابور المستشفى'),
|
|
qh_t('English operations dashboard for the hospital queue workflow.', 'لوحة عمليات عربية لمسار طابور المستشفى.')
|
|
);
|
|
?>
|
|
<div class="container-fluid container-xxl px-3 px-lg-4">
|
|
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-4">
|
|
<div>
|
|
<h1 class="h3 mb-0 text-gray-800 fw-bold"><?= qh_h(qh_t('Operations Dashboard', 'لوحة عمليات المستشفى')) ?></h1>
|
|
<p class="text-muted mb-0 mt-1"><?= qh_h(qh_t('Real-time hospital queue system metrics.', 'إحصائيات لحظية لنظام طوابير المستشفى.')) ?></p>
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<a class="btn btn-primary shadow-sm" href="<?= qh_h(qh_url('reception.php')) ?>"><?= qh_h(qh_t('Issue ticket', 'إصدار تذكرة')) ?></a>
|
|
<a class="btn btn-outline-secondary shadow-sm bg-white" href="<?= qh_h(qh_url('display.php')) ?>" target="_blank"><?= qh_h(qh_t('Public display', 'الشاشة العامة')) ?></a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-4 mb-4">
|
|
<div class="col-md-3 col-sm-6">
|
|
<div class="card shadow-sm border-0 h-100">
|
|
<div class="card-body">
|
|
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1 small"><?= qh_h(qh_t('Issued today', 'التذاكر الصادرة اليوم')) ?></div>
|
|
<div class="h3 mb-0 font-weight-bold text-gray-800"><?= qh_h((string) $stats['issued_today']) ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3 col-sm-6">
|
|
<div class="card shadow-sm border-0 h-100">
|
|
<div class="card-body">
|
|
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1 small"><?= qh_h(qh_t('Waiting vitals', 'بانتظار العلامات')) ?></div>
|
|
<div class="h3 mb-0 font-weight-bold text-gray-800"><?= qh_h((string) $stats['waiting_vitals']) ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3 col-sm-6">
|
|
<div class="card shadow-sm border-0 h-100">
|
|
<div class="card-body">
|
|
<div class="text-xs font-weight-bold text-info text-uppercase mb-1 small"><?= qh_h(qh_t('Ready for doctor', 'جاهز للطبيب')) ?></div>
|
|
<div class="h3 mb-0 font-weight-bold text-gray-800"><?= qh_h((string) $stats['ready_for_doctor']) ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3 col-sm-6">
|
|
<div class="card shadow-sm border-0 h-100">
|
|
<div class="card-body">
|
|
<div class="text-xs font-weight-bold text-success text-uppercase mb-1 small"><?= qh_h(qh_t('Active rooms', 'الغرف النشطة')) ?></div>
|
|
<div class="h3 mb-0 font-weight-bold text-gray-800"><?= qh_h((string) $stats['active_rooms']) ?></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row g-4 mb-4">
|
|
<div class="col-xl-8">
|
|
<div class="card shadow-sm border-0 h-100">
|
|
<div class="card-header bg-white border-bottom py-3 d-flex justify-content-between align-items-center">
|
|
<h5 class="mb-0 font-weight-bold text-dark"><?= qh_h(qh_t('Live queue overview', 'نظرة مباشرة على الطابور')) ?></h5>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th class="border-0 px-4 py-3"><?= qh_h(qh_t('Clinic', 'العيادة')) ?></th>
|
|
<th class="border-0 py-3"><?= qh_h(qh_t('Vitals wait', 'انتظار العلامات')) ?></th>
|
|
<th class="border-0 py-3"><?= qh_h(qh_t('Doctor wait', 'انتظار الطبيب')) ?></th>
|
|
<th class="border-0 py-3"><?= qh_h(qh_t('Active calls', 'النداءات النشطة')) ?></th>
|
|
<th class="border-0 text-end px-4 py-3"><?= qh_h(qh_t('Today total', 'إجمالي اليوم')) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($overview as $row): ?>
|
|
<tr>
|
|
<td class="fw-semibold px-4 py-3 text-dark"><?= qh_h(qh_name($row)) ?></td>
|
|
<td class="py-3"><span class="badge bg-warning text-dark px-2 py-1 rounded-pill"><?= qh_h((string) $row['vitals_waiting']) ?></span></td>
|
|
<td class="py-3"><span class="badge bg-info text-dark px-2 py-1 rounded-pill"><?= qh_h((string) $row['doctor_waiting']) ?></span></td>
|
|
<td class="py-3"><span class="badge bg-dark px-2 py-1 rounded-pill"><?= qh_h((string) $row['active_calls']) ?></span></td>
|
|
<td class="text-end px-4 py-3 text-muted"><?= qh_h((string) $row['total_today']) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-xl-4">
|
|
<div class="card shadow-sm border-0 h-100">
|
|
<div class="card-header bg-white border-bottom py-3">
|
|
<h5 class="mb-0 font-weight-bold text-dark"><?= qh_h(qh_t('Current calls', 'النداءات الحالية')) ?></h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<?php if ($calledTickets): ?>
|
|
<div class="vstack gap-3">
|
|
<?php foreach ($calledTickets as $ticket): ?>
|
|
<div class="d-flex justify-content-between align-items-center p-3 border rounded bg-light">
|
|
<div>
|
|
<div class="fw-bold h5 mb-1 text-dark"><?= qh_h($ticket['ticket_number']) ?></div>
|
|
<div class="small text-muted"><?= qh_h(qh_name($ticket, 'doctor_name', qh_t('Unassigned', 'غير محدد'))) ?> • <?= qh_h(qh_t('Room', 'غرفة')) ?> <?= qh_h($ticket['doctor_room'] ?? '--') ?></div>
|
|
</div>
|
|
<?= qh_status_badge($ticket['status']) ?>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="text-center py-4 text-muted">
|
|
<p class="mb-0"><?= qh_h(qh_t('No active calls yet.', 'لا توجد نداءات نشطة حالياً.')) ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card shadow-sm border-0 mb-4">
|
|
<div class="card-header bg-white border-bottom py-3">
|
|
<h5 class="mb-0 font-weight-bold text-dark"><?= qh_h(qh_t('Recent patient flow', 'آخر حركة للمرضى')) ?></h5>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
<?php if ($recentTickets): ?>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover align-middle mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th class="border-0 px-4 py-3"><?= qh_h(qh_t('Ticket', 'التذكرة')) ?></th>
|
|
<th class="border-0 py-3"><?= qh_h(qh_t('Patient', 'المريض')) ?></th>
|
|
<th class="border-0 py-3"><?= qh_h(qh_t('Clinic', 'العيادة')) ?></th>
|
|
<th class="border-0 py-3"><?= qh_h(qh_t('Doctor', 'الطبيب')) ?></th>
|
|
<th class="border-0 py-3"><?= qh_h(qh_t('Status', 'الحالة')) ?></th>
|
|
<th class="border-0 px-4 py-3 text-end"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($recentTickets as $ticket): ?>
|
|
<tr>
|
|
<td class="fw-bold px-4 py-3 text-dark"><?= qh_h($ticket['ticket_number']) ?></td>
|
|
<td class="py-3"><?= qh_h($ticket['patient_name']) ?></td>
|
|
<td class="py-3 text-muted"><?= qh_h(qh_name($ticket, 'clinic_name')) ?></td>
|
|
<td class="py-3 text-muted"><?= qh_h(qh_name($ticket, 'doctor_name', qh_t('Unassigned', 'غير محدد'))) ?></td>
|
|
<td class="py-3"><?= qh_status_badge($ticket['status']) ?></td>
|
|
<td class="text-end px-4 py-3"><a class="btn btn-sm btn-light border" href="<?= qh_h(qh_url('ticket.php', ['id' => (int) $ticket['id']])) ?>"><?= qh_h(qh_t('View', 'عرض')) ?></a></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="text-center py-5 text-muted">
|
|
<p class="mb-0"><?= qh_h(qh_t('No recent tickets yet.', 'لا توجد تذاكر حديثة حتى الآن.')) ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php qh_page_end(); ?>
|