170 lines
11 KiB
PHP
170 lines
11 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-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"><?= qh_h(qh_t('Hospital queue system', 'نظام طوابير المستشفى')) ?></span>
|
|
<div class="locale-chip mt-3"><?= qh_h(qh_current_language_badge()) ?></div>
|
|
<h1 class="display-title mt-3 mb-3"><?= qh_h(qh_t('One clear workflow for reception, nursing, doctors, and the public display.', 'مسار واضح للاستقبال والتمريض والأطباء والشاشة العامة.')) ?></h1>
|
|
<p class="lead text-secondary mb-4"><?= qh_h(qh_t('Track each patient with one ticket, route them to vitals only when needed, and keep staff and patients aligned in real time.', 'تابع كل مريض بتذكرة واحدة، ووجّهه إلى العلامات الحيوية عند الحاجة فقط، وحافظ على تنسيق العمل بين الطاقم والمرضى لحظياً.')) ?></p>
|
|
<div class="d-flex flex-wrap gap-2">
|
|
<a class="btn btn-dark" href="<?= qh_h(qh_url('reception.php')) ?>"><?= qh_h(qh_t('Issue ticket', 'إصدار تذكرة')) ?></a>
|
|
<a class="btn btn-outline-dark" href="<?= qh_h(qh_url('display.php')) ?>"><?= qh_h(qh_t('Open public 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"><?= qh_h(qh_t('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"><?= qh_h(qh_t('Issued tickets', 'التذاكر الصادرة')) ?></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"><?= qh_h(qh_t('Waiting 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"><?= qh_h(qh_t('Ready for doctor', 'جاهز للطبيب')) ?></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"><?= qh_h(qh_t('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"><?= qh_h(qh_t('Live queue overview', 'نظرة مباشرة على الطابور')) ?></h2>
|
|
<p class="section-copy mb-0"><?= qh_h(qh_t('See clinic demand, waiting load, and active calls at a glance.', 'اطلع بسرعة على ضغط العيادات والانتظار والنداءات النشطة.')) ?></p>
|
|
</div>
|
|
<a class="btn btn-sm btn-outline-dark" href="<?= qh_h(qh_url('admin.php')) ?>"><?= qh_h(qh_t('Manage clinics and doctors', 'إدارة العيادات والأطباء')) ?></a>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table align-middle mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th><?= qh_h(qh_t('Clinic', 'العيادة')) ?></th>
|
|
<th><?= qh_h(qh_t('Vitals wait', 'انتظار العلامات')) ?></th>
|
|
<th><?= qh_h(qh_t('Doctor wait', 'انتظار الطبيب')) ?></th>
|
|
<th><?= qh_h(qh_t('Active calls', 'النداءات النشطة')) ?></th>
|
|
<th><?= qh_h(qh_t('Today total', 'إجمالي اليوم')) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($overview as $row): ?>
|
|
<tr>
|
|
<td class="fw-semibold"><?= qh_h(qh_name($row)) ?></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">
|
|
<h2 class="section-title mb-1"><?= qh_h(qh_t('Current calls', 'النداءات الحالية')) ?></h2>
|
|
<p class="section-copy mb-3"><?= qh_h(qh_t('Patients already called into active doctor rooms.', 'المرضى الذين تم استدعاؤهم بالفعل إلى غرف الأطباء.')) ?></p>
|
|
<?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(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="empty-state compact">
|
|
<strong><?= qh_h(qh_t('No active calls yet.', 'لا توجد نداءات نشطة حالياً.')) ?></strong>
|
|
<span><?= qh_h(qh_t('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">
|
|
<?php
|
|
$workflow = [
|
|
['step' => '01', 'title' => qh_t('Reception issues one ticket', 'الاستقبال يصدر تذكرة واحدة'), 'copy' => qh_t('Choose the clinic and doctor once at the front desk.', 'يتم اختيار العيادة والطبيب مرة واحدة من مكتب الاستقبال.')],
|
|
['step' => '02', 'title' => qh_t('Optional vitals step', 'خطوة العلامات الحيوية عند الحاجة'), 'copy' => qh_t('Only clinics that require vitals route through nursing first.', 'فقط العيادات التي تتطلب العلامات الحيوية تمر أولاً على التمريض.')],
|
|
['step' => '03', 'title' => qh_t('Doctor calls the patient', 'الطبيب ينادي المريض'), 'copy' => qh_t('The doctor room page pushes the next call to the display.', 'صفحة غرفة الطبيب ترسل النداء التالي إلى الشاشة.')],
|
|
['step' => '04', 'title' => qh_t('Display announces the call', 'الشاشة تعلن النداء'), 'copy' => qh_t('Patients see the latest ticket and room assignment immediately.', 'يرى المرضى آخر تذكرة ورقم الغرفة مباشرة.')],
|
|
];
|
|
?>
|
|
<?php foreach ($workflow as $card): ?>
|
|
<div class="col-md-6 col-xl-3">
|
|
<article class="panel-card workflow-card h-100">
|
|
<span class="workflow-step"><?= qh_h($card['step']) ?></span>
|
|
<h3><?= qh_h($card['title']) ?></h3>
|
|
<p><?= qh_h($card['copy']) ?></p>
|
|
</article>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</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"><?= qh_h(qh_t('Recent patient flow', 'آخر حركة للمرضى')) ?></h2>
|
|
<p class="section-copy mb-0"><?= qh_h(qh_t('The newest in-progress tickets across the workflow.', 'أحدث التذاكر النشطة عبر مسار العمل.')) ?></p>
|
|
</div>
|
|
<a class="btn btn-sm btn-outline-dark" href="<?= qh_h(qh_url('reception.php')) ?>"><?= qh_h(qh_t('Create new ticket', 'إنشاء تذكرة جديدة')) ?></a>
|
|
</div>
|
|
<?php if ($recentTickets): ?>
|
|
<div class="table-responsive">
|
|
<table class="table align-middle mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th><?= qh_h(qh_t('Ticket', 'التذكرة')) ?></th>
|
|
<th><?= qh_h(qh_t('Patient', 'المريض')) ?></th>
|
|
<th><?= qh_h(qh_t('Clinic', 'العيادة')) ?></th>
|
|
<th><?= qh_h(qh_t('Doctor', 'الطبيب')) ?></th>
|
|
<th><?= qh_h(qh_t('Status', 'الحالة')) ?></th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($recentTickets as $ticket): ?>
|
|
<tr>
|
|
<td class="fw-semibold"><?= qh_h($ticket['ticket_number']) ?></td>
|
|
<td><?= qh_h($ticket['patient_name']) ?></td>
|
|
<td><?= qh_h(qh_name($ticket, 'clinic_name')) ?></td>
|
|
<td><?= qh_h(qh_name($ticket, 'doctor_name', qh_t('Unassigned', 'غير محدد'))) ?></td>
|
|
<td><?= qh_status_badge($ticket['status']) ?></td>
|
|
<td class="text-end"><a class="btn btn-sm btn-outline-dark" href="<?= qh_h(qh_url('ticket.php', ['id' => (int) $ticket['id']])) ?>"><?= qh_h(qh_t('View detail', 'عرض التفاصيل')) ?></a></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="empty-state compact">
|
|
<strong><?= qh_h(qh_t('No recent tickets yet.', 'لا توجد تذاكر حديثة حتى الآن.')) ?></strong>
|
|
<span><?= qh_h(qh_t('Start from reception to populate the workflow.', 'ابدأ من صفحة الاستقبال لبدء تعبئة مسار العمل.')) ?></span>
|
|
</div>
|
|
<?php endif; ?>
|
|
</section>
|
|
</div>
|
|
<?php qh_page_end(); ?>
|