diff --git a/frontend/src/components/PersonCard.jsx b/frontend/src/components/PersonCard.jsx index 6212942..8b44272 100644 --- a/frontend/src/components/PersonCard.jsx +++ b/frontend/src/components/PersonCard.jsx @@ -8,6 +8,7 @@ import ImmichFacePanel from './ImmichFacePanel.jsx' import './PersonCard.css' import PzBusy from './PzBusy.jsx' import { t, dateLocale } from '../i18n/index.js' +import { formatPlace } from '../utils/place.js' const TYPE_LABELS = { photo: t('Photo'), @@ -305,13 +306,13 @@ const PersonCard = ({ } // Rendu d'un champ éditable ou lecture seule - const renderEditableValue = ({ field, value, placeholder, type = 'text' }) => { + const renderEditableValue = ({ field, value, placeholder, type = 'text', format = null }) => { if (!editMode) { const isEmptyValue = value === null || value === undefined || value === '' // Une date complète se lit « 22 octobre 1928 », pas « 1928-10-22 » const shown = type === 'date' && /^\d{4}-\d{2}-\d{2}/.test(String(value)) ? new Date(`${String(value).slice(0, 10)}T00:00:00Z`).toLocaleDateString(dateLocale, { day: 'numeric', month: 'long', year: 'numeric', timeZone: 'UTC' }) - : value + : format ? format(value) : value return {isEmptyValue ? '-' : shown} } return ( @@ -336,7 +337,7 @@ const PersonCard = ({ const born = person.birthYear || (person.birthDate ? String(person.birthDate).slice(0, 4) : '') const died = person.deathYear || (person.deathDate ? String(person.deathDate).slice(0, 4) : '') const parts = [] - if (born) parts.push(`${born}${person.birthPlace ? `, ${person.birthPlace}` : ''}`) + if (born) parts.push(`${born}${person.birthPlace ? `, ${formatPlace(person.birthPlace)}` : ''}`) if (!person.isAlive && died) parts.push(died) return parts.join(' – ') })() @@ -593,7 +594,7 @@ const PersonCard = ({ {(person.birthPlace || editMode) && (
{t('Lieu')} - {renderEditableValue({ field: 'birthPlace', value: person.birthPlace || '', placeholder: t('Lieu de naissance') })} + {renderEditableValue({ field: 'birthPlace', value: person.birthPlace || '', placeholder: t('Lieu de naissance'), format: formatPlace })}
)} {(person.birthName || editMode) && ( diff --git a/frontend/src/utils/place.js b/frontend/src/utils/place.js new file mode 100644 index 0000000..ac0a598 --- /dev/null +++ b/frontend/src/utils/place.js @@ -0,0 +1,14 @@ +// Lieu lisible à l'affichage : un arbre importé de Heredis avant le nettoyage à l'import garde ses lieux bruts +// (« La Roche-sur-Yon,85191,Vendée,Pays de la Loire,France, »). On montre les noms seulement, sans case vide, +// sans code INSEE ni postal, sans répétition. La valeur enregistrée ne change pas (même règle qu'à l'import). +export function formatPlace(value) { + if (!value) return value + const parts = [] + for (const raw of String(value).split(',')) { + const part = raw.trim() + if (!part || /^(\d{4,5}|2[AB]\d{3})$/i.test(part)) continue + if (parts.length && parts[parts.length - 1].toLowerCase() === part.toLowerCase()) continue + parts.push(part) + } + return parts.join(', ') +} diff --git a/frontend/src/utils/place.test.js b/frontend/src/utils/place.test.js new file mode 100644 index 0000000..f2f1c61 --- /dev/null +++ b/frontend/src/utils/place.test.js @@ -0,0 +1,17 @@ +import { describe, expect, it } from 'vitest' +import { formatPlace } from './place.js' + +describe('formatPlace', () => { + it('lieu brut de Heredis', () => { + expect(formatPlace('La Roche-sur-Yon,85191,Vendée,Pays de la Loire,France,')).toBe('La Roche-sur-Yon, Vendée, Pays de la Loire, France') + expect(formatPlace('Ménéac,56129,,,,')).toBe('Ménéac') + }) + it('lieu déjà propre inchangé', () => { + expect(formatPlace('Limoges')).toBe('Limoges') + expect(formatPlace('Lille, Nord, France')).toBe('Lille, Nord, France') + }) + it('vide reste vide', () => { + expect(formatPlace(null)).toBe(null) + expect(formatPlace('')).toBe('') + }) +})