adding sound to display

This commit is contained in:
Flatlogic Bot 2026-03-22 14:59:37 +00:00
parent bcd593fb90
commit 04bd70e7d8
4 changed files with 71 additions and 6 deletions

View File

@ -4,6 +4,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST')
require_once __DIR__ . '/../helpers.php';
$db = db();
// Check for post_max_size overflow
if (empty($_POST) && empty($_FILES) && isset($_SERVER['CONTENT_LENGTH']) && $_SERVER['CONTENT_LENGTH'] > 0) {
$_SESSION['flash_message'] = 'Error: File too large (exceeds post_max_size).';
@ -310,7 +311,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST')
} elseif ($_POST['action'] === 'edit_visit') {
$id = $_POST['id'] ?? '';
// Note: patient_id is not updated as it should be immutable
$doctor_id = $_POST['doctor_id'] ?? '';
$doctor_id = $_POST['doctor_id'] ?: null;
$weight = $_POST['weight'] ?? '';
$bp = $_POST['blood_pressure'] ?? '';
$hr = $_POST['heart_rate'] ?? '';
@ -343,7 +344,7 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST')
}
}
if ($id && $doctor_id) {
if ($id) {
// Removed patient_id from UPDATE
$stmt = $db->prepare("UPDATE visits SET doctor_id = ?, weight = ?, blood_pressure = ?, heart_rate = ?, temperature = ?, symptoms = ?, diagnosis = ?, treatment_plan = ?, nursing_notes = ? WHERE id = ?");
$stmt->execute([$doctor_id, $weight, $bp, $hr, $temp, $symptoms, $diagnosis, $treatment, $nursing_notes, $id]);

View File

@ -1032,7 +1032,10 @@
</div>
<div class="col-md-12 mb-3">
<label class="form-label"><?php echo __("nursing_notes"); ?></label>
<textarea name="nursing_notes" id="visit_nursing_notes" class="form-control" rows="3"></textarea>
<button type="button" class="btn btn-sm btn-outline-info float-end" onclick="generateAISuggestion(this)" data-target="nursing_notes">
<i class="bi bi-magic"></i> AI Suggestion
</button>
<textarea name="nursing_notes" id="visit_nursing_notes" class="form-control summernote" rows="3"></textarea>
</div>
</div>
</div>
@ -1387,6 +1390,7 @@ function showRecordVisitModal(patientId = null) {
$('#visit_symptoms').summernote('code', '');
$('#visit_diagnosis').summernote('code', '');
$('#visit_treatment_plan').summernote('code', '');
$('#visit_nursing_notes').summernote('code', '');
// Clear dynamic rows
document.querySelector('#prescriptionTable tbody').innerHTML = '';
@ -1456,7 +1460,6 @@ function showEditVisitModal(data) {
document.getElementById('visit_blood_pressure').value = data.blood_pressure || '';
document.getElementById('visit_heart_rate').value = data.heart_rate || '';
document.getElementById('visit_temperature').value = data.temperature || '';
document.getElementById('visit_nursing_notes').value = data.nursing_notes || '';
// Populate new fields
$('#visit_patient_gender').val(data.patient_gender || '');
@ -1478,6 +1481,7 @@ function showEditVisitModal(data) {
$('#visit_symptoms').summernote('code', data.symptoms || '');
$('#visit_diagnosis').summernote('code', data.diagnosis || '');
$('#visit_treatment_plan').summernote('code', data.treatment_plan || '');
$('#visit_nursing_notes').summernote('code', data.nursing_notes || '');
// Populate prescriptions
const tbody = document.querySelector('#prescriptionTable tbody');
@ -1518,6 +1522,7 @@ function showVisitResultsModal(data) {
BP: ${data.blood_pressure || '-'},
Weight: ${data.weight || '-'} kg,
Temp: ${data.temperature || '-'}°C
, <br>Nursing Notes: ${data.nursing_notes || '-'}
</dd>
</dl>
`;

View File

@ -367,6 +367,7 @@ $translations = array (
'dosage' => 'Dosage',
'instructions' => 'Instructions',
'add_drug' => 'Add Drug',
'nursing_notes' => 'Nursing Notes',
),
'ar' =>
array (
@ -735,5 +736,6 @@ $translations = array (
'dosage' => 'الجرعة',
'instructions' => 'التعليمات',
'add_drug' => 'إضافة دواء',
'nursing_notes' => 'ملاحظات التمريض',
),
);

View File

@ -37,6 +37,7 @@ try {
padding: 20px;
text-align: center;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
position: relative;
}
.dept-card {
background: white;
@ -168,6 +169,9 @@ try {
<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>
<button id="audioBtn" class="btn btn-warning position-absolute top-0 start-0 m-3" style="z-index: 1001;" onclick="enableAudio()">
<i class="bi bi-volume-mute-fill"></i> Enable Sound
</button>
</div>
<div class="container-fluid p-4">
@ -184,6 +188,17 @@ try {
</div>
<script>
let audioEnabled = false;
const announcedIds = new Set();
let isFirstRun = true;
function enableAudio() {
audioEnabled = true;
document.getElementById('audioBtn').style.display = 'none';
// Play a silent utterance to unlock audio context on mobile
const u = new SpeechSynthesisUtterance('');
window.speechSynthesis.speak(u);
}
function updateClock() {
const now = new Date();
@ -197,12 +212,54 @@ try {
.then(response => response.json())
.then(data => {
if (data.success) {
checkForNewCalls(data.data);
renderDepartments(data.data);
}
})
.catch(err => console.error('Fetch error:', err));
}
function checkForNewCalls(items) {
// Filter for serving items
const serving = items.filter(i => i.status === 'serving');
if (isFirstRun) {
// On first load, just mark current serving as announced so we don't spam
serving.forEach(i => announcedIds.add(i.id));
isFirstRun = false;
return;
}
serving.forEach(item => {
if (!announcedIds.has(item.id)) {
announcedIds.add(item.id);
if (audioEnabled) {
speakToken(item);
}
}
});
}
function speakToken(item) {
// 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 uEn = new SpeechSynthesisUtterance(textEn);
uEn.lang = 'en-US';
uEn.rate = 0.9;
// Arabic
const textAr = `رقم ${item.token_number}, ${item.department_name_ar}`;
const uAr = new SpeechSynthesisUtterance(textAr);
uAr.lang = 'ar-SA';
uAr.rate = 0.8;
window.speechSynthesis.speak(uEn);
window.speechSynthesis.speak(uAr);
}
function renderDepartments(queueItems) {
// Group by department
const depts = {};