diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index c5750a1..ea1410a 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -73,7 +73,7 @@ import { readGedcomBundle, zipErrorMessage } from './utils/gedcomBundle.js' import { materializeFile } from './utils/zipReader.js' import { loadMediaRefs, loadPhotoRefs, pickFirstFaces, prepareImageForUpload, saveMediaRefs, savePhotoRefs, sizeBucket } from './utils/photoImport' import { fileToBase64, getAccountErrorMessage } from './utils/errorMessages' -import { getSiblingParentLinks } from './utils/familyLinks' +import { getCoupleParentLinks, getSiblingParentLinks } from './utils/familyLinks' import { getUploadMimeType, inferMediaTypeFromMimeType, validateMediaFile } from './utils/mediaUpload' import { getSource, @@ -1225,6 +1225,19 @@ function App() { siblingParentLinks.push(...links) } } + // Un enfant ajouté à une personne qui n'a qu'un conjoint est l'enfant du couple : il passe par les liens + // du couple, comme un frère ou une sœur. Une adoption reste au seul parent choisi. + const relationCount = (formData.relations || []).length + formData = { + ...formData, + relations: (formData.relations || []).filter((rel) => { + if (rel.type !== 'child' || rel.adopted) return true + const coupleLinks = getCoupleParentLinks(rel.personId, unions) + if (!coupleLinks.length) return true + siblingParentLinks.push(...coupleLinks) + return false + }), + } if (!tree.canEditCurrentTree) { if (isDemoMode) { @@ -1331,7 +1344,7 @@ function App() { }, ] editMode.updateDraft({ addedPersons }) - trackAppEvent('person_added', { via: addPersonViaRef.current, role: 'family', relations: (formData.relations || []).length, tree_id: opaqueTreeId }) + trackAppEvent('person_added', { via: addPersonViaRef.current, role: 'family', relations: relationCount, tree_id: opaqueTreeId }) // La personne apparaît en fantôme « Brouillon » : la famille peut en ajouter d'autres, puis envoyer une // fois avec le bouton « Envoyer » de la barre (Patch, 25/10). Avant, la fenêtre d'envoi s'ouvrait d'office, // seule façon de montrer qu'un ajout invisible comptait. @@ -1409,7 +1422,7 @@ function App() { }) await tree.refreshCurrentTreeGraph() - trackAppEvent('person_added', { via: addPersonViaRef.current, role: 'manager', relations: (formData.relations || []).length, tree_id: opaqueTreeId }) + trackAppEvent('person_added', { via: addPersonViaRef.current, role: 'manager', relations: relationCount, tree_id: opaqueTreeId }) return newPerson } catch (err) { setAddPersonError(err.message || t("Erreur lors de l'ajout de la personne")) diff --git a/frontend/src/utils/familyLinks.js b/frontend/src/utils/familyLinks.js index b68bbd2..e2b8a14 100644 --- a/frontend/src/utils/familyLinks.js +++ b/frontend/src/utils/familyLinks.js @@ -36,3 +36,20 @@ export function getSiblingParentLinks(personId, filiations, unions) { return links } + +/** + * Parents à rattacher à un nouvel enfant de `parentId` : quand cette personne n'a qu'une union, + * l'enfant est celui du couple (les deux partenaires, avec l'identifiant de l'union). + * Aucune union, ou plusieurs (on ne devine pas l'autre parent) : liste vide, l'enfant reste au seul parent. + * + * @param {string} parentId - Personne à qui l'on ajoute un enfant + * @param {Array} unions - Unions du graphe courant ({ id, partner1Id, partner2Id }) + * @returns {Array<{ parentId: string, unionId: string }>} + */ +export function getCoupleParentLinks(parentId, unions) { + const key = String(parentId) + const own = (unions || []).filter((union) => String(union.partner1Id) === key || String(union.partner2Id) === key) + if (own.length !== 1 || !own[0].partner1Id || !own[0].partner2Id) return [] + const unionId = String(own[0].id) + return [{ parentId: String(own[0].partner1Id), unionId }, { parentId: String(own[0].partner2Id), unionId }] +} diff --git a/frontend/src/utils/familyLinks.test.js b/frontend/src/utils/familyLinks.test.js index b1f2572..1efa238 100644 --- a/frontend/src/utils/familyLinks.test.js +++ b/frontend/src/utils/familyLinks.test.js @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { getSiblingParentLinks } from './familyLinks' +import { getCoupleParentLinks, getSiblingParentLinks } from './familyLinks' describe('getSiblingParentLinks', () => { const unions = [{ id: 'u1', partner1Id: 'p1', partner2Id: 'p2' }] @@ -31,3 +31,23 @@ describe('getSiblingParentLinks', () => { expect(getSiblingParentLinks('c1', undefined, undefined)).toEqual([]) }) }) + +describe('getCoupleParentLinks', () => { + it('gives both partners when the parent has a single union', () => { + const unions = [{ id: 'u1', partner1Id: 'p1', partner2Id: 'p2' }] + expect(getCoupleParentLinks('p2', unions)).toEqual([ + { parentId: 'p1', unionId: 'u1' }, + { parentId: 'p2', unionId: 'u1' }, + ]) + }) + + it('keeps the child with the parent alone when there is no union or several', () => { + expect(getCoupleParentLinks('p1', [])).toEqual([]) + expect(getCoupleParentLinks('p1', undefined)).toEqual([]) + const unions = [ + { id: 'u1', partner1Id: 'p1', partner2Id: 'p2' }, + { id: 'u2', partner1Id: 'p3', partner2Id: 'p1' }, + ] + expect(getCoupleParentLinks('p1', unions)).toEqual([]) + }) +})