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,281 @@
<?php
require_once 'includes/db.php';
require_once 'includes/auth.php';
requireLogin();
// Initialize default values to avoid errors
$totalCases = 0;
$totalFirstCalls = 0;
$totalCompleted = 0;
$totalPending = 0;
try {
// Fetch summary stats
$stmt = $pdo->query("SELECT COUNT(*) FROM incidents");
if ($stmt) {
$totalCases = $stmt->fetchColumn();
}
$stmt = $pdo->prepare("SELECT COUNT(*) FROM incidents WHERE channel LIKE :channel");
if ($stmt) {
$stmt->execute(['channel' => '%First Call%']);
$totalFirstCalls = $stmt->fetchColumn();
}
$stmt = $pdo->prepare("SELECT COUNT(*) FROM incidents WHERE status = :status");
if ($stmt) {
$stmt->execute(['status' => 'ปิดเคส']);
$totalCompleted = $stmt->fetchColumn();
}
$totalPending = max(0, $totalCases - $totalCompleted);
} catch (Exception $e) {
// Silently handle if incidents table doesn't exist yet
}
// Fetch Call Channels
$channelsQuery = "
SELECT
CASE
WHEN channel LIKE '%First Call%' THEN 'First Call (เบอร์ 1669 หลัก)'
WHEN channel LIKE '%Second Call%' THEN 'Second Call (สายซ้อนประสาน)'
WHEN channel LIKE '%วิทยุ%' THEN 'วิทยุสื่อสาร ว.6'
ELSE 'หมายเลขอื่น / ช่องทางอื่น ๆ'
END as channel_group,
COUNT(*) as count
FROM incidents
GROUP BY channel_group
";
$channelsResult = [];
try {
$stmt = $pdo->query($channelsQuery);
if ($stmt) {
$channelsResult = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
}
} catch (Exception $e) {}
// Fallback values if empty
$channels = [
'First Call (เบอร์ 1669 หลัก)' => $channelsResult['First Call (เบอร์ 1669 หลัก)'] ?? 0,
'Second Call (สายซ้อนประสาน)' => $channelsResult['Second Call (สายซ้อนประสาน)'] ?? 0,
'วิทยุสื่อสาร ว.6' => $channelsResult['วิทยุสื่อสาร ว.6'] ?? 0,
'หมายเลขอื่น / ช่องทางอื่น ๆ' => $channelsResult['หมายเลขอื่น / ช่องทางอื่น ๆ'] ?? 0,
];
// Fetch Phone Triage
$triageQuery = "
SELECT
CASE
WHEN phone_triage LIKE '%แดง%' THEN '🔴 สีแดง - วิกฤตสูงสุด'
WHEN phone_triage LIKE '%เหลือง%' THEN '🟡 สีเหลือง - เร่งด่วน'
WHEN phone_triage LIKE '%เขียว%' THEN '🟢 สีเขียว - เจ็บป่วยทั่วไป'
WHEN phone_triage LIKE '%ขาว%' THEN '⚪ สีขาว - ตรวจสุขภาพนัดส่งต่อ'
ELSE 'ไม่ระบุ'
END as triage_group,
COUNT(*) as count
FROM incidents
WHERE phone_triage IS NOT NULL AND phone_triage != ''
GROUP BY triage_group
";
$triageResult = [];
try {
$stmt = $pdo->query($triageQuery);
if ($stmt) {
$triageResult = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
}
} catch (Exception $e) {}
$triage = [
'🔴 สีแดง - วิกฤตสูงสุด' => $triageResult['🔴 สีแดง - วิกฤตสูงสุด'] ?? 0,
'🟡 สีเหลือง - เร่งด่วน' => $triageResult['🟡 สีเหลือง - เร่งด่วน'] ?? 0,
'🟢 สีเขียว - เจ็บป่วยทั่วไป' => $triageResult['🟢 สีเขียว - เจ็บป่วยทั่วไป'] ?? 0,
'⚪ สีขาว - ตรวจสุขภาพนัดส่งต่อ' => $triageResult['⚪ สีขาว - ตรวจสุขภาพนัดส่งต่อ'] ?? 0,
];
// Fetch Dispatcher Productivity
$productivity = [];
try {
$usersQuery = "SELECT id, username, full_name as name, role FROM users WHERE is_active = 1";
$stmt = $pdo->query($usersQuery);
if ($stmt) {
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($users as $user) {
// Calls & Cases Created
$stmt = $pdo->prepare("SELECT COUNT(*) FROM incidents WHERE created_by = :user_id");
$createdCount = 0;
if ($stmt) {
$stmt->execute(['user_id' => $user['id']]);
$createdCount = $stmt->fetchColumn();
}
// Assigned Cases (where they are completed_by)
$stmt = $pdo->prepare("SELECT COUNT(*) FROM incidents WHERE completed_by = :name OR completed_by = :username");
$assignedCount = 0;
if ($stmt) {
$stmt->execute(['name' => $user['name'], 'username' => $user['username']]);
$assignedCount = $stmt->fetchColumn();
}
// Completed Cases
$stmt = $pdo->prepare("SELECT COUNT(*) FROM incidents WHERE (completed_by = :name OR completed_by = :username) AND status = 'ปิดเคส'");
$resolvedCount = 0;
if ($stmt) {
$stmt->execute(['name' => $user['name'], 'username' => $user['username']]);
$resolvedCount = $stmt->fetchColumn();
}
$productivity[] = [
'fullName' => $user['name'],
'role' => $user['role'],
'createdCalls' => $createdCount,
'createdCases' => $createdCount,
'assignedCases' => $assignedCount,
'resolvedCases' => $resolvedCount,
];
}
}
} catch (Exception $e) {}
?>
<?php require_once 'includes/header.php'; ?>
<div class="space-y-6 animate-fadeIn pb-10">
<!-- Summary Cards -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div class="bg-white p-4 rounded-2xl shadow-sm border border-slate-100">
<div class="text-xs text-slate-400 font-bold">ยอดเคสสะสมในระบบ</div>
<div class="text-2xl font-black text-slate-800 mt-1"><?php echo $totalCases; ?> <span class="text-sm font-bold text-slate-500">เคส</span></div>
</div>
<div class="bg-white p-4 rounded-2xl shadow-sm border border-slate-100">
<div class="text-xs text-slate-400 font-bold">ยอดสายเรียกเข้าแรกรับ</div>
<div class="text-2xl font-black text-slate-800 mt-1"><?php echo $totalFirstCalls; ?> <span class="text-sm font-bold text-slate-500">สาย</span></div>
</div>
<div class="bg-white p-4 rounded-2xl shadow-sm border border-slate-100">
<div class="text-xs text-slate-400 font-bold">ประเมินเคสปิดสำเร็จ</div>
<div class="text-2xl font-black text-emerald-600 mt-1"><?php echo $totalCompleted; ?> <span class="text-sm font-bold text-slate-500">รายการ</span></div>
</div>
<div class="bg-white p-4 rounded-2xl shadow-sm border border-slate-100">
<div class="text-xs text-slate-400 font-bold font-sans">เคสตกค้าง/ยังไม่ปิด</div>
<div class="text-2xl font-black text-rose-600 mt-1"><?php echo $totalPending; ?> <span class="text-sm font-bold text-slate-500">รายการ</span></div>
</div>
</div>
<!-- Progress Bars Section -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Channels -->
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 p-4 md:p-5">
<h3 class="text-sm font-bold text-slate-800 mb-4">สัดส่วนช่องทางการแจ้งเหตุ (Call Channels)</h3>
<div class="space-y-4">
<?php
$maxChannels = max(array_values($channels)) ?: 1; // Prevent div by zero
$channelColors = [
'First Call (เบอร์ 1669 หลัก)' => 'bg-blue-600',
'Second Call (สายซ้อนประสาน)' => 'bg-blue-500',
'วิทยุสื่อสาร ว.6' => 'bg-indigo-500',
'หมายเลขอื่น / ช่องทางอื่น ๆ' => 'bg-purple-500'
];
foreach($channels as $name => $count):
$percent = ($count / $maxChannels) * 100;
$color = $channelColors[$name];
?>
<div>
<div class="flex justify-between items-center text-xs font-bold mb-1.5">
<span class="text-slate-600"><?php echo $name; ?></span>
<span class="text-slate-700"><?php echo $count; ?> รายการ</span>
</div>
<div class="w-full bg-slate-100 rounded-full h-2">
<div class="<?php echo $color; ?> h-2 rounded-full transition-all duration-1000" style="width: <?php echo $percent; ?>%;"></div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- Triage -->
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 p-4 md:p-5">
<h3 class="text-sm font-bold text-slate-800 mb-4">ระดับการประเมิน Phone Triage ฉุกเฉินคุกคามชีพ</h3>
<div class="space-y-4">
<?php
$maxTriage = max(array_values($triage)) ?: 1;
$triageColors = [
'🔴 สีแดง - วิกฤตสูงสุด' => 'bg-red-600',
'🟡 สีเหลือง - เร่งด่วน' => 'bg-amber-500',
'🟢 สีเขียว - เจ็บป่วยทั่วไป' => 'bg-emerald-500',
'⚪ สีขาว - ตรวจสุขภาพนัดส่งต่อ' => 'bg-slate-300'
];
foreach($triage as $name => $count):
$percent = ($count / $maxTriage) * 100;
$color = $triageColors[$name];
?>
<div>
<div class="flex justify-between items-center text-xs font-bold mb-1.5">
<span class="text-slate-600"><?php echo $name; ?></span>
<span class="text-slate-700"><?php echo $count; ?> รายการ</span>
</div>
<div class="w-full bg-slate-100 rounded-full h-2">
<div class="<?php echo $color; ?> h-2 rounded-full transition-all duration-1000" style="width: <?php echo $percent; ?>%;"></div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<!-- Productivity Table -->
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 overflow-hidden">
<div class="p-4 md:p-5 border-b border-slate-100 bg-slate-50 flex items-center justify-between">
<div>
<h3 class="text-base font-bold text-slate-800 flex items-center gap-1.5">
<i data-lucide="users" class="w-4.5 h-4.5 text-indigo-600"></i>
ดัชนีผลผลิตผู้ปฏิบัติการรับแจ้งเหตุและสั่งการ (Productivity ของเจ้าหน้าที่)
</h3>
<p class="text-xs text-slate-500 mt-1">คำนวณสถิติสรุปงานแยกรายเจ้าหน้าที่โดยอัตโนมัติอ้างอิงตาม username บันทึกข้อมูลจริงในข่าย</p>
</div>
</div>
<div class="overflow-x-auto">
<table class="w-full text-left border-collapse text-xs md:text-sm">
<thead>
<tr class="bg-slate-100/50 text-slate-600 font-bold border-b border-slate-100">
<th class="py-3 px-4">ชื่อเจ้าหน้าที่กู้ชีพกู้ภัย</th>
<th class="py-3 px-3 text-center">สิทธิ์ในระบบ</th>
<th class="py-3 px-3 text-center">รับสายโทรศัพท์ (สาย)</th>
<th class="py-3 px-3 text-center">สร้างเคสใหม่ (เคส)</th>
<th class="py-3 px-3 text-center">รับมอบ Complete (เคส)</th>
<th class="py-3 px-3 text-center">เคสที่ปิดแล้ว (เคส)</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100 text-slate-700 font-medium">
<?php foreach($productivity as $p): ?>
<tr class="hover:bg-slate-50/50 transition-colors">
<td class="py-3.5 px-4 font-bold text-slate-800"><?php echo htmlspecialchars($p['fullName']); ?></td>
<td class="py-3.5 px-3 text-center">
<span class="bg-slate-100 text-slate-600 px-2 py-0.5 rounded text-[10px] font-bold border border-slate-200 uppercase">
<?php echo htmlspecialchars($p['role']); ?>
</span>
</td>
<td class="py-3.5 px-3 text-center font-bold text-slate-700"><?php echo $p['createdCalls']; ?></td>
<td class="py-3.5 px-3 text-center font-bold text-slate-700"><?php echo $p['createdCases']; ?></td>
<td class="py-3.5 px-3 text-center font-bold text-slate-700"><?php echo $p['assignedCases']; ?></td>
<td class="py-3.5 px-3 text-center">
<span class="bg-emerald-50 text-emerald-700 font-black px-2 py-0.5 rounded text-xs">
<?php echo $p['resolvedCases']; ?> เคสสำเร็จ
</span>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<script>
lucide.createIcons();
</script>
<?php require_once 'includes/footer.php'; ?>