sackey b11cdc39c2
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
feat: Enhance invoice creation and editing with improved part selection and error handling
2025-08-16 15:27:29 +00:00

231 lines
12 KiB
PHP

<div>
<flux:header>
<flux:heading size="xl">Edit Invoice #{{ $invoice->invoice_number }}</flux:heading>
<flux:subheading>Modify invoice details and line items</flux:subheading>
<x-slot:actions>
<flux:badge :variant="$invoice->status === 'paid' ? 'success' : ($invoice->status === 'overdue' ? 'danger' : 'primary')">
{{ ucfirst($invoice->status) }}
</flux:badge>
</x-slot:actions>
</flux:header>
<form wire:submit.prevent="save" class="space-y-6">
{{-- Basic Information --}}
<div class="bg-white dark:bg-zinc-800 shadow-sm rounded-lg border border-zinc-200 dark:border-zinc-700 p-6 space-y-6">
<flux:heading size="lg">Invoice Details</flux:heading>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<flux:field>
<flux:label>Customer</flux:label>
<flux:select wire:model="customer_id" placeholder="Select customer...">
@foreach($customers as $customer)
<flux:select.option value="{{ $customer->id }}">{{ $customer->name }}</flux:select.option>
@endforeach
</flux:select>
<flux:error name="customer_id" />
</flux:field>
<flux:field>
<flux:label>Branch</flux:label>
<flux:select wire:model="branch_id" placeholder="Select branch...">
@foreach($branches as $branch)
<flux:select.option value="{{ $branch->id }}">{{ $branch->name }}</flux:select.option>
@endforeach
</flux:select>
<flux:error name="branch_id" />
</flux:field>
<flux:field>
<flux:label>Invoice Date</flux:label>
<flux:input type="date" wire:model="invoice_date" />
<flux:error name="invoice_date" />
</flux:field>
<flux:field>
<flux:label>Due Date</flux:label>
<flux:input type="date" wire:model="due_date" />
<flux:error name="due_date" />
</flux:field>
</div>
<flux:field>
<flux:label>Description</flux:label>
<flux:textarea wire:model="description" placeholder="Brief description of work performed..." rows="2" />
<flux:error name="description" />
</flux:field>
</div>
{{-- Line Items --}}
<div class="bg-white dark:bg-zinc-800 shadow-sm rounded-lg border border-zinc-200 dark:border-zinc-700 p-6 space-y-6">
<div class="flex justify-between items-center">
<flux:heading size="lg">Line Items</flux:heading>
<flux:button wire:click="addLineItem" variant="ghost" size="sm">
<flux:icon.plus class="size-4" />
Add Item
</flux:button>
</div>
<div class="space-y-4">
@foreach($line_items as $index => $item)
<div class="border rounded-lg p-4 bg-zinc-50 dark:bg-zinc-900/50">
<div class="grid grid-cols-1 md:grid-cols-12 gap-4 items-start">
{{-- Type --}}
<div class="md:col-span-2">
<flux:label>Type</flux:label>
<flux:select wire:model="line_items.{{ $index }}.type">
<flux:select.option value="labour">Labour</flux:select.option>
<flux:select.option value="parts">Parts</flux:select.option>
<flux:select.option value="miscellaneous">Miscellaneous</flux:select.option>
</flux:select>
</div>
{{-- Part Selection (only for parts) --}}
@if($item['type'] === 'parts')
<div class="md:col-span-3">
<flux:label>Part</flux:label>
<select wire:model.live="line_items.{{ $index }}.part_id" class="w-full rounded-md border-zinc-300 dark:border-zinc-600 bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500">
<option value="">Select part...</option>
@if(count($parts) === 0)
<option value="" disabled>No parts available</option>
@endif
@foreach($parts as $part)
<option value="{{ $part->id }}">{{ $part->name }} ({{ $part->part_number }}) - ${{ number_format($part->sell_price, 2) }}</option>
@endforeach
</select>
<small class="text-zinc-500">{{ count($parts) }} parts available</small>
</div>
@else
<div class="md:col-span-3">
<flux:label>Description</flux:label>
<flux:input wire:model="line_items.{{ $index }}.description" placeholder="Item description..." />
</div>
@endif
{{-- Quantity --}}
<div class="md:col-span-2">
<flux:label>Quantity</flux:label>
<flux:input type="number" wire:model="line_items.{{ $index }}.quantity" min="1" step="1" />
</div>
{{-- Unit Price --}}
<div class="md:col-span-2">
<flux:label>Unit Price</flux:label>
<flux:input type="number" wire:model="line_items.{{ $index }}.unit_price" min="0" step="0.01" />
</div>
{{-- Total --}}
<div class="md:col-span-2">
<flux:label>Total</flux:label>
<div class="px-3 py-2 bg-white dark:bg-zinc-800 border border-zinc-300 dark:border-zinc-600 rounded text-sm">
${{ number_format(($item['quantity'] ?? 0) * ($item['unit_price'] ?? 0), 2) }}
</div>
</div>
{{-- Remove Button --}}
<div class="md:col-span-1 flex items-end">
@if(count($line_items) > 1)
<flux:button wire:click="removeLineItem({{ $index }})" variant="danger" size="sm">
<flux:icon.trash class="size-4" />
</flux:button>
@endif
</div>
</div>
{{-- Additional fields for parts --}}
@if($item['type'] === 'parts')
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
<flux:field>
<flux:label>Part Number</flux:label>
<flux:input wire:model="line_items.{{ $index }}.part_number" placeholder="Part number..." />
</flux:field>
<flux:field>
<flux:label>Technical Notes</flux:label>
<flux:input wire:model="line_items.{{ $index }}.technical_notes" placeholder="Technical notes..." />
</flux:field>
</div>
@endif
{{-- Technical notes for labour --}}
@if($item['type'] === 'labour')
<div class="mt-4">
<flux:field>
<flux:label>Technical Notes</flux:label>
<flux:input wire:model="line_items.{{ $index }}.technical_notes" placeholder="Technical notes..." />
</flux:field>
</div>
@endif
</div>
@endforeach
</div>
<flux:error name="line_items" />
</div>
{{-- Totals and Additional Info --}}
<div class="bg-white dark:bg-zinc-800 shadow-sm rounded-lg border border-zinc-200 dark:border-zinc-700 p-6 space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
{{-- Additional Information --}}
<div class="space-y-4">
<flux:field>
<flux:label>Tax Rate (%)</flux:label>
<flux:input type="number" wire:model="tax_rate" min="0" max="100" step="0.01" />
<flux:error name="tax_rate" />
</flux:field>
<flux:field>
<flux:label>Discount Amount</flux:label>
<flux:input type="number" wire:model="discount_amount" min="0" step="0.01" />
<flux:error name="discount_amount" />
</flux:field>
<flux:field>
<flux:label>Notes</flux:label>
<flux:textarea wire:model="notes" placeholder="Additional notes..." rows="3" />
<flux:error name="notes" />
</flux:field>
</div>
{{-- Totals Summary --}}
<div class="bg-zinc-50 dark:bg-zinc-900/50 rounded-lg p-4">
<flux:heading size="base" class="mb-4">Invoice Summary</flux:heading>
<div class="space-y-2 text-sm">
<div class="flex justify-between">
<span>Subtotal:</span>
<span>${{ number_format($this->calculateSubtotal(), 2) }}</span>
</div>
@if($discount_amount > 0)
<div class="flex justify-between text-red-600">
<span>Discount:</span>
<span>-${{ number_format($discount_amount, 2) }}</span>
</div>
@endif
<div class="flex justify-between">
<span>Tax ({{ $tax_rate }}%):</span>
<span>${{ number_format($this->calculateTax(), 2) }}</span>
</div>
<hr class="my-2">
<div class="flex justify-between font-semibold text-lg">
<span>Total:</span>
<span>${{ number_format($this->calculateTotal(), 2) }}</span>
</div>
</div>
</div>
</div>
<flux:field>
<flux:label>Terms and Conditions</flux:label>
<flux:textarea wire:model="terms_and_conditions" placeholder="Payment terms and conditions..." rows="3" />
<flux:error name="terms_and_conditions" />
</flux:field>
</div>
{{-- Actions --}}
<div class="flex justify-end space-x-3">
<flux:button variant="ghost" href="{{ route('invoices.show', $invoice) }}">Cancel</flux:button>
<flux:button type="submit" variant="primary">Update Invoice</flux:button>
</div>
</form>
</div>