198 lines
11 KiB
PHP
198 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* Patient & EMR Management View (Glassmorphism)
|
|
*/
|
|
?>
|
|
<div x-data="patientApp" class="space-y-6">
|
|
|
|
<!-- Header & Search -->
|
|
<div class="flex flex-col md:flex-row md:items-center justify-between gap-4 glass-card p-6 rounded-2xl border">
|
|
<div>
|
|
<h1 class="text-2xl font-bold tracking-tight bg-gradient-to-r from-emerald-400 to-cyan-400 bg-clip-text text-transparent">
|
|
ทะเบียนผู้ป่วย & เวชระเบียน EMR (Patient Management)
|
|
</h1>
|
|
<p class="text-sm text-subtle mt-1">จัดการข้อมูลผู้รับบริการ ประวัติการรักษาโรค และเชื่อมต่อฐานข้อมูล HIS โรงพยาบาล</p>
|
|
</div>
|
|
|
|
<div class="flex items-center gap-3">
|
|
<div class="relative w-full sm:w-64">
|
|
<input type="text" x-model="searchQuery" @input="filterPatients()" placeholder="ค้นหา HN, ชื่อ หรือเลขบัตร 13 หลัก..." class="glass-input pl-9 text-sm">
|
|
<i class="bi bi-search text-subtle absolute left-3 top-3"></i>
|
|
</div>
|
|
<button @click="openNewModal()" class="glass-btn-primary text-sm whitespace-nowrap">
|
|
<i class="bi bi-person-plus-fill"></i>
|
|
<span>ขึ้นทะเบียนผู้ป่วยใหม่</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Patient Table Card -->
|
|
<div class="glass-card p-6 rounded-2xl border overflow-x-auto">
|
|
<table class="w-full text-left border-collapse">
|
|
<thead>
|
|
<tr class="border-b border-slate-700/60 text-xs font-semibold text-subtle uppercase">
|
|
<th class="py-3 px-4">HN / CID</th>
|
|
<th class="py-3 px-4">ชื่อ - นามสกุล</th>
|
|
<th class="py-3 px-4">อายุ / เพศ</th>
|
|
<th class="py-3 px-4">เบอร์โทรศัพท์</th>
|
|
<th class="py-3 px-4">สิทธิการรักษา</th>
|
|
<th class="py-3 px-4">โรคประจำตัว / ข้อห้าม</th>
|
|
<th class="py-3 px-4 text-right">จัดการ</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-700/40 text-sm">
|
|
<template x-for="p in displayPatients" :key="p.id">
|
|
<tr class="hover:bg-slate-800/40 transition-colors">
|
|
<td class="py-3.5 px-4 font-mono font-bold text-cyan-400">
|
|
<div x-text="p.hn">HN-2407001</div>
|
|
<div class="text-[11px] text-subtle font-normal" x-text="p.cid">1100000000001</div>
|
|
</td>
|
|
<td class="py-3.5 px-4 font-semibold" x-text="`${p.first_name_th} ${p.last_name_th}`">คุณสมชาย รักสุขภาพ</td>
|
|
<td class="py-3.5 px-4" x-text="`${p.age} ปี / ${p.gender}`">45 ปี / ชาย</td>
|
|
<td class="py-3.5 px-4 font-mono" x-text="p.phone">081-234-5678</td>
|
|
<td class="py-3.5 px-4">
|
|
<span class="px-2.5 py-0.5 rounded-full text-xs font-medium"
|
|
:class="p.right_type === 'UC / สปสช.' ? 'bg-emerald-500/20 text-emerald-300' : 'bg-purple-500/20 text-purple-300'"
|
|
x-text="p.right_type">UC / สปสช.</span>
|
|
</td>
|
|
<td class="py-3.5 px-4">
|
|
<span class="text-xs" :class="p.contraindications ? 'text-red-400 font-medium' : 'text-subtle'"
|
|
x-text="p.contraindications || 'ไม่มีประวัติแพ้ยา'">ความดันโลหิตสูง</span>
|
|
</td>
|
|
<td class="py-3.5 px-4 text-right space-x-2">
|
|
<a :href="`/clinical/soap?patient_id=${p.id}`" class="px-3 py-1 rounded-lg bg-cyan-500/10 text-cyan-400 hover:bg-cyan-500 hover:text-white text-xs font-medium transition-all" title="ดูประวัติ SOAP">
|
|
<i class="bi bi-file-earmark-medical"></i> EMR
|
|
</a>
|
|
<button @click="editPatient(p)" class="p-1.5 rounded-lg text-subtle hover:text-amber-400 transition-colors" title="แก้ไข">
|
|
<i class="bi bi-pencil-square"></i>
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
</template>
|
|
</tbody>
|
|
</table>
|
|
<div x-show="displayPatients.length === 0" class="text-center py-12 text-subtle">ไม่พบข้อมูลผู้ป่วยที่ค้นหา</div>
|
|
</div>
|
|
|
|
<!-- New / Edit Patient Modal -->
|
|
<div x-show="showModal" x-cloak class="fixed inset-0 z-50 flex items-center justify-center p-4">
|
|
<div x-show="showModal" x-transition.opacity @click="showModal = false" class="fixed inset-0 bg-black/60 backdrop-blur-sm"></div>
|
|
<div x-show="showModal" x-transition class="relative w-full max-w-lg glass-modal p-6 rounded-3xl shadow-2xl border space-y-4">
|
|
<div class="flex justify-between items-center pb-3 border-b border-emerald-500/20">
|
|
<h3 class="font-bold text-lg" x-text="form.id ? 'แก้ไขข้อมูลผู้ป่วย' : 'ขึ้นทะเบียนผู้ป่วยใหม่'">ขึ้นทะเบียนผู้ป่วย</h3>
|
|
<button @click="showModal = false" class="text-subtle hover:text-white"><i class="bi bi-x-lg"></i></button>
|
|
</div>
|
|
<form @submit.prevent="savePatient()" class="space-y-4 text-sm">
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block mb-1 font-medium">เลขบัตรประชาชน 13 หลัก:</label>
|
|
<input type="text" x-model="form.cid" required maxlength="13" class="glass-input font-mono">
|
|
</div>
|
|
<div>
|
|
<label class="block mb-1 font-medium">เบอร์โทรศัพท์:</label>
|
|
<input type="text" x-model="form.phone" required class="glass-input font-mono">
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label class="block mb-1 font-medium">ชื่อจริง (ภาษาไทย):</label>
|
|
<input type="text" x-model="form.first_name_th" required class="glass-input">
|
|
</div>
|
|
<div>
|
|
<label class="block mb-1 font-medium">นามสกุล (ภาษาไทย):</label>
|
|
<input type="text" x-model="form.last_name_th" required class="glass-input">
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-3 gap-3">
|
|
<div>
|
|
<label class="block mb-1 font-medium">อายุ (ปี):</label>
|
|
<input type="number" x-model="form.age" required class="glass-input text-center">
|
|
</div>
|
|
<div>
|
|
<label class="block mb-1 font-medium">เพศ:</label>
|
|
<select x-model="form.gender" class="glass-input">
|
|
<option value="ชาย">ชาย</option>
|
|
<option value="หญิง">หญิง</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block mb-1 font-medium">สิทธิการรักษา:</label>
|
|
<select x-model="form.right_type" class="glass-input">
|
|
<option value="UC / สปสช.">UC / สปสช.</option>
|
|
<option value="ประกันสังคม">ประกันสังคม</option>
|
|
<option value="ข้าราชการ / สร้.">ข้าราชการ</option>
|
|
<option value="ชำระเงินเอง">ชำระเงินเอง</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label class="block mb-1 font-medium text-red-400">โรคประจำตัว / ข้อห้ามในการนวด:</label>
|
|
<input type="text" x-model="form.contraindications" placeholder="เช่น ความดันสูง, ตั้งครรภ์ 3 เดือน, ลิ่มเลือดอุดตัน..." class="glass-input">
|
|
</div>
|
|
<div class="pt-3 border-t border-slate-700 flex justify-end gap-2">
|
|
<button type="button" @click="showModal = false" class="px-4 py-2 rounded-xl border border-slate-600 text-subtle">ยกเลิก</button>
|
|
<button type="submit" class="glass-btn-primary px-6 py-2 rounded-xl">บันทึกข้อมูล</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('alpine:init', () => {
|
|
Alpine.data('patientApp', () => ({
|
|
searchQuery: '',
|
|
showModal: false,
|
|
patients: [
|
|
{ id: 1, hn: 'HN-2407001', cid: '1100000000001', first_name_th: 'สมชาย', last_name_th: 'รักสุขภาพ', age: 45, gender: 'ชาย', phone: '081-234-5678', right_type: 'UC / สปสช.', contraindications: 'ความดันโลหิตสูง (วัดความดันก่อนนวด)' },
|
|
{ id: 2, hn: 'HN-2407002', cid: '1100000000002', first_name_th: 'วิภาวี', last_name_th: 'ดีเลิศ', age: 38, gender: 'หญิง', phone: '089-876-5432', right_type: 'ข้าราชการ / สร้.', contraindications: null },
|
|
{ id: 3, hn: 'HN-2407003', cid: '1100000000003', first_name_th: 'อนันต์', last_name_th: 'มั่งคั่ง', age: 62, gender: 'ชาย', phone: '086-111-2222', right_type: 'ชำระเงินเอง', contraindications: 'หมอนรองกระดูกทับเส้นประสาท (ห้ามดัดรุนแรง)' },
|
|
{ id: 4, hn: 'HN-2407004', cid: '1100000000004', first_name_th: 'โสภิตา', last_name_th: 'เสน่ห์จันทร์', age: 29, gender: 'หญิง', phone: '082-333-4444', right_type: 'ประกันสังคม', contraindications: null }
|
|
],
|
|
displayPatients: [],
|
|
form: {},
|
|
|
|
init() {
|
|
this.displayPatients = [...this.patients];
|
|
},
|
|
|
|
filterPatients() {
|
|
if (!this.searchQuery) {
|
|
this.displayPatients = [...this.patients];
|
|
return;
|
|
}
|
|
const q = this.searchQuery.toLowerCase();
|
|
this.displayPatients = this.patients.filter(p =>
|
|
p.hn.toLowerCase().includes(q) ||
|
|
p.cid.includes(q) ||
|
|
`${p.first_name_th} ${p.last_name_th}`.toLowerCase().includes(q)
|
|
);
|
|
},
|
|
|
|
openNewModal() {
|
|
this.form = { id: null, hn: `HN-240700${this.patients.length + 1}`, cid: '', first_name_th: '', last_name_th: '', age: 35, gender: 'ชาย', phone: '', right_type: 'UC / สปสช.', contraindications: '' };
|
|
this.showModal = true;
|
|
},
|
|
|
|
editPatient(p) {
|
|
this.form = { ...p };
|
|
this.showModal = true;
|
|
},
|
|
|
|
savePatient() {
|
|
if (!this.form.id) {
|
|
this.form.id = this.patients.length + 1;
|
|
this.patients.unshift({ ...this.form });
|
|
} else {
|
|
const idx = this.patients.findIndex(x => x.id === this.form.id);
|
|
if (idx !== -1) this.patients[idx] = { ...this.form };
|
|
}
|
|
this.filterPatients();
|
|
this.showModal = false;
|
|
this.toast('บันทึกข้อมูลผู้ป่วยเรียบร้อยแล้ว', 'success');
|
|
}
|
|
}));
|
|
});
|
|
</script>
|