f2d945b0c3
Hold contact/address block edits in memory and persist them via explicit saveContacts/saveAddresses on click (with saving guards), matching the task forms. Keep immediate deletion. Minor restyle of blocks and action buttons.
122 lines
4.9 KiB
TypeScript
122 lines
4.9 KiB
TypeScript
import type { Contact } from '~/modules/directory/services/dto/contact'
|
|
import type { Address } from '~/modules/directory/services/dto/address'
|
|
import { useContactService } from '~/modules/directory/services/contacts'
|
|
import { useAddressService } from '~/modules/directory/services/addresses'
|
|
|
|
type Owner = { client?: string, prospect?: string }
|
|
|
|
/**
|
|
* Logique partagée des fiches détail Client/Prospect : blocs répétables Contact
|
|
* et Adresse (chargement, ajout, suppression). L'édition est tenue en mémoire
|
|
* localement ; la persistance se fait au clic sur « Enregistrer » (saveContacts/
|
|
* saveAddresses), comme les formulaires de tâche — pas d'enregistrement au blur.
|
|
* Paramétré par l'IRI du propriétaire (`{ client }` ou `{ prospect }`), réutilisé
|
|
* tel quel par les deux pages.
|
|
*/
|
|
export function useDirectoryDetail(owner: Owner) {
|
|
const contactService = useContactService()
|
|
const addressService = useAddressService()
|
|
|
|
const contacts = ref<Contact[]>([])
|
|
const addresses = ref<Address[]>([])
|
|
const savingContacts = ref(false)
|
|
const savingAddresses = ref(false)
|
|
|
|
function emptyContact(): Contact {
|
|
return { id: 0, firstName: null, lastName: null, jobTitle: null, email: null, phonePrimary: null, phoneSecondary: null, ...owner }
|
|
}
|
|
function emptyAddress(): Address {
|
|
return { id: 0, label: null, street: null, streetComplement: null, postalCode: null, city: null, country: 'FR', ...owner }
|
|
}
|
|
|
|
// Édition locale uniquement : on remplace le bloc en mémoire, rien n'est
|
|
// persisté tant que l'utilisateur n'a pas cliqué sur « Enregistrer ».
|
|
function onContactInput(index: number, value: Contact): void {
|
|
contacts.value[index] = value
|
|
}
|
|
function onAddressInput(index: number, value: Address): void {
|
|
addresses.value[index] = value
|
|
}
|
|
|
|
function addContact(): void {
|
|
contacts.value.push(emptyContact())
|
|
}
|
|
function addAddress(): void {
|
|
addresses.value.push(emptyAddress())
|
|
}
|
|
|
|
// Suppression immédiate (comme la corbeille du formulaire de tâche) : un bloc
|
|
// déjà enregistré est supprimé côté serveur, une amorce non enregistrée est
|
|
// simplement retirée de la liste.
|
|
async function removeContact(index: number): Promise<void> {
|
|
const c = contacts.value[index]
|
|
if (c?.id && c.id > 0) await contactService.remove(c.id)
|
|
contacts.value.splice(index, 1)
|
|
}
|
|
async function removeAddress(index: number): Promise<void> {
|
|
const a = addresses.value[index]
|
|
if (a?.id && a.id > 0) await addressService.remove(a.id)
|
|
addresses.value.splice(index, 1)
|
|
}
|
|
|
|
// Persistance au clic : met à jour les blocs existants, crée les nouveaux
|
|
// blocs renseignés. Les amorces vides (sans contenu) sont ignorées.
|
|
async function saveContacts(): Promise<void> {
|
|
if (savingContacts.value) return
|
|
savingContacts.value = true
|
|
try {
|
|
for (let i = 0; i < contacts.value.length; i++) {
|
|
const c = contacts.value[i]
|
|
if (!c) continue
|
|
const payload = { firstName: c.firstName, lastName: c.lastName, jobTitle: c.jobTitle, email: c.email, phonePrimary: c.phonePrimary, phoneSecondary: c.phoneSecondary, ...owner }
|
|
if (c.id && c.id > 0) {
|
|
contacts.value[i] = await contactService.update(c.id, payload)
|
|
} else if (c.lastName || c.firstName) {
|
|
contacts.value[i] = await contactService.create(payload)
|
|
}
|
|
}
|
|
} finally {
|
|
savingContacts.value = false
|
|
}
|
|
}
|
|
async function saveAddresses(): Promise<void> {
|
|
if (savingAddresses.value) return
|
|
savingAddresses.value = true
|
|
try {
|
|
for (let i = 0; i < addresses.value.length; i++) {
|
|
const a = addresses.value[i]
|
|
if (!a) continue
|
|
const payload = { label: a.label, street: a.street, streetComplement: a.streetComplement, postalCode: a.postalCode, city: a.city, country: a.country, ...owner }
|
|
if (a.id && a.id > 0) {
|
|
addresses.value[i] = await addressService.update(a.id, payload)
|
|
} else if (a.street || a.city || a.postalCode) {
|
|
addresses.value[i] = await addressService.create(payload)
|
|
}
|
|
}
|
|
} finally {
|
|
savingAddresses.value = false
|
|
}
|
|
}
|
|
|
|
async function load(): Promise<void> {
|
|
contacts.value = await contactService.getByOwner(owner)
|
|
addresses.value = await addressService.getByOwner(owner)
|
|
}
|
|
|
|
return {
|
|
contacts,
|
|
addresses,
|
|
savingContacts,
|
|
savingAddresses,
|
|
onContactInput,
|
|
addContact,
|
|
removeContact,
|
|
saveContacts,
|
|
onAddressInput,
|
|
addAddress,
|
|
removeAddress,
|
|
saveAddresses,
|
|
load,
|
|
}
|
|
}
|