sackey e839d40a99
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
Initial commit
2025-07-30 17:15:50 +00:00

397 lines
20 KiB
PHP

<div class="space-y-6">
<!-- Header -->
<div class="flex items-center justify-between">
<flux:heading size="xl">Create Service Order</flux:heading>
<flux:button href="/service-orders" variant="outline" size="sm">
<flux:icon name="arrow-left" class="size-4" />
Back to Service Orders
</flux:button>
</div>
<form wire:submit="createServiceOrder" class="space-y-6">
<!-- Customer & Vehicle Information -->
<div class="bg-white dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700 p-6">
<flux:heading size="lg" class="mb-4">Customer & Vehicle Information</flux:heading>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<flux:field>
<flux:label>Customer *</flux:label>
<select wire:model.live="customer_id" class="w-full rounded-md border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-2 focus:ring-blue-500">
<option value="">Select Customer</option>
@foreach($customers as $customer)
<option value="{{ $customer->id }}">{{ $customer->full_name }}</option>
@endforeach
</select>
<flux:error name="customer_id" />
</flux:field>
</div>
<div>
<flux:field>
<flux:label>Vehicle *</flux:label>
<select wire:model.live="vehicle_id" class="w-full rounded-md border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-2 focus:ring-blue-500">
<option value="">Select Vehicle</option>
@foreach($vehicles as $vehicle)
<option value="{{ $vehicle->id }}">{{ $vehicle->display_name }} ({{ $vehicle->license_plate }})</option>
@endforeach
</select>
<flux:error name="vehicle_id" />
</flux:field>
</div>
</div>
</div>
<!-- Service Order Details -->
<div class="bg-white dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700 p-6">
<flux:heading size="lg" class="mb-4">Service Order Details</flux:heading>
<div class="space-y-4">
<div>
<flux:field>
<flux:label>Customer Complaint *</flux:label>
<flux:textarea
wire:model="customer_complaint"
placeholder="Describe the customer's complaint or reason for service..."
rows="3"
/>
<flux:error name="customer_complaint" />
</flux:field>
</div>
<div>
<flux:field>
<flux:label>Recommended Services</flux:label>
<flux:textarea
wire:model="recommended_services"
placeholder="List any recommended services based on inspection..."
rows="3"
/>
<flux:error name="recommended_services" />
</flux:field>
</div>
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
<div>
<flux:field>
<flux:label>Priority *</flux:label>
<select wire:model="priority" class="w-full rounded-md border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-2 focus:ring-blue-500">
<option value="low">Low</option>
<option value="normal">Normal</option>
<option value="high">High</option>
<option value="urgent">Urgent</option>
</select>
<flux:error name="priority" />
</flux:field>
</div>
<div>
<flux:field>
<flux:label>Status *</flux:label>
<select wire:model="status" class="w-full rounded-md border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-2 focus:ring-blue-500">
<option value="pending">Pending</option>
<option value="in_progress">In Progress</option>
<option value="on_hold">On Hold</option>
</select>
<flux:error name="status" />
</flux:field>
</div>
<div>
<flux:field>
<flux:label>Assigned Technician</flux:label>
<select wire:model="assigned_technician_id" class="w-full rounded-md border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-2 focus:ring-blue-500">
<option value="">Unassigned</option>
@foreach($technicians as $technician)
<option value="{{ $technician->id }}">{{ $technician->full_name }}</option>
@endforeach
</select>
<flux:error name="assigned_technician_id" />
</flux:field>
</div>
<div>
<flux:field>
<flux:label>Scheduled Date</flux:label>
<flux:input
type="date"
wire:model="scheduled_date"
/>
<flux:error name="scheduled_date" />
</flux:field>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<flux:field>
<flux:label>Estimated Hours</flux:label>
<flux:input
type="number"
step="0.5"
min="0"
wire:model="estimated_hours"
placeholder="0.0"
/>
<flux:error name="estimated_hours" />
</flux:field>
</div>
</div>
</div>
</div>
<!-- Service Items -->
<div class="bg-white dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700 p-6">
<flux:heading size="lg" class="mb-4">Service Items</flux:heading>
<!-- Add New Service Item -->
<div class="border border-zinc-200 dark:border-gray-600 rounded-lg p-4 mb-4">
<h4 class="font-medium mb-3">Add Service Item</h4>
<div class="grid grid-cols-1 md:grid-cols-5 gap-3">
<div>
<flux:input
wire:model="newServiceItem.service_name"
placeholder="Service Name"
/>
</div>
<div>
<flux:input
wire:model="newServiceItem.category"
placeholder="Category"
/>
</div>
<div>
<flux:input
type="number"
step="0.01"
min="0"
wire:model="newServiceItem.labor_rate"
placeholder="Labor Rate"
/>
</div>
<div>
<flux:input
type="number"
step="0.1"
min="0.1"
wire:model="newServiceItem.estimated_hours"
placeholder="Hours"
/>
</div>
<div>
<flux:button type="button" wire:click="addServiceItem" size="sm">
Add Item
</flux:button>
</div>
</div>
<div class="mt-2">
<flux:input
wire:model="newServiceItem.description"
placeholder="Service Description (optional)"
/>
</div>
</div>
<!-- Service Items List -->
@if(count($serviceItems) > 0)
<div class="overflow-x-auto">
<table class="min-w-full">
<thead>
<tr class="border-b border-zinc-200 dark:border-gray-600">
<th class="text-left py-2 px-2">Service</th>
<th class="text-left py-2 px-2">Category</th>
<th class="text-left py-2 px-2">Rate</th>
<th class="text-left py-2 px-2">Hours</th>
<th class="text-left py-2 px-2">Cost</th>
<th class="text-left py-2 px-2">Actions</th>
</tr>
</thead>
<tbody>
@foreach($serviceItems as $index => $item)
<tr class="border-b border-gray-100 dark:border-zinc-700">
<td class="py-2 px-2">
<div class="font-medium">{{ $item['service_name'] }}</div>
@if($item['description'])
<div class="text-sm text-zinc-500 dark:text-zinc-400">{{ $item['description'] }}</div>
@endif
</td>
<td class="py-2 px-2">{{ $item['category'] }}</td>
<td class="py-2 px-2">${{ number_format($item['labor_rate'], 2) }}</td>
<td class="py-2 px-2">{{ $item['estimated_hours'] }}</td>
<td class="py-2 px-2">${{ number_format($item['labor_cost'], 2) }}</td>
<td class="py-2 px-2">
<flux:button
type="button"
wire:click="removeServiceItem({{ $index }})"
variant="danger"
size="sm"
>
Remove
</flux:button>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<div class="text-center py-4 text-zinc-500 dark:text-zinc-400">
No service items added yet.
</div>
@endif
</div>
<!-- Parts -->
<div class="bg-white dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700 p-6">
<flux:heading size="lg" class="mb-4">Parts</flux:heading>
<!-- Add New Part -->
<div class="border border-zinc-200 dark:border-gray-600 rounded-lg p-4 mb-4">
<h4 class="font-medium mb-3">Add Part</h4>
<div class="grid grid-cols-1 md:grid-cols-4 gap-3">
<div class="md:col-span-2">
<select wire:model.live="newPart.part_id" class="w-full rounded-md border border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-2 focus:ring-blue-500">
<option value="">Select Part</option>
@foreach($availableParts as $part)
<option value="{{ $part->id }}">{{ $part->name }} ({{ $part->part_number }}) - ${{ $part->sell_price }}</option>
@endforeach
</select>
</div>
<div>
<flux:input
type="number"
min="1"
wire:model="newPart.quantity_used"
placeholder="Quantity"
/>
</div>
<div>
<flux:button type="button" wire:click="addPart" size="sm">
Add Part
</flux:button>
</div>
</div>
<div class="mt-2 grid grid-cols-1 md:grid-cols-2 gap-3">
<div>
<flux:input
type="number"
step="0.01"
min="0"
wire:model="newPart.unit_price"
placeholder="Unit Price"
/>
</div>
<div>
<flux:input
wire:model="newPart.notes"
placeholder="Notes (optional)"
/>
</div>
</div>
</div>
<!-- Parts List -->
@if(count($selectedParts) > 0)
<div class="overflow-x-auto">
<table class="min-w-full">
<thead>
<tr class="border-b border-zinc-200 dark:border-gray-600">
<th class="text-left py-2 px-2">Part</th>
<th class="text-left py-2 px-2">Part #</th>
<th class="text-left py-2 px-2">Qty</th>
<th class="text-left py-2 px-2">Unit Price</th>
<th class="text-left py-2 px-2">Total</th>
<th class="text-left py-2 px-2">Actions</th>
</tr>
</thead>
<tbody>
@foreach($selectedParts as $index => $part)
<tr class="border-b border-gray-100 dark:border-zinc-700">
<td class="py-2 px-2">{{ $part['part_name'] }}</td>
<td class="py-2 px-2">{{ $part['part_number'] }}</td>
<td class="py-2 px-2">{{ $part['quantity_used'] }}</td>
<td class="py-2 px-2">${{ number_format($part['unit_price'], 2) }}</td>
<td class="py-2 px-2">${{ number_format($part['total_price'], 2) }}</td>
<td class="py-2 px-2">
<flux:button
type="button"
wire:click="removePart({{ $index }})"
variant="danger"
size="sm"
>
Remove
</flux:button>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<div class="text-center py-4 text-zinc-500 dark:text-zinc-400">
No parts added yet.
</div>
@endif
</div>
<!-- Order Totals -->
<div class="bg-white dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700 p-6">
<flux:heading size="lg" class="mb-4">Order Totals</flux:heading>
<div class="space-y-2">
<div class="flex justify-between">
<span>Labor Cost:</span>
<span>${{ number_format($this->getTotalLaborCost(), 2) }}</span>
</div>
<div class="flex justify-between">
<span>Parts Cost:</span>
<span>${{ number_format($this->getTotalPartsCost(), 2) }}</span>
</div>
<div class="flex justify-between border-t pt-2">
<span>Subtotal:</span>
<span>${{ number_format($this->getSubtotal(), 2) }}</span>
</div>
<div class="flex justify-between">
<span>Tax (8%):</span>
<span>${{ number_format($this->getTaxAmount(), 2) }}</span>
</div>
<div class="flex justify-between border-t pt-2 font-bold text-lg">
<span>Total:</span>
<span>${{ number_format($this->getTotalAmount(), 2) }}</span>
</div>
</div>
</div>
<!-- Notes -->
<div class="bg-white dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700 p-6">
<flux:heading size="lg" class="mb-4">Notes</flux:heading>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<flux:field>
<flux:label>Internal Notes</flux:label>
<flux:textarea
wire:model="internal_notes"
placeholder="Internal notes for technicians..."
rows="4"
/>
<flux:error name="internal_notes" />
</flux:field>
</div>
<div>
<flux:field>
<flux:label>Customer Notes</flux:label>
<flux:textarea
wire:model="customer_notes"
placeholder="Notes visible to customer..."
rows="4"
/>
<flux:error name="customer_notes" />
</flux:field>
</div>
</div>
</div>
<!-- Form Actions -->
<div class="flex items-center justify-between pt-6 border-t border-zinc-200 dark:border-zinc-700">
<flux:button href="/service-orders" variant="outline">
Cancel
</flux:button>
<flux:button type="submit" variant="primary">
Create Service Order
</flux:button>
</div>
</form>
</div>