feat(directory) : add client/prospect deletion from list with confirm modal
Pull Request — Quality gate / Frontend (build) (pull_request) Successful in 39s
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 1m35s

This commit is contained in:
Matthieu
2026-06-23 17:38:17 +02:00
parent 4a7fd46493
commit 3d991f78e5
3 changed files with 139 additions and 7 deletions
@@ -31,6 +31,17 @@
<template #cell-phone="{ item }">
{{ (item as Client).phone ?? '—' }}
</template>
<template #cell-actions="{ item }">
<div class="flex justify-end" @click.stop>
<MalioButtonIcon
icon="mdi:trash-can-outline"
:aria-label="$t('common.delete')"
button-class="!bg-red-100 !text-red-700"
:icon-size="18"
@click="askDeleteClient(item as Client)"
/>
</div>
</template>
</MalioDataTable>
</div>
</template>
@@ -75,20 +86,23 @@
{{ (item as ProspectRow).phone ?? '—' }}
</template>
<template #cell-actions="{ item }">
<div
v-if="!(item as ProspectRow).convertedClient"
class="flex justify-end"
@click.stop
>
<div class="flex justify-end gap-2" @click.stop>
<MalioButtonIcon
v-if="!(item as ProspectRow).convertedClient"
icon="mdi:account-convert"
:aria-label="$t('prospects.convert')"
button-class="!bg-green-100 !text-green-700"
:icon-size="18"
@click="convertProspect(item as ProspectRow)"
/>
<MalioButtonIcon
icon="mdi:trash-can-outline"
:aria-label="$t('common.delete')"
button-class="!bg-red-100 !text-red-700"
:icon-size="18"
@click="askDeleteProspect(item as ProspectRow)"
/>
</div>
<span v-else class="text-neutral-300"></span>
</template>
</MalioDataTable>
</div>
@@ -105,6 +119,13 @@
:prospect="selectedProspect"
@saved="onProspectSaved"
/>
<ConfirmDeleteModal
v-model="deleteModalOpen"
:title="deleteModalTitle"
:message="deleteModalMessage"
@confirm="confirmDelete"
/>
</div>
</template>
@@ -139,6 +160,7 @@ const clientColumns = [
{ key: 'name', label: t('prospects.fields.name') },
{ key: 'email', label: t('prospects.fields.email') },
{ key: 'phone', label: t('prospects.fields.phone') },
{ key: 'actions', label: '' },
]
async function loadClients() {
@@ -225,6 +247,54 @@ async function onProspectSaved() {
await Promise.all([loadProspects(), loadClients()])
}
// --- Suppression (clients & prospects) ---
type DeleteTarget =
| { type: 'client'; item: Client }
| { type: 'prospect'; item: Prospect }
const deleteModalOpen = ref(false)
const deleteTarget = ref<DeleteTarget | null>(null)
const deleteModalTitle = computed(() =>
deleteTarget.value?.type === 'prospect'
? t('prospects.deleteConfirmTitle')
: t('clients.deleteConfirmTitle'),
)
const deleteModalMessage = computed(() => {
if (!deleteTarget.value) return ''
const name = deleteTarget.value.item.name
return deleteTarget.value.type === 'prospect'
? t('prospects.deleteConfirmMessage', { name })
: t('clients.deleteConfirmMessage', { name })
})
function askDeleteClient(item: Client) {
deleteTarget.value = { type: 'client', item }
deleteModalOpen.value = true
}
function askDeleteProspect(item: Prospect) {
deleteTarget.value = { type: 'prospect', item }
deleteModalOpen.value = true
}
async function confirmDelete() {
const target = deleteTarget.value
if (!target) return
if (target.type === 'client') {
await clientService.remove(target.item.id)
await loadClients()
} else {
await prospectService.remove(target.item.id)
await loadProspects()
}
deleteModalOpen.value = false
deleteTarget.value = null
}
watch(statusFilter, loadProspects)
onMounted(async () => {