feat(directory) : refonte UI des fiches + onglet rapport (LST-72)
Pull Request — Quality gate / Backend (PHP CS + PHPUnit) (pull_request) Successful in 1m17s
Pull Request — Quality gate / Frontend (build) (pull_request) Successful in 1m25s

Fiches Client / Prospect / Prestataire (onglet Rapport mis à part) :
- Champs email/téléphone : composants MalioInputEmail / MalioInputPhone
- Grilles en 4 colonnes (Info + blocs Contact/Adresse)
- Boutons « Nouveau contact/adresse » en secondary ; « Enregistrer » en
  taille Malio standard ; marge form↔bouton homogène entre onglets
- Bouton retour ghost (mdi:arrow-left-bold) comme Starseed
- Adresse : flux CP → ville → rue (rue conditionnée au CP+ville, cascade
  de reset), titre du bloc = libellé saisi
- Suppression d'un bloc Contact/Adresse : modal de confirmation (logique
  centralisée dans useDirectoryDetail)

Onglet Rapport :
- Bouton d'ajout en taille Malio standard, label « Ajouter »
- Suppression compte-rendu : passe à la ConfirmModal partagée (remplace
  l'ancienne ConfirmDeleteReportModal, supprimée)
- Suppression d'un document joint : ajout d'une modal de confirmation
- Upload via MalioInputUpload ; bouton supprimer document aligné
  (mdi:delete-outline ghost)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-26 17:09:23 +02:00
parent 81069915c1
commit ba462a091b
11 changed files with 299 additions and 199 deletions
@@ -2,7 +2,14 @@
<div>
<PageHeader>
<span class="inline-flex items-center gap-3">
<MalioButtonIcon icon="mdi:arrow-left" :aria-label="$t('common.back')" @click="goBack" />
<MalioButtonIcon
icon="mdi:arrow-left-bold"
icon-size="24"
variant="ghost"
:title="$t('common.back')"
:aria-label="$t('common.back')"
@click="goBack"
/>
{{ client?.name ?? '…' }}
</span>
</PageHeader>
@@ -13,7 +20,7 @@
<MalioTabList v-model="activeTab" :tabs="tabs">
<template #info>
<div class="flex flex-col gap-4 pt-6">
<div class="grid grid-cols-2 gap-x-[44px] gap-y-4">
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4 pb-5">
<MalioInputText
v-model="info.name"
class="col-span-2"
@@ -21,12 +28,12 @@
:error="infoTouched.name && !info.name.trim() ? $t('directory.validation.nameRequired') : ''"
@blur="infoTouched.name = true"
/>
<MalioInputText
<MalioInputEmail
v-model="info.email"
:label="$t('directory.info.fields.email')"
:error="emailError"
/>
<MalioInputText
<MalioInputPhone
v-model="info.phone"
:label="$t('directory.info.fields.phone')"
:error="phoneError"
@@ -40,7 +47,6 @@
</div>
<div class="flex justify-center pt-2">
<MalioButton
button-class="w-auto px-6"
:label="$t('common.save')"
:disabled="savingInfo || !infoValid"
@click="saveInfo"
@@ -59,11 +65,11 @@
:removable="contacts.length > 0"
:last="i === contacts.length - 1"
@update:model-value="(v) => onContactInput(i, v)"
@remove="removeContact(i)"
@remove="askRemoveContact(i)"
/>
<div class="flex justify-center gap-3 pt-2">
<MalioButton
variant="tertiary"
variant="secondary"
icon-name="mdi:plus"
icon-position="left"
button-class="w-auto px-4"
@@ -71,7 +77,6 @@
@click="addContact"
/>
<MalioButton
button-class="w-auto px-6"
:label="$t('common.save')"
:disabled="savingContacts"
@click="saveContacts"
@@ -90,11 +95,11 @@
:removable="addresses.length > 0"
:last="i === addresses.length - 1"
@update:model-value="(v) => onAddressInput(i, v)"
@remove="removeAddress(i)"
@remove="askRemoveAddress(i)"
/>
<div class="flex justify-center gap-3 pt-2">
<MalioButton
variant="tertiary"
variant="secondary"
icon-name="mdi:plus"
icon-position="left"
button-class="w-auto px-4"
@@ -102,7 +107,6 @@
@click="addAddress"
/>
<MalioButton
button-class="w-auto px-6"
:label="$t('common.save')"
:disabled="savingAddresses"
@click="saveAddresses"
@@ -117,6 +121,13 @@
</MalioTabList>
</template>
</div>
<ConfirmModal
v-model="removeModalOpen"
:title="removeModalTitle"
:message="removeModalMessage"
@confirm="confirmRemove"
/>
</div>
</template>
@@ -143,13 +154,17 @@ const {
savingAddresses,
onContactInput,
addContact,
removeContact,
askRemoveContact,
saveContacts,
onAddressInput,
addAddress,
removeAddress,
askRemoveAddress,
saveAddresses,
load,
removeModalOpen,
removeModalTitle,
removeModalMessage,
confirmRemove,
} = useDirectoryDetail(owner)
const { can } = usePermissions()
@@ -2,7 +2,14 @@
<div>
<PageHeader>
<span class="inline-flex items-center gap-3">
<MalioButtonIcon icon="mdi:arrow-left" :aria-label="$t('common.back')" @click="goBack" />
<MalioButtonIcon
icon="mdi:arrow-left-bold"
icon-size="24"
variant="ghost"
:title="$t('common.back')"
:aria-label="$t('common.back')"
@click="goBack"
/>
{{ prestataire?.name ?? '…' }}
</span>
</PageHeader>
@@ -13,7 +20,7 @@
<MalioTabList v-model="activeTab" :tabs="tabs">
<template #info>
<div class="flex flex-col gap-4 pt-6">
<div class="grid grid-cols-2 gap-x-[44px] gap-y-4">
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4 pb-5">
<MalioInputText
v-model="info.name"
class="col-span-2"
@@ -21,12 +28,12 @@
:error="infoTouched.name && !info.name.trim() ? $t('directory.validation.nameRequired') : ''"
@blur="infoTouched.name = true"
/>
<MalioInputText
<MalioInputEmail
v-model="info.email"
:label="$t('directory.info.fields.email')"
:error="emailError"
/>
<MalioInputText
<MalioInputPhone
v-model="info.phone"
:label="$t('directory.info.fields.phone')"
:error="phoneError"
@@ -40,7 +47,6 @@
</div>
<div class="flex justify-center pt-2">
<MalioButton
button-class="w-auto px-6"
:label="$t('common.save')"
:disabled="savingInfo || !infoValid"
@click="saveInfo"
@@ -59,11 +65,11 @@
:removable="contacts.length > 0"
:last="i === contacts.length - 1"
@update:model-value="(v) => onContactInput(i, v)"
@remove="removeContact(i)"
@remove="askRemoveContact(i)"
/>
<div class="flex justify-center gap-3 pt-2">
<MalioButton
variant="tertiary"
variant="secondary"
icon-name="mdi:plus"
icon-position="left"
button-class="w-auto px-4"
@@ -71,7 +77,6 @@
@click="addContact"
/>
<MalioButton
button-class="w-auto px-6"
:label="$t('common.save')"
:disabled="savingContacts"
@click="saveContacts"
@@ -90,11 +95,11 @@
:removable="addresses.length > 0"
:last="i === addresses.length - 1"
@update:model-value="(v) => onAddressInput(i, v)"
@remove="removeAddress(i)"
@remove="askRemoveAddress(i)"
/>
<div class="flex justify-center gap-3 pt-2">
<MalioButton
variant="tertiary"
variant="secondary"
icon-name="mdi:plus"
icon-position="left"
button-class="w-auto px-4"
@@ -102,7 +107,6 @@
@click="addAddress"
/>
<MalioButton
button-class="w-auto px-6"
:label="$t('common.save')"
:disabled="savingAddresses"
@click="saveAddresses"
@@ -117,6 +121,13 @@
</MalioTabList>
</template>
</div>
<ConfirmModal
v-model="removeModalOpen"
:title="removeModalTitle"
:message="removeModalMessage"
@confirm="confirmRemove"
/>
</div>
</template>
@@ -143,13 +154,17 @@ const {
savingAddresses,
onContactInput,
addContact,
removeContact,
askRemoveContact,
saveContacts,
onAddressInput,
addAddress,
removeAddress,
askRemoveAddress,
saveAddresses,
load,
removeModalOpen,
removeModalTitle,
removeModalMessage,
confirmRemove,
} = useDirectoryDetail(owner)
const { can } = usePermissions()
@@ -2,7 +2,14 @@
<div>
<PageHeader>
<span class="inline-flex items-center gap-3">
<MalioButtonIcon icon="mdi:arrow-left" :aria-label="$t('common.back')" @click="goBack" />
<MalioButtonIcon
icon="mdi:arrow-left-bold"
icon-size="24"
variant="ghost"
:title="$t('common.back')"
:aria-label="$t('common.back')"
@click="goBack"
/>
{{ prospect?.company ?? '…' }}
</span>
</PageHeader>
@@ -13,7 +20,7 @@
<MalioTabList v-model="activeTab" :tabs="tabs">
<template #info>
<div class="flex flex-col gap-4 pt-6">
<div class="grid grid-cols-2 gap-x-[44px] gap-y-4">
<div class="grid grid-cols-4 gap-x-[44px] gap-y-4 pb-5">
<MalioInputText
v-model="info.company"
class="col-span-2"
@@ -32,12 +39,12 @@
:label="$t('prospects.fields.website')"
:error="websiteError"
/>
<MalioInputText
<MalioInputEmail
v-model="info.email"
:label="$t('prospects.fields.email')"
:error="emailError"
/>
<MalioInputText
<MalioInputPhone
v-model="info.phone"
:label="$t('prospects.fields.phone')"
:error="phoneError"
@@ -49,13 +56,12 @@
/>
<MalioInputTextArea
v-model="info.notes"
class="col-span-2"
class="col-span-4"
:label="$t('prospects.fields.notes')"
/>
</div>
<div class="flex justify-center pt-2">
<MalioButton
button-class="w-auto px-6"
:label="$t('common.save')"
:disabled="savingInfo || !infoValid"
@click="saveInfo"
@@ -74,11 +80,11 @@
:removable="contacts.length > 0"
:last="i === contacts.length - 1"
@update:model-value="(v) => onContactInput(i, v)"
@remove="removeContact(i)"
@remove="askRemoveContact(i)"
/>
<div class="flex justify-center gap-3 pt-2">
<MalioButton
variant="tertiary"
variant="secondary"
icon-name="mdi:plus"
icon-position="left"
button-class="w-auto px-4"
@@ -86,7 +92,6 @@
@click="addContact"
/>
<MalioButton
button-class="w-auto px-6"
:label="$t('common.save')"
:disabled="savingContacts"
@click="saveContacts"
@@ -105,11 +110,11 @@
:removable="addresses.length > 0"
:last="i === addresses.length - 1"
@update:model-value="(v) => onAddressInput(i, v)"
@remove="removeAddress(i)"
@remove="askRemoveAddress(i)"
/>
<div class="flex justify-center gap-3 pt-2">
<MalioButton
variant="tertiary"
variant="secondary"
icon-name="mdi:plus"
icon-position="left"
button-class="w-auto px-4"
@@ -117,7 +122,6 @@
@click="addAddress"
/>
<MalioButton
button-class="w-auto px-6"
:label="$t('common.save')"
:disabled="savingAddresses"
@click="saveAddresses"
@@ -132,6 +136,13 @@
</MalioTabList>
</template>
</div>
<ConfirmModal
v-model="removeModalOpen"
:title="removeModalTitle"
:message="removeModalMessage"
@confirm="confirmRemove"
/>
</div>
</template>
@@ -158,13 +169,17 @@ const {
savingAddresses,
onContactInput,
addContact,
removeContact,
askRemoveContact,
saveContacts,
onAddressInput,
addAddress,
removeAddress,
askRemoveAddress,
saveAddresses,
load,
removeModalOpen,
removeModalTitle,
removeModalMessage,
confirmRemove,
} = useDirectoryDetail(owner)
const { can } = usePermissions()