sackey a65fee9d75
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
Add customer portal workflow progress component and analytics dashboard
- Implemented the customer portal workflow progress component with detailed service progress tracking, including current status, workflow steps, and contact information.
- Developed a management workflow analytics dashboard featuring key performance indicators, charts for revenue by branch, labor utilization, and recent quality issues.
- Created tests for admin-only middleware to ensure proper access control for admin routes.
- Added tests for customer portal view rendering and workflow integration, ensuring the workflow service operates correctly through various stages.
- Introduced a .gitignore file for the debugbar storage directory to prevent unnecessary files from being tracked.
2025-08-10 19:41:25 +00:00

518 lines
31 KiB
PHP

<div>
<div class="max-w-4xl mx-auto space-y-6">
<!-- Page Header -->
<div class="flex items-center justify-between">
<div>
<flux:heading size="xl">Create Job Card</flux:heading>
<flux:subheading>Steps 1-2: Vehicle Reception & Initial Inspection</flux:subheading>
</div>
<flux:button href="{{ route('job-cards.index') }}" variant="ghost" size="sm" icon="arrow-left">
Back to Job Cards
</flux:button>
</div>
<!-- 11-Step Workflow Progress -->
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
<div class="mb-6">
<flux:heading size="lg">11-Step Automotive Workflow</flux:heading>
<flux:subheading>Track progress through the complete service process</flux:subheading>
</div>
<!-- Progress Steps - Using simple flex layout instead of grid -->
<div class="flex flex-wrap gap-4 mb-6">
<!-- Step 1: Vehicle Reception (Current) -->
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-blue-600 text-white rounded-full flex items-center justify-center font-semibold text-sm mb-2">1</div>
<div class="text-xs font-medium text-blue-600 text-center">Vehicle<br>Reception</div>
</div>
<!-- Step 2: Initial Inspection (Current) -->
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-blue-600 text-white rounded-full flex items-center justify-center font-semibold text-sm mb-2">2</div>
<div class="text-xs font-medium text-blue-600 text-center">Initial<br>Inspection</div>
</div>
<!-- Steps 3-11 (Inactive) -->
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-zinc-300 text-zinc-600 rounded-full flex items-center justify-center font-semibold text-sm mb-2">3</div>
<div class="text-xs text-zinc-500 text-center">Service<br>Assignment</div>
</div>
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-zinc-300 text-zinc-600 rounded-full flex items-center justify-center font-semibold text-sm mb-2">4</div>
<div class="text-xs text-zinc-500 text-center">Diagnosis</div>
</div>
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-zinc-300 text-zinc-600 rounded-full flex items-center justify-center font-semibold text-sm mb-2">5</div>
<div class="text-xs text-zinc-500 text-center">Estimate</div>
</div>
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-zinc-300 text-zinc-600 rounded-full flex items-center justify-center font-semibold text-sm mb-2">6</div>
<div class="text-xs text-zinc-500 text-center">Approval</div>
</div>
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-zinc-300 text-zinc-600 rounded-full flex items-center justify-center font-semibold text-sm mb-2">7</div>
<div class="text-xs text-zinc-500 text-center">Parts<br>Procurement</div>
</div>
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-zinc-300 text-zinc-600 rounded-full flex items-center justify-center font-semibold text-sm mb-2">8</div>
<div class="text-xs text-zinc-500 text-center">Repairs</div>
</div>
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-zinc-300 text-zinc-600 rounded-full flex items-center justify-center font-semibold text-sm mb-2">9</div>
<div class="text-xs text-zinc-500 text-center">Final<br>Inspection</div>
</div>
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-zinc-300 text-zinc-600 rounded-full flex items-center justify-center font-semibold text-sm mb-2">10</div>
<div class="text-xs text-zinc-500 text-center">Delivery</div>
</div>
<div class="flex flex-col items-center">
<div class="w-8 h-8 bg-zinc-300 text-zinc-600 rounded-full flex items-center justify-center font-semibold text-sm mb-2">11</div>
<div class="text-xs text-zinc-500 text-center">Archival</div>
</div>
</div>
<!-- Current Step Info -->
<div class="p-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
<div class="flex items-center space-x-3">
<div class="flex space-x-1">
<div class="w-8 h-8 bg-blue-600 text-white rounded-full flex items-center justify-center font-semibold text-sm">1</div>
<div class="w-8 h-8 bg-blue-600 text-white rounded-full flex items-center justify-center font-semibold text-sm">2</div>
</div>
<div>
<div class="font-medium text-blue-900 dark:text-blue-100">Vehicle Reception + Initial Inspection</div>
<div class="text-sm text-blue-700 dark:text-blue-300">Capture vehicle information, customer complaints, and perform incoming inspection</div>
</div>
</div>
</div>
</div>
<!-- Enhanced Form -->
<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 p-6">
<flux:heading size="lg" class="mb-6">Customer & Vehicle Information</flux:heading>
<div class="space-y-6">
<!-- Customer Selection -->
<div>
<flux:select wire:model.live="customer_id" label="Customer" placeholder="Select customer..." required>
@if($customers && count($customers) > 0)
@foreach($customers as $customer)
<option value="{{ $customer->id }}">{{ $customer->full_name }} - {{ $customer->phone }}</option>
@endforeach
@endif
</flux:select>
@error('customer_id')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Vehicle Selection -->
<div>
<flux:select wire:model="vehicle_id" label="Vehicle" placeholder="Select vehicle..." required>
@if($vehicles && count($vehicles) > 0)
@foreach($vehicles as $vehicle)
<option value="{{ $vehicle->id }}">{{ $vehicle->year }} {{ $vehicle->make }} {{ $vehicle->model }} - {{ $vehicle->license_plate }}</option>
@endforeach
@endif
</flux:select>
@error('vehicle_id')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
</div>
</div>
<!-- Service Assignment -->
<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">Service Assignment</flux:heading>
<div class="space-y-6">
<!-- Service Advisor -->
<div>
<flux:select wire:model="service_advisor_id" label="Service Advisor" placeholder="Select service advisor..." required>
@if($serviceAdvisors && count($serviceAdvisors) > 0)
@foreach($serviceAdvisors as $advisor)
<option value="{{ $advisor->id }}">{{ $advisor->name }}</option>
@endforeach
@endif
</flux:select>
@error('service_advisor_id')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Branch Selection -->
<div>
<flux:select wire:model="branch_code" label="Branch" placeholder="Select branch..." required>
@if($branches && count($branches) > 0)
@foreach($branches as $branch)
<option value="{{ $branch->code }}">{{ $branch->name }}</option>
@endforeach
@endif
</flux:select>
@error('branch_code')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Priority -->
<div>
<flux:select wire:model="priority" label="Priority" required>
<option value="low">Low</option>
<option value="medium" selected>Medium</option>
<option value="high">High</option>
<option value="urgent">Urgent</option>
</flux:select>
@error('priority')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
</div>
</div>
<!-- Vehicle Reception Details -->
<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 Reception Details</flux:heading>
<div class="space-y-6">
<!-- Row 1: Dates and Mileage -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- Arrival DateTime -->
<div>
<flux:input
type="datetime-local"
wire:model="arrival_datetime"
label="Arrival Date & Time"
required
/>
@error('arrival_datetime')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Expected Completion -->
<div>
<flux:input
type="date"
wire:model="expected_completion_date"
label="Expected Completion Date"
/>
@error('expected_completion_date')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Mileage -->
<div>
<flux:input
type="number"
wire:model="mileage_in"
label="Mileage (km)"
placeholder="e.g., 45000"
min="0"
step="1"
required
/>
@error('mileage_in')
<flux:error>{{ $message }}</flux:error>
@enderror
<p class="text-sm text-zinc-600 dark:text-zinc-400 mt-1">Enter the current odometer reading</p>
</div>
</div>
<!-- Row 2: Fuel Level and Keys -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Fuel Level -->
<div>
<flux:select wire:model="fuel_level_in" label="Fuel Level">
<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 Quarters">Three Quarters (60-85%)</option>
<option value="Full">Full (85-100%)</option>
</flux:select>
@error('fuel_level_in')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Keys Location -->
<div>
<flux:input
wire:model="keys_location"
label="Keys Location"
placeholder="e.g., In vehicle, With service advisor, Key box"
/>
@error('keys_location')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
</div>
<!-- Row 3: Checkboxes -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Personal Items Removed -->
<div>
<flux:checkbox wire:model="personal_items_removed" label="Personal items removed from vehicle" />
@error('personal_items_removed')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Photos Taken -->
<div>
<flux:checkbox wire:model="photos_taken" label="Photos taken of vehicle condition" />
@error('photos_taken')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
</div>
</div>
</div>
<!-- Initial Inspection Section -->
<div class="bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg p-6">
<div class="mb-6">
<flux:heading size="lg">Initial Vehicle Inspection</flux:heading>
<flux:subheading>Perform incoming inspection as part of vehicle reception</flux:subheading>
</div>
<div class="space-y-6">
<!-- Perform Inspection Toggle -->
<div>
<flux:checkbox wire:model.live="perform_inspection" label="Perform initial inspection during reception" checked />
<p class="text-sm text-zinc-600 dark:text-zinc-400 mt-1">Recommended for quality control and customer protection</p>
</div>
@if($perform_inspection)
<!-- Inspector Selection -->
<div>
<flux:select wire:model="inspector_id" label="Inspector" placeholder="Select inspector..." required>
@if($inspectors && count($inspectors) > 0)
@foreach($inspectors as $inspector)
<option value="{{ $inspector->id }}">{{ $inspector->name }}</option>
@endforeach
@endif
</flux:select>
@error('inspector_id')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Overall Condition -->
<div>
<flux:select wire:model="overall_condition" label="Overall Vehicle Condition" placeholder="Select overall condition..." required>
<option value="excellent">Excellent - Like new condition</option>
<option value="good">Good - Well maintained with minor wear</option>
<option value="fair">Fair - Normal wear, some issues present</option>
<option value="poor">Poor - Significant issues or damage</option>
</flux:select>
@error('overall_condition')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Inspection Questionnaire -->
<div>
<flux:field>
<flux:label>Inspection Questionnaire</flux:label>
<flux:description>Rate each vehicle component based on visual inspection</flux:description>
<div class="mt-4 space-y-6">
<!-- Exterior Condition -->
<div class="border border-zinc-200 dark:border-zinc-700 rounded-lg p-4">
<h4 class="font-medium text-zinc-900 dark:text-zinc-100 mb-3">Exterior Condition</h4>
<div class="grid grid-cols-1 md:grid-cols-4 gap-3">
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.exterior_damage" value="excellent" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Excellent</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.exterior_damage" value="good" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Good</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.exterior_damage" value="fair" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Fair</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.exterior_damage" value="poor" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Poor</span>
</label>
</div>
</div>
<!-- Interior Condition -->
<div class="border border-zinc-200 dark:border-zinc-700 rounded-lg p-4">
<h4 class="font-medium text-zinc-900 dark:text-zinc-100 mb-3">Interior Condition</h4>
<div class="grid grid-cols-1 md:grid-cols-4 gap-3">
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.interior_condition" value="excellent" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Excellent</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.interior_condition" value="good" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Good</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.interior_condition" value="fair" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Fair</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.interior_condition" value="poor" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Poor</span>
</label>
</div>
</div>
<!-- Tire Condition -->
<div class="border border-zinc-200 dark:border-zinc-700 rounded-lg p-4">
<h4 class="font-medium text-zinc-900 dark:text-zinc-100 mb-3">Tire Condition</h4>
<div class="grid grid-cols-1 md:grid-cols-4 gap-3">
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.tire_condition" value="excellent" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Excellent</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.tire_condition" value="good" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Good</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.tire_condition" value="fair" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Fair</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.tire_condition" value="poor" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Poor</span>
</label>
</div>
</div>
<!-- Fluid Levels -->
<div class="border border-zinc-200 dark:border-zinc-700 rounded-lg p-4">
<h4 class="font-medium text-zinc-900 dark:text-zinc-100 mb-3">Fluid Levels</h4>
<div class="grid grid-cols-1 md:grid-cols-4 gap-3">
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.fluid_levels" value="excellent" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Excellent</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.fluid_levels" value="good" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Good</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.fluid_levels" value="fair" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Fair</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.fluid_levels" value="poor" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Poor</span>
</label>
</div>
</div>
<!-- Lights Working -->
<div class="border border-zinc-200 dark:border-zinc-700 rounded-lg p-4">
<h4 class="font-medium text-zinc-900 dark:text-zinc-100 mb-3">Lights & Electrical</h4>
<div class="grid grid-cols-1 md:grid-cols-4 gap-3">
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.lights_working" value="excellent" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Excellent</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.lights_working" value="good" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Good</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.lights_working" value="fair" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Fair</span>
</label>
<label class="flex items-center">
<input type="radio" wire:model="inspection_checklist.lights_working" value="poor" class="text-blue-600 focus:ring-blue-500">
<span class="ml-2 text-sm">Poor</span>
</label>
</div>
</div>
</div>
</flux:field>
</div>
<!-- Inspection Notes -->
<div>
<flux:textarea
wire:model="inspection_notes"
label="Inspection Notes"
placeholder="Document any findings, damage, or areas of concern discovered during inspection..."
rows="4"
/>
@error('inspection_notes')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
@endif
</div>
</div>
<!-- Issues & Condition Assessment -->
<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">Issues & Condition Assessment</flux:heading>
<div class="space-y-6">
<!-- Customer Reported Issues -->
<div>
<flux:textarea
wire:model="customer_reported_issues"
label="Customer Reported Issues"
placeholder="What is the customer reporting? Be specific about symptoms, when they occur, and any relevant details..."
rows="4"
required
/>
@error('customer_reported_issues')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Vehicle Condition Notes -->
<div>
<flux:textarea
wire:model="vehicle_condition_notes"
label="Vehicle Condition Notes"
placeholder="Initial visual inspection findings, exterior/interior condition, existing damage..."
rows="4"
/>
@error('vehicle_condition_notes')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
<!-- Additional Notes -->
<div>
<flux:textarea
wire:model="notes"
label="Additional Notes"
placeholder="Any special instructions, customer requests, or other relevant information..."
rows="3"
/>
@error('notes')
<flux:error>{{ $message }}</flux:error>
@enderror
</div>
</div>
</div>
<!-- Form Actions -->
<div class="flex flex-col-reverse sm:flex-row sm:justify-end gap-3 pt-6 border-t border-zinc-200 dark:border-zinc-700">
<flux:button href="{{ route('job-cards.index') }}" variant="ghost" size="sm">
Cancel
</flux:button>
<flux:button type="submit" variant="primary" icon="check">
<span wire:loading.remove wire:target="save">Create Job Card</span>
<span wire:loading wire:target="save">Creating...</span>
</flux:button>
</div>
</form>
</div>
</div>