- 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.
197 lines
14 KiB
PHP
197 lines
14 KiB
PHP
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
|
<!-- Page Header -->
|
|
<div class="mb-8">
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<h1 class="text-3xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100">Diagnoses</h1>
|
|
<p class="mt-2 text-sm text-zinc-600 dark:text-zinc-400">
|
|
Manage vehicle diagnostic records and analysis
|
|
</p>
|
|
</div>
|
|
<div class="flex items-center space-x-3">
|
|
<button wire:click="refreshList" 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-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
|
|
</svg>
|
|
Refresh
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Filters -->
|
|
<div class="bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 shadow-sm mb-8">
|
|
<div class="p-6">
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Search</label>
|
|
<input type="text" wire:model.live="search" placeholder="Search by job card number, customer..."
|
|
class="w-full rounded-lg border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Status</label>
|
|
<select wire:model.live="statusFilter"
|
|
class="w-full rounded-lg border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
<option value="">All Statuses</option>
|
|
<option value="in_progress">In Progress</option>
|
|
<option value="completed">Completed</option>
|
|
<option value="pending_approval">Pending Approval</option>
|
|
<option value="approved">Approved</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Priority</label>
|
|
<select wire:model.live="priorityFilter"
|
|
class="w-full rounded-lg border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
<option value="">All Priorities</option>
|
|
<option value="low">Low</option>
|
|
<option value="medium">Medium</option>
|
|
<option value="high">High</option>
|
|
<option value="critical">Critical</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">Date Range</label>
|
|
<input type="date" wire:model.live="dateFrom"
|
|
class="w-full rounded-lg border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Diagnoses List -->
|
|
<div class="bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700 shadow-sm">
|
|
<div class="px-6 py-4 border-b border-zinc-200 dark:border-zinc-700">
|
|
<h2 class="text-lg font-semibold text-zinc-900 dark:text-zinc-100">
|
|
Diagnosis Records
|
|
<span class="text-sm font-normal text-zinc-500 dark:text-zinc-400 ml-2">({{ $diagnoses->total() }} total)</span>
|
|
</h2>
|
|
</div>
|
|
|
|
@if($diagnoses->count() > 0)
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full">
|
|
<thead class="bg-zinc-50 dark:bg-zinc-900">
|
|
<tr>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Job Card</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Customer</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Vehicle</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Status</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Priority</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Technician</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Date</th>
|
|
<th class="px-6 py-3 text-left text-xs font-medium text-zinc-500 dark:text-zinc-400 uppercase tracking-wider">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-zinc-200 dark:divide-zinc-700">
|
|
@foreach($diagnoses as $diagnosis)
|
|
<tr class="hover:bg-zinc-50 dark:hover:bg-zinc-700/50">
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<div class="text-sm font-medium text-zinc-900 dark:text-zinc-100">
|
|
{{ $diagnosis->jobCard->job_card_number }}
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<div class="text-sm text-zinc-900 dark:text-zinc-100">{{ $diagnosis->jobCard->customer->name }}</div>
|
|
<div class="text-xs text-zinc-500 dark:text-zinc-400">{{ $diagnosis->jobCard->customer->phone }}</div>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<div class="text-sm text-zinc-900 dark:text-zinc-100">
|
|
{{ $diagnosis->jobCard->vehicle->year }} {{ $diagnosis->jobCard->vehicle->make }} {{ $diagnosis->jobCard->vehicle->model }}
|
|
</div>
|
|
<div class="text-xs text-zinc-500 dark:text-zinc-400">{{ $diagnosis->jobCard->vehicle->license_plate }}</div>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full
|
|
@switch($diagnosis->diagnosis_status)
|
|
@case('in_progress')
|
|
bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200
|
|
@break
|
|
@case('completed')
|
|
bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200
|
|
@break
|
|
@case('pending_approval')
|
|
bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200
|
|
@break
|
|
@case('approved')
|
|
bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200
|
|
@break
|
|
@default
|
|
bg-zinc-100 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200
|
|
@endswitch
|
|
">
|
|
{{ str_replace('_', ' ', $diagnosis->diagnosis_status) }}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap">
|
|
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full
|
|
@switch($diagnosis->priority_level)
|
|
@case('low')
|
|
bg-zinc-100 text-zinc-800 dark:bg-zinc-900 dark:text-zinc-200
|
|
@break
|
|
@case('medium')
|
|
bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200
|
|
@break
|
|
@case('high')
|
|
bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200
|
|
@break
|
|
@case('critical')
|
|
bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200
|
|
@break
|
|
@endswitch
|
|
">
|
|
{{ ucfirst($diagnosis->priority_level) }}
|
|
</span>
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-900 dark:text-zinc-100">
|
|
{{ $diagnosis->serviceCoordinator->name }}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-zinc-500 dark:text-zinc-400">
|
|
{{ $diagnosis->diagnosis_date?->format('M j, Y') ?? $diagnosis->created_at->format('M j, Y') }}
|
|
</td>
|
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium space-x-2">
|
|
<a href="{{ route('diagnosis.show', $diagnosis) }}" class="text-blue-600 hover:text-blue-900 dark:text-blue-400 dark:hover:text-blue-300">
|
|
View
|
|
</a>
|
|
<a href="{{ route('diagnosis.edit', $diagnosis) }}" class="text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-300">
|
|
Edit
|
|
</a>
|
|
@if(!$diagnosis->estimate)
|
|
<a href="{{ route('estimates.create', $diagnosis) }}" class="text-green-600 hover:text-green-900 dark:text-green-400 dark:hover:text-green-300">
|
|
Estimate
|
|
</a>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
<div class="px-6 py-4 border-t border-zinc-200 dark:border-zinc-700">
|
|
{{ $diagnoses->links() }}
|
|
</div>
|
|
@else
|
|
<div class="p-12 text-center">
|
|
<svg class="mx-auto h-12 w-12 text-zinc-400 mb-4" 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"/>
|
|
</svg>
|
|
<h3 class="text-lg font-medium text-zinc-900 dark:text-zinc-100 mb-2">No diagnoses found</h3>
|
|
<p class="text-sm text-zinc-500 dark:text-zinc-400 mb-4">
|
|
@if($search || $statusFilter || $priorityFilter || $dateFrom)
|
|
No diagnoses match your current filters.
|
|
@else
|
|
Get started by creating a diagnosis from a job card.
|
|
@endif
|
|
</p>
|
|
@if($search || $statusFilter || $priorityFilter || $dateFrom)
|
|
<button wire:click="clearFilters" 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">
|
|
Clear Filters
|
|
</button>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|