- Added buttons for assigning diagnosis and starting diagnosis based on job card status in the job card view. - Implemented a modal for assigning technicians for diagnosis, including form validation and technician selection. - Updated routes to include a test route for job cards. - Created a new Blade view for testing inspection inputs. - Developed comprehensive feature tests for the estimate module, including creation, viewing, editing, and validation of estimates. - Added tests for estimate model relationships and statistics calculations. - Introduced a basic feature test for job cards index.
311 lines
19 KiB
PHP
311 lines
19 KiB
PHP
<div class="max-w-7xl mx-auto space-y-8">
|
|
<!-- Print Styles -->
|
|
<style>
|
|
@media print {
|
|
body { -webkit-print-color-adjust: exact; }
|
|
.no-print { display: none !important; }
|
|
.print-break { page-break-before: always; }
|
|
.max-w-7xl { max-width: none; }
|
|
.space-y-8 > * + * { margin-top: 1.5rem; }
|
|
.grid { display: block; }
|
|
.grid > * { margin-bottom: 1rem; }
|
|
.bg-white, .dark\\:bg-zinc-800 { background-color: white !important; }
|
|
.border { border: 1px solid #ccc !important; }
|
|
.text-zinc-600, .dark\\:text-zinc-400 { color: #666 !important; }
|
|
.text-zinc-900, .dark\\:text-zinc-100 { color: #000 !important; }
|
|
}
|
|
</style>
|
|
|
|
<!-- Print Header (only visible when printing) -->
|
|
<div class="hidden print:block">
|
|
<div class="text-center border-b-2 border-gray-300 pb-4 mb-6">
|
|
<h1 class="text-2xl font-bold">Vehicle Inspection Report</h1>
|
|
<p class="text-gray-600 mt-2">Generated on {{ now()->format('F d, Y \a\t g:i A') }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Header -->
|
|
<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>
|
|
<flux:heading size="xl" class="text-zinc-900 dark:text-zinc-100">Inspection Details</flux:heading>
|
|
<p class="text-zinc-600 dark:text-zinc-400 mt-2 text-lg">
|
|
{{ ucfirst($inspection->inspection_type) }} inspection for {{ $inspection->jobCard->vehicle->year }} {{ $inspection->jobCard->vehicle->make }} {{ $inspection->jobCard->vehicle->model }}
|
|
</p>
|
|
</div>
|
|
<div class="flex space-x-3 no-print">
|
|
<flux:button href="{{ route('job-cards.show', $inspection->jobCard) }}" variant="ghost" size="sm" icon="arrow-left">
|
|
Back to Job Card
|
|
</flux:button>
|
|
<flux:button
|
|
size="sm"
|
|
variant="outline"
|
|
icon="printer"
|
|
onclick="window.open('{{ route('inspections.print', $inspection) }}', '_blank', 'width=800,height=600,scrollbars=yes,resizable=yes')"
|
|
>
|
|
Print Report
|
|
</flux:button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Quick Stats -->
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-6">
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6 text-center">
|
|
<div class="text-3xl font-bold text-blue-600 dark:text-blue-400">{{ ucfirst($inspection->overall_condition) }}</div>
|
|
<div class="text-sm text-zinc-600 dark:text-zinc-400 mt-1">Overall Condition</div>
|
|
</div>
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6 text-center">
|
|
<div class="text-3xl font-bold text-green-600 dark:text-green-400">{{ number_format($inspection->current_mileage) }}</div>
|
|
<div class="text-sm text-zinc-600 dark:text-zinc-400 mt-1">Kilometers</div>
|
|
</div>
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6 text-center">
|
|
<div class="text-3xl font-bold text-orange-600 dark:text-orange-400">{{ $inspection->cleanliness_rating }}/10</div>
|
|
<div class="text-sm text-zinc-600 dark:text-zinc-400 mt-1">Cleanliness Rating</div>
|
|
</div>
|
|
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6 text-center">
|
|
<div class="text-3xl font-bold text-purple-600 dark:text-purple-400">{{ ucwords(str_replace('_', ' ', $inspection->fuel_level)) }}</div>
|
|
<div class="text-sm text-zinc-600 dark:text-zinc-400 mt-1">Fuel Level</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Vehicle & Customer Info -->
|
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
|
<!-- 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-6 text-zinc-900 dark:text-zinc-100">Vehicle Information</flux:heading>
|
|
|
|
<div class="space-y-4">
|
|
<div class="flex justify-between py-3 border-b border-zinc-100 dark:border-zinc-700">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">Vehicle</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400">{{ $inspection->jobCard->vehicle->year }} {{ $inspection->jobCard->vehicle->make }} {{ $inspection->jobCard->vehicle->model }}</span>
|
|
</div>
|
|
<div class="flex justify-between py-3 border-b border-zinc-100 dark:border-zinc-700">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">License Plate</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400 font-mono">{{ $inspection->jobCard->vehicle->license_plate }}</span>
|
|
</div>
|
|
<div class="flex justify-between py-3 border-b border-zinc-100 dark:border-zinc-700">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">VIN</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400 font-mono text-sm">{{ $inspection->jobCard->vehicle->vin }}</span>
|
|
</div>
|
|
<div class="flex justify-between py-3">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">Color</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400">{{ $inspection->jobCard->vehicle->color ?? 'Not specified' }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Customer 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 text-zinc-900 dark:text-zinc-100">Customer Information</flux:heading>
|
|
|
|
<div class="space-y-4">
|
|
<div class="flex justify-between py-3 border-b border-zinc-100 dark:border-zinc-700">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">Name</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400">{{ $inspection->jobCard->customer->first_name }} {{ $inspection->jobCard->customer->last_name }}</span>
|
|
</div>
|
|
<div class="flex justify-between py-3 border-b border-zinc-100 dark:border-zinc-700">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">Phone</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400 font-mono">{{ $inspection->jobCard->customer->phone ?? 'Not provided' }}</span>
|
|
</div>
|
|
<div class="flex justify-between py-3 border-b border-zinc-100 dark:border-zinc-700">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">Email</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400 text-sm">{{ $inspection->jobCard->customer->email ?? 'Not provided' }}</span>
|
|
</div>
|
|
<div class="flex justify-between py-3">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">Customer ID</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400">#{{ $inspection->jobCard->customer->id }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Inspection 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 text-zinc-900 dark:text-zinc-100">Inspection Information</flux:heading>
|
|
|
|
<div class="space-y-4">
|
|
<div class="flex justify-between py-3 border-b border-zinc-100 dark:border-zinc-700">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">Type</span>
|
|
<flux:badge color="blue" size="sm">{{ ucfirst($inspection->inspection_type) }}</flux:badge>
|
|
</div>
|
|
<div class="flex justify-between py-3 border-b border-zinc-100 dark:border-zinc-700">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">Date & Time</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400">{{ $inspection->inspection_date->format('M d, Y \a\t g:i A') }}</span>
|
|
</div>
|
|
<div class="flex justify-between py-3 border-b border-zinc-100 dark:border-zinc-700">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">Inspector</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400">{{ $inspection->inspector->name }}</span>
|
|
</div>
|
|
<div class="flex justify-between py-3">
|
|
<span class="font-medium text-zinc-900 dark:text-zinc-100">Job Card</span>
|
|
<span class="text-zinc-600 dark:text-zinc-400">#{{ $inspection->jobCard->job_card_number }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Inspection Checklist -->
|
|
@if($inspection->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 text-zinc-900 dark:text-zinc-100">Inspection Checklist</flux:heading>
|
|
|
|
<div class="grid grid-cols-1 xl:grid-cols-2 gap-8">
|
|
@foreach($inspection->inspection_checklist as $section => $items)
|
|
<div class="border border-zinc-200 dark:border-zinc-600 rounded-lg p-5">
|
|
<h4 class="font-semibold text-lg text-zinc-900 dark:text-zinc-100 mb-4 pb-2 border-b border-zinc-200 dark:border-zinc-600 capitalize">
|
|
{{ str_replace('_', ' ', $section) }}
|
|
</h4>
|
|
<div class="space-y-3">
|
|
@foreach($items as $item => $status)
|
|
<div class="flex items-center justify-between py-2">
|
|
<span class="text-sm text-zinc-700 dark:text-zinc-300 flex-1">{{ ucwords(str_replace('_', ' ', $item)) }}</span>
|
|
<div class="ml-4">
|
|
@if($status === 'yes')
|
|
<div class="flex items-center space-x-2">
|
|
<div class="w-3 h-3 rounded-full bg-green-500"></div>
|
|
<flux:badge color="green" size="sm">Pass</flux:badge>
|
|
</div>
|
|
@elseif($status === 'no')
|
|
<div class="flex items-center space-x-2">
|
|
<div class="w-3 h-3 rounded-full bg-red-500"></div>
|
|
<flux:badge color="red" size="sm">Fail</flux:badge>
|
|
</div>
|
|
@else
|
|
<div class="flex items-center space-x-2">
|
|
<div class="w-3 h-3 rounded-full bg-zinc-400"></div>
|
|
<flux:badge color="zinc" size="sm">N/A</flux:badge>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Notes and Comments -->
|
|
@if($inspection->additional_comments || $inspection->damage_notes || $inspection->recommendations || $inspection->notes)
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
@if($inspection->additional_comments || $inspection->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 text-zinc-900 dark:text-zinc-100">Comments & Notes</flux:heading>
|
|
|
|
<div class="space-y-6">
|
|
@if($inspection->additional_comments)
|
|
<div>
|
|
<h5 class="font-medium text-zinc-900 dark:text-zinc-100 mb-3 flex items-center">
|
|
<svg class="w-5 h-5 mr-2 text-blue-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-1.586l-4 4z"></path>
|
|
</svg>
|
|
Additional Comments
|
|
</h5>
|
|
<div class="bg-zinc-50 dark:bg-zinc-900 rounded-lg p-4">
|
|
<p class="text-zinc-700 dark:text-zinc-300 leading-relaxed">{{ $inspection->additional_comments }}</p>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
@if($inspection->notes)
|
|
<div>
|
|
<h5 class="font-medium text-zinc-900 dark:text-zinc-100 mb-3 flex items-center">
|
|
<svg class="w-5 h-5 mr-2 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
|
|
</svg>
|
|
Inspector Notes
|
|
</h5>
|
|
<div class="bg-zinc-50 dark:bg-zinc-900 rounded-lg p-4">
|
|
<p class="text-zinc-700 dark:text-zinc-300 leading-relaxed">{{ $inspection->notes }}</p>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
@if($inspection->damage_notes || $inspection->recommendations)
|
|
<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 text-zinc-900 dark:text-zinc-100">Damage & Recommendations</flux:heading>
|
|
|
|
<div class="space-y-6">
|
|
@if($inspection->damage_notes)
|
|
<div>
|
|
<h5 class="font-medium text-zinc-900 dark:text-zinc-100 mb-3 flex items-center">
|
|
<svg class="w-5 h-5 mr-2 text-red-500" 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.732-.833-2.5 0L4.268 19.5c-.77.833.192 2.5 1.732 2.5z"></path>
|
|
</svg>
|
|
Damage Notes
|
|
</h5>
|
|
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4">
|
|
<p class="text-red-800 dark:text-red-300 leading-relaxed">{{ $inspection->damage_notes }}</p>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
@if($inspection->recommendations)
|
|
<div>
|
|
<h5 class="font-medium text-zinc-900 dark:text-zinc-100 mb-3 flex items-center">
|
|
<svg class="w-5 h-5 mr-2 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"></path>
|
|
</svg>
|
|
Recommendations
|
|
</h5>
|
|
<div class="bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-4">
|
|
<p class="text-amber-800 dark:text-amber-300 leading-relaxed">{{ $inspection->recommendations }}</p>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Damage Diagram -->
|
|
@if($inspection->damage_diagram_data && !empty($inspection->damage_diagram_data))
|
|
<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 text-zinc-900 dark:text-zinc-100 flex items-center">
|
|
<svg class="w-6 h-6 mr-2 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path>
|
|
</svg>
|
|
Vehicle Damage Report
|
|
</flux:heading>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
@foreach($inspection->damage_diagram_data as $index => $damage)
|
|
<div class="border border-zinc-200 dark:border-zinc-600 rounded-lg p-4 hover:shadow-md transition-shadow">
|
|
<div class="flex items-center justify-between mb-3">
|
|
<h5 class="font-medium text-zinc-900 dark:text-zinc-100">Damage #{{ $index + 1 }}</h5>
|
|
@php
|
|
$colorClass = match($damage['type']) {
|
|
'damage' => 'bg-red-500',
|
|
'dent' => 'bg-orange-500',
|
|
'scratch' => 'bg-yellow-500',
|
|
default => 'bg-blue-500'
|
|
};
|
|
$textColorClass = match($damage['type']) {
|
|
'damage' => 'text-red-700 dark:text-red-300',
|
|
'dent' => 'text-orange-700 dark:text-orange-300',
|
|
'scratch' => 'text-yellow-700 dark:text-yellow-300',
|
|
default => 'text-blue-700 dark:text-blue-300'
|
|
};
|
|
@endphp
|
|
<div class="flex items-center space-x-2">
|
|
<span class="inline-block w-4 h-4 rounded-full {{ $colorClass }}"></span>
|
|
<span class="text-sm font-medium {{ $textColorClass }} capitalize">{{ $damage['type'] }}</span>
|
|
</div>
|
|
</div>
|
|
@if(!empty($damage['description']))
|
|
<p class="text-sm text-zinc-600 dark:text-zinc-400 leading-relaxed">{{ $damage['description'] }}</p>
|
|
@else
|
|
<p class="text-sm text-zinc-400 dark:text-zinc-500 italic">No description provided</p>
|
|
@endif
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|