sackey e3b2b220d2
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
Enhance UI and functionality across various components
- 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.
2025-08-16 14:36:58 +00:00

751 lines
48 KiB
PHP

<div>
<div class="max-w-6xl mx-auto space-y-6">
<!-- Header -->
<div class="flex items-center justify-between">
<div>
<flux:heading size="xl">{{ ucfirst($type) }} Vehicle Inspection</flux:heading>
<flux:subheading>Job Card: {{ $jobCard->job_card_number }} - {{ $jobCard->customer->name ?? 'Unknown Customer' }}</flux:subheading>
</div>
<flux:button href="{{ route('job-cards.show', $jobCard) }}" variant="ghost" size="sm" icon="arrow-left">
Back to Job Card
</flux:button>
</div>
<!-- Workflow Progress -->
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-4">
<!-- Step 1: Vehicle Reception -->
<div class="flex items-center">
<div class="flex items-center justify-center w-8 h-8 bg-green-500 text-white rounded-full text-sm font-semibold">
</div>
<span class="ml-2 text-sm font-medium text-green-600 dark:text-green-400">Vehicle Reception</span>
</div>
<div class="w-8 h-0.5 bg-green-500"></div>
<!-- Step 2: Initial Inspection (Current) -->
<div class="flex items-center">
<div class="flex items-center justify-center w-8 h-8 bg-blue-500 text-white rounded-full text-sm font-semibold animate-pulse">
2
</div>
<span class="ml-2 text-sm font-medium text-blue-600 dark:text-blue-400">{{ ucfirst($type) }} Inspection</span>
</div>
<div class="w-8 h-0.5 bg-zinc-300 dark:bg-zinc-600"></div>
<!-- Step 3: Diagnosis -->
<div class="flex items-center">
<div class="flex items-center justify-center w-8 h-8 bg-zinc-300 dark:bg-zinc-600 text-zinc-600 dark:text-zinc-400 rounded-full text-sm font-semibold">
3
</div>
<span class="ml-2 text-sm text-zinc-500 dark:text-zinc-400">Diagnosis</span>
</div>
</div>
</div>
</div>
<!-- Vehicle Information -->
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
<flux:heading size="lg" class="mb-4 flex items-center">
<svg class="w-5 h-5 mr-2 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12a1 1 0 01-1-1V7a1 1 0 011-1h6a1 1 0 011 1v4a1 1 0 01-1 1m-6 0h6m-6 0v4a1 1 0 001 1h4a1 1 0 001-1v-4"></path>
</svg>
Vehicle Information
</flux:heading>
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 text-sm">
<div>
<span class="font-medium text-zinc-700 dark:text-zinc-300">Customer:</span>
<div class="text-zinc-900 dark:text-zinc-100">{{ $jobCard->customer->name ?? 'Unknown Customer' }}</div>
@if($jobCard->customer->phone)
<div class="text-zinc-500 dark:text-zinc-400">{{ $jobCard->customer->phone }}</div>
@endif
</div>
<div>
<span class="font-medium text-zinc-700 dark:text-zinc-300">Vehicle:</span>
<div class="text-zinc-900 dark:text-zinc-100">{{ $jobCard->vehicle->year ?? '' }} {{ $jobCard->vehicle->make ?? '' }} {{ $jobCard->vehicle->model ?? '' }}</div>
</div>
<div>
<span class="font-medium text-zinc-700 dark:text-zinc-300">License Plate:</span>
<div class="text-zinc-900 dark:text-zinc-100">{{ $jobCard->vehicle->license_plate ?? '' }}</div>
</div>
<div>
<span class="font-medium text-zinc-700 dark:text-zinc-300">VIN:</span>
<div class="text-zinc-900 dark:text-zinc-100 text-xs break-all">{{ $jobCard->vehicle->vin ?? 'N/A' }}</div>
</div>
</div>
@if($jobCard->customer_reported_issues)
<div class="mt-4 p-4 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg">
<h5 class="font-medium text-amber-800 dark:text-amber-200 mb-2">Customer Reported Issues:</h5>
<p class="text-amber-700 dark:text-amber-300 text-sm">{{ $jobCard->customer_reported_issues }}</p>
</div>
@endif
</div>
<!-- Inspection Form -->
<form wire:submit="save" class="space-y-6">
<!-- Basic Information -->
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
<flux:heading size="lg" class="mb-6">Basic Information</flux:heading>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div>
@if($jobCard->mileage_in)
<flux:input
wire:model="current_mileage"
label="Current Mileage (km)"
type="number"
readonly
required
/>
<p class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">
<svg class="w-3 h-3 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
Pulled from Job Card
</p>
@else
<flux:input
wire:model="current_mileage"
label="Current Mileage (km)"
type="number"
placeholder="Enter current mileage"
required
/>
@endif
@error('current_mileage')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<div>
@if($jobCard->fuel_level_in)
<div>
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Fuel Level</label>
<select disabled class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-md bg-zinc-50 dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100">
<option value="{{ $fuel_level }}">{{ ucwords(str_replace('_', ' ', $fuel_level)) }}</option>
</select>
<p class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">
<svg class="w-3 h-3 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
Pulled from Job Card
</p>
</div>
@else
<flux:select wire:model="fuel_level" label="Fuel Level" required>
<option value="">Select fuel level...</option>
<option value="empty">Empty (0-10%)</option>
<option value="low">Low (10-25%)</option>
<option value="quarter">Quarter (25-40%)</option>
<option value="half">Half (40-60%)</option>
<option value="three_quarter">Three Quarter (60-85%)</option>
<option value="full">Full (85-100%)</option>
</flux:select>
@endif
@error('fuel_level')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<div>
<flux:select wire:model="overall_condition" label="Overall Condition" required>
<option value="">Select condition...</option>
<option value="excellent">Excellent</option>
<option value="good">Good</option>
<option value="fair">Fair</option>
<option value="poor">Poor</option>
</flux:select>
@error('overall_condition')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
</div>
</div>
<!-- Inspection Checklist -->
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
<flux:heading size="lg" class="mb-6">Vehicle Inspection Checklist</flux:heading>
@error('checklist')
<div class="mb-4 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg">
<div class="flex">
<svg class="w-5 h-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
</svg>
<div class="ml-3">
<h3 class="text-sm font-medium text-red-800 dark:text-red-200">Checklist Incomplete</h3>
<p class="mt-1 text-sm text-red-700 dark:text-red-300">{{ $message }}</p>
</div>
</div>
</div>
@enderror
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- Left Column -->
<div class="space-y-8">
<!-- Documentation -->
<div>
<h4 class="text-lg font-semibold text-zinc-900 dark:text-zinc-100 mb-4 flex items-center">
<svg class="w-5 h-5 mr-2 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
Documentation
</h4>
<div class="space-y-3">
@foreach([
'manufacturers_handbook' => "Manufacturer's handbook",
'service_record_book' => 'Service record book (up-to-date)',
'company_drivers_handbook' => "Company driver's handbook",
'accident_report_form' => 'Accident report form',
'safety_inspection_sticker' => 'Copy of annual safety inspection sticker or form'
] as $key => $label)
<div class="flex items-center justify-between py-2 border-b border-zinc-100 dark:border-zinc-700">
<span class="text-sm text-zinc-700 dark:text-zinc-300">{{ $label }}</span>
<div class="flex space-x-4">
<label class="flex items-center">
<input type="radio" wire:model="checklist.documentation.{{ $key }}" value="yes" class="text-green-600 focus:ring-green-500">
<span class="ml-1 text-xs text-green-600">Yes</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="checklist.documentation.{{ $key }}" value="no" class="text-red-600 focus:ring-red-500">
<span class="ml-1 text-xs text-red-600">No</span>
</label>
</div>
</div>
@endforeach
</div>
</div>
<!-- Vehicle Interior -->
<div>
<h4 class="text-lg font-semibold text-zinc-900 dark:text-zinc-100 mb-4 flex items-center">
<svg class="w-5 h-5 mr-2 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"></path>
</svg>
Vehicle Interior
</h4>
<div class="space-y-3">
@foreach([
'heating' => 'Heating',
'air_conditioning' => 'Air Conditioning',
'windshield_defrosting_system' => 'Windshield defrosting system',
'window_operation' => 'Window operation',
'door_handles_locks' => 'Door handles / locks',
'alarm' => 'Alarm',
'signals' => 'Signals',
'seat_belts_work' => 'Seat belts work and free of damage / excessive wear',
'interior_lights' => 'Interior Lights',
'mirrors_good_position' => 'Mirrors are in good position and properly adjusted',
'warning_lights' => 'No warning lights are on',
'fuel_levels' => 'Fuel levels',
'oil_level_sufficient' => 'Oil level is sufficiently high',
'washer_fluids_sufficient' => 'Washer fluids levels are sufficiently high',
'radiator_fluid_sufficient' => 'Radiator fluid levels are sufficient',
'emergency_roadside_supplies' => 'Emergency roadside supplies are properly stocked and located in the trunk of vehicle'
] as $key => $label)
<div class="flex items-center justify-between py-2 border-b border-zinc-100 dark:border-zinc-700">
<span class="text-sm text-zinc-700 dark:text-zinc-300">{{ $label }}</span>
<div class="flex space-x-4">
<label class="flex items-center">
<input type="radio" wire:model="checklist.interior.{{ $key }}" value="yes" class="text-green-600 focus:ring-green-500">
<span class="ml-1 text-xs text-green-600">Yes</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="checklist.interior.{{ $key }}" value="no" class="text-red-600 focus:ring-red-500">
<span class="ml-1 text-xs text-red-600">No</span>
</label>
</div>
</div>
@endforeach
</div>
</div>
<!-- Engine Compartment -->
<div>
<h4 class="text-lg font-semibold text-zinc-900 dark:text-zinc-100 mb-4 flex items-center">
<svg class="w-5 h-5 mr-2 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
</svg>
Engine Compartment
</h4>
<div class="space-y-3">
@foreach([
'engine_oil_level' => 'Engine oil level',
'coolant_level_antifreeze' => 'Coolant level (anti-freeze)',
'battery_secured' => 'Battery secured',
'brake_fluid_level' => 'Brake fluid level',
'air_filter_clean' => 'Air filter is clean',
'belts_hoses_good' => 'Belts and hoses are in good condition - no cracks, full with adequate tension'
] as $key => $label)
<div class="flex items-center justify-between py-2 border-b border-zinc-100 dark:border-zinc-700">
<span class="text-sm text-zinc-700 dark:text-zinc-300">{{ $label }}</span>
<div class="flex space-x-4">
<label class="flex items-center">
<input type="radio" wire:model="checklist.engine.{{ $key }}" value="yes" class="text-green-600 focus:ring-green-500">
<span class="ml-1 text-xs text-green-600">Yes</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="checklist.engine.{{ $key }}" value="no" class="text-red-600 focus:ring-red-500">
<span class="ml-1 text-xs text-red-600">No</span>
</label>
</div>
</div>
@endforeach
</div>
</div>
</div>
<!-- Right Column -->
<div class="space-y-8">
<!-- Vehicle Exterior -->
<div>
<h4 class="text-lg font-semibold text-zinc-900 dark:text-zinc-100 mb-4 flex items-center">
<svg class="w-5 h-5 mr-2 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 14v3m4-3v3m4-3v3M3 21h18M3 10h18M3 7l9-4 9 4M4 10h16v11H4V10z"></path>
</svg>
Vehicle Exterior
</h4>
<div class="space-y-3">
@foreach([
'windshield_not_cracked' => 'Windows/windshield not severely cracked',
'windshield_wipers_functional' => 'Functional Windshield wipers',
'headlights_high_low' => 'Headlights (high/low beam)',
'tail_lights_brake_lights' => 'Tail lights / brake lights',
'emergency_brake_working' => 'Emergency brake in good working order',
'power_brakes_working' => 'Power brakes are in good working order',
'horn_works' => 'Horn works',
'tires_good_shape' => 'Tires in good shape (no damages and adequately inflated)',
'no_air_leaks' => 'No air leaks (walk around the vehicle and listen for air leaks while driver applies the brakes)',
'no_oil_grease_leaks' => 'No oil / grease leaks (oil wheel seats or under the vehicle)',
'no_fuel_leaks' => 'No fuel leaks or odour of gasoline detected',
'mirrors_good_position' => 'Mirrors are in good position and properly adjusted',
'exhaust_system_working' => 'Exhaust system is in good working order',
'wheels_fasteners_tight' => 'Wheels and fasteners are fitted tightly',
'turn_signals' => 'Turn signals',
'vehicle_free_damage' => 'Vehicle is free of excessive damage',
'loads_fastened' => 'All loads are fastened / secured',
'spare_tire_good' => 'Spare tire is in good condition',
'vehicle_condition_satisfactory' => 'Vehicle condition is satisfactory',
'defects_recorded' => 'Defects recorded'
] as $key => $label)
<div class="flex items-center justify-between py-2 border-b border-zinc-100 dark:border-zinc-700">
<span class="text-sm text-zinc-700 dark:text-zinc-300">{{ $label }}</span>
<div class="flex space-x-4">
<label class="flex items-center">
<input type="radio" wire:model="checklist.exterior.{{ $key }}" value="yes" class="text-green-600 focus:ring-green-500">
<span class="ml-1 text-xs text-green-600">Yes</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="checklist.exterior.{{ $key }}" value="no" class="text-red-600 focus:ring-red-500">
<span class="ml-1 text-xs text-red-600">No</span>
</label>
</div>
</div>
@endforeach
</div>
</div>
<!-- Vehicle Damage Diagram -->
<div>
<h4 class="text-lg font-semibold text-zinc-900 dark:text-zinc-100 mb-4 flex items-center">
<svg class="w-5 h-5 mr-2 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
Vehicle Damage Diagram
</h4>
<div class="bg-zinc-50 dark:bg-zinc-700 rounded-lg p-4">
<p class="text-sm text-zinc-600 dark:text-zinc-400 mb-4">Click on any area of the vehicle to mark damage, dents, or scratches</p>
<!-- Vehicle Diagram Container -->
<div class="border-2 border-dashed border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-800 p-4">
<div id="vehicle-diagram-container" class="relative">
<!-- Vehicle SVG Diagram -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 450" class="w-full h-auto max-h-96">
<!-- Left Side View -->
<g id="left-side" transform="translate(50, 50)">
<rect x="0" y="50" width="180" height="70" fill="#f8fafc" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="left-body"/>
<circle cx="25" cy="130" r="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="left-front-wheel"/>
<circle cx="155" cy="130" r="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="left-rear-wheel"/>
<rect x="0" y="30" width="35" height="20" fill="#f8fafc" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="left-front-bumper"/>
<rect x="145" y="30" width="35" height="20" fill="#f8fafc" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="left-rear-bumper"/>
<text x="90" y="20" text-anchor="middle" class="text-xs fill-zinc-700 dark:fill-zinc-300">Left Side</text>
</g>
<!-- Top View -->
<g id="top-view" transform="translate(320, 50)">
<rect x="0" y="0" width="70" height="180" fill="#f8fafc" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="roof"/>
<rect x="-8" y="25" width="16" height="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="front-left-wheel"/>
<rect x="62" y="25" width="16" height="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="front-right-wheel"/>
<rect x="-8" y="135" width="16" height="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="rear-left-wheel"/>
<rect x="62" y="135" width="16" height="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="rear-right-wheel"/>
<rect x="10" y="-5" width="50" height="10" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="windshield"/>
<rect x="10" y="175" width="50" height="10" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="rear-window"/>
<text x="35" y="-15" text-anchor="middle" class="text-xs fill-zinc-700 dark:fill-zinc-300">Top View</text>
</g>
<!-- Right Side View -->
<g id="right-side" transform="translate(450, 50)">
<rect x="0" y="50" width="180" height="70" fill="#f8fafc" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="right-body"/>
<circle cx="25" cy="130" r="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="right-front-wheel"/>
<circle cx="155" cy="130" r="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="right-rear-wheel"/>
<rect x="0" y="30" width="35" height="20" fill="#f8fafc" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="right-front-bumper"/>
<rect x="145" y="30" width="35" height="20" fill="#f8fafc" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="right-rear-bumper"/>
<text x="90" y="20" text-anchor="middle" class="text-xs fill-zinc-700 dark:fill-zinc-300">Right Side</text>
</g>
<!-- Front View -->
<g id="front-view" transform="translate(150, 250)">
<rect x="0" y="0" width="90" height="70" fill="#f8fafc" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="front"/>
<rect x="-8" y="60" width="20" height="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="front-left-tire"/>
<rect x="78" y="60" width="20" height="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="front-right-tire"/>
<rect x="15" y="-8" width="60" height="8" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="hood"/>
<text x="45" y="-15" text-anchor="middle" class="text-xs fill-zinc-700 dark:fill-zinc-300">Front View</text>
</g>
<!-- Rear View -->
<g id="rear-view" transform="translate(350, 250)">
<rect x="0" y="0" width="90" height="70" fill="#f8fafc" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="rear"/>
<rect x="-8" y="60" width="20" height="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="rear-left-tire"/>
<rect x="78" y="60" width="20" height="20" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="rear-right-tire"/>
<rect x="15" y="70" width="60" height="8" fill="#e2e8f0" stroke="#64748b" stroke-width="2" class="clickable-area" data-area="trunk"/>
<text x="45" y="-10" text-anchor="middle" class="text-xs fill-zinc-700 dark:fill-zinc-300">Rear View</text>
</g>
<!-- Damage markers will be added here dynamically -->
<g id="damage-markers"></g>
</svg>
</div>
</div>
<!-- Damage Legend -->
<div class="mt-4 grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
<div class="flex items-center">
<div class="w-6 h-6 bg-red-500 rounded-full mr-2"></div>
<span class="text-zinc-700 dark:text-zinc-300">Damage</span>
</div>
<div class="flex items-center">
<div class="w-6 h-6 bg-orange-500 rounded-full mr-2"></div>
<span class="text-zinc-700 dark:text-zinc-300">Dent</span>
</div>
<div class="flex items-center">
<div class="w-6 h-6 bg-yellow-500 rounded-full mr-2"></div>
<span class="text-zinc-700 dark:text-zinc-300">Scratch</span>
</div>
<div class="flex items-center">
<div class="w-6 h-6 bg-blue-500 rounded-full mr-2"></div>
<span class="text-zinc-700 dark:text-zinc-300">Other</span>
</div>
</div>
<!-- Selected Damage List -->
<div id="damage-list" class="mt-4">
<h5 class="font-medium text-zinc-900 dark:text-zinc-100 mb-2">Marked Damage:</h5>
<div id="damage-items" class="space-y-2"></div>
</div>
</div>
</div>
</div>
</div>
<!-- Additional Comments Section -->
<div class="mt-8 pt-6 border-t border-zinc-200 dark:border-zinc-700">
<h4 class="text-lg font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Additional Comments</h4>
<flux:textarea
wire:model="additional_comments"
placeholder="Record any additional observations, defects, or comments..."
rows="4"
class="w-full"
/>
</div>
<!-- Inspection Signature Section -->
<div class="mt-8 pt-6 border-t border-zinc-200 dark:border-zinc-700">
<h4 class="text-lg font-semibold text-zinc-900 dark:text-zinc-100 mb-4">Inspection Performed By</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Employee Name</label>
<input type="text" value="{{ auth()->user()->name }}" readonly
class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-md bg-zinc-50 dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100">
</div>
<div>
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Date & Time</label>
<input type="text" value="{{ now()->format('M d, Y \a\t g:i A') }}" readonly
class="w-full px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-md bg-zinc-50 dark:bg-zinc-700 text-zinc-900 dark:text-zinc-100">
</div>
</div>
<div class="mt-4">
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Digital Signature</label>
<div class="px-3 py-2 border border-zinc-300 dark:border-zinc-600 rounded-md bg-zinc-50 dark:bg-zinc-700 text-zinc-600 dark:text-zinc-400 italic">
By completing this inspection, {{ auth()->user()->name }} confirms the accuracy of all recorded information.
</div>
</div>
</div>
</div>
<!-- Additional Notes -->
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
<flux:heading size="lg" class="mb-6">Additional Information</flux:heading>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<flux:textarea
wire:model="damage_notes"
label="Damage Notes"
placeholder="Note any visible damage, scratches, dents, etc..."
rows="4"
/>
@error('damage_notes')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<div>
<flux:textarea
wire:model="recommendations"
label="Recommendations"
placeholder="Any recommendations for maintenance or repairs..."
rows="4"
/>
@error('recommendations')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
</div>
<div class="mt-6">
<flux:textarea
wire:model="notes"
label="Additional Notes"
placeholder="Any other observations or notes..."
rows="3"
/>
@error('notes')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<div class="mt-6 grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Cleanliness Rating</label>
<flux:select wire:model="cleanliness_rating">
<option value="1">1 - Very Poor</option>
<option value="2">2 - Poor</option>
<option value="3">3 - Fair</option>
<option value="4">4 - Good</option>
<option value="5">5 - Excellent</option>
</flux:select>
</div>
<div class="flex items-center">
<input
type="checkbox"
wire:model="follow_up_required"
id="follow_up_required"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-zinc-300 rounded"
>
<label for="follow_up_required" class="ml-2 block text-sm text-zinc-700 dark:text-zinc-300">
Follow-up inspection required
</label>
</div>
</div>
</div>
<!-- Form Actions -->
<div class="flex justify-between items-center">
<flux:button href="{{ route('job-cards.show', $jobCard) }}" variant="ghost" size="sm">
Cancel
</flux:button>
<flux:button type="submit" variant="primary" size="sm" wire:loading.attr="disabled" wire:target="save">
<span wire:loading.remove wire:target="save">Complete {{ ucfirst($type) }} Inspection</span>
<span wire:loading wire:target="save">Processing...</span>
</flux:button>
</div>
</form>
</div>
<!-- Vehicle Damage Diagram Script -->
<script>
document.addEventListener('DOMContentLoaded', function() {
let damageData = @this.get('damage_diagram_data');
let currentDamageType = 'damage';
// Add damage type selector
const diagramContainer = document.querySelector('#vehicle-diagram-container');
if (diagramContainer) {
const typeSelector = document.createElement('div');
typeSelector.className = 'mb-4 flex gap-2 flex-wrap';
typeSelector.innerHTML = `
<button type="button" onclick="setDamageType('damage')" class="damage-type-btn active px-3 py-1 text-xs rounded-full bg-red-500 text-white" data-type="damage">Damage</button>
<button type="button" onclick="setDamageType('dent')" class="damage-type-btn px-3 py-1 text-xs rounded-full bg-orange-500 text-white" data-type="dent">Dent</button>
<button type="button" onclick="setDamageType('scratch')" class="damage-type-btn px-3 py-1 text-xs rounded-full bg-yellow-500 text-white" data-type="scratch">Scratch</button>
<button type="button" onclick="setDamageType('other')" class="damage-type-btn px-3 py-1 text-xs rounded-full bg-blue-500 text-white" data-type="other">Other</button>
`;
diagramContainer.insertBefore(typeSelector, diagramContainer.firstChild);
}
// Set damage type function
window.setDamageType = function(type) {
currentDamageType = type;
document.querySelectorAll('.damage-type-btn').forEach(btn => {
btn.classList.remove('active', 'ring-2', 'ring-offset-2');
if (btn.dataset.type === type) {
btn.classList.add('active', 'ring-2', 'ring-offset-2');
}
});
};
// Add click handlers to clickable areas
document.querySelectorAll('.clickable-area').forEach(area => {
area.style.cursor = 'pointer';
area.addEventListener('click', function(e) {
const areaName = this.dataset.area;
const rect = this.getBoundingClientRect();
const svg = document.querySelector('#vehicle-diagram-container svg');
const svgRect = svg.getBoundingClientRect();
// Calculate relative position within the SVG
const x = ((e.clientX - svgRect.left) / svgRect.width) * 800;
const y = ((e.clientY - svgRect.top) / svgRect.height) * 450;
addDamageMarker(areaName, x, y, currentDamageType);
});
// Add hover effect
area.addEventListener('mouseenter', function() {
this.style.fill = 'rgba(59, 130, 246, 0.2)';
});
area.addEventListener('mouseleave', function() {
this.style.fill = '';
});
});
// Add damage marker function
function addDamageMarker(area, x, y, type) {
const colors = {
damage: '#ef4444',
dent: '#f97316',
scratch: '#eab308',
other: '#3b82f6'
};
const markerId = Date.now();
const damageMarkers = document.querySelector('#damage-markers');
// Create marker circle
const marker = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
marker.setAttribute('cx', x);
marker.setAttribute('cy', y);
marker.setAttribute('r', '8');
marker.setAttribute('fill', colors[type]);
marker.setAttribute('stroke', '#fff');
marker.setAttribute('stroke-width', '2');
marker.setAttribute('class', 'damage-marker');
marker.setAttribute('data-id', markerId);
marker.style.cursor = 'pointer';
// Add click to remove
marker.addEventListener('click', function(e) {
e.stopPropagation();
removeDamageMarker(markerId);
});
damageMarkers.appendChild(marker);
// Update damage data
const newDamage = {
id: markerId,
area: area,
x: x,
y: y,
type: type,
description: `${type} on ${area.replace(/-/g, ' ')}`
};
damageData.push(newDamage);
updateDamageList();
}
// Remove damage marker function
function removeDamageMarker(id) {
const marker = document.querySelector(`[data-id="${id}"]`);
if (marker) {
marker.remove();
}
const index = damageData.findIndex(item => item.id == id);
if (index > -1) {
damageData.splice(index, 1);
}
updateDamageList();
}
// Update damage list display
function updateDamageList() {
const damageItems = document.querySelector('#damage-items');
damageItems.innerHTML = '';
damageData.forEach(damage => {
const colors = {
damage: 'bg-red-100 text-red-800',
dent: 'bg-orange-100 text-orange-800',
scratch: 'bg-yellow-100 text-yellow-800',
other: 'bg-blue-100 text-blue-800'
};
const item = document.createElement('div');
item.className = `flex items-center justify-between p-2 rounded ${colors[damage.type]}`;
item.innerHTML = `
<span class="text-sm">${damage.description}</span>
<button type="button" onclick="removeDamageMarker(${damage.id})" class="text-red-600 hover:text-red-800">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
`;
damageItems.appendChild(item);
});
}
// Initialize with existing damage data
if (damageData && damageData.length > 0) {
damageData.forEach(damage => {
const colors = {
damage: '#ef4444',
dent: '#f97316',
scratch: '#eab308',
other: '#3b82f6'
};
const damageMarkers = document.querySelector('#damage-markers');
const marker = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
marker.setAttribute('cx', damage.x);
marker.setAttribute('cy', damage.y);
marker.setAttribute('r', '8');
marker.setAttribute('fill', colors[damage.type]);
marker.setAttribute('stroke', '#fff');
marker.setAttribute('stroke-width', '2');
marker.setAttribute('class', 'damage-marker');
marker.setAttribute('data-id', damage.id);
marker.style.cursor = 'pointer';
marker.addEventListener('click', function(e) {
e.stopPropagation();
removeDamageMarker(damage.id);
});
damageMarkers.appendChild(marker);
});
updateDamageList();
}
// Make remove function global
window.removeDamageMarker = removeDamageMarker;
});
</script>
</div>