From b89ceb4e00585e671f66bdf857b075514f3dc165 Mon Sep 17 00:00:00 2001 From: IliesAllali Date: Sat, 7 Nov 2026 00:45:15 +0100 Subject: [PATCH] =?UTF-8?q?r=C3=A9glages=20:=20curseur=20du=20seuil,=20ong?= =?UTF-8?q?lets=20cr=C3=A9=C3=A9s=20affich=C3=A9s=20en=20direct?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- frontend/src/App.jsx | 2 +- frontend/src/components/AdminPanel.jsx | 32 ++++++++++++++++------ frontend/src/components/SettingsPanels.css | 6 ++-- frontend/src/i18n/en/arbre.js | 4 +-- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index aae7433..2f315c6 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -586,7 +586,7 @@ function App() { const setFamilyTabs = useCallback((on) => { setFamilyTabsState(on); try { localStorage.setItem('parenthese.familyTabs', on ? 'on' : 'off') } catch { /* navigateur sans stockage */ } }, []) // Nom de famille sous le prénom dans l'arbre, celui de naissance s'il est connu (#168). Réglage de ce navigateur. // Onglets par nom : nombre de porteurs d'un nom à partir duquel il a son onglet (8 par défaut, Patch, 07/11) - const [tabMinCount, setTabMinCountState] = useState(() => { try { const v = Number(localStorage.getItem('parenthese.tabMinCount')); return v >= 2 && v <= 99 ? v : 8 } catch { return 8 } }) + const [tabMinCount, setTabMinCountState] = useState(() => { try { const v = Number(localStorage.getItem('parenthese.tabMinCount')); return v >= 2 && v <= 30 ? v : 8 } catch { return 8 } }) const setTabMinCount = useCallback((n) => { setTabMinCountState(n); try { localStorage.setItem('parenthese.tabMinCount', String(n)) } catch { /* navigateur sans stockage */ } }, []) const [fullNames, setFullNamesState] = useState(() => { try { return localStorage.getItem('parenthese.fullNames') === 'on' } catch { return false } }) const setFullNames = useCallback((on) => { setFullNamesState(on); try { localStorage.setItem('parenthese.fullNames', on ? 'on' : 'off') } catch { /* navigateur sans stockage */ } }, []) diff --git a/frontend/src/components/AdminPanel.jsx b/frontend/src/components/AdminPanel.jsx index 935855e..fa0ece3 100644 --- a/frontend/src/components/AdminPanel.jsx +++ b/frontend/src/components/AdminPanel.jsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react' +import { useEffect, useMemo, useRef, useState } from 'react' import { Download, ImagePlus, Trash2, Unplug, X } from 'lucide-react' import './SettingsPanels.css' import { @@ -25,6 +25,7 @@ import { t } from '../i18n/index.js' import { readGedcomFile } from '../utils/gedcomText.js' import { readGedcomBundle, zipErrorMessage } from '../utils/gedcomBundle.js' import Skeleton from './Skeleton.jsx' +import { nameTabsOf } from './galaxy/nameTabs.js' function normalizeSlug(value) { return String(value || '') @@ -62,6 +63,16 @@ const AdminPanel = ({ onOpenPhotoStart, }) => { const [section, setSection] = useState('tree') + // Seuil des onglets : le curseur montre tout de suite les onglets qu'il crée ; l'arbre ne se recalcule qu'une + // fois le curseur posé + const [tabDraft, setTabDraft] = useState(tabMinCount) + useEffect(() => { setTabDraft(tabMinCount) }, [tabMinCount]) + useEffect(() => { + if (tabDraft === tabMinCount) return undefined + const timer = setTimeout(() => onTabMinCountChange?.(tabDraft), 350) + return () => clearTimeout(timer) + }, [tabDraft, tabMinCount, onTabMinCountChange]) + const tabPreview = useMemo(() => (visible && familyTabs ? nameTabsOf(null, tabDraft).slice(1) : []), [visible, familyTabs, tabDraft]) const [loading, setLoading] = useState(false) const [saving, setSaving] = useState(false) const [errorMessage, setErrorMessage] = useState('') @@ -552,18 +563,21 @@ const AdminPanel = ({ {familyTabs && (
- + { const n = Math.round(Number(event.target.value)); if (n >= 2 && n <= 99) onTabMinCountChange?.(n) }} + max={30} + step={1} + value={tabDraft} + onChange={(event) => setTabDraft(Number(event.target.value))} /> - {t('personnes au même nom')} +

+ {tabPreview.length + ? tabPreview.map((tb) => {tb.label} {tb.count}) + : t("Aucun onglet à ce seuil : tout l'arbre sur une seule page.")} +

)}