sackey cbae4564b9
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
Add customer portal views for dashboard, estimates, invoices, vehicles, and work orders
- Implemented dashboard view with vehicle stats, active services, recent activity, and upcoming appointments.
- Created estimates view with filtering options and a list of service estimates.
- Developed invoices view to manage service invoices and payment history with filtering.
- Added vehicles view to display registered vehicles and their details.
- Built work orders view to track the progress of vehicle services with filtering and detailed information.
2025-08-08 09:56:26 +00:00

196 lines
9.9 KiB
PHP

<div class="space-y-6">
<!-- Header -->
<div class="flex items-center justify-between">
<flux:heading size="xl">Customer Management</flux:heading>
<flux:button href="/customers/create" size="sm">
<flux:icon name="plus" class="size-4" />
Add New Customer
</flux:button>
</div>
<!-- Flash Messages -->
@if (session()->has('success'))
<div class="bg-green-50 border border-green-200 text-green-800 rounded-md p-4">
<div class="flex">
<flux:icon name="check-circle" class="h-5 w-5 text-green-400" />
<div class="ml-3">
<p class="text-sm font-medium">{{ session('success') }}</p>
</div>
</div>
</div>
@endif
@if (session()->has('error'))
<div class="bg-red-50 border border-red-200 text-red-800 rounded-md p-4">
<div class="flex">
<flux:icon name="exclamation-circle" class="h-5 w-5 text-red-400" />
<div class="ml-3">
<p class="text-sm font-medium">{{ session('error') }}</p>
</div>
</div>
</div>
@endif
<!-- Filters -->
<div class="bg-white dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 p-4">
<flux:input
wire:model.live="search"
placeholder="Search customers..."
icon="magnifying-glass"
/>
<select wire:model.live="status" class="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="">All Statuses</option>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
<div class="flex gap-2">
<flux:button wire:click="$refresh" variant="outline" size="sm">
<flux:icon name="arrow-path" class="size-4" />
Refresh
</flux:button>
</div>
</div>
</div>
<!-- Customers Table -->
<div class="bg-white dark:bg-zinc-800 rounded-lg border border-zinc-200 dark:border-zinc-700">
<div class="overflow-x-auto">
<table class="min-w-full">
<thead>
<tr class="border-b border-zinc-200 dark:border-zinc-700">
<th class="text-left py-3 px-4">
<button wire:click="sortBy('first_name')" class="flex items-center space-x-1 hover:text-blue-600">
<span>Name</span>
@if($sortBy === 'first_name')
<flux:icon name="{{ $sortDirection === 'asc' ? 'chevron-up' : 'chevron-down' }}" class="size-3" />
@endif
</button>
</th>
<th class="text-left py-3 px-4">
<button wire:click="sortBy('email')" class="flex items-center space-x-1 hover:text-blue-600">
<span>Contact</span>
@if($sortBy === 'email')
<flux:icon name="{{ $sortDirection === 'asc' ? 'chevron-up' : 'chevron-down' }}" class="size-3" />
@endif
</button>
</th>
<th class="text-left py-3 px-4">Address</th>
<th class="text-left py-3 px-4">Vehicles</th>
<th class="text-left py-3 px-4">Portal Access</th>
<th class="text-left py-3 px-4">
<button wire:click="sortBy('last_service_date')" class="flex items-center space-x-1 hover:text-blue-600">
<span>Last Service</span>
@if($sortBy === 'last_service_date')
<flux:icon name="{{ $sortDirection === 'asc' ? 'chevron-up' : 'chevron-down' }}" class="size-3" />
@endif
</button>
</th>
<th class="text-left py-3 px-4">Status</th>
<th class="text-left py-3 px-4">Actions</th>
</tr>
</thead>
<tbody>
@forelse($customers as $customer)
<tr class="border-b border-zinc-200 dark:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-700">
<td class="py-3 px-4">
<div>
<div class="font-medium">{{ $customer->full_name }}</div>
<div class="text-sm text-zinc-500 dark:text-zinc-400">ID: {{ $customer->id }}</div>
</div>
</td>
<td class="py-3 px-4">
<div>
<div class="text-sm">{{ $customer->email }}</div>
<div class="text-sm text-zinc-500 dark:text-zinc-400">{{ $customer->phone }}</div>
</div>
</td>
<td class="py-3 px-4">
<div class="text-sm">
{{ $customer->city }}, {{ $customer->state }}
</div>
</td>
<td class="py-3 px-4">
<div class="text-sm">
<flux:badge variant="outline" size="sm">
{{ $customer->vehicles->count() }} vehicle(s)
</flux:badge>
</div>
</td>
<td class="py-3 px-4">
@if($customer->user && $customer->user->isCustomer())
<flux:badge variant="success" size="sm">
<flux:icon name="check-circle" class="size-3 mr-1" />
Active
</flux:badge>
@else
<flux:badge variant="outline" size="sm">
<flux:icon name="x-circle" class="size-3 mr-1" />
No Access
</flux:badge>
@endif
</td>
<td class="py-3 px-4">
<div class="text-sm">
@if($customer->last_service_date)
{{ $customer->last_service_date->format('M j, Y') }}
@else
<span class="text-zinc-400 dark:text-zinc-500">Never</span>
@endif
</div>
</td>
<td class="py-3 px-4">
<flux:badge
:color="$customer->status === 'active' ? 'green' : 'gray'"
size="sm"
>
{{ ucfirst($customer->status) }}
</flux:badge>
</td>
<td class="py-3 px-4">
<div class="flex space-x-2">
<flux:button href="/customers/{{ $customer->id }}" variant="outline" size="sm">
View
</flux:button>
<flux:button href="/customers/{{ $customer->id }}/edit" variant="outline" size="sm">
Edit
</flux:button>
<flux:button href="/service-orders/create?customer={{ $customer->id }}" size="sm">
New Order
</flux:button>
<flux:button
wire:click="deleteCustomer({{ $customer->id }})"
wire:confirm="Are you sure you want to delete {{ $customer->full_name }}? This action cannot be undone."
variant="danger"
size="sm"
>
Delete
</flux:button>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="text-center py-8 text-zinc-500 dark:text-zinc-400">
@if($search)
No customers found matching "{{ $search }}"
@else
No customers found. <a href="/customers/create" class="text-blue-600 hover:underline">Add your first customer</a>
@endif
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
@if($customers->hasPages())
<div class="mt-4 px-4 pb-4">
{{ $customers->links() }}
</div>
@endif
</div>
</div>