66 lines
1.5 KiB
Vue
66 lines
1.5 KiB
Vue
<script setup lang="ts">
|
|
const { data, error, pending } = useCustomer('/')
|
|
|
|
const search = ref('')
|
|
|
|
const filtered = computed(() => {
|
|
if (!data.value) return []
|
|
if (!search.value) return data.value
|
|
|
|
return data.value.filter((c: any) =>
|
|
`${c.first_name} ${c.last_name} ${c.email}`
|
|
.toLowerCase()
|
|
.includes(search.value.toLowerCase())
|
|
)
|
|
})
|
|
|
|
const total = computed(() => data.value?.length ?? 0)
|
|
</script>
|
|
|
|
<template>
|
|
<div class="p-8 space-y-8 bg-gray-50 min-h-screen">
|
|
|
|
<!-- Header -->
|
|
<div class="flex justify-between items-center">
|
|
<div>
|
|
<h1 class="text-3xl text-slate-900 font-bold">Customers</h1>
|
|
<p class="text-gray-500 text-sm">Customer Relationship Management</p>
|
|
</div>
|
|
|
|
<UButton icon="i-heroicons-plus" color="primary" to="/customers/new">
|
|
New Customer
|
|
</UButton>
|
|
</div>
|
|
<!-- Error -->
|
|
<UAlert
|
|
v-if="error"
|
|
color="red"
|
|
variant="soft"
|
|
title="Failed to load customers"
|
|
:description="error.message"
|
|
/>
|
|
|
|
<!-- Loading -->
|
|
<div
|
|
v-else-if="pending"
|
|
class="grid gap-6 md:grid-cols-2 lg:grid-cols-3"
|
|
>
|
|
<UCard v-for="n in 6" :key="n">
|
|
<div class="h-32 animate-pulse bg-gray-200 rounded" />
|
|
</UCard>
|
|
</div>
|
|
|
|
<!-- Customer Grid -->
|
|
<div
|
|
v-else
|
|
class="grid gap-6 md:grid-cols-2 lg:grid-cols-3"
|
|
>
|
|
<CustomerCard
|
|
v-for="customer in filtered"
|
|
:key="customer.id"
|
|
:customer="customer"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|