Initial commit

This commit is contained in:
Porawit Dongwang
2026-09-16 23:20:08 +07:00
commit 0041668dbb
32577 changed files with 3687927 additions and 0 deletions
+901
View File
@@ -0,0 +1,901 @@
<?php
require_once("../core/auth.php");
require_once("../config/db.php");
require_once("../core/utils.php");
require_once("../core/settings.php");
$current_page = 'ncd_registry.php';
// Initialize variables and clinic data
$t_diag = ['E119', 'I10', 'E785', 'N183'];
$curr_clinic = $_GET['clinic'] ?? 'ALL';
$ncd_clinics = [
'DM' => 'คลินิกเบาหวาน (DM)',
'HT' => 'คลินิกความดันฯ (HT)',
'DLP' => 'คลินิกไขมันฯ (DLP)',
'CKD' => 'คลินิกโรคไต (CKD)'
];
$app_settings = get_app_settings();
$clinic_codes = [
'DM' => $app_settings['ncd_clinic_dm_code'] ?? '001',
'HT' => $app_settings['ncd_clinic_ht_code'] ?? '002',
'DLP' => $app_settings['ncd_clinic_dlp_code'] ?? '039',
'CKD' => $app_settings['ncd_clinic_ckd_code'] ?? '051'
];
$clinic_code = $clinic_codes[$curr_clinic] ?? null;
// Date parameters for filtering
$ds1 = $_GET['ds1'] ?? date('Y-m-d', strtotime('-1 month'));
$ds2 = $_GET['ds2'] ?? date('Y-m-d');
// Create reverse mapping for clinic codes to names
$clinic_code_to_name = [];
foreach ($clinic_codes as $key => $code) {
$clinic_code_to_name[$code] = $ncd_clinics[$key];
}
$patientsData = [];
// Execute query only if ds1 and ds2 are submitted
$dashboardData = [];
if (isset($_GET['ds1']) && isset($_GET['ds2'])) {
if ($curr_clinic === 'ALL') {
// Run dashboard queries instead of fetching all patients
$dashboard_keys = [
'dashboard_dm_all', 'dashboard_dm_hba1c',
'dashboard_dm_1', 'dashboard_dm_2', 'dashboard_dm_3', 'dashboard_dm_4', 'dashboard_dm_5', 'dashboard_dm_eye',
'dashboard_ht_all', 'dashboard_ht_1', 'dashboard_ht_2',
'dashboard_dlp_all',
'dashboard_ckd_all', 'dashboard_ckd_1'
];
foreach ($dashboard_keys as $k) {
$dashboardData[$k] = ($k === 'dashboard_ckd_1') ? [] : 0;
if (!empty($app_settings[$k])) {
$sql = str_replace(['{ds1}', '{ds2}'], [$ds1, $ds2], $app_settings[$k]);
if ($res = $conn1->query($sql)) {
if ($k === 'dashboard_ckd_1') {
while ($r = $res->fetch_assoc()) {
$dashboardData[$k][$r['stage']] = $r['total_patient'];
}
} else {
if ($r = $res->fetch_assoc()) {
$dashboardData[$k] = $r['total_patient'] ?? 0;
}
}
}
}
}
} else {
$clinic_cond = "AND cl.clinic = '" . $conn1->real_escape_string($clinic_code) . "'";
$raw_sql = $app_settings['ncd_sql'] ?? '';
$sql = str_replace('{clinic_cond}', $clinic_cond, $raw_sql);
if ($stmt = $conn1->prepare($sql)) {
$stmt->bind_param("ss", $ds1, $ds2);
$stmt->execute();
$result = $stmt->get_result();
if ($result) {
while ($row = $result->fetch_assoc()) {
$patientsData[] = $row;
}
}
$stmt->close();
}
// Bulk fetch additional clinical data (Labs & Screenings)
if (!empty($patientsData)) {
$hn_list = array_column($patientsData, 'hn');
$hn_sql_in = "'" . implode("','", array_map(function($hn) use ($conn1) {
return $conn1->real_escape_string($hn);
}, array_unique($hn_list))) . "'";
$extraData = [];
foreach ($hn_list as $hn) {
$extraData[$hn] = [
'hba1c' => ['res' => '-', 'date' => '-'],
'urine_prot' => ['res' => '-', 'date' => '-'],
'cr' => ['res' => '-', 'date' => '-'],
'urine_alb' => ['res' => '-', 'date' => '-'],
'urine_cr' => ['res' => '-', 'date' => '-'],
'hbsag' => ['res' => '-', 'date' => '-'],
'anti_hcv' => ['res' => '-', 'date' => '-'],
'hpv' => ['res' => '-', 'date' => '-'],
'colon_cancer' => ['res' => '-', 'date' => '-'],
'ldl' => ['res' => '-', 'date' => '-'],
'eye_screen' => '-',
'foot_screen' => '-',
'oral_cancer' => '-'
];
}
// 1. LAB Data
$lab_sql = "SELECT a.hn, b.lab_items_code, b.lab_order_result, a.order_date
FROM lab_head a
JOIN lab_order b ON a.lab_order_number=b.lab_order_number
WHERE a.hn IN ($hn_sql_in)
AND b.lab_items_code IN ('288','223','224','802','78','226','227','641','656','659','2215','1896','1549','479')
AND (
(b.lab_items_code != '1549' AND a.order_date BETWEEN '$ds1' AND '$ds2') OR
(b.lab_items_code = '1549' AND a.order_date BETWEEN '2024-10-01' AND '2026-06-11')
)
ORDER BY a.order_date ASC";
if ($res_lab = $conn1->query($lab_sql)) {
while ($r = $res_lab->fetch_assoc()) {
$hn = $r['hn'];
$code = $r['lab_items_code'];
$res = trim($r['lab_order_result'] ?? '');
$date = (!empty($r['order_date']) && $r['order_date'] != '0000-00-00') ? thai_date2($r['order_date']) : '-';
if ($code == '288') $extraData[$hn]['hba1c'] = ['res' => $res, 'date' => $date];
else if (in_array($code, ['223','224'])) $extraData[$hn]['urine_prot'] = ['res' => $res, 'date' => $date];
else if (in_array($code, ['802','78','226','227'])) {
$extraData[$hn]['cr'] = ['res' => $res, 'date' => $date];
if ($code == '227') $extraData[$hn]['urine_cr'] = ['res' => $res, 'date' => $date];
}
else if ($code == '641') $extraData[$hn]['urine_alb'] = ['res' => $res, 'date' => $date];
else if ($code == '656') $extraData[$hn]['hbsag'] = ['res' => $res, 'date' => $date];
else if ($code == '659') $extraData[$hn]['anti_hcv'] = ['res' => $res, 'date' => $date];
else if (in_array($code, ['2215','1896'])) $extraData[$hn]['hpv'] = ['res' => $res, 'date' => $date];
else if ($code == '1549') $extraData[$hn]['colon_cancer'] = ['res' => $res, 'date' => $date];
else if ($code == '479') $extraData[$hn]['ldl'] = ['res' => $res, 'date' => $date];
}
}
// 2. Eye/Foot Screening
$screen_sql = "SELECT hn, screen_date, do_eye_screen, do_foot_screen
FROM clinicmember_cormobidity_screen
WHERE hn IN ($hn_sql_in) AND screen_date BETWEEN '$ds1' AND '$ds2'
ORDER BY screen_date ASC";
if ($res_scr = $conn1->query($screen_sql)) {
while ($r = $res_scr->fetch_assoc()) {
$hn = $r['hn'];
$date = (!empty($r['screen_date']) && $r['screen_date'] != '0000-00-00') ? thai_date2($r['screen_date']) : '-';
if ($r['do_eye_screen'] == 'Y') $extraData[$hn]['eye_screen'] = $date;
if ($r['do_foot_screen'] == 'Y') $extraData[$hn]['foot_screen'] = $date;
}
}
// 3. Oral Cancer Screening
$oral_sql = "SELECT hn, vstdate
FROM dtmain
WHERE hn IN ($hn_sql_in) AND tmcode IN ('001480') AND vstdate BETWEEN '$ds1' AND '$ds2'
ORDER BY vstdate ASC";
if ($res_oral = $conn1->query($oral_sql)) {
while ($r = $res_oral->fetch_assoc()) {
$date = (!empty($r['vstdate']) && $r['vstdate'] != '0000-00-00') ? thai_date2($r['vstdate']) : '-';
$extraData[$r['hn']]['oral_cancer'] = $date;
}
}
// Merge back into patientsData
foreach ($patientsData as &$p) {
$h = $p['hn'];
$p['extra'] = $extraData[$h] ?? [];
}
unset($p);
}
}
}
?>
<!DOCTYPE html>
<html lang="th">
<head>
<?php
$page_title = "ทะเบียนผู้ป่วย NCD";
require_once("../components/head.php");
?>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css">
<link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.4.1/css/buttons.dataTables.min.css">
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.1/js/dataTables.buttons.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.1/js/buttons.html5.min.js"></script>
<link rel="stylesheet" href="https://cdn.datatables.net/fixedcolumns/4.3.0/css/fixedColumns.dataTables.min.css">
<script src="https://cdn.datatables.net/fixedcolumns/4.3.0/js/dataTables.fixedColumns.min.js"></script>
<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
body { font-family: 'Sarabun', sans-serif; }
.glass-card {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
border-radius: 1rem;
}
.tab-btn.active {
border-bottom: 2px solid #3b82f6;
color: #3b82f6;
font-weight: 600;
}
.ncd-table th {
position: sticky;
top: 0;
background: #f8fafc;
z-index: 10;
border-bottom: 2px solid #cbd5e1;
white-space: nowrap;
text-align: center !important;
}
.ncd-table td {
white-space: nowrap;
}
/* Sticky first 3 columns */
.ncd-table th:nth-child(1), .ncd-table td:nth-child(1) { position: sticky; left: 0; z-index: 20; background: inherit; }
.ncd-table th:nth-child(2), .ncd-table td:nth-child(2) { position: sticky; left: 50px; z-index: 20; background: inherit; }
.ncd-table th:nth-child(3), .ncd-table td:nth-child(3) { position: sticky; left: 130px; z-index: 20; background: inherit; }
.ncd-table th:nth-child(1) { z-index: 30; }
.ncd-table th:nth-child(2) { z-index: 30; }
.ncd-table th:nth-child(3) { z-index: 30; }
/* Shadow for fixed columns */
.ncd-table td:nth-child(3)::after, .ncd-table th:nth-child(3)::after {
content: '';
position: absolute;
top: 0; right: 0; bottom: -1px; width: 30px;
transform: translateX(100%);
transition: box-shadow 0.3s;
pointer-events: none;
box-shadow: inset 10px 0 8px -8px rgba(0, 0, 0, 0.15);
}
.dashboard-gradient-dm {
background: linear-gradient(135deg, #4f46e5 0%, #3b82f6 100%);
}
.dashboard-gradient-ht {
background: linear-gradient(135deg, #f97316 0%, #f59e0b 100%);
}
.dashboard-gradient-dlp {
background: linear-gradient(135deg, #8b5cf6 0%, #a855f7 100%);
}
.dashboard-gradient-ckd {
background: linear-gradient(135deg, #0d9488 0%, #14b8a6 100%);
}
.progress-bar-bg { background-color: #e2e8f0; border-radius: 9999px; height: 6px; width: 100%; overflow: hidden; margin-top: 8px; }
.progress-bar-fill-dm { background-color: #4f46e5; height: 100%; border-radius: 9999px; }
.progress-bar-fill-ht { background-color: #f97316; height: 100%; border-radius: 9999px; }
.progress-bar-fill-dlp { background-color: #8b5cf6; height: 100%; border-radius: 9999px; }
.progress-bar-fill-ckd { background-color: #0d9488; height: 100%; border-radius: 9999px; }
/* Custom CSS to make DataTables look good with Tailwind */
.dataTables_wrapper .dataTables_length select, .dataTables_wrapper .dataTables_filter input {
border: 1px solid #e2e8f0;
border-radius: 0.5rem;
padding: 0.25rem 0.5rem;
outline: none;
}
.dataTables_wrapper .dataTables_length select:focus, .dataTables_wrapper .dataTables_filter input:focus {
border-color: #10b981;
box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.2);
}
.dataTables_wrapper .dataTables_paginate .paginate_button {
border-radius: 0.5rem !important;
padding: 0.25rem 0.75rem !important;
margin: 0 0.125rem !important;
border: 1px solid transparent !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button.current {
background: #10b981 !important;
color: white !important;
border: none !important;
}
.dataTables_wrapper .dataTables_paginate .paginate_button:hover:not(.current) {
background: #f1f5f9 !important;
color: #334155 !important;
}
table.dataTable.no-footer {
border-bottom: 1px solid #cbd5e1;
}
/* Fixed columns styling & Shadow */
.ncd-table th.dtfc-fixed-left {
background-color: #f1f5f9 !important;
z-index: 50 !important;
}
.ncd-table tr.bg-white td.dtfc-fixed-left {
background-color: #ffffff !important;
z-index: 40 !important;
}
.ncd-table tr.bg-slate-50 td.dtfc-fixed-left {
background-color: #f8fafc !important;
z-index: 40 !important;
}
.ncd-table tr:hover td.dtfc-fixed-left {
background-color: #eff6ff !important;
}
/* Add shadow to the rightmost fixed column to show elevation */
.ncd-table th:nth-child(3).dtfc-fixed-left,
.ncd-table td:nth-child(3).dtfc-fixed-left {
box-shadow: 4px 0 6px -2px rgba(0, 0, 0, 0.1) !important;
border-right: 1px solid #e2e8f0;
}
/* Custom Sort Icons using SVG Backgrounds */
table.dataTable thead th.sorting,
table.dataTable thead th.sorting_asc,
table.dataTable thead th.sorting_desc {
background-image: none !important;
position: relative;
}
table.dataTable thead th.sorting:before,
table.dataTable thead th.sorting:after,
table.dataTable thead th.sorting_asc:before,
table.dataTable thead th.sorting_asc:after,
table.dataTable thead th.sorting_desc:before,
table.dataTable thead th.sorting_desc:after {
display: none !important;
content: none !important;
}
table.dataTable thead th.sorting::after,
table.dataTable thead th.sorting_asc::after,
table.dataTable thead th.sorting_desc::after {
content: "" !important;
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
width: 10px;
height: 14px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
display: block !important;
opacity: 1 !important;
}
table.dataTable thead th.sorting::after {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="%23cbd5e1" d="M137.4 41.4c12.5-12.5 32.8-12.5 45.3 0l128 128c9.2 9.2 11.9 22.9 6.9 34.9s-16.6 19.8-29.6 19.8H32c-12.9 0-24.6-7.8-29.6-19.8s-2.2-25.7 6.9-34.9l128-128zm0 429.3l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8h256c12.9 0 24.6 7.8 29.6 19.8s2.2 25.7-6.9 34.9l-128 128c-12.5 12.5-32.8 12.5-45.3 0z"/></svg>') !important;
}
table.dataTable thead th.sorting_asc::after {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="%2310b981" d="M182.6 41.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8h256c12.9 0 24.6 7.8 29.6 19.8s-2.2-25.7-6.9-34.9l-128-128z"/></svg>') !important;
}
table.dataTable thead th.sorting_desc::after {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="%2310b981" d="M182.6 470.6c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-9.2-9.2-11.9-22.9-6.9-34.9s16.6-19.8 29.6-19.8h256c12.9 0 24.6 7.8 29.6 19.8s-2.2 25.7-6.9 34.9l-128 128z"/></svg>') !important;
}
</style>
</head>
<body class="bg-gradient-to-br from-emerald-50 to-emerald-100 text-slate-800 font-sans antialiased min-h-screen flex">
<?php require_once("../components/layout_sidebar.php"); ?>
<main class="flex-1 flex flex-col min-w-0 h-screen overflow-hidden">
<?php require_once("../components/layout_topbar.php"); ?>
<div class="flex-1 overflow-y-auto p-4 md:p-6 lg:p-8">
<div class="max-w-7xl mx-auto">
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6 gap-4">
<div>
<h1 class="text-2xl font-bold text-slate-800 flex items-center gap-3">
<svg class="w-7 h-7 text-emerald-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"></path></svg>
ทะเบียนผู้ป่วย<?= ($curr_clinic !== 'ALL') ? " " . ($ncd_clinics[$curr_clinic] ?? $curr_clinic) : " NCD รวม" ?>
<?php
$show_dm = ($curr_clinic === 'ALL' || $curr_clinic === 'DM');
$show_ht = ($curr_clinic === 'ALL' || $curr_clinic === 'HT');
$show_dlp = ($curr_clinic === 'ALL' || $curr_clinic === 'DLP');
$show_ckd = ($curr_clinic === 'ALL' || $curr_clinic === 'CKD');
if ($curr_clinic !== 'ALL') {
echo " - " . ($ncd_clinics[$curr_clinic] ?? '');
}
?>
</h1>
<p class="text-slate-500 mt-1">ระบบลงทะเบียนและติดตามผู้ป่วยโรคเรื้อรัง</p>
</div>
</div>
<!-- CONDITIONAL VIEW: DASHBOARD OR TABLE -->
<?php if ($curr_clinic === 'ALL'): ?>
<!-- DASHBOARD VIEW -->
<div id="view-dash" class="space-y-6">
<div class="glass-card p-4 flex flex-col md:flex-row justify-between items-center gap-4 border-b border-slate-200">
<h3 class="font-bold text-slate-800 flex items-center gap-2">
ตัวชี้วัดสถิติ NCD
</h3>
<form method="GET" action="ncd_registry.php" class="flex flex-col sm:flex-row items-center gap-3" onsubmit="return showProcessingModal();">
<input type="hidden" name="clinic" value="<?= htmlspecialchars($curr_clinic) ?>">
<div class="flex items-center gap-2">
<label class="text-sm font-semibold text-slate-600">ตั้งแต่:</label>
<input type="date" name="ds1" value="<?= htmlspecialchars($ds1) ?>" class="border border-slate-200 rounded px-3 py-1.5 text-sm focus:ring-emerald-500 focus:border-emerald-500 bg-white" required>
</div>
<div class="flex items-center gap-2">
<label class="text-sm font-semibold text-slate-600">ถึง:</label>
<input type="date" name="ds2" value="<?= htmlspecialchars($ds2) ?>" class="border border-slate-200 rounded px-3 py-1.5 text-sm focus:ring-emerald-500 focus:border-emerald-500 bg-white" required>
</div>
<button type="submit" class="bg-emerald-600 hover:bg-emerald-700 text-white px-4 py-1.5 rounded-md text-sm font-semibold transition-colors shadow-sm whitespace-nowrap">ประมวลผล (Dashboard)</button>
</form>
</div>
<!-- DM Section -->
<div>
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-bold text-slate-800 flex items-center gap-2">
<div class="w-3 h-3 rounded-full bg-blue-600"></div>
คลินิกโรคเบาหวาน (Diabetes Mellitus)
</h3>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ผู้ป่วยเบาหวานทั้งหมด</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_dm_all'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ได้รับการตรวจ HBA1C</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_dm_hba1c'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">DM ไม่มีโรคร่วม (HbA1C < 7)</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_dm_1'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">DM มีโรคร่วม (HbA1C < 8)</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_dm_2'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ได้รับการตรวจ LDL</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_dm_3'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ได้รับการตรวจไต</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_dm_4'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ได้รับการตรวจเท้า</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_dm_5'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ได้รับการตรวจตา</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_dm_eye'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
</div>
</div>
<!-- HT Section -->
<div>
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-bold text-slate-800 flex items-center gap-2">
<div class="w-3 h-3 rounded-full bg-emerald-500"></div>
คลินิกโรคความดันโลหิตสูง (Hypertension)
</h3>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ผู้ป่วยความดันโลหิตสูงทั้งหมด</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_ht_all'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ความดัน 2 ครั้งสุดท้าย < 139/89</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_ht_1'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ได้รับการตรวจไต</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_ht_2'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
</div>
</div>
<!-- DLP Section -->
<div>
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-bold text-slate-800 flex items-center gap-2">
<div class="w-3 h-3 rounded-full bg-purple-600"></div>
คลินิกโรคไขมันในเลือดสูง (Dyslipidemia)
</h3>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ผู้ป่วยไขมันในเลือดสูงทั้งหมด</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_dlp_all'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
</div>
</div>
<!-- CKD Section -->
<div>
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-bold text-slate-800 flex items-center gap-2">
<div class="w-3 h-3 rounded-full bg-teal-500"></div>
คลินิกโรคไตเรื้อรัง (CKD)
</h3>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-2">ผู้ป่วยโรคไตเรื้อรังทั้งหมด</div>
<div class="text-3xl font-bold text-slate-800"><?php echo number_format($dashboardData['dashboard_ckd_all'] ?? 0); ?> <span class="text-sm font-normal text-slate-400">คน</span></div>
</div>
</div>
<div class="bg-white rounded-xl p-5 border border-slate-200 shadow-sm">
<div class="text-sm text-slate-500 mb-4 font-bold">จำนวนผู้ป่วยโรคไตแยกตาม Stage</div>
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3">
<?php
$stages = ['1' => 'Stage 1', '2' => 'Stage 2', '3a' => 'Stage 3a', '3b' => 'Stage 3b', '4' => 'Stage 4', '5' => 'Stage 5'];
foreach ($stages as $st => $st_name):
$val = isset($dashboardData['dashboard_ckd_1'][$st]) ? $dashboardData['dashboard_ckd_1'][$st] : 0;
?>
<div class="bg-slate-50 rounded-lg p-3 border border-slate-100 text-center">
<div class="text-xs text-slate-500 mb-1 font-semibold"><?php echo $st_name; ?></div>
<div class="text-xl font-bold text-slate-800"><?php echo number_format($val); ?></div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<?php else: ?>
<!-- TABLE VIEW -->
<div id="view-table" class="glass-card overflow-hidden">
<div class="p-4 border-b border-slate-200 flex flex-col xl:flex-row justify-between items-center gap-4 bg-white/50">
<h3 class="font-bold text-slate-800 flex items-center gap-2">
ทะเบียนผู้ป่วย<?= ($curr_clinic !== 'ALL') ? " " . ($ncd_clinics[$curr_clinic] ?? $curr_clinic) : " NCD รวม" ?>
</h3>
<form method="GET" action="ncd_registry.php" class="flex flex-col sm:flex-row items-center gap-3" onsubmit="return showProcessingModal();">
<input type="hidden" name="clinic" value="<?= htmlspecialchars($curr_clinic) ?>">
<div class="flex items-center gap-2">
<label class="text-sm font-semibold text-slate-600">ตั้งแต่:</label>
<input type="date" name="ds1" value="<?= htmlspecialchars($ds1) ?>" class="border border-slate-200 rounded px-3 py-1.5 text-sm focus:ring-emerald-500 focus:border-emerald-500 bg-white" required>
</div>
<div class="flex items-center gap-2">
<label class="text-sm font-semibold text-slate-600">ถึง:</label>
<input type="date" name="ds2" value="<?= htmlspecialchars($ds2) ?>" class="border border-slate-200 rounded px-3 py-1.5 text-sm focus:ring-emerald-500 focus:border-emerald-500 bg-white" required>
</div>
<button type="submit" class="bg-emerald-600 hover:bg-emerald-700 text-white px-4 py-1.5 rounded-md text-sm font-semibold transition-colors shadow-sm whitespace-nowrap">ประมวลผล (ค้นหา)</button>
</form>
</div>
<div class="overflow-y-auto overflow-x-hidden w-full p-4" style="max-height: calc(100vh - 250px);">
<table class="ncd-table w-full text-left text-sm" id="ncdTable">
<thead class="bg-slate-100">
<tr>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[50px]">ลำดับ</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[80px]">HN</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[150px]">ชื่อ-สกุล</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[140px]">CID</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[100px]">วันเกิด</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[50px]">อายุ</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[60px]">เพศ</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[180px]">ที่อยู่</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[50px]">หมู่</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[100px]">ตำบล</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[100px]">ประเภทบ้าน</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[100px]">เบอร์โทร</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[120px]">รหัสทะเบียน</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[120px]">วันที่ขึ้นทะเบียน</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[120px]">สิทธิการรักษา</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[150px]">โรงพยาบาล</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[100px]">Person ID</th>
<th class="py-3 pl-3 pr-8 font-semibold text-slate-700 text-center whitespace-nowrap min-w-[80px]">Diag</th>
<th class="py-3 pl-3 pr-8 font-semibold text-indigo-700 text-center whitespace-nowrap min-w-[80px] bg-indigo-50 border-l border-indigo-100">HbA1C</th>
<th class="py-3 pl-3 pr-8 font-semibold text-indigo-700 text-center whitespace-nowrap min-w-[100px] bg-indigo-50">Urine Protein</th>
<th class="py-3 pl-3 pr-8 font-semibold text-indigo-700 text-center whitespace-nowrap min-w-[80px] bg-indigo-50">Cr</th>
<th class="py-3 pl-3 pr-8 font-semibold text-indigo-700 text-center whitespace-nowrap min-w-[100px] bg-indigo-50">Urine Albumin</th>
<th class="py-3 pl-3 pr-8 font-semibold text-indigo-700 text-center whitespace-nowrap min-w-[100px] bg-indigo-50">Urine Cr</th>
<th class="py-3 pl-3 pr-8 font-semibold text-indigo-700 text-center whitespace-nowrap min-w-[80px] bg-indigo-50">HBsAg</th>
<th class="py-3 pl-3 pr-8 font-semibold text-indigo-700 text-center whitespace-nowrap min-w-[80px] bg-indigo-50">Anti HCV</th>
<th class="py-3 pl-3 pr-8 font-semibold text-indigo-700 text-center whitespace-nowrap min-w-[80px] bg-indigo-50">HPV</th>
<th class="py-3 pl-3 pr-8 font-semibold text-indigo-700 text-center whitespace-nowrap min-w-[100px] bg-indigo-50">มะเร็งลำไส้</th>
<th class="py-3 pl-3 pr-8 font-semibold text-indigo-700 text-center whitespace-nowrap min-w-[80px] bg-indigo-50">LDL</th>
<th class="py-3 pl-3 pr-8 font-semibold text-amber-700 text-center whitespace-nowrap min-w-[100px] bg-amber-50 border-l border-amber-100">ตรวจตา</th>
<th class="py-3 pl-3 pr-8 font-semibold text-amber-700 text-center whitespace-nowrap min-w-[100px] bg-amber-50">ตรวจเท้า</th>
<th class="py-3 pl-3 pr-8 font-semibold text-amber-700 text-center whitespace-nowrap min-w-[120px] bg-amber-50">มะเร็งช่องปาก</th>
</tr>
</thead>
<tbody>
<?php
// Helper functions for rendering cells and JSON mapping
$fmtLabObj = function($data) {
if (empty($data) || $data['res'] === '-') return '-';
return $data['res'] . ' (' . $data['date'] . ')';
};
if (!function_exists('fmtLabCell')) {
function fmtLabCell($data) {
if(empty($data) || $data['res'] === '-') return '<span class="text-slate-300">-</span>';
return '<span class="font-bold text-indigo-700">' . htmlspecialchars($data['res']) . '</span> <span class="text-[10px] text-slate-500 block leading-tight">(' . htmlspecialchars($data['date']) . ')</span>';
}
}
if (!function_exists('fmtScrCell')) {
function fmtScrCell($date) {
if(empty($date) || $date === '-') return '<span class="text-slate-300">-</span>';
return '<span class="font-medium text-amber-700">' . htmlspecialchars($date) . '</span>';
}
}
$no = 1;
foreach ($patientsData as $row):
$bg = $no % 2 == 0 ? 'bg-white' : 'bg-slate-50';
?>
<tr class="<?php echo $bg; ?> hover:bg-blue-50 border-b border-slate-100 table-row-item">
<td class="p-3 text-slate-500 text-center"><?php echo $no++; ?></td>
<td class="p-3 font-medium text-slate-700 hn-col"><?php echo htmlspecialchars($row['hn'] ?? ''); ?></td>
<td class="p-3 name-col">
<?php
$bday_formatted = '';
if (!empty($row['birthday']) && $row['birthday'] !== '0000-00-00') {
$time = strtotime($row['birthday']);
if ($time) {
$bday_formatted = date('d-m-', $time) . (date('Y', $time) + 543);
}
}
$ext = $row['extra'] ?? [];
$patient_json = htmlspecialchars(json_encode([
'hn' => $row['hn'] ?? '',
'name' => $row['pt_name'] ?? '',
'cid' => $row['cid'] ?? '',
'birthday' => $bday_formatted,
'age' => $row['age_y'] ?? '',
'sex' => $row['sex_name'] ?? '',
'address' => $row['addrpart'] ?? '',
'moo' => $row['moopart'] ?? '',
'tumbon' => $row['tmb_name'] ?? '',
'house_type' => $row['house_regist_type_id'] ?? '',
'phone' => $row['mobile_phone_number'] ?? '',
'member_id' => $row['clinicmember_id'] ?? '',
'clinic' => $row['clinic_name'] ?? $clinic_code_to_name[$row['clinic'] ?? ''] ?? $row['clinic'] ?? '-',
'regdate' => (!empty($row['regdate']) && $row['regdate'] != '0000-00-00') ? thai_date2($row['regdate']) : '-',
'dchdate' => (!empty($row['dchdate']) && $row['dchdate'] != '0000-00-00') ? thai_date2($row['dchdate']) : 'ยังไม่จำหน่าย',
'pttype' => $row['pttype_name'] ?? '',
'hospital' => $row['hosp_name'] ?? '',
'person_id' => $row['person_id'] ?? '',
'icd10' => $row['icd10'] ?? '',
'nextdate' => (!empty($row['nextdate']) && $row['nextdate'] != '0000-00-00') ? thai_date2($row['nextdate']) : 'ไม่มีนัด',
'nexttime' => (!empty($row['nexttime']) && $row['nexttime'] != '00:00:00') ? substr($row['nexttime'], 0, 5) . ' น.' : '-',
'labs' => [
'hba1c' => $fmtLabObj($ext['hba1c'] ?? null),
'urine_prot' => $fmtLabObj($ext['urine_prot'] ?? null),
'cr' => $fmtLabObj($ext['cr'] ?? null),
'urine_alb' => $fmtLabObj($ext['urine_alb'] ?? null),
'urine_cr' => $fmtLabObj($ext['urine_cr'] ?? null),
'hbsag' => $fmtLabObj($ext['hbsag'] ?? null),
'anti_hcv' => $fmtLabObj($ext['anti_hcv'] ?? null),
'hpv' => $fmtLabObj($ext['hpv'] ?? null),
'colon' => $fmtLabObj($ext['colon_cancer'] ?? null),
'ldl' => $fmtLabObj($ext['ldl'] ?? null)
],
'screen' => [
'eye' => $ext['eye_screen'] ?? '-',
'foot' => $ext['foot_screen'] ?? '-',
'oral' => $ext['oral_cancer'] ?? '-'
]
]), ENT_QUOTES, 'UTF-8');
?>
<button onclick="showPatientDetails(this)" data-patient="<?php echo $patient_json; ?>"
class="inline-flex items-center gap-3 group text-blue-600 hover:text-emerald-600 transition-colors cursor-pointer text-left focus:outline-none"
title="คลิกเพื่อดูรายละเอียดผู้ป่วย">
<div class="w-8 h-8 rounded-full bg-blue-50 text-blue-500 flex items-center justify-center shrink-0 group-hover:bg-emerald-50 group-hover:text-emerald-500 group-hover:scale-110 transition-all duration-300 shadow-sm border border-blue-100 group-hover:border-emerald-200">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path></svg>
</div>
<span class="font-bold tracking-tight underline-offset-4 group-hover:underline">
<?php echo htmlspecialchars($row['pt_name'] ?? ''); ?>
</span>
</button>
</td>
<td class="p-3 text-slate-600 cid-col"><?php echo htmlspecialchars($row['cid'] ?? ''); ?></td>
<td class="p-3 text-slate-500 text-center"><?php echo htmlspecialchars($bday_formatted); ?></td>
<td class="p-3 text-slate-700 text-center"><?php echo htmlspecialchars($row['age_y'] ?? ''); ?></td>
<td class="p-3 text-slate-500 text-center"><?php echo htmlspecialchars($row['sex_name'] ?? ''); ?></td>
<td class="p-3 text-slate-500 truncate max-w-[180px]" title="<?php echo htmlspecialchars($row['addrpart'] ?? ''); ?>"><?php echo htmlspecialchars($row['addrpart'] ?? ''); ?></td>
<td class="p-3 text-slate-500 text-center"><?php echo htmlspecialchars($row['moopart'] ?? ''); ?></td>
<td class="p-3 text-slate-600"><?php echo htmlspecialchars($row['tmb_name'] ?? ''); ?></td>
<td class="p-3 text-slate-500 text-center"><?php echo htmlspecialchars($row['house_regist_type_id'] ?? ''); ?></td>
<td class="p-3 text-slate-600"><?php echo htmlspecialchars($row['mobile_phone_number'] ?? ''); ?></td>
<td class="p-3 text-slate-600"><?php echo htmlspecialchars($row['clinicmember_id'] ?? ''); ?></td>
<td class="p-3 text-slate-500 text-center"><?php echo htmlspecialchars($row['regdate'] ?? ''); ?></td>
<td class="p-3 text-slate-700"><?php echo htmlspecialchars($row['pttype_name'] ?? ''); ?></td>
<td class="p-3 text-slate-600"><?php echo htmlspecialchars($row['hosp_name'] ?? ''); ?></td>
<td class="p-3 text-slate-500"><?php echo htmlspecialchars($row['person_id'] ?? ''); ?></td>
<td class="p-3 font-bold text-slate-700 text-center"><?php echo htmlspecialchars($row['icd10'] ?? ''); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-indigo-50/30 border-l border-indigo-100/50"><?php echo fmtLabCell($ext['hba1c'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-indigo-50/30"><?php echo fmtLabCell($ext['urine_prot'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-indigo-50/30"><?php echo fmtLabCell($ext['cr'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-indigo-50/30"><?php echo fmtLabCell($ext['urine_alb'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-indigo-50/30"><?php echo fmtLabCell($ext['urine_cr'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-indigo-50/30"><?php echo fmtLabCell($ext['hbsag'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-indigo-50/30"><?php echo fmtLabCell($ext['anti_hcv'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-indigo-50/30"><?php echo fmtLabCell($ext['hpv'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-indigo-50/30"><?php echo fmtLabCell($ext['colon_cancer'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-indigo-50/30"><?php echo fmtLabCell($ext['ldl'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-amber-50/30 border-l border-amber-100/50"><?php echo fmtScrCell($ext['eye_screen'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-amber-50/30"><?php echo fmtScrCell($ext['foot_screen'] ?? null); ?></td>
<td class="p-3 text-center whitespace-nowrap bg-amber-50/30"><?php echo fmtScrCell($ext['oral_cancer'] ?? null); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="p-3 border-t border-slate-200 bg-slate-50 text-xs text-slate-500 flex justify-between items-center">
<span>ดึงข้อมูลจาก HOSxP Database (<?php echo count($patientsData); ?> รายการ)</span>
</div>
</div>
<?php endif; ?>
</div>
</div>
<?php require_once("../components/layout_footer.php"); ?>
</main>
<script src="../assets/js/micro-interactions.js"></script>
<script>
$(document).ready(function() {
// Disabled prototype alert since we are querying real DB now
// Swal.fire({
// icon: 'info',
// ...
// });
$('#ncdTable').DataTable({
"pageLength": 10,
"language": {
"lengthMenu": "แสดง _MENU_ รายการต่อหน้า",
"zeroRecords": "ไม่พบข้อมูล",
"info": "แสดงหน้า _PAGE_ จาก _PAGES_",
"infoEmpty": "ไม่มีข้อมูล",
"infoFiltered": "(กรองจากทั้งหมด _MAX_ รายการ)",
"search": "ค้นหา:",
"paginate": {
"first": "หน้าแรก",
"last": "หน้าสุดท้าย",
"next": "ถัดไป",
"previous": "ก่อนหน้า"
}
},
"dom": '<"flex flex-col sm:flex-row justify-between items-center mb-4"<"flex items-center gap-4"l><"flex items-center gap-2 text-sm"fB>>rt<"flex flex-col sm:flex-row justify-between items-center mt-4"<"text-sm text-slate-500"i><"text-sm"p>>',
"buttons": {
dom: {
button: {
className: ''
}
},
buttons: [
{
extend: 'excelHtml5',
text: '<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2M15.8,20H14L12,16.6L10,20H8.2L11.1,15.5L8.2,11H10L12,14.4L14,11H15.8L12.9,15.5L15.8,20M13,9V3.5L18.5,9H13Z" /></svg>',
className: 'inline-flex items-center justify-center w-9 h-9 bg-gradient-to-r from-emerald-500 to-teal-600 rounded-lg text-white shadow-sm hover:shadow-md hover:from-emerald-600 hover:to-teal-700 focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:ring-offset-1 transition-all duration-200 p-0 ml-2 border-0 cursor-pointer',
titleAttr: 'ส่งออก Excel',
title: 'NCD_Registry_Export'
}
]
},
"scrollX": true,
"fixedColumns": {
left: 3
},
"ordering": true,
"order": [[ 1, "asc" ]] // Order by HN (Column index 1)
});
});
</script>
<!-- Processing Modal -->
<div id="processingModal" class="fixed inset-0 z-[100] hidden items-center justify-center bg-slate-900/50 backdrop-blur-sm transition-all duration-300 opacity-0">
<div class="bg-white rounded-2xl shadow-2xl p-8 max-w-sm w-full mx-4 transform scale-95 transition-all duration-300 flex flex-col items-center border border-emerald-100">
<!-- Spinner -->
<div class="relative w-20 h-20 mb-6">
<div class="absolute inset-0 border-4 border-slate-100 rounded-full"></div>
<div class="absolute inset-0 border-4 border-emerald-500 rounded-full border-t-transparent animate-spin"></div>
<div class="absolute inset-0 flex items-center justify-center text-emerald-600">
<svg class="w-8 h-8 animate-pulse" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path></svg>
</div>
</div>
<h3 class="text-xl font-bold text-slate-800 mb-2">กำลังประมวลผลข้อมูล...</h3>
<p class="text-sm text-slate-500 text-center mb-6">กรุณารอสักครู่ ระบบกำลังดึงและรวบรวมข้อมูลผู้ป่วยจากฐานข้อมูล HOSxP</p>
<!-- Timer -->
<div class="bg-emerald-50/50 border border-emerald-100 rounded-xl px-6 py-4 w-full flex justify-center items-center gap-3">
<svg class="w-5 h-5 text-emerald-600 animate-pulse" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<span id="processingTimer" class="font-mono text-2xl font-bold text-emerald-700 tracking-wider">00:00</span>
</div>
</div>
</div>
<script>
let timerInterval;
let secondsElapsed = 0;
function showProcessingModal() {
const modal = document.getElementById('processingModal');
const timerDisplay = document.getElementById('processingTimer');
secondsElapsed = 0;
timerDisplay.textContent = '00:00';
modal.classList.remove('hidden');
modal.classList.add('flex');
// Trigger reflow
void modal.offsetWidth;
modal.classList.remove('opacity-0');
modal.querySelector('div').classList.remove('scale-95');
modal.querySelector('div').classList.add('scale-100');
timerInterval = setInterval(() => {
secondsElapsed++;
const mins = String(Math.floor(secondsElapsed / 60)).padStart(2, '0');
const secs = String(secondsElapsed % 60).padStart(2, '0');
timerDisplay.textContent = `${mins}:${secs}`;
}, 1000);
return true;
}
function showPatientDetails(btn) {
const data = JSON.parse(btn.getAttribute('data-patient'));
Swal.fire({
title: '<div class="text-2xl font-bold text-slate-800 flex items-center gap-3 justify-center"><div class="w-10 h-10 rounded-full bg-emerald-100 text-emerald-600 flex items-center justify-center shrink-0"><svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path></svg></div>รายละเอียดผู้ป่วย NCD</div>',
html: `
<div class="mt-4 text-left space-y-4">
<div class="bg-slate-50 rounded-xl p-5 border border-slate-100 shadow-inner grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-4">
<!-- Section: ข้อมูลบุคคล -->
<div class="md:col-span-2 border-b border-slate-200 pb-2 mb-2">
<h4 class="font-bold text-slate-800 flex items-center gap-2"><svg class="w-4 h-4 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path></svg> ข้อมูลส่วนตัว</h4>
</div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">ชื่อ-สกุล</span><span class="text-sm font-bold text-emerald-700">${data.name}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">เลขบัตร ปชช.</span><span class="text-sm font-medium text-slate-700 tracking-wider">${data.cid}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">อายุ / เพศ</span><span class="text-sm font-medium text-slate-700">${data.age} ปี / ${data.sex} <span class="text-[11px] text-slate-400 font-normal ml-1 bg-white px-1.5 py-0.5 rounded border border-slate-200">เกิด ${data.birthday}</span></span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">เบอร์โทรติดต่อ</span><span class="text-sm font-medium text-slate-700">${data.phone || '-'}</span></div>
<div class="md:col-span-2 flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">ที่อยู่ปัจจุบัน</span><span class="text-sm font-medium text-slate-700">บ้านเลขที่ ${data.address} หมู่ ${data.moo} ต.${data.tumbon} <span class="text-[11px] bg-slate-200 text-slate-600 px-1.5 py-0.5 rounded">ประเภทบ้าน: ${data.house_type}</span></span></div>
<!-- Section: ข้อมูลคลินิกและการรักษา -->
<div class="md:col-span-2 border-b border-slate-200 pb-2 mt-2 mb-2">
<h4 class="font-bold text-slate-800 flex items-center gap-2"><svg class="w-4 h-4 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path></svg> ข้อมูลการรับบริการ</h4>
</div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">HN / Person ID</span><span class="text-sm font-bold text-blue-600 bg-blue-50 px-2 py-0.5 rounded border border-blue-100 w-max">${data.hn} / ${data.person_id}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">รหัสทะเบียน / Diag</span><span class="text-sm font-medium text-slate-700">${data.member_id} / <span class="font-bold text-slate-800">${data.icd10}</span></span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">คลินิกโรคเรื้อรัง</span><span class="text-sm font-bold text-slate-800">${data.clinic}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">สิทธิการรักษา / รพ.</span><span class="text-sm font-medium text-slate-700">${data.pttype} (${data.hospital})</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">วันที่ขึ้นทะเบียน</span><span class="text-sm font-medium text-slate-700">${data.regdate}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">สถานะจำหน่าย</span><span class="text-sm font-medium ${data.dchdate === 'ยังไม่จำหน่าย' ? 'text-emerald-600' : 'text-amber-600'}">${data.dchdate}</span></div>
<!-- Section: ผลทางห้องปฏิบัติการ (LAB) -->
<div class="md:col-span-2 border-b border-slate-200 pb-2 mt-4 mb-2">
<h4 class="font-bold text-slate-800 flex items-center gap-2"><svg class="w-4 h-4 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19.428 15.428a2 2 0 00-1.022-.547l-2.387-.477a6 6 0 00-3.86.517l-.318.158a6 6 0 01-3.86.517L6.05 15.21a2 2 0 00-1.806.547M8 4h8l-1 1v5.172a2 2 0 00.586 1.414l5 5c1.26 1.26.367 3.414-1.415 3.414H4.828c-1.782 0-2.674-2.154-1.414-3.414l5-5A2 2 0 009 10.172V5L8 4z"></path></svg> ผลทางห้องปฏิบัติการ (LAB ล่าสุด)</h4>
</div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">HbA1C</span><span class="text-sm font-bold text-indigo-700">${data.labs.hba1c}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">Urine Protein</span><span class="text-sm font-bold text-indigo-700">${data.labs.urine_prot}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">Cr</span><span class="text-sm font-bold text-indigo-700">${data.labs.cr}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">Urine Albumin</span><span class="text-sm font-bold text-indigo-700">${data.labs.urine_alb}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">Urine Cr</span><span class="text-sm font-bold text-indigo-700">${data.labs.urine_cr}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">HBsAg</span><span class="text-sm font-bold text-indigo-700">${data.labs.hbsag}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">Anti HCV</span><span class="text-sm font-bold text-indigo-700">${data.labs.anti_hcv}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">HPV</span><span class="text-sm font-bold text-indigo-700">${data.labs.hpv}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">มะเร็งลำไส้</span><span class="text-sm font-bold text-indigo-700">${data.labs.colon}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">LDL</span><span class="text-sm font-bold text-indigo-700">${data.labs.ldl}</span></div>
<!-- Section: การตรวจคัดกรอง -->
<div class="md:col-span-2 border-b border-slate-200 pb-2 mt-2 mb-2">
<h4 class="font-bold text-slate-800 flex items-center gap-2"><svg class="w-4 h-4 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path></svg> การตรวจคัดกรอง (ล่าสุด)</h4>
</div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">ตรวจตา</span><span class="text-sm font-bold text-amber-700">${data.screen.eye}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">ตรวจเท้า</span><span class="text-sm font-bold text-amber-700">${data.screen.foot}</span></div>
<div class="flex flex-col gap-1"><span class="text-xs font-semibold text-slate-500">มะเร็งช่องปาก</span><span class="text-sm font-bold text-amber-700">${data.screen.oral}</span></div>
</div>
</div>
`,
showCloseButton: true,
showConfirmButton: true,
confirmButtonText: 'ปิดหน้าต่าง',
confirmButtonColor: '#10b981',
customClass: {
container: 'backdrop-blur-sm',
popup: 'rounded-3xl shadow-2xl border border-slate-100 p-2',
title: 'border-b border-slate-100 pb-4',
closeButton: 'focus:outline-none hover:text-red-500 transition-colors',
confirmButton: 'rounded-xl px-6 py-2.5 font-bold shadow-sm'
},
width: '42rem'
});
}
</script>
</body>
</html>