adding timezone

This commit is contained in:
Flatlogic Bot 2026-04-01 01:50:29 +00:00
parent 1fb5dec73f
commit e2985ac197
4 changed files with 74 additions and 22 deletions

View File

@ -98,6 +98,21 @@ qh_page_start(
<label class="form-label fw-bold" for="newsTickerAr"><?= qh_h(qh_t('News Ticker (Arabic)', 'شريط الأخبار بالعربية')) ?></label> <label class="form-label fw-bold" for="newsTickerAr"><?= qh_h(qh_t('News Ticker (Arabic)', 'شريط الأخبار بالعربية')) ?></label>
<input id="newsTickerAr" class="form-control" type="text" name="news_ticker_ar" value="<?= qh_h((string) ($profile['news_ticker_ar'] ?? '')) ?>" placeholder="<?= qh_h(qh_t('Scrolling text for display board', 'نص متحرك لشاشة العرض')) ?>"> <input id="newsTickerAr" class="form-control" type="text" name="news_ticker_ar" value="<?= qh_h((string) ($profile['news_ticker_ar'] ?? '')) ?>" placeholder="<?= qh_h(qh_t('Scrolling text for display board', 'نص متحرك لشاشة العرض')) ?>">
</div> </div>
<div class="col-lg-6">
<label class="form-label fw-bold" for="appTimezone"><?= qh_h(qh_t('Timezone', 'المنطقة الزمنية')) ?></label>
<select id="appTimezone" class="form-select" name="timezone">
<?php foreach (timezone_identifiers_list() as $tz): ?>
<option value="<?= qh_h($tz) ?>" <?= ($profile['timezone'] ?? 'UTC') === $tz ? 'selected' : '' ?>><?= qh_h($tz) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-lg-6">
<label class="form-label fw-bold" for="appDefaultLanguage"><?= qh_h(qh_t('Default Language', 'اللغة الافتراضية')) ?></label>
<select id="appDefaultLanguage" class="form-select" name="default_language">
<option value="en" <?= ($profile['default_language'] ?? 'en') === 'en' ? 'selected' : '' ?>><?= qh_h(qh_t('English', 'الإنجليزية')) ?></option>
<option value="ar" <?= ($profile['default_language'] ?? 'en') === 'ar' ? 'selected' : '' ?>><?= qh_h(qh_t('Arabic', 'العربية')) ?></option>
</select>
</div>
</div> </div>
</div> </div>

View File

@ -1184,7 +1184,7 @@ html[dir="rtl"] .hospital-detail-list dd {
top: 0; top: 0;
width: 80mm; width: 80mm;
margin: 0; margin: 0;
padding: 5mm; padding: 2mm 5mm;
display: block !important; display: block !important;
background: white; background: white;
color: black; color: black;
@ -1197,40 +1197,40 @@ html[dir="rtl"] .hospital-detail-list dd {
} }
.pt-header { .pt-header {
font-size: 1.2rem; font-size: 1rem;
font-weight: bold; font-weight: bold;
margin-bottom: 5px; margin-bottom: 2px;
border-bottom: 1px solid black; border-bottom: 1px solid black;
padding-bottom: 5px; padding-bottom: 2px;
} }
.pt-token-title { .pt-token-title {
font-size: 0.9rem; font-size: 0.8rem;
margin-top: 10px; margin-top: 5px;
} }
.pt-token-number { .pt-token-number {
font-size: 3.5rem; font-size: 2.5rem;
font-weight: bold; font-weight: bold;
line-height: 1; line-height: 1;
margin: 5px 0 10px 0; margin: 2px 0 5px 0;
} }
.pt-patient-name { .pt-patient-name {
font-size: 1.1rem; font-size: 0.9rem;
font-weight: bold; font-weight: bold;
margin-bottom: 10px; margin-bottom: 5px;
} }
.pt-divider { .pt-divider {
border-top: 1px dashed black; border-top: 1px dashed black;
margin: 10px 0; margin: 5px 0;
} }
.pt-detail { .pt-detail {
font-size: 1rem; font-size: 0.85rem;
text-align: left; text-align: left;
margin-bottom: 5px; margin-bottom: 2px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
@ -1245,13 +1245,13 @@ html[dir="rtl"] .hospital-detail-list dd {
} }
.pt-datetime { .pt-datetime {
margin-top: 8px; margin-top: 4px;
font-size: 0.85rem; font-size: 0.75rem;
} }
.pt-footer { .pt-footer {
font-size: 0.85rem; font-size: 0.75rem;
margin-top: 10px; margin-top: 5px;
} }
@page { @page {

View File

@ -37,11 +37,19 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
const locale = document.body.dataset.locale || 'en'; const locale = document.body.dataset.locale || 'en';
const timeZone = document.body.dataset.timezone || 'UTC';
const liveClock = document.querySelector('.js-live-clock'); const liveClock = document.querySelector('.js-live-clock');
if (liveClock) { if (liveClock) {
const renderClock = () => { const renderClock = () => {
const now = new Date(); const now = new Date();
liveClock.textContent = now.toLocaleTimeString(locale === 'ar' ? 'ar-SA' : 'en-US', { hour: '2-digit', minute: '2-digit' }); const opts = { hour: '2-digit', minute: '2-digit' };
if (timeZone) opts.timeZone = timeZone;
try {
liveClock.textContent = now.toLocaleTimeString(locale === 'ar' ? 'ar-SA' : 'en-US', opts);
} catch (e) {
opts.timeZone = undefined;
liveClock.textContent = now.toLocaleTimeString(locale === 'ar' ? 'ar-SA' : 'en-US', opts);
}
}; };
renderClock(); renderClock();
window.setInterval(renderClock, 1000 * 30); window.setInterval(renderClock, 1000 * 30);

View File

@ -17,6 +17,17 @@ function qh_boot(): void
qh_ensure_schema(); qh_ensure_schema();
qh_seed_demo_data(); qh_seed_demo_data();
qh_seed_hospital_profile(); qh_seed_hospital_profile();
$profile = qh_fetch_hospital_profile();
$timezone = $profile['timezone'] ?? 'UTC';
if ($timezone) {
date_default_timezone_set($timezone);
try {
$offset = (new DateTime('now', new DateTimeZone($timezone)))->format('P');
db()->exec("SET time_zone = " . db()->quote($offset));
} catch (\Throwable $e) {}
}
$booted = true; $booted = true;
} }
@ -81,6 +92,8 @@ SQL;
db()->exec($profileSql); db()->exec($profileSql);
try { db()->exec("ALTER TABLE hospital_profile_settings ADD COLUMN news_ticker_en VARCHAR(1000) DEFAULT NULL"); } catch (\Throwable $e) {} try { db()->exec("ALTER TABLE hospital_profile_settings ADD COLUMN news_ticker_en VARCHAR(1000) DEFAULT NULL"); } catch (\Throwable $e) {}
try { db()->exec("ALTER TABLE hospital_profile_settings ADD COLUMN news_ticker_ar VARCHAR(1000) DEFAULT NULL"); } catch (\Throwable $e) {} try { db()->exec("ALTER TABLE hospital_profile_settings ADD COLUMN news_ticker_ar VARCHAR(1000) DEFAULT NULL"); } catch (\Throwable $e) {}
try { db()->exec("ALTER TABLE hospital_profile_settings ADD COLUMN timezone VARCHAR(100) DEFAULT 'UTC'"); } catch (\Throwable $e) {}
try { db()->exec("ALTER TABLE hospital_profile_settings ADD COLUMN default_language VARCHAR(10) DEFAULT 'en'"); } catch (\Throwable $e) {}
} }
function qh_seed_demo_data(): void function qh_seed_demo_data(): void
@ -230,8 +243,14 @@ function qh_locale(): string
$_SESSION['qh_lang'] = $requested; $_SESSION['qh_lang'] = $requested;
} }
$sessionLocale = strtolower(trim((string) ($_SESSION['qh_lang'] ?? 'en'))); $sessionLocale = strtolower(trim((string) ($_SESSION['qh_lang'] ?? '')));
$locale = in_array($sessionLocale, ['en', 'ar'], true) ? $sessionLocale : 'en'; if (in_array($sessionLocale, ['en', 'ar'], true)) {
$locale = $sessionLocale;
} else {
$profile = qh_fetch_hospital_profile();
$defaultLang = strtolower(trim((string) ($profile['default_language'] ?? 'en')));
$locale = in_array($defaultLang, ['en', 'ar'], true) ? $defaultLang : 'en';
}
return $locale; return $locale;
} }
@ -551,7 +570,9 @@ function qh_page_start(string $activePage, string $pageTitle, string $metaDescri
echo ' <link rel="stylesheet" href="assets/css/custom.css?v=' . $assetVersionCss . '">'; echo ' <link rel="stylesheet" href="assets/css/custom.css?v=' . $assetVersionCss . '">';
echo ' <style>:root{--accent:' . qh_h($primaryColor) . ';--accent-strong:' . qh_h($secondaryColor) . ';}</style>'; echo ' <style>:root{--accent:' . qh_h($primaryColor) . ';--accent-strong:' . qh_h($secondaryColor) . ';}</style>';
echo '</head>'; echo '</head>';
echo '<body class="' . qh_h($bodyClass) . '" data-page="' . qh_h($activePage) . '" data-locale="' . qh_h($locale) . '">'; $profile = qh_fetch_hospital_profile();
$timezone = qh_h($profile['timezone'] ?? 'UTC');
echo '<body class="' . qh_h($bodyClass) . '" data-page="' . qh_h($activePage) . '" data-locale="' . qh_h($locale) . '" data-timezone="' . $timezone . '">';
if ($activePage !== 'display') { if ($activePage !== 'display') {
qh_render_nav($activePage); qh_render_nav($activePage);
} }
@ -1115,6 +1136,10 @@ function qh_admin_handle_request(): void
$workingHoursAr = trim((string) ($_POST['working_hours_ar'] ?? '')); $workingHoursAr = trim((string) ($_POST['working_hours_ar'] ?? ''));
$newsTickerEn = trim((string) ($_POST['news_ticker_en'] ?? '')); $newsTickerEn = trim((string) ($_POST['news_ticker_en'] ?? ''));
$newsTickerAr = trim((string) ($_POST['news_ticker_ar'] ?? '')); $newsTickerAr = trim((string) ($_POST['news_ticker_ar'] ?? ''));
$timezone = trim((string) ($_POST['timezone'] ?? ''));
if ($timezone === '' || !in_array($timezone, timezone_identifiers_list(), true)) $timezone = 'UTC';
$defaultLanguage = trim((string) ($_POST['default_language'] ?? 'en'));
if (!in_array($defaultLanguage, ['en', 'ar'], true)) $defaultLanguage = 'en';
$profile = qh_fetch_hospital_profile(); $profile = qh_fetch_hospital_profile();
$logoUrl = $profile['logo_url'] ?? ''; $logoUrl = $profile['logo_url'] ?? '';
$faviconUrl = $profile['favicon_url'] ?? ''; $faviconUrl = $profile['favicon_url'] ?? '';
@ -1165,7 +1190,9 @@ function qh_admin_handle_request(): void
primary_color = :primary_color, primary_color = :primary_color,
secondary_color = :secondary_color, secondary_color = :secondary_color,
news_ticker_en = :news_ticker_en, news_ticker_en = :news_ticker_en,
news_ticker_ar = :news_ticker_ar news_ticker_ar = :news_ticker_ar,
timezone = :timezone,
default_language = :default_language
WHERE id = 1" WHERE id = 1"
); );
$stmt->execute([ $stmt->execute([
@ -1187,6 +1214,8 @@ function qh_admin_handle_request(): void
'secondary_color' => $secondaryColor, 'secondary_color' => $secondaryColor,
'news_ticker_en' => $newsTickerEn, 'news_ticker_en' => $newsTickerEn,
'news_ticker_ar' => $newsTickerAr, 'news_ticker_ar' => $newsTickerAr,
'timezone' => $timezone,
'default_language' => $defaultLanguage,
]); ]);
qh_set_flash('success', qh_t('Hospital profile updated successfully.', 'تم تحديث ملف المستشفى بنجاح.')); qh_set_flash('success', qh_t('Hospital profile updated successfully.', 'تم تحديث ملف المستشفى بنجاح.'));
} }