save nursing

This commit is contained in:
Flatlogic Bot 2026-04-02 12:53:32 +00:00
parent 7b06146e61
commit 9dff4a2e24
3 changed files with 165 additions and 23 deletions

View File

@ -4,7 +4,7 @@ require_once __DIR__ . '/queue_bootstrap.php';
qh_boot();
qh_nursing_handle_request();
$waitingTickets = qh_fetch_tickets(['waiting_vitals'], null, 20);
$waitingTickets = qh_fetch_tickets(['waiting_vitals', 'nursing_called'], null, 20);
qh_page_start(
'nursing',
@ -39,17 +39,17 @@ qh_page_start(
</div>
<div class="d-flex gap-2 flex-wrap align-items-center">
<?= qh_status_badge($ticket['status']) ?>
<a class="btn btn-sm btn-outline-secondary bg-white shadow-sm" href="<?= qh_h(qh_url('ticket.php', ['id' => (int) $ticket['id']])) ?>"><?= qh_h(qh_t('Details', 'تفاصيل')) ?></a>
</div>
</div>
<form method="post" class="row g-3 align-items-end">
<input type="hidden" name="ticket_id" value="<?= qh_h((string) $ticket['id']) ?>">
<div class="col-lg-9">
<div class="col-lg-8">
<label class="form-label text-dark fw-semibold small"><?= qh_h(qh_t('Vitals note', 'ملاحظة العلامات الحيوية')) ?></label>
<textarea class="form-control bg-white" name="vitals_notes" rows="2" placeholder="<?= qh_h(qh_t('Blood pressure, pulse, temperature...', 'الضغط والنبض والحرارة...')) ?>" required></textarea>
</div>
<div class="col-lg-3 d-grid">
<button class="btn btn-success shadow-sm" type="submit"><i class="bi bi-check2-circle me-1"></i><?= qh_h(qh_t('Send to Doctor', 'إرسال للطبيب')) ?></button>
<div class="col-lg-4 d-flex flex-column gap-2">
<button class="btn btn-<?= $ticket['status'] === 'waiting_vitals' ? 'primary' : 'warning' ?> shadow-sm" type="submit" name="action" value="call_ticket" formnovalidate><i class="bi bi-megaphone me-1"></i><?= qh_h($ticket['status'] === 'waiting_vitals' ? qh_t('Call', 'نداء') : qh_t('Recall', 'إعادة النداء')) ?></button>
<button class="btn btn-success shadow-sm" type="submit" name="action" value="send"><i class="bi bi-check2-circle me-1"></i><?= qh_h(qh_t('Send to Doctor', 'إرسال للطبيب')) ?></button>
</div>
</form>
</div>

117
patch.php Normal file
View File

@ -0,0 +1,117 @@
<?php
$content = file_get_contents('queue_bootstrap.php');
$search1 = <<<'EOD'
'waiting_vitals' => ['class' => 'warning', 'en' => 'Waiting for vitals', 'ar' => 'بانتظار العلامات الحيوية'],
EOD;
$replace1 = <<<'EOD'
'waiting_vitals' => ['class' => 'warning', 'en' => 'Waiting for vitals', 'ar' => 'بانتظار العلامات الحيوية'],
'nursing_called' => ['class' => 'primary', 'en' => 'Nursing Call', 'ar' => 'نداء التمريض'],
EOD;
$content = str_replace($search1, $replace1, $content);
$search2 = <<<'EOD'
SUM(CASE WHEN t.status = 'waiting_vitals' THEN 1 ELSE 0 END) AS vitals_waiting,
EOD;
$replace2 = <<<'EOD'
SUM(CASE WHEN t.status IN ('waiting_vitals', 'nursing_called') THEN 1 ELSE 0 END) AS vitals_waiting,
EOD;
$content = str_replace($search2, $replace2, $content);
$search3 = <<<'EOD'
'waiting_vitals' => (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE() AND status = 'waiting_vitals'")->fetchColumn(),
EOD;
$replace3 = <<<'EOD'
'waiting_vitals' => (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE() AND status IN ('waiting_vitals', 'nursing_called')")->fetchColumn(),
EOD;
$content = str_replace($search3, $replace3, $content);
$search4 = <<<'EOD'
function qh_call_message(array $ticket): array
{
$ticketNumber = $ticket['ticket_number'] ?? '---';
$doctorNameEn = $ticket['doctor_name_en'] ?? 'Doctor';
EOD;
$replace4 = <<<'EOD'
function qh_call_message(array $ticket): array
{
$ticketNumber = $ticket['ticket_number'] ?? '---';
if (("ticket['status']" ?? '') === 'nursing_called') {
return [
'en' => sprintf('Ticket %s, please proceed to Nursing Station.', $ticketNumber),
'ar' => sprintf('رقم التذكرة %s، يرجى التوجه إلى محطة التمريض.', $ticketNumber),
];
}
$doctorNameEn = $ticket['doctor_name_en'] ?? 'Doctor';
EOD;
$content = str_replace($search4, $replace4, $content);
$searchHandler = <<<'EOD'
$ticketId = (int) ($_POST['ticket_id'] ?? 0);
$vitalsNotes = trim((string) ($_POST['vitals_notes'] ?? ''));
if ($ticketId <= 0 || $vitalsNotes === '') {
throw new InvalidArgumentException(qh_t('Please add a short vitals note before sending the patient forward.', 'يرجى إضافة ملاحظة قصيرة للعلامات الحيوية قبل إرسال المريض.'));
}
$stmt = db()->prepare(
"UPDATE hospital_queue_records
SET vitals_notes = :vitals_notes,
status = 'ready_for_doctor',
display_note = 'Vitals completed. Wait for doctor call.'
WHERE item_type = 'ticket' AND id = :ticket_id AND status = 'waiting_vitals'"
);
$stmt->execute([
'vitals_notes' => $vitalsNotes,
'ticket_id' => $ticketId,
]);
qh_set_flash('success', qh_t('Vitals captured and patient moved to the doctor queue.', 'تم حفظ العلامات الحيوية ونقل المريض إلى طابور الطبيب.'));
EOD;
$replaceHandler = <<<'EOD'
$ticketId = (int) ($_POST['ticket_id'] ?? 0);
$action = trim((string) ($_POST['action'] ?? 'send'));
$ticket = qh_fetch_ticket($ticketId);
if (!$ticket) throw new InvalidArgumentException(qh_t('Invalid ticket.', 'تذكرة غير صالحة.'));
if ($action === 'call_ticket') {
$stmt = db()->prepare(
"UPDATE hospital_queue_records
SET status = 'nursing_called', called_at = NOW(), display_note = :display_note
WHERE item_type = 'ticket' AND id = :ticket_id"
);
$stmt->execute([
'display_note' => sprintf('Ticket %s, proceed to Nursing Station.', $ticket['ticket_number']),
'ticket_id' => $ticketId
]);
qh_set_flash('success', qh_t('Patient call was sent to the public display.', 'تم إرسال نداء المريض إلى الشاشة العامة.'));
} else {
$vitalsNotes = trim((string) ($_POST['vitals_notes'] ?? ''));
if ($vitalsNotes === '') throw new InvalidArgumentException(qh_t('Please add a short vitals note before sending the patient forward.', 'يرجى إضافة ملاحظة قصيرة للعلامات الحيوية قبل إرسال المريض.'));
$stmt = db()->prepare(
"UPDATE hospital_queue_records
SET vitals_notes = :vitals_notes,
status = 'ready_for_doctor',
display_note = 'Vitals completed. Wait for doctor call.'
WHERE item_type = 'ticket' AND id = :ticket_id AND status IN ('waiting_vitals', 'nursing_called')"
);
$stmt->execute([
'vitals_notes' => $vitalsNotes,
'ticket_id' => $ticketId,
]);
qh_set_flash('success', qh_t('Vitals captured and patient moved to the doctor queue.', 'تم حفظ العلامات الحيوية ونقل المريض إلى طابور الطبيب.'));
}
EOD;
$content = str_replace($searchHandler, $replaceHandler, $content);
file_put_contents('queue_bootstrap.php', $content);
echo "SUCCESS!\n";
?>

View File

@ -851,7 +851,7 @@ function qh_fetch_tickets(array $statuses = [], ?int $doctorId = null, ?int $lim
function qh_queue_overview(): array
{
$sql = "SELECT c.id, c.name_en, c.name_ar, c.code,
SUM(CASE WHEN t.status = 'waiting_vitals' THEN 1 ELSE 0 END) AS vitals_waiting,
SUM(CASE WHEN t.status IN ('waiting_vitals', 'nursing_called') THEN 1 ELSE 0 END) AS vitals_waiting,
SUM(CASE WHEN t.status = 'ready_for_doctor' THEN 1 ELSE 0 END) AS doctor_waiting,
SUM(CASE WHEN t.status IN ('called', 'in_progress') THEN 1 ELSE 0 END) AS active_calls,
COUNT(t.id) AS total_today
@ -872,7 +872,7 @@ function qh_dashboard_stats(): array
$pdo = db();
return [
'issued_today' => (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE()")->fetchColumn(),
'waiting_vitals' => (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE() AND status = 'waiting_vitals'")->fetchColumn(),
'waiting_vitals' => (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE() AND status IN ('waiting_vitals', 'nursing_called')")->fetchColumn(),
'ready_for_doctor' => (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE() AND status = 'ready_for_doctor'")->fetchColumn(),
'active_rooms' => (int) $pdo->query("SELECT COUNT(DISTINCT doctor_id) FROM hospital_queue_records WHERE item_type = 'ticket' AND DATE(created_at) = CURDATE() AND status IN ('called', 'in_progress') AND doctor_id IS NOT NULL")->fetchColumn(),
];
@ -950,6 +950,7 @@ function qh_status_meta(string $status): array
{
$map = [
'waiting_vitals' => ['class' => 'warning', 'en' => 'Waiting for vitals', 'ar' => 'بانتظار العلامات الحيوية'],
'nursing_called' => ['class' => 'primary', 'en' => 'Nursing Call', 'ar' => 'نداء التمريض'],
'ready_for_doctor' => ['class' => 'info', 'en' => 'Ready for doctor', 'ar' => 'جاهز للطبيب'],
'called' => ['class' => 'primary', 'en' => 'Called', 'ar' => 'تم النداء'],
'in_progress' => ['class' => 'secondary', 'en' => 'In consultation', 'ar' => 'داخل العيادة'],
@ -971,6 +972,14 @@ function qh_status_badge(string $status): string
function qh_call_message(array $ticket): array
{
$ticketNumber = $ticket['ticket_number'] ?? '---';
if (("ticket['status']" ?? '') === 'nursing_called') {
return [
'en' => sprintf('Ticket %s, please proceed to Nursing Station.', $ticketNumber),
'ar' => sprintf('رقم التذكرة %s، يرجى التوجه إلى محطة التمريض.', $ticketNumber),
];
}
$doctorNameEn = $ticket['doctor_name_en'] ?? 'Doctor';
$doctorNameAr = $ticket['doctor_name_ar'] ?? 'الطبيب';
$room = $ticket['doctor_room'] ?? '--';
@ -1324,23 +1333,39 @@ function qh_nursing_handle_request(): void
try {
$ticketId = (int) ($_POST['ticket_id'] ?? 0);
$vitalsNotes = trim((string) ($_POST['vitals_notes'] ?? ''));
if ($ticketId <= 0 || $vitalsNotes === '') {
throw new InvalidArgumentException(qh_t('Please add a short vitals note before sending the patient forward.', 'يرجى إضافة ملاحظة قصيرة للعلامات الحيوية قبل إرسال المريض.'));
}
$action = trim((string) ($_POST['action'] ?? 'send'));
$ticket = qh_fetch_ticket($ticketId);
if (!$ticket) throw new InvalidArgumentException(qh_t('Invalid ticket.', 'تذكرة غير صالحة.'));
$stmt = db()->prepare(
"UPDATE hospital_queue_records
SET vitals_notes = :vitals_notes,
status = 'ready_for_doctor',
display_note = 'Vitals completed. Wait for doctor call.'
WHERE item_type = 'ticket' AND id = :ticket_id AND status = 'waiting_vitals'"
);
$stmt->execute([
'vitals_notes' => $vitalsNotes,
'ticket_id' => $ticketId,
]);
qh_set_flash('success', qh_t('Vitals captured and patient moved to the doctor queue.', 'تم حفظ العلامات الحيوية ونقل المريض إلى طابور الطبيب.'));
if ($action === 'call_ticket') {
$stmt = db()->prepare(
"UPDATE hospital_queue_records
SET status = 'nursing_called', called_at = NOW(), display_note = :display_note
WHERE item_type = 'ticket' AND id = :ticket_id"
);
$stmt->execute([
'display_note' => sprintf('Ticket %s, proceed to Nursing Station.', $ticket['ticket_number']),
'ticket_id' => $ticketId
]);
qh_set_flash('success', qh_t('Patient call was sent to the public display.', 'تم إرسال نداء المريض إلى الشاشة العامة.'));
} else {
$vitalsNotes = trim((string) ($_POST['vitals_notes'] ?? ''));
if ($vitalsNotes === '') throw new InvalidArgumentException(qh_t('Please add a short vitals note before sending the patient forward.', 'يرجى إضافة ملاحظة قصيرة للعلامات الحيوية قبل إرسال المريض.'));
$stmt = db()->prepare(
"UPDATE hospital_queue_records
SET vitals_notes = :vitals_notes,
status = 'ready_for_doctor',
display_note = 'Vitals completed. Wait for doctor call.'
WHERE item_type = 'ticket' AND id = :ticket_id AND status IN ('waiting_vitals', 'nursing_called')"
);
$stmt->execute([
'vitals_notes' => $vitalsNotes,
'ticket_id' => $ticketId,
]);
qh_set_flash('success', qh_t('Vitals captured and patient moved to the doctor queue.', 'تم حفظ العلامات الحيوية ونقل المريض إلى طابور الطبيب.'));
}
} catch (Throwable $exception) {
qh_set_flash('danger', $exception->getMessage());
}