add rooms for doctors

This commit is contained in:
Flatlogic Bot 2026-03-23 02:54:44 +00:00
parent fbacfd6e29
commit 620485b60a
9 changed files with 139 additions and 27 deletions

View File

@ -79,6 +79,7 @@ try {
d.name_$lang as doctor_name,
d.name_en as doctor_name_en,
d.name_ar as doctor_name_ar,
d.room_number,
dept.name_$lang as department_name,
dept.name_en as department_name_en,
dept.name_ar as department_name_ar

View File

@ -0,0 +1,8 @@
<?php
require_once 'db/config.php';
$db = db();
$stmt = $db->query("DESCRIBE employees");
$columns = $stmt->fetchAll(PDO::FETCH_COLUMN);
echo "Columns in employees table:\n";
print_r($columns);
?>

View File

@ -0,0 +1 @@
ALTER TABLE departments ADD COLUMN active BOOLEAN DEFAULT 1;

View File

@ -0,0 +1 @@
ALTER TABLE employees ADD COLUMN room_number VARCHAR(50) NULL AFTER email;

View File

@ -151,9 +151,10 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST')
$name_en = $_POST['name_en'] ?? '';
$name_ar = $_POST['name_ar'] ?? '';
$show_in_queue = isset($_POST['show_in_queue']) ? 1 : 0;
$active = isset($_POST['active']) ? 1 : 0;
if ($name_en && $name_ar) {
$stmt = $db->prepare("INSERT INTO departments (name_en, name_ar, show_in_queue) VALUES (?, ?, ?)");
$stmt->execute([$name_en, $name_ar, $show_in_queue]);
$stmt = $db->prepare("INSERT INTO departments (name_en, name_ar, show_in_queue, active) VALUES (?, ?, ?, ?)");
$stmt->execute([$name_en, $name_ar, $show_in_queue, $active]);
$_SESSION['flash_message'] = __('add_department') . ' ' . __('successfully');
$redirect = true;
}
@ -162,9 +163,10 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST')
$name_en = $_POST['name_en'] ?? '';
$name_ar = $_POST['name_ar'] ?? '';
$show_in_queue = isset($_POST['show_in_queue']) ? 1 : 0;
$active = isset($_POST['active']) ? 1 : 0;
if ($id && $name_en && $name_ar) {
$stmt = $db->prepare("UPDATE departments SET name_en = ?, name_ar = ?, show_in_queue = ? WHERE id = ?");
$stmt->execute([$name_en, $name_ar, $show_in_queue, $id]);
$stmt = $db->prepare("UPDATE departments SET name_en = ?, name_ar = ?, show_in_queue = ?, active = ? WHERE id = ?");
$stmt->execute([$name_en, $name_ar, $show_in_queue, $active, $id]);
$_SESSION['flash_message'] = __('edit_department') . ' ' . __('successfully');
$redirect = true;
}
@ -427,12 +429,13 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST')
$dob = $_POST['dob'] ?: null;
$mobile = $_POST['mobile'] ?? '';
$email = $_POST['email'] ?? '';
$room_number = $_POST['room_number'] ?? '';
$dept_id = $_POST['department_id'] ?: null;
$position_id = $_POST['position_id'] ?: null;
if ($name_en && $name_ar) {
$stmt = $db->prepare("INSERT INTO employees (name_en, name_ar, dob, mobile, email, department_id, position_id) VALUES (?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$name_en, $name_ar, $dob, $mobile, $email, $dept_id, $position_id]);
$stmt = $db->prepare("INSERT INTO employees (name_en, name_ar, dob, mobile, email, room_number, department_id, position_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$name_en, $name_ar, $dob, $mobile, $email, $room_number, $dept_id, $position_id]);
$_SESSION['flash_message'] = __('add_employee') . ' ' . __('successfully');
$redirect = true;
}
@ -443,12 +446,13 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST')
$dob = $_POST['dob'] ?: null;
$mobile = $_POST['mobile'] ?? '';
$email = $_POST['email'] ?? '';
$room_number = $_POST['room_number'] ?? '';
$dept_id = $_POST['department_id'] ?: null;
$position_id = $_POST['position_id'] ?: null;
if ($id && $name_en && $name_ar) {
$stmt = $db->prepare("UPDATE employees SET name_en = ?, name_ar = ?, dob = ?, mobile = ?, email = ?, department_id = ?, position_id = ? WHERE id = ?");
$stmt->execute([$name_en, $name_ar, $dob, $mobile, $email, $dept_id, $position_id, $id]);
$stmt = $db->prepare("UPDATE employees SET name_en = ?, name_ar = ?, dob = ?, mobile = ?, email = ?, room_number = ?, department_id = ?, position_id = ? WHERE id = ?");
$stmt->execute([$name_en, $name_ar, $dob, $mobile, $email, $room_number, $dept_id, $position_id, $id]);
$_SESSION['flash_message'] = __('edit_employee') . ' ' . __('successfully');
$redirect = true;
}

View File

@ -32,7 +32,7 @@ if (isset($_GET['ajax_search'])) {
if (empty($departments)):
?>
<tr>
<td colspan="5" class="text-center py-5 text-muted">
<td colspan="6" class="text-center py-5 text-muted">
<i class="bi bi-diagram-3 display-4 d-block mb-3"></i>
<?php echo __('no_departments_found'); ?>
</td>
@ -44,12 +44,19 @@ if (isset($_GET['ajax_search'])) {
<td class="fw-semibold text-dark"><?php echo htmlspecialchars($dept['name_en']); ?></td>
<td class="text-secondary"><?php echo htmlspecialchars($dept['name_ar']); ?></td>
<td class="text-center">
<?php if ($dept['show_in_queue']): ?>
<?php if ($dept['active']): ?>
<span class="badge bg-success-subtle text-success rounded-pill px-3"><?php echo __('active'); ?></span>
<?php else: ?>
<span class="badge bg-secondary-subtle text-secondary rounded-pill px-3"><?php echo __('inactive'); ?></span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if ($dept['show_in_queue']): ?>
<span class="badge bg-info-subtle text-info rounded-pill px-3"><?php echo __('yes'); ?></span>
<?php else: ?>
<span class="badge bg-secondary-subtle text-secondary rounded-pill px-3"><?php echo __('no'); ?></span>
<?php endif; ?>
</td>
<td class="text-end px-4">
<div class="btn-group shadow-sm border rounded bg-white">
<button class="btn btn-link text-primary py-1 px-2 border-end"
@ -157,6 +164,7 @@ if (isset($_GET['ajax_search'])) {
<th class="px-4 py-3">#</th>
<th class="py-3"><?php echo __('name_en'); ?></th>
<th class="py-3"><?php echo __('name_ar'); ?></th>
<th class="py-3 text-center"><?php echo __('active'); ?></th>
<th class="py-3 text-center"><?php echo __('show_in_queue'); ?></th>
<th class="py-3 text-end px-4"><?php echo __('actions'); ?></th>
</tr>
@ -164,7 +172,7 @@ if (isset($_GET['ajax_search'])) {
<tbody id="departmentsTableBody">
<?php if (empty($departments)): ?>
<tr>
<td colspan="5" class="text-center py-5 text-muted">
<td colspan="6" class="text-center py-5 text-muted">
<i class="bi bi-diagram-3 display-4 d-block mb-3"></i>
<?php echo __('no_departments_found'); ?>
</td>
@ -176,12 +184,19 @@ if (isset($_GET['ajax_search'])) {
<td class="fw-semibold text-dark"><?php echo htmlspecialchars($dept['name_en']); ?></td>
<td class="text-secondary"><?php echo htmlspecialchars($dept['name_ar']); ?></td>
<td class="text-center">
<?php if ($dept['show_in_queue']): ?>
<?php if ($dept['active']): ?>
<span class="badge bg-success-subtle text-success rounded-pill px-3"><?php echo __('active'); ?></span>
<?php else: ?>
<span class="badge bg-secondary-subtle text-secondary rounded-pill px-3"><?php echo __('inactive'); ?></span>
<?php endif; ?>
</td>
<td class="text-center">
<?php if ($dept['show_in_queue']): ?>
<span class="badge bg-info-subtle text-info rounded-pill px-3"><?php echo __('yes'); ?></span>
<?php else: ?>
<span class="badge bg-secondary-subtle text-secondary rounded-pill px-3"><?php echo __('no'); ?></span>
<?php endif; ?>
</td>
<td class="text-end px-4">
<div class="btn-group shadow-sm border rounded bg-white">
<button class="btn btn-link text-primary py-1 px-2 border-end"
@ -285,6 +300,10 @@ if (isset($_GET['ajax_search'])) {
</button>
</div>
</div>
<div class="mb-3 form-check form-switch">
<input type="checkbox" class="form-check-input" name="active" id="deptActive" value="1" checked>
<label class="form-check-label" for="deptActive"><?php echo __('active'); ?></label>
</div>
<div class="mb-3 form-check form-switch">
<input type="checkbox" class="form-check-input" name="show_in_queue" id="deptShowInQueue" value="1" checked>
<label class="form-check-label" for="deptShowInQueue"><?php echo __('show_in_queue'); ?></label>
@ -394,6 +413,7 @@ function resetDepartmentModal() {
document.getElementById('deptNameEn').value = '';
document.getElementById('deptNameAr').value = '';
document.getElementById('deptActive').checked = true;
document.getElementById('deptShowInQueue').checked = true;
}
@ -404,6 +424,7 @@ function showEditDepartmentModal(dept) {
document.getElementById('deptNameEn').value = dept.name_en;
document.getElementById('deptNameAr').value = dept.name_ar;
document.getElementById('deptActive').checked = (dept.active == 1);
document.getElementById('deptShowInQueue').checked = (dept.show_in_queue == 1);
var modal = new bootstrap.Modal(document.getElementById('addDepartmentModal'));

View File

@ -79,6 +79,7 @@ if (isset($_GET['ajax_search'])) {
<td>
<div class="small text-secondary"><i class="bi bi-telephone me-1"></i> <?php echo htmlspecialchars($emp['mobile'] ?: '-'); ?></div>
<div class="small text-secondary"><i class="bi bi-envelope me-1"></i> <?php echo htmlspecialchars($emp['email'] ?: '-'); ?></div>
<div class="small text-secondary"><i class="bi bi-door-open me-1"></i> <?php echo __('room_number'); ?>: <?php echo htmlspecialchars($emp['room_number'] ?: '-'); ?></div>
</td>
<td class="text-end px-4">
<div class="btn-group shadow-sm border rounded bg-white">
@ -226,6 +227,7 @@ if (isset($_GET['ajax_search'])) {
<td>
<div class="small text-secondary"><i class="bi bi-telephone me-1"></i> <?php echo htmlspecialchars($emp['mobile'] ?: '-'); ?></div>
<div class="small text-secondary"><i class="bi bi-envelope me-1"></i> <?php echo htmlspecialchars($emp['email'] ?: '-'); ?></div>
<div class="small text-secondary"><i class="bi bi-door-open me-1"></i> <?php echo __('room_number'); ?>: <?php echo htmlspecialchars($emp['room_number'] ?: '-'); ?></div>
</td>
<td class="text-end px-4">
<div class="btn-group shadow-sm border rounded bg-white">
@ -322,6 +324,12 @@ if (isset($_GET['ajax_search'])) {
<input type="text" class="form-control" name="name_ar" id="empNameAr" required>
</div>
<!-- Room Number moved to top -->
<div class="col-md-6">
<label class="form-label"><?php echo __('room_number') ?: 'Room Number'; ?></label>
<input type="text" class="form-control" name="room_number" id="empRoomNumber" placeholder="<?php echo __('room_number'); ?>">
</div>
<div class="col-md-6">
<label class="form-label"><?php echo __('email'); ?></label>
<input type="email" class="form-control" name="email" id="empEmail">
@ -487,6 +495,7 @@ function resetEmployeeModal() {
document.getElementById('empNameAr').value = '';
document.getElementById('empEmail').value = '';
document.getElementById('empMobile').value = '';
document.getElementById('empRoomNumber').value = '';
document.getElementById('empDob').value = '';
document.getElementById('empDeptId').value = '';
document.getElementById('empPosId').value = '';
@ -502,6 +511,7 @@ function showEditEmployeeModal(emp) {
document.getElementById('empNameAr').value = emp.name_ar;
document.getElementById('empEmail').value = emp.email;
document.getElementById('empMobile').value = emp.mobile;
document.getElementById('empRoomNumber').value = emp.room_number || '';
document.getElementById('empDob').value = emp.dob;
document.getElementById('empDeptId').value = emp.department_id;
document.getElementById('empPosId').value = emp.position_id;

View File

@ -439,7 +439,8 @@ $translations = array (
'smtp_test_failed' => 'SMTP Connection Failed',
'none' => 'None',
'ssl' => 'SSL',
'tls' => 'TLS'
'tls' => 'TLS',
'room_number' => 'Room Number'
),
'ar' =>
array (
@ -880,6 +881,7 @@ $translations = array (
'smtp_test_failed' => 'فشل الاتصال بخادم SMTP',
'none' => 'بدون',
'ssl' => 'SSL',
'tls' => 'TLS'
'tls' => 'TLS',
'room_number' => 'رقم الغرفة'
)
);

View File

@ -34,10 +34,18 @@ try {
.header {
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
color: white;
padding: 20px;
text-align: center;
padding: 15px 20px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
position: relative;
}
.header h1 {
margin: 0;
font-size: 1.8rem;
display: flex;
align-items: center;
gap: 10px;
}
.dept-card {
background: white;
@ -129,10 +137,12 @@ try {
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.clock-container {
display: flex;
align-items: center;
gap: 15px;
}
.clock {
position: absolute;
top: 20px;
right: 20px;
font-size: 1.5rem;
font-weight: bold;
color: white;
@ -164,11 +174,16 @@ try {
}
</style>
</head>
<body>
<body onclick="enableAudioContext()">
<div class="header">
<h1 class="m-0"><i class="bi bi-hospital"></i> Hospital Queue Status / حالة انتظار المستشفى</h1>
<div class="clock" id="clock">00:00:00</div>
<div class="clock-container">
<button id="soundToggle" class="btn btn-outline-light btn-sm" onclick="toggleSound(event)">
<i class="bi bi-volume-up-fill" id="soundIcon"></i> Sound: ON
</button>
<div class="clock" id="clock">00:00:00</div>
</div>
</div>
<div class="container-fluid p-4">
@ -188,6 +203,7 @@ try {
let audioEnabled = true;
const announcedIds = new Set();
let isFirstRun = true;
let audioContextResumed = false;
function updateClock() {
const now = new Date();
@ -196,6 +212,44 @@ try {
setInterval(updateClock, 1000);
updateClock();
function enableAudioContext() {
if (!audioContextResumed) {
// Some browsers require a user interaction to allow speech synthesis
if (window.speechSynthesis) {
window.speechSynthesis.resume();
}
audioContextResumed = true;
}
}
function toggleSound(e) {
if (e) e.stopPropagation(); // Prevent body onclick
audioEnabled = !audioEnabled;
const icon = document.getElementById('soundIcon');
const btn = document.getElementById('soundToggle');
if (audioEnabled) {
icon.className = 'bi bi-volume-up-fill';
btn.innerHTML = '<i class="bi bi-volume-up-fill" id="soundIcon"></i> Sound: ON';
btn.classList.remove('btn-outline-danger');
btn.classList.add('btn-outline-light');
enableAudioContext();
// Test speak
if (window.speechSynthesis) {
const u = new SpeechSynthesisUtterance("Sound enabled");
window.speechSynthesis.speak(u);
}
} else {
icon.className = 'bi bi-volume-mute-fill';
btn.innerHTML = '<i class="bi bi-volume-mute-fill" id="soundIcon"></i> Sound: OFF';
btn.classList.remove('btn-outline-light');
btn.classList.add('btn-outline-danger');
if (window.speechSynthesis) {
window.speechSynthesis.cancel();
}
}
}
function fetchQueueStatus() {
fetch('api/queue.php?action=list')
.then(response => response.json())
@ -230,17 +284,19 @@ try {
}
function speakToken(item) {
if (!window.speechSynthesis) return;
// Cancel any pending speech to announce current immediately
window.speechSynthesis.cancel();
// English
const textEn = `Token number ${item.token_number}, Department ${item.department_name_en}`;
const textEn = `Token number ${item.token_number}, Room ${item.room_number ? item.room_number : ''}`;
const uEn = new SpeechSynthesisUtterance(textEn);
uEn.lang = 'en-US';
uEn.rate = 0.9;
// Arabic
const textAr = `رقم ${item.token_number}, ${item.department_name_ar}`;
const textAr = `رقم ${item.token_number}, غرفة ${item.room_number ? item.room_number : ''}`;
const uAr = new SpeechSynthesisUtterance(textAr);
uAr.lang = 'ar-SA';
uAr.rate = 0.8;
@ -295,10 +351,18 @@ try {
docName = s.doctor_name || '';
}
let roomInfo = '';
if (s.room_number) {
roomInfo = `<div class="mt-1 fw-bold text-dark badge bg-warning text-dark" style="font-size:0.85rem;">Room/غرفة: ${s.room_number}</div>`;
}
return `
<div class="serving-item">
<div class="serving-number">${s.token_number}</div>
<div class="small text-muted text-center" style="line-height:1.2; font-size:0.85rem;">${docName}</div>
<div class="small text-muted text-center mt-1" style="line-height:1.2; font-size:0.85rem;">
${docName}
${roomInfo}
</div>
</div>`;
}).join('');
}