282 lines
14 KiB
PHP
282 lines
14 KiB
PHP
<?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'; ?>
|