Files
2026-09-16 23:20:08 +07:00

327 lines
31 KiB
PHP

<?php
require_once 'includes/auth.php';
require_once 'includes/db.php';
$pageTitle = 'พนักงานขับรถ | ระบบจัดการข้อมูลยานพาหนะ โรงพยาบาลเกาะสมุย';
$pageTitleDisplay = 'พนักงานขับรถ';
$breadcrumbs = ['พนักงานขับรถ'];
require_once 'includes/header.php';
// ดึงข้อมูลพนักงานขับรถ
$stmt = $pdo->query("SELECT * FROM drivers ORDER BY first_name ASC");
$drivers = $stmt->fetchAll();
?>
<!-- Floating Background -->
<div class="fixed top-0 left-0 w-full h-full overflow-hidden -z-10 pointer-events-none">
<div class="absolute top-[-10%] left-[-10%] w-[40%] h-[40%] bg-primary-500/10 rounded-full blur-[100px]"></div>
<div class="absolute bottom-[-10%] right-[-10%] w-[40%] h-[40%] bg-secondary/10 rounded-full blur-[100px]"></div>
</div>
<!-- Layout Wrapper -->
<div x-data="driverManager()" class="flex h-screen overflow-hidden">
<!-- Sidebar -->
<?php include 'includes/sidebar.php'; ?>
<!-- Main Content -->
<main class="flex-1 flex flex-col min-w-0 overflow-hidden relative z-10">
<!-- Top Navbar -->
<?php include 'includes/navbar.php'; ?>
<!-- Dashboard Content -->
<div class="flex-1 overflow-y-auto p-4 pt-0 custom-scrollbar page-transition">
<div class="mb-6 flex justify-between items-end">
<div>
<h1 class="text-2xl font-bold dark:text-white tracking-tight">พนักงานขับรถ</h1>
<p class="text-slate-500 dark:text-slate-400 mt-1">รายชื่อและสถานะของพนักงานขับรถทั้งหมด</p>
</div>
<button @click="openModal()" class="btn-gradient px-4 py-2 text-sm flex items-center shadow-lg shadow-primary-500/30 hover:shadow-primary-500/50 transition-all hover:-translate-y-0.5">
<i class="fa-solid fa-user-plus mr-2"></i> เพิ่มพนักงาน
</button>
</div>
<!-- Grid Section -->
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
<?php if(count($drivers) > 0): ?>
<?php foreach($drivers as $d): ?>
<div class="glass-card p-6 flex flex-col hover:-translate-y-1 transition-transform duration-300 relative overflow-hidden">
<!-- Status Indicator (Top Right) -->
<div class="absolute top-4 right-4">
<select @change="updateStatus(<?= $d['id'] ?>, $event.target.value)" class="text-xs bg-white/50 dark:bg-slate-800/50 border border-slate-200 dark:border-slate-700 rounded-lg px-2 py-1 focus:outline-none focus:ring-1 focus:ring-primary-500">
<option value="available" <?= $d['status'] == 'available' ? 'selected' : '' ?>>🟢 ว่าง</option>
<option value="busy" <?= $d['status'] == 'busy' ? 'selected' : '' ?>>🟠 ติดภารกิจ</option>
<option value="leave" <?= $d['status'] == 'leave' ? 'selected' : '' ?>>⚪ ลางาน</option>
</select>
</div>
<div class="flex items-center space-x-4 mb-4">
<img src="<?= !empty($d['hr_cid']) ? 'api/hr_image.php?cid='.urlencode($d['hr_cid']) : ($d['avatar'] ? htmlspecialchars($d['avatar']) : 'https://ui-avatars.com/api/?name='.urlencode($d['first_name'].' '.$d['last_name']).'&background=random') ?>" alt="Avatar" class="w-16 h-16 rounded-full object-cover border-2 border-primary-100 dark:border-primary-900 shadow-md bg-slate-100">
<div>
<h3 class="text-lg font-bold dark:text-white flex items-center gap-2">
<?= htmlspecialchars($d['first_name'] . ' ' . $d['last_name']) ?>
<?php if(!empty($d['sex']) && $d['sex'] === 'M'): ?><i class="fa-solid fa-mars text-blue-500 text-sm" title="ชาย"></i><?php endif; ?>
<?php if(!empty($d['sex']) && $d['sex'] === 'F'): ?><i class="fa-solid fa-venus text-pink-500 text-sm" title="หญิง"></i><?php endif; ?>
</h3>
<p class="text-sm text-slate-500 dark:text-slate-400"><?= !empty($d['position']) ? htmlspecialchars($d['position']) : 'พนักงานขับรถประจำ' ?></p>
<?php if(!empty($d['department'])): ?>
<p class="text-xs text-primary-600/80 dark:text-primary-400/80 mt-0.5 font-medium"><?= htmlspecialchars($d['department']) ?></p>
<?php endif; ?>
</div>
</div>
<div class="space-y-2 mt-2 mb-4">
<div class="flex items-center text-sm text-slate-600 dark:text-slate-300">
<i class="fa-solid fa-phone w-5 text-center text-slate-400"></i>
<span class="ml-2"><?= htmlspecialchars($d['phone'] ?: 'ไม่ได้ระบุ') ?></span>
</div>
<?php if(!empty($d['license_type'])): ?>
<div class="flex items-center text-sm text-slate-600 dark:text-slate-300 mb-1">
<i class="fa-solid fa-id-badge w-5 text-center text-slate-400"></i>
<span class="ml-2">ประเภทใบขับขี่: <?= htmlspecialchars($d['license_type']) ?></span>
</div>
<?php endif; ?>
<?php if(!empty($d['license_expiry_date'])): ?>
<div class="flex items-center text-sm <?php echo (strtotime($d['license_expiry_date']) < time()) ? 'text-danger font-medium' : 'text-slate-600 dark:text-slate-300'; ?>">
<i class="fa-solid fa-id-card w-5 text-center <?php echo (strtotime($d['license_expiry_date']) < time()) ? 'text-danger' : 'text-slate-400'; ?>"></i>
<span class="ml-2">หมดอายุ: <span x-text="formatThaiDate('<?= $d['license_expiry_date'] ?>')"></span></span>
</div>
<?php endif; ?>
</div>
<div class="mt-auto pt-4 border-t border-slate-200 dark:border-slate-700/50 flex justify-end space-x-2">
<button @click="deleteDriver(<?= $d['id'] ?>)" class="px-3 py-1.5 text-xs font-medium text-danger bg-red-50 hover:bg-red-100 dark:bg-red-900/20 dark:hover:bg-red-900/40 rounded-lg transition-colors"><i class="fa-solid fa-trash mr-1"></i> ลบ</button>
<button @click="openModal(<?= htmlspecialchars(json_encode($d), ENT_QUOTES, 'UTF-8') ?>)" class="px-3 py-1.5 text-xs font-medium text-white bg-primary-600 hover:bg-primary-700 rounded-lg transition-colors shadow-sm shadow-primary-600/30"><i class="fa-solid fa-pen-to-square mr-1"></i> แก้ไข</button>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="col-span-full glass-card p-10 flex flex-col items-center justify-center text-slate-500">
<i class="fa-solid fa-users-slash text-4xl mb-4 opacity-50"></i>
<p>ไม่พบข้อมูลพนักงานขับรถ</p>
</div>
<?php endif; ?>
</div>
</div>
<!-- Driver Modal -->
<div x-show="showModal" style="display: none;" class="fixed inset-0 z-50 overflow-y-auto" aria-labelledby="modal-title" role="dialog" aria-modal="true">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div x-show="showModal" x-transition.opacity class="fixed inset-0 bg-slate-900/60 dark:bg-slate-900/80 backdrop-blur-sm transition-opacity" @click="closeModal()"></div>
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
<div x-show="showModal"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
class="relative z-10 inline-block align-bottom bg-white dark:bg-slate-800 rounded-[20px] text-left overflow-hidden shadow-2xl transform transition-all sm:my-8 sm:align-middle sm:max-w-md w-full border border-slate-200 dark:border-slate-700/50">
<div class="px-6 py-5 border-b border-slate-100 dark:border-slate-700/50 flex justify-between items-center bg-slate-50/50 dark:bg-slate-800/50">
<h3 class="text-lg leading-6 font-bold text-slate-900 dark:text-white" id="modal-title" x-text="isEdit ? 'แก้ไขข้อมูลพนักงาน' : 'เพิ่มพนักงานใหม่'"></h3>
<button @click="closeModal()" class="text-slate-400 hover:text-slate-500 focus:outline-none bg-slate-100 hover:bg-slate-200 dark:bg-slate-700 dark:hover:bg-slate-600 rounded-full p-2 transition-colors">
<i class="fa-solid fa-xmark w-4 h-4 flex items-center justify-center"></i>
</button>
</div>
<div class="px-6 py-5">
<form @submit.prevent="saveDriver">
<div class="grid grid-cols-1 gap-y-4 gap-x-4 sm:grid-cols-2">
<div class="sm:col-span-2 relative" x-show="!isEdit">
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1"><i class="fa-solid fa-hospital-user text-primary-500 mr-1"></i> ค้นหาพนักงานจากระบบ HIS (hosoffice)</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<i class="fa-solid fa-search text-slate-400"></i>
</div>
<input type="text" x-model="hrSearchQuery" @input.debounce.500ms="searchHrPerson" class="glass-input block w-full pl-10 p-2.5 text-sm" placeholder="พิมพ์ชื่อหรือนามสกุล (อย่างน้อย 2 ตัวอักษร)...">
</div>
<!-- Autocomplete Dropdown -->
<div x-show="hrSearchResults.length > 0" @click.away="hrSearchResults = []" style="display: none;" class="absolute z-10 w-full mt-1 bg-white dark:bg-slate-800 rounded-md shadow-lg shadow-slate-200/50 dark:shadow-slate-900/50 border border-slate-200 dark:border-slate-700 max-h-80 overflow-auto">
<ul class="py-1 text-sm text-slate-700 dark:text-slate-200">
<template x-for="person in hrSearchResults">
<li>
<button type="button" @click="selectHrPerson(person)" class="w-full text-left px-4 py-3 hover:bg-primary-50 dark:hover:bg-slate-700 transition-colors border-b border-slate-100 dark:border-slate-700/50 last:border-0 flex items-start gap-3">
<div class="flex-shrink-0 mt-0.5">
<img x-show="person.has_image" :src="'api/hr_image.php?cid=' + person.cid" class="w-10 h-10 rounded-full object-cover border border-slate-200 dark:border-slate-600">
<div x-show="!person.has_image" class="w-10 h-10 rounded-full bg-slate-200 dark:bg-slate-700 flex items-center justify-center text-slate-500 dark:text-slate-400">
<i class="fa-solid fa-user"></i>
</div>
</div>
<div class="flex-1 min-w-0">
<div class="font-bold text-primary-700 dark:text-primary-400 flex items-center gap-2">
<span x-text="person.full_name"></span>
<i x-show="person.sex === 'M'" class="fa-solid fa-mars text-blue-500 text-xs" title="ชาย"></i>
<i x-show="person.sex === 'F'" class="fa-solid fa-venus text-pink-500 text-xs" title="หญิง"></i>
</div>
<div class="text-xs text-slate-500 dark:text-slate-400 mt-1 flex flex-col gap-0.5">
<span x-show="person.position" x-text="'ตำแหน่ง: ' + person.position"></span>
<span x-show="person.department" x-text="'หน่วยงาน: ' + person.department"></span>
<span x-show="person.work_duration" x-text="'อายุงาน: ' + person.work_duration"></span>
</div>
</div>
</button>
</li>
</template>
</ul>
</div>
</div>
<div>
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">ชื่อ <span class="text-danger">*</span></label>
<input type="text" x-model="form.first_name" required class="glass-input block w-full p-2.5 text-sm" placeholder="เช่น สมชาย">
</div>
<div>
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">นามสกุล <span class="text-danger">*</span></label>
<input type="text" x-model="form.last_name" required class="glass-input block w-full p-2.5 text-sm" placeholder="เช่น รักดี">
</div>
<div class="sm:col-span-2">
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">เบอร์โทรศัพท์</label>
<input type="text" x-model="form.phone" class="glass-input block w-full p-2.5 text-sm" placeholder="เช่น 0812345678">
</div>
<!-- ข้อมูลจาก HIS (Readonly) -->
<div class="sm:col-span-2 grid grid-cols-1 sm:grid-cols-2 gap-4 mt-2 p-4 bg-primary-50/50 dark:bg-primary-900/10 rounded-xl border border-primary-100 dark:border-primary-900/30" x-show="form.hr_cid" style="display: none;">
<div class="sm:col-span-2 mb-1">
<h4 class="text-xs font-bold text-primary-600 dark:text-primary-400 uppercase tracking-wider"><i class="fa-solid fa-link mr-1"></i> ข้อมูลที่เชื่อมโยงจาก HIS</h4>
</div>
<div>
<label class="block text-xs font-medium text-slate-500 dark:text-slate-400 mb-1">ตำแหน่ง</label>
<input type="text" x-model="form.position" readonly class="glass-input block w-full p-2 text-sm bg-slate-50 dark:bg-slate-800/50 text-slate-600 dark:text-slate-300 border-slate-200 dark:border-slate-700 cursor-not-allowed">
</div>
<div>
<label class="block text-xs font-medium text-slate-500 dark:text-slate-400 mb-1">หน่วยงาน</label>
<input type="text" x-model="form.department" readonly class="glass-input block w-full p-2 text-sm bg-slate-50 dark:bg-slate-800/50 text-slate-600 dark:text-slate-300 border-slate-200 dark:border-slate-700 cursor-not-allowed">
</div>
<div>
<label class="block text-xs font-medium text-slate-500 dark:text-slate-400 mb-1">ประเภทพนักงาน</label>
<input type="text" x-model="form.person_type" readonly class="glass-input block w-full p-2 text-sm bg-slate-50 dark:bg-slate-800/50 text-slate-600 dark:text-slate-300 border-slate-200 dark:border-slate-700 cursor-not-allowed">
</div>
<div>
<label class="block text-xs font-medium text-slate-500 dark:text-slate-400 mb-1">รหัสอ้างอิง (CID)</label>
<input type="text" x-model="form.hr_cid" readonly class="glass-input block w-full p-2 text-sm bg-slate-50 dark:bg-slate-800/50 text-slate-600 dark:text-slate-300 border-slate-200 dark:border-slate-700 cursor-not-allowed">
</div>
</div>
<div class="sm:col-span-2">
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">สถานะเริ่มต้น</label>
<select x-model="form.status" class="glass-input block w-full p-2.5 text-sm">
<option value="available">ว่าง</option>
<option value="busy">ติดภารกิจ</option>
<option value="leave">ลางาน</option>
</select>
</div>
<div class="sm:col-span-2">
<div class="flex items-center mb-1">
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300">ประเภทใบขับขี่</label>
<div class="relative ml-2 flex items-center group">
<i class="fa-solid fa-circle-info text-slate-400 group-hover:text-primary-500 cursor-help transition-colors"></i>
<div class="absolute left-6 top-1/2 -translate-y-1/2 z-50 w-72 p-3 text-xs leading-relaxed bg-white dark:bg-slate-800 text-slate-600 dark:text-slate-300 rounded-lg shadow-xl border border-slate-200 dark:border-slate-700 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200">
<div class="font-bold mb-1 border-b pb-1 dark:border-slate-700">รายละเอียดใบขับขี่แต่ละประเภท</div>
<ul class="list-disc pl-4 space-y-1 mt-1">
<li><b>ท.1 / บ.1</b>: รถยนต์ส่วนบุคคล / รถตู้ (น้ำหนักไม่เกิน 3,500 กก.)</li>
<li><b>ท.2 / บ.2</b>: รถบรรทุก 6 ล้อ, 10 ล้อ</li>
<li><b>ท.3 / บ.3</b>: รถพ่วง, รถลากจูง</li>
<li><b>ท.4 / บ.4</b>: รถวัตถุอันตราย</li>
</ul>
<div class="mt-2 text-[10px] text-slate-400 bg-slate-50 dark:bg-slate-700/50 p-1.5 rounded">
<span class="font-bold text-primary-500">ท</span> = ประเภททุกประเภท (รับจ้าง/สาธารณะ)<br>
<span class="font-bold text-primary-500">บ</span> = ประเภทส่วนบุคคล
</div>
</div>
</div>
</div>
<select x-model="form.license_type" class="glass-input block w-full p-2.5 text-sm mb-3">
<option value="">-- ไม่ระบุ --</option>
<option value="ท.1">ท.1 (รถยนต์ทุกประเภท)</option>
<option value="บ.1">บ.1 (รถยนต์ส่วนบุคคล)</option>
<option value="ท.2">ท.2 (รถบรรทุกทุกประเภท)</option>
<option value="บ.2">บ.2 (รถบรรทุกส่วนบุคคล)</option>
<option value="ท.3">ท.3 (รถลากจูงทุกประเภท)</option>
<option value="บ.3">บ.3 (รถลากจูงส่วนบุคคล)</option>
<option value="ท.4">ท.4 (รถวัตถุอันตรายทุกประเภท)</option>
<option value="บ.4">บ.4 (รถวัตถุอันตรายส่วนบุคคล)</option>
</select>
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">วันหมดอายุใบขับขี่</label>
<input type="date" x-model="form.license_expiry_date" class="glass-input block w-full p-2.5 text-sm">
</div>
<div class="sm:col-span-2 text-xs text-slate-500 mt-2">
<i class="fa-solid fa-circle-info mr-1"></i> ระบบจะสร้างรูปโปรไฟล์จากชื่อให้อัตโนมัติ
</div>
</div>
<!-- Document Section (Only show when editing an existing driver) -->
<div class="mt-8 border-t border-slate-200 dark:border-slate-700 pt-6" x-show="isEdit" style="display: none;">
<div class="flex justify-between items-center mb-4">
<h4 class="text-md font-bold text-slate-800 dark:text-white"><i class="fa-solid fa-file-pdf text-red-500 mr-2"></i> เอกสารใบขับขี่</h4>
<div class="relative">
<input type="file" id="driverDocInput" accept="application/pdf" class="hidden" @change="uploadDocument($event)">
<button type="button" @click="document.getElementById('driverDocInput').click()" class="btn-gradient px-3 py-1.5 text-xs flex items-center shadow-md shadow-primary-500/20" :disabled="isUploadingDoc">
<i class="fa-solid" :class="isUploadingDoc ? 'fa-spinner fa-spin' : 'fa-upload'"></i>
<span class="ml-2" x-text="isUploadingDoc ? 'กำลังอัปโหลด...' : 'อัปโหลด PDF'"></span>
</button>
</div>
</div>
<div class="bg-slate-50 dark:bg-slate-800/50 rounded-xl border border-slate-200 dark:border-slate-700 p-4">
<!-- Loading state -->
<div x-show="isLoadingDocs" class="text-center py-4 text-slate-500">
<i class="fa-solid fa-spinner fa-spin text-2xl mb-2 text-primary-500"></i>
<p class="text-xs">กำลังโหลดเอกสาร...</p>
</div>
<!-- Empty state -->
<div x-show="!isLoadingDocs && documents.length === 0" class="text-center py-6 text-slate-500" style="display: none;">
<i class="fa-solid fa-folder-open text-3xl mb-2 opacity-30"></i>
<p class="text-sm">ยังไม่มีเอกสารแนบ</p>
</div>
<!-- Document List -->
<ul x-show="!isLoadingDocs && documents.length > 0" class="space-y-2">
<template x-for="doc in documents" :key="doc.id">
<li class="flex items-center justify-between p-3 bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700 shadow-sm hover:border-primary-300 dark:hover:border-primary-700 transition-colors group">
<a :href="doc.file_path" target="_blank" class="flex items-center flex-1 min-w-0 hover:text-primary-600 dark:hover:text-primary-400 transition-colors">
<i class="fa-solid fa-file-pdf text-red-500 text-lg mr-3"></i>
<div class="truncate">
<p class="text-sm font-medium text-slate-700 dark:text-slate-300 truncate" x-text="doc.original_name"></p>
<p class="text-xs text-slate-500" x-text="formatDate(doc.created_at)"></p>
</div>
</a>
<button type="button" @click="deleteDocument(doc.id)" class="ml-4 p-2 text-slate-400 hover:text-danger hover:bg-red-50 dark:hover:bg-red-900/20 rounded-lg transition-colors opacity-0 group-hover:opacity-100 focus:opacity-100" title="ลบเอกสาร">
<i class="fa-solid fa-trash-can"></i>
</button>
</li>
</template>
</ul>
</div>
</div>
<div class="mt-6 pt-5 border-t border-slate-100 dark:border-slate-700/50 flex justify-end space-x-3">
<button type="button" @click="closeModal()" class="px-4 py-2.5 text-sm font-medium text-slate-700 bg-white border border-slate-300 rounded-xl hover:bg-slate-50 dark:bg-slate-800 dark:text-slate-300 dark:border-slate-600 dark:hover:bg-slate-700 transition-colors">
ยกเลิก
</button>
<button type="submit" :disabled="isLoading" class="btn-gradient px-4 py-2.5 text-sm flex items-center justify-center min-w-[100px] shadow-lg shadow-primary-500/30">
<span x-show="!isLoading" x-text="isEdit ? 'บันทึกการแก้ไข' : 'เพิ่มข้อมูล'"></span>
<span x-show="isLoading" style="display: none;"><i class="fa-solid fa-spinner fa-spin mr-2"></i> กำลังบันทึก...</span>
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</main>
</div>
<?php require_once 'includes/footer.php'; ?>