'Tanggal pendaftaran wajib diisi.', 'appointment_date.after_or_equal' => 'Tanggal pendaftaran tidak boleh di masa lalu.', 'service_category_id.required' => 'Poli / Layanan wajib dipilih.', 'service_category_id.exists' => 'Poli yang dipilih tidak valid.', 'doctor_id.required' => 'Dokter wajib dipilih.', 'doctor_id.exists' => 'Dokter yang dipilih tidak valid.', 'notes.required' => 'Keluhan singkat wajib diisi.', 'notes.max' => 'Keluhan singkat tidak boleh lebih dari 255 karakter.', ]; public function mount() { $this->appointment_date = date('Y-m-d'); $this->service_category_id = \App\Models\ServiceCategory::first()?->id; $this->doctor_id = \App\Models\Doctor::first()?->id; } // Fungsi untuk membatalkan antrean public function cancelAppointment($id) { $appointment = Appointment::where('patient_id', Auth::id()) ->where('status', 'waiting') ->findOrFail($id); $appointment->update(['status' => 'cancelled']); Toaster::success('Antrean berhasil dibatalkan.'); } // Fungsi untuk mengambil data tiket dan buka modal public function showTicketModal($id) { $this->selectedAppointment = Appointment::with('patient')->findOrFail($id); // Pastikan variabel showTicket tetap true jika Anda masih menggunakannya untuk @if di blade $this->showTicket = true; // Membuka modal menggunakan Flux Javascript API $this->js("Flux.modal('ticket-modal').show()"); } public function save() { $this->validate([ 'appointment_date' => 'required|date|after_or_equal:today', 'doctor_id' => 'required|exists:doctors,id', 'service_category_id' => 'required|exists:service_categories,id', 'notes' => 'required|string|max:255', ]); // Cek duplikasi: 1 pasien, 1 hari, 1 dokter $exists = Appointment::where('patient_id', Auth::id()) ->where('doctor_id', $this->doctor_id) ->whereDate('appointment_date', $this->appointment_date) ->exists(); if ($exists) { Toaster::error('Anda sudah terdaftar untuk dokter ini di tanggal tersebut.'); return; } // Nomor antrean spesifik per DOKTER dan per TANGGAL $lastQueue = Appointment::where('doctor_id', $this->doctor_id) ->whereDate('appointment_date', $this->appointment_date) ->max('queue_number') ?? 0; $newApp = Appointment::create([ 'patient_id' => Auth::id(), 'doctor_id' => $this->doctor_id, 'service_category_id' => $this->service_category_id, 'appointment_date' => $this->appointment_date, 'queue_number' => $lastQueue + 1, 'notes' => $this->notes, 'status' => 'waiting', 'created_by' => Auth::id(), ]); $this->reset(['notes', 'doctor_id', 'service_category_id']); $this->showTicketModal($newApp->id); } public function render() { // Ambil nomor yang statusnya 'calling' hari ini $currentCalling = Appointment::whereDate('appointment_date', date('Y-m-d')) ->where('status', 'calling') ->when($this->filter_doctor, function ($query) { return $query->where('doctor_id', $this->filter_doctor); }) ->with(['patient', 'doctor', 'serviceCategory']) // Eager load agar tidak error ->latest('updated_at') // Ambil yang paling baru dipanggil ->first(); return view('livewire.patient.booking-antrean', [ 'myAppointments' => Appointment::where('patient_id', Auth::id()) ->latest() ->paginate(5), 'currentCalling' => $currentCalling, // Kirim ke view 'categories' => \App\Models\ServiceCategory::all(), // Data Poli 'doctors' => \App\Models\Doctor::all(), // Data Dokter ]); } }