appointmentService = $appointmentService; } public function index(Request $request) { $query = Appointment::with(['patient', 'user']); if ($request->has('patient_id')) { $query->where('patient_id', $request->patient_id); } if ($request->has('therapist_id')) { $query->where('user_id', $request->therapist_id); } if ($request->has('status')) { $query->where('status', $request->status); } if ($request->has('date_from')) { $query->whereDate('appointment_date', '>=', $request->date_from); } if ($request->has('date_to')) { $query->whereDate('appointment_date', '<=', $request->date_to); } if ($request->has('date')) { $query->whereDate('appointment_date', $request->date); } $appointments = $query->orderBy('appointment_date')->paginate($request->per_page ?? 20); return AppointmentResource::collection($appointments); } public function store(StoreAppointmentRequest $request) { $data = $request->validated(); // Check for conflicts $appointmentDate = \Carbon\Carbon::parse($data['appointment_date']); if ($this->appointmentService->hasConflict($data['therapist_id'], $appointmentDate, $data['duration_minutes'])) { return response()->json([ 'message' => 'Therapist has a conflicting appointment at this time', ], 422); } if ($this->appointmentService->hasPatientConflict($data['patient_id'], $appointmentDate, $data['duration_minutes'])) { return response()->json([ 'message' => 'Patient has a conflicting appointment at this time', ], 422); } $appointment = Appointment::create([ 'patient_id' => $data['patient_id'], 'user_id' => $data['therapist_id'], 'appointment_date' => $data['appointment_date'], 'duration_minutes' => $data['duration_minutes'], 'notes' => $data['notes'] ?? null, ]); // Generate reminders $reminderService = new \App\Services\ReminderService(); $reminderService->generateReminders($appointment); return new AppointmentResource($appointment); } public function show(Appointment $appointment) { return new AppointmentResource($appointment); } public function update(UpdateAppointmentRequest $request, Appointment $appointment) { $data = $request->validated(); // Check for conflicts if date/therapist changed if (isset($data['appointment_date']) || isset($data['therapist_id'])) { $newDate = isset($data['appointment_date']) ? \Carbon\Carbon::parse($data['appointment_date']) : $appointment->appointment_date; $newTherapistId = $data['therapist_id'] ?? $appointment->user_id; $duration = $data['duration_minutes'] ?? $appointment->duration_minutes; if ($this->appointmentService->hasConflict($newTherapistId, $newDate, $duration, $appointment->id)) { return response()->json([ 'message' => 'Therapist has a conflicting appointment at this time', ], 422); } } $appointment->update([ 'patient_id' => $data['patient_id'], 'user_id' => $data['therapist_id'], 'appointment_date' => $data['appointment_date'], 'duration_minutes' => $data['duration_minutes'], 'status' => $data['status'], 'notes' => $data['notes'] ?? null, 'cancellation_reason' => $data['cancellation_reason'] ?? null, ]); if ($data['status'] === 'cancelled') { $appointment->cancelled_by = auth()->id(); $appointment->cancelled_at = now(); $appointment->save(); } return new AppointmentResource($appointment); } public function destroy(Appointment $appointment) { $appointment->delete(); return response()->json(['message' => 'Appointment deleted successfully']); } public function calendar(Request $request) { $request->validate([ 'start' => 'required|date', 'end' => 'required|date|after_or_equal:start', ]); $feed = $this->appointmentService->getCalendarFeed( $request->start, $request->end, $request->therapist_id ); return response()->json($feed); } public function availableSlots(Request $request) { $request->validate([ 'therapist_id' => 'required|exists:users,id', 'date' => 'required|date', 'duration' => 'nullable|integer|min:15', ]); $slots = $this->appointmentService->getAvailableSlots( $request->therapist_id, $request->date, $request->duration ?? 60 ); return response()->json(['slots' => $slots]); } }