[ERP-62] Page Répertoire clients (datatable + Ajouter / Exporter) #44
@@ -52,12 +52,10 @@
|
|||||||
"showArchived": "Voir les archivés",
|
"showArchived": "Voir les archivés",
|
||||||
"empty": "Aucun client pour l'instant.",
|
"empty": "Aucun client pour l'instant.",
|
||||||
"column": {
|
"column": {
|
||||||
"companyName": "Nom entreprise",
|
"companyName": "Nom",
|
||||||
"contact": "Contact principal",
|
|
||||||
"phone": "Téléphone principal",
|
|
||||||
"email": "Email principal",
|
|
||||||
"categories": "Catégories",
|
"categories": "Catégories",
|
||||||
"sites": "Site(s)"
|
"sites": "Site",
|
||||||
|
"lastActivity": "Dernière activité"
|
||||||
},
|
},
|
||||||
"tab": {
|
"tab": {
|
||||||
"information": "Information",
|
"information": "Information",
|
||||||
|
|||||||
@@ -29,12 +29,10 @@ export interface ClientCategory {
|
|||||||
export interface Client {
|
export interface Client {
|
||||||
id: number
|
id: number
|
||||||
companyName: string
|
companyName: string
|
||||||
firstName: string | null
|
|
||||||
lastName: string | null
|
|
||||||
phonePrimary: string | null
|
|
||||||
email: string | null
|
|
||||||
categories: ClientCategory[]
|
categories: ClientCategory[]
|
||||||
sites: ClientSite[]
|
sites: ClientSite[]
|
||||||
|
/** Date ISO de derniere modification (default:read) — colonne « Dernière activité ». */
|
||||||
|
updatedAt: string | null
|
||||||
isArchived: boolean
|
isArchived: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,17 +3,9 @@
|
|||||||
<PageHeader>
|
<PageHeader>
|
||||||
{{ t('commercial.clients.title') }}
|
{{ t('commercial.clients.title') }}
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<MalioButton
|
|
||||||
v-if="canView"
|
|
||||||
variant="secondary"
|
|
||||||
:label="t('commercial.clients.export')"
|
|
||||||
icon-name="mdi:file-export-outline"
|
|
||||||
icon-position="left"
|
|
||||||
:disabled="exporting"
|
|
||||||
@click="exportXlsx"
|
|
||||||
/>
|
|
||||||
<MalioButton
|
<MalioButton
|
||||||
v-if="canManage"
|
v-if="canManage"
|
||||||
|
variant="secondary"
|
||||||
:label="t('commercial.clients.add')"
|
:label="t('commercial.clients.add')"
|
||||||
icon-name="mdi:add-bold"
|
icon-name="mdi:add-bold"
|
||||||
icon-position="left"
|
icon-position="left"
|
||||||
@@ -43,21 +35,12 @@
|
|||||||
:per-page="itemsPerPage"
|
:per-page="itemsPerPage"
|
||||||
:per-page-options="itemsPerPageOptions"
|
:per-page-options="itemsPerPageOptions"
|
||||||
row-clickable
|
row-clickable
|
||||||
|
table-class="table-fixed"
|
||||||
:empty-message="t('commercial.clients.empty')"
|
:empty-message="t('commercial.clients.empty')"
|
||||||
@row-click="onRowClick"
|
@row-click="onRowClick"
|
||||||
@update:page="goToPage"
|
@update:page="goToPage"
|
||||||
@update:per-page="setItemsPerPage"
|
@update:per-page="setItemsPerPage"
|
||||||
>
|
>
|
||||||
<!-- Contact principal : prenom + nom (l'un des deux peut etre vide). -->
|
|
||||||
<template #cell-contact="{ item }">
|
|
||||||
{{ formatContact(item) }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Telephone principal formate XX XX XX XX XX (ERP-66). -->
|
|
||||||
<template #cell-phone="{ item }">
|
|
||||||
{{ formatPhoneFR(item.phonePrimary as string | null) }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- Categories : codes stables separes par une virgule (ERP-78). -->
|
<!-- Categories : codes stables separes par une virgule (ERP-78). -->
|
||||||
<template #cell-categories="{ item }">
|
<template #cell-categories="{ item }">
|
||||||
{{ formatCategories(item) }}
|
{{ formatCategories(item) }}
|
||||||
@@ -76,7 +59,21 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- Derniere activite : date de derniere modification (updatedAt). -->
|
||||||
|
<template #cell-lastActivity="{ item }">
|
||||||
|
{{ formatLastActivity(item) }}
|
||||||
|
</template>
|
||||||
</MalioDataTable>
|
</MalioDataTable>
|
||||||
|
<div class="flex justify-center mt-6">
|
||||||
|
<MalioButton
|
||||||
|
v-if="canView"
|
||||||
|
variant="primary"
|
||||||
|
:label="t('commercial.clients.export')"
|
||||||
|
:disabled="exporting"
|
||||||
|
@click="exportXlsx"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -115,34 +112,38 @@ const {
|
|||||||
const rows = computed(() => clients.value.map(client => ({
|
const rows = computed(() => clients.value.map(client => ({
|
||||||
id: client.id,
|
id: client.id,
|
||||||
companyName: client.companyName,
|
companyName: client.companyName,
|
||||||
firstName: client.firstName,
|
|
||||||
lastName: client.lastName,
|
|
||||||
phonePrimary: client.phonePrimary,
|
|
||||||
email: client.email,
|
|
||||||
categories: client.categories,
|
categories: client.categories,
|
||||||
sites: client.sites,
|
sites: client.sites,
|
||||||
|
updatedAt: client.updatedAt,
|
||||||
})))
|
})))
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ key: 'companyName', label: t('commercial.clients.column.companyName') },
|
{ key: 'companyName', label: t('commercial.clients.column.companyName') },
|
||||||
{ key: 'contact', label: t('commercial.clients.column.contact') },
|
|
||||||
{ key: 'phone', label: t('commercial.clients.column.phone') },
|
|
||||||
{ key: 'email', label: t('commercial.clients.column.email') },
|
|
||||||
{ key: 'categories', label: t('commercial.clients.column.categories') },
|
{ key: 'categories', label: t('commercial.clients.column.categories') },
|
||||||
{ key: 'sites', label: t('commercial.clients.column.sites') },
|
{ key: 'sites', label: t('commercial.clients.column.sites') },
|
||||||
|
{ key: 'lastActivity', label: t('commercial.clients.column.lastActivity') },
|
||||||
]
|
]
|
||||||
|
|
||||||
/** Contact principal : « Prenom Nom » en ignorant les parties vides. */
|
|
||||||
function formatContact(item: Record<string, unknown>): string {
|
|
||||||
return [item.firstName, item.lastName].filter(Boolean).join(' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Codes des categories du client, separes par une virgule (ERP-78). */
|
/** Codes des categories du client, separes par une virgule (ERP-78). */
|
||||||
function formatCategories(item: Record<string, unknown>): string {
|
function formatCategories(item: Record<string, unknown>): string {
|
||||||
const categories = (item.categories as Client['categories']) ?? []
|
const categories = (item.categories as Client['categories']) ?? []
|
||||||
return categories.map(c => c.code).join(', ')
|
return categories.map(c => c.code).join(', ')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derniere activite : faute de suivi d'activite metier au M1, on affiche la
|
||||||
|
* date de derniere modification de la fiche (updatedAt, expose en liste via
|
||||||
|
* default:read). Format court francais jj/mm/aaaa.
|
||||||
|
*/
|
||||||
|
function formatLastActivity(item: Record<string, unknown>): string {
|
||||||
|
const value = item.updatedAt as string | null | undefined
|
||||||
|
if (!value) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Date(value).toLocaleDateString('fr-FR')
|
||||||
|
}
|
||||||
|
|
||||||
/** Clic sur une ligne → ecran Consultation (route a plat /clients/{id}). */
|
/** Clic sur une ligne → ecran Consultation (route a plat /clients/{id}). */
|
||||||
function onRowClick(item: Record<string, unknown>): void {
|
function onRowClick(item: Record<string, unknown>): void {
|
||||||
router.push(`/clients/${item.id}`)
|
router.push(`/clients/${item.id}`)
|
||||||
|
|||||||
Reference in New Issue
Block a user