install file
This commit is contained in:
parent
e2985ac197
commit
a2f276f05e
@ -1309,5 +1309,5 @@ html[dir="rtl"] .news-ticker-item::after {
|
||||
}
|
||||
|
||||
body {
|
||||
padding-bottom: 3.5rem;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
20
display.php
20
display.php
@ -32,9 +32,16 @@ qh_page_start(
|
||||
qh_t('Public queue display.', 'شاشة طوابير عامة.')
|
||||
);
|
||||
?>
|
||||
<div class="container-fluid px-3 px-lg-4 py-3" data-auto-refresh="20">
|
||||
<style>
|
||||
/* Remove top spacing from the shell wrapper */
|
||||
main.app-shell {
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
</style>
|
||||
<div class="container-fluid px-0 px-lg-0 py-0 m-0" data-auto-refresh="20" style="min-height: 100vh; display: flex; flex-direction: column; ">
|
||||
<!-- Top Header for Display Board -->
|
||||
<header class="d-flex justify-content-between align-items-center mb-4 bg-white p-3 rounded shadow-sm border-0">
|
||||
<header class="d-flex justify-content-between align-items-center bg-white py-2 px-3 shadow-sm border-0">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<?php if ($logoUrl = qh_hospital_logo_url()): ?>
|
||||
<img src="<?= qh_h($logoUrl) ?>" alt="<?= qh_h(qh_hospital_name()) ?>" style="height: 50px;">
|
||||
@ -56,10 +63,11 @@ qh_page_start(
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="row g-4 h-100">
|
||||
<?php $pb = !empty($activeNews) ? "padding-bottom: 4rem !important;" : "padding-bottom: 1.5rem !important;"; ?>
|
||||
<div class="row g-4 m-0 mt-2 px-3 px-lg-4 pt-0 flex-grow-1" style="<?= $pb ?>">
|
||||
<div class="col-xl-8 col-lg-7 d-flex flex-column gap-4">
|
||||
<div class="card shadow-sm border-0 flex-grow-1">
|
||||
<div class="card-header bg-white border-bottom py-3 d-flex justify-content-between align-items-center">
|
||||
<div class="card-header bg-white border-bottom py-2 d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h2 class="h4 mb-0 text-gray-800 fw-bold"><?= qh_h(qh_t('Now Serving', 'يتم الآن النداء')) ?></h2>
|
||||
</div>
|
||||
@ -98,7 +106,7 @@ qh_page_start(
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-header bg-white border-bottom py-3">
|
||||
<div class="card-header bg-white border-bottom py-2">
|
||||
<h5 class="mb-0 font-weight-bold text-dark"><?= qh_h(qh_t('Queue by Clinic', 'الإنتظار حسب العيادة')) ?></h5>
|
||||
</div>
|
||||
<div class="card-body p-4 bg-light">
|
||||
@ -171,7 +179,7 @@ qh_page_start(
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="card shadow-sm border-0 h-100 bg-primary text-white">
|
||||
<div class="card-header border-bottom border-light border-opacity-25 py-3 bg-transparent d-flex justify-content-between align-items-center">
|
||||
<div class="card-header border-bottom border-light border-opacity-25 py-2 bg-transparent d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0 font-weight-bold text-white"><i class="bi bi-info-circle me-2"></i><?= qh_h(qh_t('Information', 'معلومات')) ?></h5>
|
||||
<span class="badge bg-white text-primary rounded-pill small"><?= qh_h(qh_t('Notices', 'تنبيهات')) ?></span>
|
||||
</div>
|
||||
|
||||
16
doctor.php
16
doctor.php
@ -85,7 +85,7 @@ qh_page_start(
|
||||
<td class="py-3 fw-semibold text-dark"><?= qh_h($ticket['patient_name']) ?></td>
|
||||
<td class="py-3"><?= qh_status_badge($ticket['status']) ?></td>
|
||||
<td class="text-end px-4 py-3">
|
||||
<form method="post" class="d-inline-flex gap-2 flex-wrap justify-content-end">
|
||||
<form method="post" class="d-inline-flex gap-2 flex-wrap justify-content-end align-items-center">
|
||||
<input type="hidden" name="ticket_id" value="<?= qh_h((string) $ticket['id']) ?>"> <input type="hidden" name="doctor_id" value="<?= qh_h((string) $selectedDoctorId) ?>">
|
||||
|
||||
<?php if ($ticket['status'] === 'ready_for_doctor'): ?>
|
||||
@ -97,6 +97,18 @@ qh_page_start(
|
||||
<button class="btn btn-sm btn-outline-danger shadow-sm bg-white" type="submit" name="action" value="mark_no_show"><?= qh_h(qh_t('Not Show', 'غائب')) ?></button>
|
||||
|
||||
<button class="btn btn-sm btn-success shadow-sm" type="submit" name="action" value="complete_ticket"><?= qh_h(qh_t('Served', 'تمت الخدمة')) ?></button>
|
||||
|
||||
<div class="input-group input-group-sm ms-lg-2 mt-2 mt-lg-0" style="max-width: 180px;">
|
||||
<select name="refer_to_doctor_id" class="form-select border-secondary text-secondary">
|
||||
<option value=""><?= qh_h(qh_t('Refer to...', 'تحويل إلى...')) ?></option>
|
||||
<?php foreach ($doctors as $d): if ($d['id'] == $selectedDoctorId) continue; ?>
|
||||
<option value="<?= qh_h((string) $d['id']) ?>"><?= qh_h(qh_name($d)) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<button class="btn btn-outline-secondary bg-white" type="submit" name="action" value="refer_ticket" title="<?= qh_h(qh_t('Refer Patient', 'تحويل المريض')) ?>">
|
||||
<i class="bi bi-arrow-right-circle"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@ -110,4 +122,4 @@ qh_page_start(
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php qh_page_end(); ?>
|
||||
<?php qh_page_end(); ?>
|
||||
|
||||
214
install.php
Normal file
214
install.php
Normal file
@ -0,0 +1,214 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
if (file_exists(__DIR__ . '/.installed')) {
|
||||
die('Installation already completed. To reinstall, delete the .installed file.');
|
||||
}
|
||||
|
||||
$step = isset($_GET['step']) ? (int)$_GET['step'] : 1;
|
||||
$error = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$step = isset($_POST['step']) ? (int)$_POST['step'] : $step;
|
||||
if ($step === 3) {
|
||||
$dbHost = $_POST['db_host'] ?? '';
|
||||
$dbName = $_POST['db_name'] ?? '';
|
||||
$dbUser = $_POST['db_user'] ?? '';
|
||||
$dbPass = $_POST['db_pass'] ?? '';
|
||||
|
||||
try {
|
||||
$pdo = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4", $dbUser, $dbPass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
||||
|
||||
|
||||
// Rewrite db/config.php
|
||||
$configContent = "<?php\n" .
|
||||
"define('DB_HOST', '$dbHost');\n" .
|
||||
"define('DB_NAME', '$dbName');\n" .
|
||||
"define('DB_USER', '$dbUser');\n" .
|
||||
"define('DB_PASS', '$dbPass');\n\n" .
|
||||
"function db() {\n" .
|
||||
" static \$pdo;\n" .
|
||||
" if (!\$pdo) {\n" .
|
||||
" \$pdo = new PDO('mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=utf8mb4', DB_USER, DB_PASS, [
|
||||
" .
|
||||
" PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,\n" .
|
||||
" PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,\n" .
|
||||
" ]);\n" .
|
||||
" }\n" .
|
||||
" return \$pdo;\n" .
|
||||
"}\n";
|
||||
file_put_contents(__DIR__ . '/db/config.php', $configContent);
|
||||
header('Location: install.php?step=4');
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
$error = 'Database Connection Failed: ' . $e->getMessage();
|
||||
}
|
||||
} elseif ($step === 4) {
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
$username = $_POST['username'] ?? '';
|
||||
$password = $_POST['password'] ?? '';
|
||||
|
||||
if (empty($username) || empty($password)) {
|
||||
$error = 'Please provide both username and password.';
|
||||
} else {
|
||||
try {
|
||||
$pdo = db();
|
||||
$pdo->exec("CREATE TABLE IF NOT EXISTS users (
|
||||
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
|
||||
|
||||
$hash = password_hash($password, PASSWORD_DEFAULT);
|
||||
$stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (:username, :password) ON DUPLICATE KEY UPDATE password = :password");
|
||||
$stmt->execute(['username' => $username, 'password' => $hash]);
|
||||
|
||||
header('Location: install.php?step=5');
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
$error = 'Failed to create user: ' . $e->getMessage();
|
||||
}
|
||||
}
|
||||
} elseif ($step === 5) {
|
||||
file_put_contents(__DIR__ . '/.installed', date('Y-m-d H:i:s'));
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Installation</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body { background-color: #f8f9fa; }
|
||||
.install-card { border: none; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.05); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8 col-lg-6">
|
||||
<div class="card install-card">
|
||||
<div class="card-header bg-white border-bottom-0 pt-4 pb-0">
|
||||
<h3 class="card-title text-center text-primary mb-0 fw-bold">System Installation</h3>
|
||||
<div class="text-center text-muted mt-2">Step <?= $step ?> of 5</div>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($step === 1): ?>
|
||||
<h4 class="mb-3 text-dark">Welcome</h4>
|
||||
<p class="text-secondary">Welcome to the Hospital Queue Center installation wizard. This will set up your environment, configure the database variables, and create your super admin account so you are ready to go.</p>
|
||||
<div class="text-end mt-4">
|
||||
<a href="install.php?step=2" class="btn btn-primary px-4 py-2 rounded-pill">Next: Environment Check</a>
|
||||
</div>
|
||||
|
||||
<?php elseif ($step === 2): ?>
|
||||
<h4 class="mb-3 text-dark">Environment Check</h4>
|
||||
<ul class="list-group mb-4 rounded-3">
|
||||
<?php
|
||||
$phpOk = version_compare(PHP_VERSION, '8.0.0', '>=');
|
||||
$pdoOk = extension_loaded('pdo_mysql');
|
||||
$dbWritable = is_writable(__DIR__ . '/db') || is_writable(__DIR__ . '/db/config.php');
|
||||
?>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
PHP Version (>= 8.0)
|
||||
<span class="badge bg-<?= $phpOk ? 'success' : 'danger' ?> rounded-pill px-3 py-2"><?= PHP_VERSION ?></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
PDO MySQL Extension
|
||||
<span class="badge bg-<?= $pdoOk ? 'success' : 'danger' ?> rounded-pill px-3 py-2"><?= $pdoOk ? 'Yes' : 'No' ?></span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
DB Config Writable
|
||||
<span class="badge bg-<?= $dbWritable ? 'success' : 'danger' ?> rounded-pill px-3 py-2"><?= $dbWritable ? 'Yes' : 'No' ?></span>
|
||||
</li>
|
||||
</ul>
|
||||
<?php if ($phpOk && $pdoOk && $dbWritable): ?>
|
||||
<div class="text-end">
|
||||
<a href="install.php?step=3" class="btn btn-primary px-4 py-2 rounded-pill">Next: Database Variables</a>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-warning">Please fix the environment issues before proceeding.</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php elseif ($step === 3): ?>
|
||||
<h4 class="mb-3 text-dark">Database Variables</h4>
|
||||
<?php
|
||||
$dbHost = defined('DB_HOST') ? DB_HOST : '127.0.0.1';
|
||||
$dbName = defined('DB_NAME') ? DB_NAME : '';
|
||||
$dbUser = defined('DB_USER') ? DB_USER : '';
|
||||
$dbPass = defined('DB_PASS') ? DB_PASS : '';
|
||||
if (file_exists(__DIR__ . '/db/config.php')) {
|
||||
$content = file_get_contents(__DIR__ . '/db/config.php');
|
||||
if (preg_match("/define\('DB_HOST',\s*'([^']+)'\)/", $content, $m)) $dbHost = $m[1];
|
||||
if (preg_match("/define\('DB_NAME',\s*'([^']+)'\)/", $content, $m)) $dbName = $m[1];
|
||||
if (preg_match("/define\('DB_USER',\s*'([^']+)'\)/", $content, $m)) $dbUser = $m[1];
|
||||
if (preg_match("/define\('DB_PASS',\s*'([^']+)'\)/", $content, $m)) $dbPass = $m[1];
|
||||
}
|
||||
?>
|
||||
<form method="POST" action="install.php">
|
||||
<input type="hidden" name="step" value="3">
|
||||
<div class="mb-3">
|
||||
<label class="form-label text-secondary fw-semibold">Database Host</label>
|
||||
<input type="text" name="db_host" class="form-control form-control-lg bg-light" value="<?= htmlspecialchars($dbHost) ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label text-secondary fw-semibold">Database Name</label>
|
||||
<input type="text" name="db_name" class="form-control form-control-lg bg-light" value="<?= htmlspecialchars($dbName) ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label text-secondary fw-semibold">Database User</label>
|
||||
<input type="text" name="db_user" class="form-control form-control-lg bg-light" value="<?= htmlspecialchars($dbUser) ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label text-secondary fw-semibold">Database Password</label>
|
||||
<input type="password" name="db_pass" class="form-control form-control-lg bg-light" value="<?= htmlspecialchars($dbPass) ?>" required>
|
||||
</div>
|
||||
<div class="text-end mt-4">
|
||||
<button type="submit" class="btn btn-primary px-4 py-2 rounded-pill">Save & Next</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php elseif ($step === 4): ?>
|
||||
<h4 class="mb-3 text-dark">Super Admin Credentials</h4>
|
||||
<form method="POST" action="install.php">
|
||||
<input type="hidden" name="step" value="4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label text-secondary fw-semibold">Admin Username</label>
|
||||
<input type="text" name="username" class="form-control form-control-lg bg-light" value="admin" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label text-secondary fw-semibold">Admin Password</label>
|
||||
<input type="password" name="password" class="form-control form-control-lg bg-light" required>
|
||||
</div>
|
||||
<div class="text-end mt-4">
|
||||
<button type="submit" class="btn btn-primary px-4 py-2 rounded-pill">Create Admin & Next</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php elseif ($step === 5): ?>
|
||||
<h4 class="mb-3 text-success fw-bold">Ready to go!</h4>
|
||||
<p class="text-secondary mb-4">The installation has been successfully completed. Your database is set up and the super admin account is ready.</p>
|
||||
<form method="POST" action="install.php">
|
||||
<input type="hidden" name="step" value="5">
|
||||
<button type="submit" class="btn btn-success w-100 py-3 rounded-pill fw-bold" style="font-size: 1.1rem;">Finish & Go to Login</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
99
login.php
Normal file
99
login.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/queue_bootstrap.php';
|
||||
|
||||
if (!empty($_SESSION['user_id'])) {
|
||||
qh_redirect('index.php');
|
||||
}
|
||||
|
||||
$error = '';
|
||||
|
||||
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
|
||||
$username = trim((string) ($_POST['username'] ?? ''));
|
||||
$password = (string) ($_POST['password'] ?? '');
|
||||
|
||||
if ($username === '' || $password === '') {
|
||||
$error = qh_t('Please enter your username and password.', 'يرجى إدخال اسم المستخدم وكلمة المرور.');
|
||||
} else {
|
||||
try {
|
||||
$stmt = db()->prepare("SELECT id, password FROM users WHERE username = :username LIMIT 1");
|
||||
$stmt->execute(['username' => $username]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if ($user && password_verify($password, $user['password'])) {
|
||||
$_SESSION['user_id'] = (int) $user['id'];
|
||||
$_SESSION['username'] = $username;
|
||||
qh_redirect('index.php');
|
||||
} else {
|
||||
$error = qh_t('Invalid username or password.', 'اسم المستخدم أو كلمة المرور غير صحيحة.');
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
$error = qh_t('Login failed due to a system error.', 'فشل تسجيل الدخول بسبب خطأ في النظام.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qh_page_start(
|
||||
'login',
|
||||
qh_t('Sign In', 'تسجيل الدخول'),
|
||||
qh_t('Sign in to the hospital queue system.', 'تسجيل الدخول إلى نظام طوابير المستشفى.')
|
||||
);
|
||||
?>
|
||||
<style>
|
||||
.login-wrapper {
|
||||
min-height: calc(100vh - 200px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.login-card {
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 30px rgba(0,0,0,0.08);
|
||||
overflow: hidden;
|
||||
}
|
||||
.login-header {
|
||||
background: var(--accent, #0F8B8D);
|
||||
color: white;
|
||||
padding: 2rem 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
.login-body {
|
||||
padding: 2rem;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid container-xxl px-3 px-lg-4">
|
||||
<div class="login-wrapper">
|
||||
<div class="card login-card">
|
||||
<div class="login-header">
|
||||
<h3 class="mb-0 fw-bold"><?= qh_h(qh_hospital_name()) ?></h3>
|
||||
<p class="text-white-50 mt-2 mb-0"><?= qh_h(qh_t('Secure Access', 'الوصول الآمن')) ?></p>
|
||||
</div>
|
||||
<div class="login-body">
|
||||
<?php if ($error !== ''): ?>
|
||||
<div class="alert alert-danger mb-4"><?= qh_h($error) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="POST" action="<?= qh_h(qh_url('login.php')) ?>">
|
||||
<div class="mb-4">
|
||||
<label class="form-label text-secondary fw-semibold"><?= qh_h(qh_t('Username', 'اسم المستخدم')) ?></label>
|
||||
<input type="text" name="username" class="form-control form-control-lg bg-light" required autofocus>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label class="form-label text-secondary fw-semibold"><?= qh_h(qh_t('Password', 'كلمة المرور')) ?></label>
|
||||
<input type="password" name="password" class="form-control form-control-lg bg-light" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100 py-3 rounded-pill fw-bold" style="font-size: 1.1rem;">
|
||||
<?= qh_h(qh_t('Sign In', 'تسجيل الدخول')) ?>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php qh_page_end(); ?>
|
||||
12
logout.php
Normal file
12
logout.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$_SESSION = [];
|
||||
session_destroy();
|
||||
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
@ -4,6 +4,19 @@ declare(strict_types=1);
|
||||
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
session_start();
|
||||
}
|
||||
$publicPages = ["login.php", "logout.php", "install.php", "display.php", "ticket.php"];
|
||||
$currentPage = basename((string) ($_SERVER["PHP_SELF"] ?? "index.php"));
|
||||
if (!file_exists(__DIR__ . "/.installed") && $currentPage !== "install.php") {
|
||||
header("Location: install.php");
|
||||
exit;
|
||||
}
|
||||
if (file_exists(__DIR__ . "/.installed") && !in_array($currentPage, $publicPages, true)) {
|
||||
if (empty($_SESSION["user_id"])) {
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
|
||||
@ -639,6 +652,10 @@ function qh_render_nav(string $activePage): void
|
||||
$activeClass = $key === $activePage ? ' active' : '';
|
||||
echo ' <li class="nav-item"><a class="nav-link' . $activeClass . '" href="' . qh_h($link['href']) . '">' . qh_h($link['label']) . '</a></li>';
|
||||
}
|
||||
if (!empty($_SESSION["user_id"])) {
|
||||
echo ' <li class="nav-item"><a class="nav-link text-danger fw-semibold" href="' . qh_h(qh_url("logout.php")) . '"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="me-1"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>' . qh_h(qh_t("Logout", "تسجيل الخروج")) . '</a></li>';
|
||||
}
|
||||
|
||||
echo ' </ul>';
|
||||
echo ' <div class="lang-switcher ms-lg-3 mt-3 mt-lg-0">';
|
||||
foreach (['en', 'ar'] as $lang) {
|
||||
@ -754,7 +771,7 @@ function qh_fetch_tickets(array $statuses = [], ?int $doctorId = null, ?int $lim
|
||||
FROM hospital_queue_records t
|
||||
LEFT JOIN hospital_queue_records c ON c.id = t.clinic_id AND c.item_type = 'clinic'
|
||||
LEFT JOIN hospital_queue_records d ON d.id = t.doctor_id AND d.item_type = 'doctor'
|
||||
WHERE t.item_type = 'ticket'";
|
||||
WHERE t.item_type = 'ticket' AND DATE(t.created_at) = CURDATE()";
|
||||
|
||||
$params = [];
|
||||
|
||||
@ -808,9 +825,9 @@ 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 status = 'waiting_vitals'")->fetchColumn(),
|
||||
'ready_for_doctor' => (int) $pdo->query("SELECT COUNT(*) FROM hospital_queue_records WHERE item_type = 'ticket' 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 status IN ('called', 'in_progress') AND doctor_id IS NOT NULL")->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(),
|
||||
'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(),
|
||||
];
|
||||
}
|
||||
|
||||
@ -858,6 +875,7 @@ function qh_generate_ticket_number(string $clinicCode): string
|
||||
"SELECT COUNT(*)
|
||||
FROM hospital_queue_records
|
||||
WHERE item_type = 'ticket'
|
||||
AND DATE(created_at) = CURDATE()
|
||||
AND ticket_number LIKE :prefix"
|
||||
);
|
||||
$stmt->execute(['prefix' => $prefix . '-%']);
|
||||
@ -1326,6 +1344,21 @@ function qh_doctor_handle_request(): void
|
||||
);
|
||||
$stmt->execute(['ticket_id' => $ticketId]);
|
||||
qh_set_flash('success', qh_t('Visit marked as completed.', 'تم إنهاء الزيارة.'));
|
||||
} elseif ($action === 'refer_ticket') {
|
||||
$referToDoctorId = (int) (
emote_POST['refer_to_doctor_id'] ?? 0);
|
||||
if ($referToDoctorId <= 0 || $referToDoctorId === $doctorId) {
|
||||
throw new InvalidArgumentException(qh_t('Please select a valid doctor to refer the patient to.', 'يرجى اختيار طبيب صالح لتحويل المريض إليه.'));
|
||||
}
|
||||
$stmt = db()->prepare(
|
||||
"UPDATE hospital_queue_records
|
||||
SET status = 'ready_for_doctor', doctor_id = :refer_to_doctor_id, display_note = 'Referred'
|
||||
WHERE item_type = 'ticket' AND id = :ticket_id"
|
||||
);
|
||||
$stmt->execute([
|
||||
'refer_to_doctor_id' => $referToDoctorId,
|
||||
'ticket_id' => $ticketId,
|
||||
]);
|
||||
qh_set_flash('success', qh_t('Patient referred successfully.', 'تم تحويل المريض بنجاح.'));
|
||||
} elseif ($action === 'mark_no_show') {
|
||||
$stmt = db()->prepare(
|
||||
"UPDATE hospital_queue_records
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user