171 lines
5.5 KiB
PHP
171 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Api;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\StoreAppointmentRequest;
|
|
use App\Http\Requests\UpdateAppointmentRequest;
|
|
use App\Http\Resources\AppointmentResource;
|
|
use App\Models\Appointment;
|
|
use App\Services\AppointmentService;
|
|
use Illuminate\Http\Request;
|
|
|
|
class AppointmentController extends Controller
|
|
{
|
|
protected $appointmentService;
|
|
|
|
public function __construct(AppointmentService $appointmentService)
|
|
{
|
|
$this->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]);
|
|
}
|
|
}
|