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
@@ -0,0 +1,42 @@
<?php
// includes/db.php
$host = '10.0.250.250'; // กำหนด IP ของ Server ฐานข้อมูล HOSxP
$db = 'hos'; // ชื่อฐานข้อมูล
$user = 'dmstele'; // Username
$pass = 'dmstele10742'; // Password
$charset = 'utf8';
$settings_password = '123456'; // รหัสผ่านสำหรับเข้าหน้าตั้งค่า
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
// ในกรณีที่เชื่อมต่อไม่ได้ ให้แสดง Error (หรือจัดการ Error ตามต้องการ)
// throw new \PDOException($e->getMessage(), (int)$e->getCode());
$pdo = null;
}
// ------------------------------------------------------------------
// ฐานข้อมูลตัวที่ 2: สำหรับเก็บ SQL Configuration (Dashboard)
// ------------------------------------------------------------------
$host2 = '127.0.0.1'; // TODO: เปลี่ยนเป็น IP ของเซิร์ฟเวอร์ฐานข้อมูล dashboard
$db2 = 'dashboard'; // ชื่อฐานข้อมูล
$user2 = 'root'; // TODO: เปลี่ยน Username
$pass2 = ''; // TODO: เปลี่ยน Password
$dsn2 = "mysql:host=$host2;dbname=$db2;charset=$charset";
try {
$pdo_dashboard = new PDO($dsn2, $user2, $pass2, $options);
} catch (\PDOException $e) {
$pdo_dashboard = null; // หากต่อไม่ติดให้ fallback กลับไปใช้ JSON หรือ Error
}
@@ -0,0 +1,60 @@
<!-- includes/header.php -->
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ลดแออัดลดระยะเวลารอคอย - One Province One Hospital (รพ.เกาะสมุย)</title>
<!-- Favicon -->
<link rel="icon" type="image/png" href="assets/img/logo.png">
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- Chart.js DataLabels Plugin -->
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.0.0"></script>
<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<!-- SQL Formatter -->
<script src="https://unpkg.com/sql-formatter@15.3.0/dist/sql-formatter.min.js"></script>
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { sans: ['Sarabun', 'sans-serif'], },
colors: { medical: { 50: '#f0f9ff', 100: '#e0f2fe', 500: '#0ea5e9', 600: '#0284c7', 700: '#0369a1', 900: '#0f172a' } },
boxShadow: { 'premium': '0 8px 30px -4px rgba(0,0,0,0.06)', 'premium-hover': '0 20px 40px -10px rgba(0,0,0,0.12)', 'inner-glow': 'inset 0 2px 10px rgba(255,255,255,0.3)' }
}
}
}
</script>
<style>
body { font-family: 'Sarabun', sans-serif; background-color: #f8fafc; }
.gradient-text { background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
.card-premium { background: #ffffff; border-radius: 1rem; box-shadow: 0 8px 30px -4px rgba(0,0,0,0.05); border: 1px solid rgba(226, 232, 240, 0.6); transition: all 0.3s ease; position: relative; overflow: hidden; }
.card-premium:hover { transform: translateY(-3px); box-shadow: 0 20px 40px -10px rgba(0,0,0,0.1); }
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 10px; border: 2px solid #f8fafc; }
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
.flow-container { position: relative; z-index: 1; }
.flow-line { position: absolute; top: 50%; left: 5%; right: 5%; height: 4px; background: linear-gradient(90deg, #3b82f6, #10b981); z-index: -1; transform: translateY(-50%); border-radius: 4px; opacity: 0.3; }
@media (max-width: 768px) { .flow-line { display: none; } }
.glass-dark { background: rgba(15, 23, 42, 0.85); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-bottom: 1px solid rgba(255, 255, 255, 0.05); }
#sidebar { transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1); }
.custom-scrollbar::-webkit-scrollbar { width: 4px; }
@keyframes fadeIn {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-fade-in {
animation: fadeIn 0.35s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
</style>
</head>
@@ -0,0 +1,74 @@
<!-- includes/sidebar.php -->
<aside id="sidebar" class="fixed inset-y-0 left-0 z-50 w-72 bg-gradient-to-b from-[#0f172a] to-slate-900 text-slate-300 transform -translate-x-full transition-transform duration-300 shadow-[20px_0_40px_rgba(0,0,0,0.3)] flex flex-col border-r border-slate-800">
<div class="h-[72px] flex items-center justify-between px-6 border-b border-slate-800/80 shrink-0 bg-slate-900/50">
<div class="flex items-center gap-3">
<div class="w-8 h-8 rounded-lg bg-white flex items-center justify-center shadow-lg shadow-blue-500/30 overflow-hidden">
<img src="assets/img/logo.png" alt="Logo" class="w-full h-full object-contain p-0.5">
</div>
<span class="font-bold text-lg text-white tracking-wide">เมนูระบบ</span>
</div>
<button onclick="window.closeSidebar()" class="text-slate-400 hover:text-white p-2 rounded-lg hover:bg-slate-800 transition-colors focus:outline-none">
<i class="fa-solid fa-xmark text-xl"></i>
</button>
</div>
<nav class="flex-1 px-4 py-6 space-y-2 overflow-y-auto custom-scrollbar">
<p class="px-3 text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-3">ระบบประเมินผล (Dashboards)</p>
<button onclick="window.switchTab('tab-overview', this, 'ภาพรวมโรงพยาบาล (Overview)')" class="w-full flex items-center px-4 py-3.5 rounded-xl bg-blue-600/20 text-blue-400 font-bold sidebar-tab transition-all border border-blue-500/20 shadow-[inset_0_1px_1px_rgba(255,255,255,0.05)]">
<i class="fa-solid fa-chart-pie w-6 text-lg"></i> <span class="tracking-wide">ภาพรวม</span>
</button>
<div class="pt-1 pb-1">
<button onclick="window.toggleSubmenu('submenu-opd', this)" class="w-full flex items-center justify-between px-4 py-3.5 rounded-xl text-slate-400 hover:bg-slate-800/80 hover:text-white font-medium transition-all group border border-transparent focus:outline-none">
<div class="flex items-center"><i class="fa-solid fa-stopwatch w-6 text-lg group-hover:text-blue-400 transition-colors"></i> <span class="tracking-wide">ลดรอคอย OPD</span></div>
<i class="fa-solid fa-chevron-down text-xs transition-transform duration-300" id="icon-submenu-opd"></i>
</button>
<div id="submenu-opd" class="hidden flex-col pl-11 pr-2 py-2 mt-1 space-y-1.5 border-l border-slate-700 ml-5 relative before:absolute before:top-0 before:bottom-0 before:left-[-1px] before:w-[2px] before:bg-gradient-to-b before:from-blue-500/50 before:to-transparent">
<button onclick="window.switchTab('tab-opd-overview', this, 'ภาพรวมลดรอคอย OPD')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group"><span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-blue-400 transition-colors"></span><i class="fa-solid fa-chart-line mr-3 text-slate-500 group-hover:text-blue-400 transition-colors"></i> ภาพรวมลดรอคอย</button>
<button onclick="window.switchTab('tab-opd-condition', this, 'ระยะเวลาตามเงื่อนไข (OPD)')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group"><span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-blue-400 transition-colors"></span><i class="fa-solid fa-filter mr-3 text-slate-500 group-hover:text-blue-400 transition-colors"></i> ระยะเวลาตามเงื่อนไข</button>
<button onclick="window.switchTab('tab-opd-service', this, 'บริการผู้ป่วยนอก')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group"><span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-blue-400 transition-colors"></span><i class="fa-solid fa-hand-holding-medical mr-3 text-slate-500 group-hover:text-blue-400 transition-colors"></i> บริการผู้ป่วยนอก</button>
<button onclick="window.switchTab('tab-opd-refer', this, 'ข้อมูลการส่งต่อผู้ป่วยนอก (Refer OPD)')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group"><span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-blue-400 transition-colors"></span><i class="fa-solid fa-truck-medical mr-3 text-slate-500 group-hover:text-blue-400 transition-colors"></i> Refer OPD</button>
<button onclick="window.switchTab('tab-opd-doctor', this, 'เวลาลงตรวจ')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group"><span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-blue-400 transition-colors"></span><i class="fa-solid fa-user-doctor mr-3 text-slate-500 group-hover:text-blue-400 transition-colors"></i> เวลาลงตรวจ</button>
<button onclick="window.switchTab('tab-opd-satisfaction', this, 'ความพึงพอใจผู้รับบริการ')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group"><span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-blue-400 transition-colors"></span><i class="fa-solid fa-face-smile-beam mr-3 text-slate-500 group-hover:text-blue-400 transition-colors"></i> ความพึงพอใจ</button>
</div>
</div>
<div class="pt-1 pb-1">
<button onclick="window.toggleSubmenu('submenu-ipd', this)" class="w-full flex items-center justify-between px-4 py-3.5 rounded-xl text-slate-400 hover:bg-slate-800/80 hover:text-white font-medium transition-all group border border-transparent focus:outline-none">
<div class="flex items-center"><i class="fa-solid fa-bed-pulse w-6 text-lg group-hover:text-emerald-400 transition-colors"></i> <span class="tracking-wide">ลดแออัด IPD</span></div>
<i class="fa-solid fa-chevron-down text-xs transition-transform duration-300" id="icon-submenu-ipd"></i>
</button>
<div id="submenu-ipd" class="hidden flex-col pl-11 pr-2 py-2 mt-1 space-y-1.5 border-l border-slate-700 ml-5 relative before:absolute before:top-0 before:bottom-0 before:left-[-1px] before:w-[2px] before:bg-gradient-to-b before:from-emerald-500/50 before:to-transparent">
<button onclick="window.switchTab('tab-ipd-occ', this, 'อัตราการครองเตียง (IPD)')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group"><span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-emerald-400 transition-colors"></span><i class="fa-solid fa-chart-column mr-3 text-slate-500 group-hover:text-emerald-400 transition-colors"></i> อัตราการครองเตียง</button>
<button onclick="window.switchTab('tab-ipd-round', this, 'สถิติแพทย์ Round Ward')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group"><span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-emerald-400 transition-colors"></span><i class="fa-solid fa-user-md mr-3 text-slate-500 group-hover:text-emerald-400 transition-colors"></i> แพทย์ Round Ward</button>
<button onclick="window.switchTab('tab-ipd-refer', this, 'ข้อมูลการส่งต่อผู้ป่วย (Refer IPD)')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group"><span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-emerald-400 transition-colors"></span><i class="fa-solid fa-truck-medical mr-3 text-slate-500 group-hover:text-emerald-400 transition-colors"></i> ข้อมูลการส่งต่อ (Refer)</button>
<button onclick="window.switchTab('tab-ipd-adjrw', this, 'สถิติ Sum AdjRW (การส่งต่อ)')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group"><span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-emerald-400 transition-colors"></span><i class="fa-solid fa-weight-scale mr-3 text-slate-500 group-hover:text-emerald-400 transition-colors"></i> Sum AdjRW</button>
</div>
</div>
<div class="pt-1 pb-1">
<button onclick="window.toggleSubmenu('submenu-stats', this)" class="w-full flex items-center justify-between px-4 py-3.5 rounded-xl text-slate-400 hover:bg-slate-800/80 hover:text-white font-medium transition-all group border border-transparent focus:outline-none">
<div class="flex items-center"><i class="fa-solid fa-chart-bar w-6 text-lg group-hover:text-indigo-400 transition-colors"></i> <span class="tracking-wide">ข้อมูลสถิติ (Statistics)</span></div>
<i class="fa-solid fa-chevron-down text-xs transition-transform duration-300" id="icon-submenu-stats"></i>
</button>
<div id="submenu-stats" class="hidden flex-col pl-11 pr-2 py-2 mt-1 space-y-1.5 border-l border-slate-700 ml-5 relative before:absolute before:top-0 before:bottom-0 before:left-[-1px] before:w-[2px] before:bg-gradient-to-b before:from-indigo-500/50 before:to-transparent">
<button onclick="window.switchTab('tab-disease', this, 'สถิติโรค')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group">
<span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-indigo-400 transition-colors"></span>
<i class="fa-solid fa-virus mr-3 text-slate-500 group-hover:text-indigo-400 transition-colors"></i> สถิติโรค
</button>
<button onclick="window.switchTab('tab-service', this, 'สถิติรับบริการรวม')" class="w-full flex items-center px-4 py-2.5 rounded-lg text-slate-400 hover:bg-slate-800/80 hover:text-white text-sm sidebar-tab transition-all relative group">
<span class="absolute left-[-17px] top-1/2 -translate-y-1/2 w-3 h-[1px] bg-slate-600 group-hover:bg-indigo-400 transition-colors"></span>
<i class="fa-solid fa-users mr-3 text-slate-500 group-hover:text-indigo-400 transition-colors"></i> สถิติรับบริการรวม
</button>
</div>
</div>
<p class="px-3 text-[10px] font-bold text-slate-500 uppercase tracking-wider mb-3 mt-4">ตั้งค่าระบบ (Settings)</p>
<button onclick="window.switchTab('tab-settings', this, 'ตั้งค่าชุดคำสั่ง SQL (SQL Settings)')" class="w-full flex items-center px-4 py-3.5 rounded-xl text-slate-400 hover:bg-slate-800/80 hover:text-white font-medium sidebar-tab transition-all border border-transparent focus:outline-none group">
<i class="fa-solid fa-gear w-6 text-lg group-hover:text-slate-300 transition-colors"></i> <span class="tracking-wide">ตั้งค่า SQL</span>
</button>
</nav>
</aside>
@@ -0,0 +1,32 @@
<?php
// includes/sql_config.php
require_once __DIR__ . '/db.php';
$sql_config = [];
$fallback_json_path = __DIR__ . '/sql_config.json';
$fallback_config = file_exists($fallback_json_path) ? json_decode(file_get_contents($fallback_json_path), true) : [];
if (isset($pdo_dashboard) && $pdo_dashboard) {
try {
$stmt = $pdo_dashboard->query("SELECT section_name, query_key, sql_text FROM waiting");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$sql_config[$row['section_name']][$row['query_key']] = $row['sql_text'];
}
} catch (\PDOException $e) {
// อาจจะยังไม่มีตาราง waiting ให้ fallback ไปใช้ JSON ก่อน
}
}
// หากใน DB ไม่มีข้อมูลบาง key จะดึงจาก JSON มาเติมให้สมบูรณ์ (Fallback)
if (is_array($fallback_config)) {
foreach ($fallback_config as $section => $keys) {
if (!isset($sql_config[$section])) {
$sql_config[$section] = [];
}
foreach ($keys as $key => $sql) {
if (!isset($sql_config[$section][$key])) {
$sql_config[$section][$key] = $sql;
}
}
}
}
@@ -0,0 +1,23 @@
<!-- includes/topbar.php -->
<header class="glass-dark text-white z-20 shadow-xl shrink-0 h-[72px] flex items-center">
<div class="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-blue-500 via-teal-400 to-emerald-500"></div>
<div class="px-4 md:px-6 flex justify-between items-center w-full">
<div class="flex items-center gap-3 md:gap-4">
<button onclick="window.openSidebar()" class="text-white hover:text-blue-400 focus:outline-none p-2 md:p-2.5 rounded-xl bg-white/5 hover:bg-white/10 border border-white/10 transition-all shadow-sm">
<i class="fa-solid fa-bars text-lg md:text-xl"></i>
</button>
<div class="flex items-center">
<div class="w-10 h-10 bg-white rounded-xl flex items-center justify-center mr-3 shadow-[0_0_10px_rgba(255,255,255,0.1)] hidden sm:flex overflow-hidden">
<img src="assets/img/logo.png" alt="MOPH Logo" class="w-full h-full object-contain p-1">
</div>
<div>
<h1 class="font-extrabold text-sm sm:text-base tracking-wide bg-gradient-to-r from-white to-blue-200 gradient-text leading-tight">ลดแออัดลดระยะเวลารอคอย</h1>
<p class="text-[9px] sm:text-[10px] text-blue-300 uppercase tracking-widest font-semibold hidden sm:block">One province one hospital (รพ.เกาะสมุย)</p>
</div>
</div>
</div>
<div class="flex items-center gap-3">
<!-- ปุ่มพิมพ์ถูกนำออกตามคำขอ -->
</div>
</div>
</header>