- Increased icon sizes in service items, service orders, users, and technician management for better visibility. - Added custom loading indicators with appropriate icons in search fields for vehicles, work orders, and technicians. - Introduced invoice management routes for better organization and access control. - Created a new test for the estimate PDF functionality to ensure proper rendering and data integrity.
186 lines
13 KiB
PHP
186 lines
13 KiB
PHP
<div>
|
|
<div class="max-w-4xl mx-auto space-y-6">
|
|
<!-- Header -->
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<h1 class="text-3xl font-bold text-zinc-900 dark:text-zinc-100">Schedule Appointment</h1>
|
|
<p class="text-zinc-600 dark:text-zinc-400">Create a new appointment for a customer</p>
|
|
</div>
|
|
<a href="{{ route('appointments.index') }}" class="inline-flex items-center px-4 py-2 border border-zinc-300 dark:border-zinc-600 hover:bg-zinc-50 dark:hover:bg-zinc-700 text-zinc-700 dark:text-zinc-300 font-medium rounded-lg transition-colors">
|
|
<svg class="w-6 h-6 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
|
|
</svg>
|
|
Back to Appointments
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Success Message -->
|
|
@if (session()->has('message'))
|
|
<div class="bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-lg p-4">
|
|
<div class="flex">
|
|
<svg class="w-5 h-5 text-green-400 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
|
</svg>
|
|
<p class="text-green-800 dark:text-green-200">{{ session('message') }}</p>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Error Message -->
|
|
@if ($errors->has('general'))
|
|
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
|
|
<div class="flex">
|
|
<svg class="w-5 h-5 text-red-400 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
</svg>
|
|
<p class="text-red-800 dark:text-red-200">{{ $errors->first('general') }}</p>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<form wire:submit="save" class="space-y-6">
|
|
<!-- Customer & Vehicle Information -->
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg">
|
|
<div class="flex items-center gap-3 p-4 border-b border-zinc-200 dark:border-zinc-700">
|
|
<svg class="text-blue-500 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
|
|
</svg>
|
|
<h3 class="text-lg font-medium text-zinc-900 dark:text-zinc-100">Customer & Vehicle</h3>
|
|
</div>
|
|
|
|
<div class="p-6 space-y-6">
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<!-- Customer Selection -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Customer *</label>
|
|
<select wire:model.live="customer_id" class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
|
<option value="">Select customer...</option>
|
|
@foreach($customers as $customer)
|
|
<option value="{{ $customer->id }}">{{ $customer->first_name }} {{ $customer->last_name }}</option>
|
|
@endforeach
|
|
</select>
|
|
@error('customer_id') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
|
</div>
|
|
|
|
<!-- Vehicle Selection -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Vehicle *</label>
|
|
<select wire:model="vehicle_id" {{ !$customer_id ? 'disabled' : '' }} class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 disabled:opacity-50">
|
|
<option value="">Select vehicle...</option>
|
|
@foreach($vehicles as $vehicle)
|
|
<option value="{{ $vehicle->id }}">
|
|
{{ $vehicle->year }} {{ $vehicle->make }} {{ $vehicle->model }}
|
|
</option>
|
|
@endforeach
|
|
</select>
|
|
@error('vehicle_id') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Appointment Details -->
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg">
|
|
<div class="flex items-center gap-3 p-4 border-b border-zinc-200 dark:border-zinc-700">
|
|
<svg class="text-green-500 w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
|
</svg>
|
|
<h3 class="text-lg font-medium text-zinc-900 dark:text-zinc-100">Appointment Details</h3>
|
|
</div>
|
|
|
|
<div class="p-6 space-y-6">
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
<!-- Date -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Date *</label>
|
|
<input type="date" wire:model.live="scheduled_date" class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
|
@error('scheduled_date') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
|
</div>
|
|
|
|
<!-- Time -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Time *</label>
|
|
<select wire:model="scheduled_time" class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
|
<option value="">Select time...</option>
|
|
@foreach($availableTimeSlots as $slot)
|
|
<option value="{{ $slot['value'] }}">{{ $slot['label'] }}</option>
|
|
@endforeach
|
|
</select>
|
|
@error('scheduled_time') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
|
</div>
|
|
|
|
<!-- Duration -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Duration</label>
|
|
<select wire:model.live="estimated_duration_minutes" class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
|
@foreach($durationOptions as $minutes => $label)
|
|
<option value="{{ $minutes }}">{{ $label }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<!-- Appointment Type -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Type</label>
|
|
<select wire:model="appointment_type" class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
|
@foreach($appointmentTypes as $value => $label)
|
|
<option value="{{ $value }}">{{ $label }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Technician -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Assigned Technician (Optional)</label>
|
|
<select wire:model.live="assigned_technician_id" class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
|
<option value="">Auto-assign later</option>
|
|
@foreach($technicians as $technician)
|
|
<option value="{{ $technician->id }}">{{ $technician->first_name }} {{ $technician->last_name }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Service Requested -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Service Requested *</label>
|
|
<textarea wire:model="service_requested" rows="3" class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Describe the service requested..."></textarea>
|
|
@error('service_requested') <p class="text-red-600 text-sm mt-1">{{ $message }}</p> @enderror
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<!-- Customer Notes -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Customer Notes</label>
|
|
<textarea wire:model="customer_notes" rows="3" class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Customer comments or special requests..."></textarea>
|
|
</div>
|
|
|
|
<!-- Internal Notes -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Internal Notes</label>
|
|
<textarea wire:model="internal_notes" rows="3" class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Internal notes for staff..."></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Actions -->
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
|
|
<div class="flex flex-col sm:flex-row gap-4 justify-end">
|
|
<a href="{{ route('appointments.index') }}" class="inline-flex items-center justify-center px-6 py-3 border border-zinc-300 dark:border-zinc-600 hover:bg-zinc-50 dark:hover:bg-zinc-700 text-zinc-700 dark:text-zinc-300 font-medium rounded-lg transition-colors">
|
|
Cancel
|
|
</a>
|
|
<button type="submit" class="inline-flex items-center justify-center px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors">
|
|
<svg class="w-6 h-6 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
|
|
</svg>
|
|
Schedule Appointment
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|