205 lines
6.8 KiB
PHP
205 lines
6.8 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Appointments;
|
|
|
|
use Livewire\Component;
|
|
use Livewire\Attributes\On;
|
|
use App\Models\Appointment;
|
|
use App\Models\Customer;
|
|
use App\Models\Vehicle;
|
|
use App\Models\Technician;
|
|
use Carbon\Carbon;
|
|
|
|
class Form extends Component
|
|
{
|
|
public $showModal = true;
|
|
public $appointment = null;
|
|
public $editing = false;
|
|
|
|
// Form fields
|
|
public $customer_id = '';
|
|
public $vehicle_id = '';
|
|
public $assigned_technician_id = '';
|
|
public $scheduled_date = '';
|
|
public $scheduled_time = '';
|
|
public $estimated_duration_minutes = 60;
|
|
public $appointment_type = 'maintenance';
|
|
public $service_requested = '';
|
|
public $customer_notes = '';
|
|
public $internal_notes = '';
|
|
|
|
// Options
|
|
public $customers = [];
|
|
public $vehicles = [];
|
|
public $technicians = [];
|
|
public $availableTimeSlots = [];
|
|
|
|
public $appointmentTypes = [
|
|
'maintenance' => 'Maintenance',
|
|
'repair' => 'Repair',
|
|
'inspection' => 'Inspection',
|
|
'estimate' => 'Estimate',
|
|
'pickup' => 'Pickup',
|
|
'delivery' => 'Delivery'
|
|
];
|
|
|
|
public $durationOptions = [
|
|
30 => '30 minutes',
|
|
60 => '1 hour',
|
|
90 => '1.5 hours',
|
|
120 => '2 hours',
|
|
180 => '3 hours',
|
|
240 => '4 hours',
|
|
300 => '5 hours',
|
|
360 => '6 hours',
|
|
480 => '8 hours'
|
|
];
|
|
|
|
protected $rules = [
|
|
'customer_id' => 'required|exists:customers,id',
|
|
'vehicle_id' => 'required|exists:vehicles,id',
|
|
'assigned_technician_id' => 'nullable|exists:technicians,id',
|
|
'scheduled_date' => 'required|date|after_or_equal:today',
|
|
'scheduled_time' => 'required|date_format:H:i',
|
|
'estimated_duration_minutes' => 'required|integer|min:15|max:480',
|
|
'appointment_type' => 'required|in:maintenance,repair,inspection,estimate,pickup,delivery',
|
|
'service_requested' => 'required|string|max:1000',
|
|
'customer_notes' => 'nullable|string|max:1000',
|
|
'internal_notes' => 'nullable|string|max:1000'
|
|
];
|
|
|
|
public function mount($appointment = null)
|
|
{
|
|
$this->customers = Customer::orderBy('first_name')->get();
|
|
$this->technicians = Technician::where('status', 'active')->orderBy('first_name')->get();
|
|
|
|
if ($appointment) {
|
|
$this->appointment = $appointment;
|
|
$this->editing = true;
|
|
$this->loadAppointmentData();
|
|
} else {
|
|
$this->scheduled_date = now()->addDay()->format('Y-m-d');
|
|
$this->scheduled_time = '09:00';
|
|
}
|
|
}
|
|
|
|
public function loadAppointmentData()
|
|
{
|
|
$this->customer_id = $this->appointment->customer_id;
|
|
$this->vehicle_id = $this->appointment->vehicle_id;
|
|
$this->assigned_technician_id = $this->appointment->assigned_technician_id;
|
|
$this->scheduled_date = $this->appointment->scheduled_datetime->format('Y-m-d');
|
|
$this->scheduled_time = $this->appointment->scheduled_datetime->format('H:i');
|
|
$this->estimated_duration_minutes = $this->appointment->estimated_duration_minutes;
|
|
$this->appointment_type = $this->appointment->appointment_type;
|
|
$this->service_requested = $this->appointment->service_requested;
|
|
$this->customer_notes = $this->appointment->customer_notes;
|
|
$this->internal_notes = $this->appointment->internal_notes;
|
|
|
|
$this->loadVehicles();
|
|
}
|
|
|
|
public function updatedCustomerId()
|
|
{
|
|
$this->vehicle_id = '';
|
|
$this->loadVehicles();
|
|
}
|
|
|
|
public function updatedScheduledDate()
|
|
{
|
|
$this->checkTimeSlotAvailability();
|
|
}
|
|
|
|
public function updatedScheduledTime()
|
|
{
|
|
$this->checkTimeSlotAvailability();
|
|
}
|
|
|
|
public function updatedAssignedTechnicianId()
|
|
{
|
|
$this->checkTimeSlotAvailability();
|
|
}
|
|
|
|
public function loadVehicles()
|
|
{
|
|
if ($this->customer_id) {
|
|
$this->vehicles = Vehicle::where('customer_id', $this->customer_id)->get();
|
|
} else {
|
|
$this->vehicles = [];
|
|
}
|
|
}
|
|
|
|
public function checkTimeSlotAvailability()
|
|
{
|
|
if (!$this->scheduled_date || !$this->scheduled_time || !$this->assigned_technician_id) {
|
|
return;
|
|
}
|
|
|
|
$scheduledDateTime = Carbon::parse($this->scheduled_date . ' ' . $this->scheduled_time);
|
|
$endDateTime = $scheduledDateTime->copy()->addMinutes($this->estimated_duration_minutes);
|
|
|
|
// Check for conflicts
|
|
$conflicts = Appointment::where('assigned_technician_id', $this->assigned_technician_id)
|
|
->where('status', '!=', 'cancelled')
|
|
->where(function ($query) use ($scheduledDateTime, $endDateTime) {
|
|
$query->whereBetween('scheduled_datetime', [$scheduledDateTime, $endDateTime])
|
|
->orWhere(function ($q) use ($scheduledDateTime, $endDateTime) {
|
|
$q->where('scheduled_datetime', '<=', $scheduledDateTime)
|
|
->whereRaw('DATE_ADD(scheduled_datetime, INTERVAL estimated_duration_minutes MINUTE) > ?', [$scheduledDateTime]);
|
|
});
|
|
});
|
|
|
|
if ($this->editing && $this->appointment) {
|
|
$conflicts->where('id', '!=', $this->appointment->id);
|
|
}
|
|
|
|
if ($conflicts->exists()) {
|
|
$this->addError('scheduled_time', 'This time slot conflicts with another appointment for the selected technician.');
|
|
} else {
|
|
$this->resetErrorBag('scheduled_time');
|
|
}
|
|
}
|
|
|
|
public function save()
|
|
{
|
|
$this->validate();
|
|
|
|
$scheduledDateTime = Carbon::parse($this->scheduled_date . ' ' . $this->scheduled_time);
|
|
|
|
$data = [
|
|
'customer_id' => $this->customer_id,
|
|
'vehicle_id' => $this->vehicle_id,
|
|
'assigned_technician_id' => $this->assigned_technician_id ?: null,
|
|
'scheduled_datetime' => $scheduledDateTime,
|
|
'estimated_duration_minutes' => $this->estimated_duration_minutes,
|
|
'appointment_type' => $this->appointment_type,
|
|
'service_requested' => $this->service_requested,
|
|
'customer_notes' => $this->customer_notes,
|
|
'internal_notes' => $this->internal_notes,
|
|
'status' => 'scheduled'
|
|
];
|
|
|
|
if ($this->editing && $this->appointment) {
|
|
$this->appointment->update($data);
|
|
session()->flash('message', 'Appointment updated successfully!');
|
|
} else {
|
|
Appointment::create($data);
|
|
session()->flash('message', 'Appointment scheduled successfully!');
|
|
}
|
|
|
|
$this->dispatch('appointment-saved');
|
|
$this->closeModal();
|
|
}
|
|
|
|
public function closeModal()
|
|
{
|
|
$this->showModal = false;
|
|
$this->dispatch('close-appointment-form');
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.appointments.form');
|
|
}
|
|
}
|