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

150 lines
8.8 KiB
PHP

<?php
/**
* Room Management & เตียงนวด View (Glassmorphism)
*/
?>
<div x-data="roomApp" class="space-y-6">
<!-- Header -->
<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">
จัดการห้องนวด & เตียงบริการ (Room & Bed Management)
</h1>
<p class="text-sm text-subtle mt-1">ตั้งค่าสถานะห้องนวด, กำหนดประเภทบริการประจำเตียง และจัดการความสะอาด</p>
</div>
<button @click="openModal()" class="glass-btn-primary text-sm">
<i class="bi bi-plus-circle-fill"></i>
<span>เพิ่มห้องนวดใหม่</span>
</button>
</div>
<!-- Rooms Grid -->
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
<template x-for="r in rooms" :key="r.id">
<div class="glass-card p-5 rounded-2xl border relative overflow-hidden flex flex-col justify-between"
:class="r.status === 'Available' ? 'border-emerald-500/30' : (r.status === 'In_Use' ? 'border-amber-500/40 bg-amber-950/10' : 'border-cyan-500/30 bg-cyan-950/10')">
<div>
<div class="flex justify-between items-center mb-3">
<span class="text-2xl font-extrabold font-mono" x-text="r.room_no">R-101</span>
<span class="px-2.5 py-0.5 rounded-full text-xs font-bold"
:class="r.status === 'Available' ? 'bg-emerald-500/20 text-emerald-300' : (r.status === 'In_Use' ? 'bg-amber-500/20 text-amber-300' : 'bg-cyan-500/20 text-cyan-300')"
x-text="r.status === 'Available' ? 'ว่างพร้อมใช้' : (r.status === 'In_Use' ? 'กำลังให้บริการ' : 'ทำความสะอาด')"></span>
</div>
<p class="font-bold text-base mb-1" x-text="r.name_th">ห้องนวดไทย VIP 1</p>
<p class="text-xs text-subtle mb-3" x-text="`ประเภท: ${r.room_type} | ความจุ: ${r.capacity || 1} เตียง`">ประเภท: VIP Private</p>
<div class="p-3 rounded-xl bg-slate-800/60 border border-slate-700/60 space-y-1 text-xs">
<p class="text-subtle">หมอนวดประจำห้อง: <strong class="text-white" x-text="r.assigned_therapist || 'ยังไม่กำหนด'">-</strong></p>
<p class="text-subtle">ผู้ป่วยปัจจุบัน: <strong class="text-emerald-400" x-text="r.current_patient || 'ไม่มี'">-</strong></p>
</div>
</div>
<div class="pt-4 mt-4 border-t border-slate-700/60 flex justify-between items-center">
<button @click="changeStatus(r)" class="text-xs font-medium text-cyan-400 hover:underline">
<i class="bi bi-arrow-repeat"></i> เปลี่ยนสถานะ
</button>
<button @click="editRoom(r)" class="text-xs text-subtle hover:text-white">
<i class="bi bi-gear"></i> ตั้งค่า
</button>
</div>
</div>
</template>
</div>
<!-- New / Edit Room 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-md 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="saveRoom()" class="space-y-4 text-sm">
<div>
<label class="block mb-1 font-medium">รหัสห้อง (Room No.):</label>
<input type="text" x-model="form.room_no" required placeholder="เช่น R-107, B-201" class="glass-input font-mono uppercase">
</div>
<div>
<label class="block mb-1 font-medium">ชื่อห้อง (ภาษาไทย):</label>
<input type="text" x-model="form.name_th" required placeholder="เช่น ห้องนวดไทยราชสำนัก 3" class="glass-input">
</div>
<div class="grid grid-cols-2 gap-3">
<div>
<label class="block mb-1 font-medium">ประเภทห้อง:</label>
<select x-model="form.room_type" class="glass-input">
<option value="VIP Private">VIP Private</option>
<option value="Standard Bed">Standard Bed</option>
<option value="Foot Spa">Foot Spa</option>
<option value="Aroma Oil">Aroma Oil</option>
</select>
</div>
<div>
<label class="block mb-1 font-medium">สถานะห้อง:</label>
<select x-model="form.status" class="glass-input">
<option value="Available">ว่างพร้อมใช้ (Available)</option>
<option value="Cleaning">ทำความสะอาด (Cleaning)</option>
<option value="Maintenance">ปิดปรับปรุง (Maintenance)</option>
</select>
</div>
</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('roomApp', () => ({
showModal: false,
rooms: [
{ id: 1, room_no: 'R-101', name_th: 'ห้องนวดไทย VIP 1', room_type: 'VIP Private', status: 'In_Use', assigned_therapist: 'หมอสมศรี (T-102)', current_patient: 'คุณสมชาย รักสุขภาพ' },
{ id: 2, room_no: 'R-102', name_th: 'ห้องนวดไทย VIP 2', room_type: 'VIP Private', status: 'Available', assigned_therapist: null, current_patient: null },
{ id: 3, room_no: 'R-103', name_th: 'ห้องนวดฝ่าเท้า 1', room_type: 'Foot Spa', status: 'In_Use', assigned_therapist: 'หมอใจดี (T-105)', current_patient: 'คุณวิภาวี ดีเลิศ' },
{ id: 4, room_no: 'R-104', name_th: 'ห้องนวดน้ำมันอโรมา 1', room_type: 'Aroma Oil', status: 'Cleaning', assigned_therapist: '-', current_patient: 'รอทำความสะอาด' },
{ id: 5, room_no: 'R-105', name_th: 'ห้องประคบสมุนไพร 1', room_type: 'Standard Bed', status: 'Available', assigned_therapist: null, current_patient: null },
{ id: 6, room_no: 'R-106', name_th: 'ห้องนวดไทยสแตนดาร์ด 1', room_type: 'Standard Bed', status: 'Available', assigned_therapist: null, current_patient: null }
],
form: {},
openModal() {
this.form = { id: null, room_no: `R-10${this.rooms.length + 1}`, name_th: '', room_type: 'Standard Bed', status: 'Available' };
this.showModal = true;
},
editRoom(r) {
this.form = { ...r };
this.showModal = true;
},
changeStatus(r) {
const next = r.status === 'Available' ? 'Cleaning' : 'Available';
r.status = next;
r.current_patient = next === 'Available' ? null : 'รอทำความสะอาด';
this.toast(`เปลี่ยนสถานะห้อง ${r.room_no} เป็น ${next === 'Available' ? 'ว่างพร้อมใช้' : 'ทำความสะอาด'} แล้ว`, 'success');
},
saveRoom() {
if (!this.form.id) {
this.form.id = this.rooms.length + 1;
this.rooms.push({ ...this.form, assigned_therapist: null, current_patient: null });
} else {
const idx = this.rooms.findIndex(x => x.id === this.form.id);
if (idx !== -1) this.rooms[idx] = { ...this.rooms[idx], ...this.form };
}
this.showModal = false;
this.toast('บันทึกข้อมูลห้องนวดเรียบร้อยแล้ว', 'success');
}
}));
});
</script>