sackey e3b2b220d2
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
Enhance UI and functionality across various components
- Increased icon sizes in service items, service orders, users, and technician management for better visibility.
- Added custom loading indicators with appropriate icons in search fields for vehicles, work orders, and technicians.
- Introduced invoice management routes for better organization and access control.
- Created a new test for the estimate PDF functionality to ensure proper rendering and data integrity.
2025-08-16 14:36:58 +00:00

513 lines
16 KiB
PHP

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Invoice #{{ $invoice->invoice_number }}</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'DejaVu Sans', Arial, sans-serif;
font-size: 11px;
line-height: 1.4;
color: #333;
}
.header {
border-bottom: 3px solid #2563eb;
padding-bottom: 20px;
margin-bottom: 30px;
}
.header-content {
display: table;
width: 100%;
}
.company-info {
display: table-cell;
width: 50%;
vertical-align: top;
}
.invoice-info {
display: table-cell;
width: 50%;
vertical-align: top;
text-align: right;
}
.company-name {
font-size: 20px;
font-weight: bold;
color: #2563eb;
margin-bottom: 5px;
}
.invoice-title {
font-size: 24px;
font-weight: bold;
color: #1f2937;
margin-bottom: 10px;
}
.invoice-number {
font-size: 14px;
font-weight: bold;
margin-bottom: 5px;
}
.section {
margin-bottom: 25px;
}
.section-title {
font-size: 14px;
font-weight: bold;
color: #1f2937;
margin-bottom: 10px;
border-bottom: 1px solid #e5e7eb;
padding-bottom: 5px;
}
.info-grid {
display: table;
width: 100%;
margin-bottom: 20px;
}
.info-column {
display: table-cell;
width: 50%;
vertical-align: top;
padding-right: 20px;
}
.info-row {
margin-bottom: 8px;
}
.info-label {
font-weight: bold;
display: inline-block;
width: 100px;
}
.status-badge {
padding: 3px 8px;
border-radius: 4px;
font-size: 10px;
font-weight: bold;
text-transform: uppercase;
}
.status-draft {
background-color: #f3f4f6;
color: #374151;
}
.status-sent {
background-color: #dbeafe;
color: #1e40af;
}
.status-paid {
background-color: #d1fae5;
color: #065f46;
}
.status-overdue {
background-color: #fee2e2;
color: #991b1b;
}
.status-cancelled {
background-color: #f3f4f6;
color: #6b7280;
}
.items-table {
width: 100%;
border-collapse: collapse;
margin: 15px 0;
}
.items-table th,
.items-table td {
border: 1px solid #e5e7eb;
padding: 8px;
text-align: left;
}
.items-table th {
background-color: #f9fafb;
font-weight: bold;
font-size: 10px;
text-transform: uppercase;
}
.items-table td {
font-size: 11px;
}
.text-right {
text-align: right;
}
.text-center {
text-align: center;
}
.type-badge {
padding: 2px 6px;
border-radius: 3px;
font-size: 9px;
font-weight: bold;
text-transform: uppercase;
}
.type-labour {
background-color: #dbeafe;
color: #1e40af;
}
.type-parts {
background-color: #d1fae5;
color: #065f46;
}
.type-miscellaneous {
background-color: #f3f4f6;
color: #374151;
}
.summary-table {
width: 300px;
margin-left: auto;
margin-top: 20px;
}
.summary-table td {
padding: 5px 10px;
border: none;
}
.summary-row {
border-bottom: 1px solid #e5e7eb;
}
.total-row {
font-weight: bold;
font-size: 14px;
border-top: 2px solid #2563eb;
background-color: #eff6ff;
}
.payment-section {
margin-top: 30px;
padding: 15px;
background-color: #f9fafb;
border-radius: 5px;
}
.notes-section {
margin-top: 20px;
padding: 15px;
background-color: #f9fafb;
border-radius: 5px;
}
.terms-section {
margin-top: 20px;
font-size: 10px;
color: #6b7280;
border-top: 1px solid #e5e7eb;
padding-top: 15px;
}
.footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
text-align: center;
font-size: 9px;
color: #9ca3af;
border-top: 1px solid #e5e7eb;
padding: 10px 0;
background-color: white;
}
.page-break {
page-break-before: always;
}
.paid-watermark {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(-45deg);
font-size: 72px;
font-weight: bold;
color: rgba(34, 197, 94, 0.1);
z-index: -1;
pointer-events: none;
}
</style>
</head>
<body>
@if($invoice->status === 'paid')
<div class="paid-watermark">PAID</div>
@endif
<!-- Header -->
<div class="header">
<div class="header-content">
<div class="company-info">
<div class="company-name">{{ app(\App\Settings\GeneralSettings::class)->shop_name ?? 'Car Repairs Shop' }}</div>
<div>{{ app(\App\Settings\GeneralSettings::class)->shop_address ?? 'Shop Address' }}</div>
<div>{{ app(\App\Settings\GeneralSettings::class)->shop_phone ?? 'Phone Number' }}</div>
<div>{{ app(\App\Settings\GeneralSettings::class)->shop_email ?? 'Email Address' }}</div>
</div>
<div class="invoice-info">
<div class="invoice-title">INVOICE</div>
<div class="invoice-number">#{{ $invoice->invoice_number }}</div>
<div>Date: {{ $invoice->invoice_date->format('M j, Y') }}</div>
<div>Due: {{ $invoice->due_date->format('M j, Y') }}</div>
@if($invoice->isPaid())
<div>Paid: {{ $invoice->paid_at->format('M j, Y') }}</div>
@endif
<div style="margin-top: 10px;">
<span class="status-badge status-{{ $invoice->status }}">{{ ucfirst($invoice->status) }}</span>
</div>
</div>
</div>
</div>
<!-- Customer Information -->
<div class="section">
<div class="section-title">Bill To</div>
<div class="info-grid">
<div class="info-column">
<div class="info-row">
<span class="info-label">Name:</span>
{{ $invoice->customer->name }}
</div>
<div class="info-row">
<span class="info-label">Email:</span>
{{ $invoice->customer->email }}
</div>
<div class="info-row">
<span class="info-label">Phone:</span>
{{ $invoice->customer->phone }}
</div>
</div>
<div class="info-column">
@if($invoice->customer->address)
<div class="info-row">
<span class="info-label">Address:</span>
{{ $invoice->customer->address }}
</div>
@endif
@if($invoice->customer->city)
<div class="info-row">
<span class="info-label">City:</span>
{{ $invoice->customer->city }}, {{ $invoice->customer->state ?? '' }} {{ $invoice->customer->zip_code ?? '' }}
</div>
@endif
</div>
</div>
</div>
<!-- Vehicle Information (if applicable) -->
@php
$vehicle = $invoice->serviceOrder?->vehicle ?? $invoice->jobCard?->vehicle;
@endphp
@if($vehicle)
<div class="section">
<div class="section-title">Vehicle Information</div>
<div class="info-grid">
<div class="info-column">
<div class="info-row">
<span class="info-label">Vehicle:</span>
{{ $vehicle->year }} {{ $vehicle->make }} {{ $vehicle->model }}
</div>
<div class="info-row">
<span class="info-label">License:</span>
{{ $vehicle->license_plate }}
</div>
</div>
<div class="info-column">
@if($vehicle->vin)
<div class="info-row">
<span class="info-label">VIN:</span>
{{ $vehicle->vin }}
</div>
@endif
@if($vehicle->mileage)
<div class="info-row">
<span class="info-label">Mileage:</span>
{{ number_format($vehicle->mileage) }} miles
</div>
@endif
</div>
</div>
</div>
@endif
<!-- Service Information (if applicable) -->
@if($invoice->serviceOrder || $invoice->jobCard || $invoice->estimate)
<div class="section">
<div class="section-title">Service Information</div>
@if($invoice->serviceOrder)
<div class="info-row">
<span class="info-label">Service Order:</span>
#{{ $invoice->serviceOrder->order_number }}
</div>
@endif
@if($invoice->jobCard)
<div class="info-row">
<span class="info-label">Job Card:</span>
#{{ $invoice->jobCard->job_number }}
</div>
@endif
@if($invoice->estimate)
<div class="info-row">
<span class="info-label">Estimate:</span>
#{{ $invoice->estimate->estimate_number }}
</div>
@endif
</div>
@endif
<!-- Line Items -->
<div class="section">
<div class="section-title">Services & Parts</div>
@if($invoice->lineItems->count() > 0)
<table class="items-table">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
<th class="text-center">Qty</th>
<th class="text-right">Unit Price</th>
<th class="text-right">Total</th>
</tr>
</thead>
<tbody>
@foreach($invoice->lineItems as $item)
<tr>
<td>
<span class="type-badge type-{{ $item->type }}">
{{ ucfirst($item->type) }}
</span>
</td>
<td>
{{ $item->description }}
@if($item->part)
<br><small style="color: #6b7280;">Part #: {{ $item->part->part_number }}</small>
@endif
@if($item->part_number)
<br><small style="color: #6b7280;">Part #: {{ $item->part_number }}</small>
@endif
@if($item->technical_notes)
<br><small style="color: #6b7280;">{{ $item->technical_notes }}</small>
@endif
</td>
<td class="text-center">{{ $item->quantity }}</td>
<td class="text-right">${{ number_format($item->unit_price, 2) }}</td>
<td class="text-right">${{ number_format($item->total_amount, 2) }}</td>
</tr>
@endforeach
</tbody>
</table>
@else
<div style="text-align: center; padding: 20px; color: #6b7280;">
No line items available
</div>
@endif
</div>
<!-- Summary -->
<table class="summary-table">
<tr class="summary-row">
<td>Subtotal:</td>
<td class="text-right">${{ number_format($invoice->subtotal, 2) }}</td>
</tr>
@if($invoice->discount_amount > 0)
<tr class="summary-row">
<td>Discount:</td>
<td class="text-right" style="color: #dc2626;">-${{ number_format($invoice->discount_amount, 2) }}</td>
</tr>
@endif
<tr class="summary-row">
<td>Tax ({{ $invoice->tax_rate }}%):</td>
<td class="text-right">${{ number_format($invoice->tax_amount, 2) }}</td>
</tr>
<tr class="total-row">
<td><strong>Total:</strong></td>
<td class="text-right"><strong>${{ number_format($invoice->total_amount, 2) }}</strong></td>
</tr>
</table>
<!-- Payment Information -->
@if($invoice->isPaid())
<div class="payment-section">
<div class="section-title">Payment Information</div>
<div>
<p><strong>Payment Date:</strong> {{ $invoice->paid_at->format('M j, Y g:i A') }}</p>
@if($invoice->payment_method)
<p><strong>Payment Method:</strong> {{ ucfirst(str_replace('_', ' ', $invoice->payment_method)) }}</p>
@endif
@if($invoice->payment_reference)
<p><strong>Reference:</strong> {{ $invoice->payment_reference }}</p>
@endif
@if($invoice->payment_notes)
<p><strong>Notes:</strong> {{ $invoice->payment_notes }}</p>
@endif
</div>
</div>
@else
<div class="payment-section">
<div class="section-title">Payment Information</div>
<div>
<p>Payment is due by {{ $invoice->due_date->format('M j, Y') }}.</p>
<p>Please include invoice number {{ $invoice->invoice_number }} with your payment.</p>
<p class="mt-2">
<strong>Payment Methods:</strong> Cash, Credit Card, Check, Bank Transfer
</p>
</div>
</div>
@endif
<!-- Customer Notes -->
@if($invoice->notes)
<div class="notes-section">
<div class="section-title">Notes</div>
<div style="white-space: pre-wrap;">{{ $invoice->notes }}</div>
</div>
@endif
<!-- Terms & Conditions -->
@if($invoice->terms_and_conditions)
<div class="terms-section">
<div style="font-weight: bold; margin-bottom: 10px;">Terms & Conditions</div>
<div style="white-space: pre-wrap;">{{ $invoice->terms_and_conditions }}</div>
</div>
@endif
<!-- Footer -->
<div class="footer">
<div>Invoice generated on {{ now()->format('M j, Y g:i A') }}</div>
@if($invoice->createdBy)
<div>Prepared by: {{ $invoice->createdBy->name }}</div>
@endif
</div>
</body>
</html>