- Add explicit imports for useClientService/useProjectService (not auto-imported from services/) - Fix AppDrawer v-if placement on Teleport to avoid slot warning - Add json format support in API Platform config (415 fix) - Support both hydra:member and member keys in extractHydraMembers - Add Vite/Nitro dev proxy for API calls - Update CLAUDE.md with full project documentation - Use tertiary-500 background for project cards Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
97 lines
3.1 KiB
Vue
97 lines
3.1 KiB
Vue
<template>
|
|
<div>
|
|
<div class="flex items-center justify-between">
|
|
<h1 class="text-2xl font-bold text-neutral-900">Clients</h1>
|
|
<button
|
|
class="rounded-md bg-primary-500 px-4 py-2 text-sm font-semibold text-white hover:bg-secondary-500"
|
|
@click="openCreate"
|
|
>
|
|
+ Ajouter un client
|
|
</button>
|
|
</div>
|
|
|
|
<div class="mt-6 overflow-x-auto rounded-lg border border-neutral-200">
|
|
<table class="w-full text-left text-sm">
|
|
<thead class="border-b border-neutral-200 bg-neutral-50">
|
|
<tr>
|
|
<th class="px-4 py-3 font-semibold text-neutral-700">Nom</th>
|
|
<th class="px-4 py-3 font-semibold text-neutral-700">Email</th>
|
|
<th class="px-4 py-3 font-semibold text-neutral-700">Adresse</th>
|
|
<th class="px-4 py-3 font-semibold text-neutral-700">Téléphone</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr
|
|
v-for="client in clients"
|
|
:key="client.id"
|
|
class="border-b border-neutral-100 hover:bg-neutral-50 cursor-pointer"
|
|
@click="openEdit(client)"
|
|
>
|
|
<td class="px-4 py-3 font-semibold text-primary-500">{{ client.name }}</td>
|
|
<td class="px-4 py-3 text-primary-500">{{ client.email ?? '-' }}</td>
|
|
<td class="px-4 py-3 text-neutral-700">{{ formatAddress(client) }}</td>
|
|
<td class="px-4 py-3 text-primary-500">{{ client.phone ?? '-' }}</td>
|
|
</tr>
|
|
<tr v-if="clients.length === 0 && !isLoading">
|
|
<td colspan="4" class="px-4 py-8 text-center text-neutral-400">
|
|
Aucun client trouvé.
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<ClientDrawer
|
|
v-model="drawerOpen"
|
|
:client="selectedClient"
|
|
@saved="onSaved"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { Client } from '~/services/dto/client'
|
|
import { useClientService } from '~/services/clients'
|
|
|
|
useHead({ title: 'Clients' })
|
|
|
|
const { getAll } = useClientService()
|
|
const clients = ref<Client[]>([])
|
|
const isLoading = ref(true)
|
|
const drawerOpen = ref(false)
|
|
const selectedClient = ref<Client | null>(null)
|
|
|
|
async function loadClients() {
|
|
isLoading.value = true
|
|
try {
|
|
clients.value = await getAll()
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
function openCreate() {
|
|
selectedClient.value = null
|
|
drawerOpen.value = true
|
|
}
|
|
|
|
function openEdit(client: Client) {
|
|
selectedClient.value = client
|
|
drawerOpen.value = true
|
|
}
|
|
|
|
function formatAddress(client: Client): string {
|
|
return [client.street, client.postalCode, client.city]
|
|
.filter(Boolean)
|
|
.join(', ') || '-'
|
|
}
|
|
|
|
async function onSaved() {
|
|
await loadClients()
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadClients()
|
|
})
|
|
</script>
|