mirror of
https://github.com/IliesAllali/parenthese.git
synced 2026-11-12 16:16:09 +00:00
réglages : curseur du seuil, onglets créés affichés en direct
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
61d9bcc328
commit
b89ceb4e00
4 files changed
+30
-14
No files matched your search
@@ -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 */ } }, [])
|
||||
|
||||
@@ -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 = ({
|
||||
</label>
|
||||
{familyTabs && (
|
||||
<div className="ts-min-count">
|
||||
<label htmlFor="settingsTabMinCount">{t('À partir de')}</label>
|
||||
<label htmlFor="settingsTabMinCount">{t('À partir de {n} personnes au même nom', { n: tabDraft })}</label>
|
||||
<input
|
||||
id="settingsTabMinCount"
|
||||
className="pz-input"
|
||||
type="number"
|
||||
inputMode="numeric"
|
||||
type="range"
|
||||
min={2}
|
||||
max={99}
|
||||
value={tabMinCount}
|
||||
onChange={(event) => { 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))}
|
||||
/>
|
||||
<span>{t('personnes au même nom')}</span>
|
||||
<p className="ts-tab-preview" aria-live="polite">
|
||||
{tabPreview.length
|
||||
? tabPreview.map((tb) => <span key={tb.key} className="pz-tag">{tb.label} <small>{tb.count}</small></span>)
|
||||
: t("Aucun onglet à ce seuil : tout l'arbre sur une seule page.")}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<label className={`ts-choice ${familyTabs ? '' : 'is-active'}`}>
|
||||
|
||||
@@ -305,5 +305,7 @@
|
||||
}
|
||||
.tm-share-btn { justify-self: start; }
|
||||
|
||||
.ts-min-count { display: flex; flex-wrap: wrap; align-items: center; white-space: nowrap; gap: 10px; margin: 0 0 10px 16px; font: 400 14px var(--pz-sans); color: var(--pz-ink-2); }
|
||||
.ts-min-count .pz-input { width: 72px; padding-block: 8px; text-align: center; font-variant-numeric: tabular-nums; }
|
||||
.ts-min-count { display: grid; gap: 8px; margin: 0 0 12px 16px; font: 400 14px var(--pz-sans); color: var(--pz-ink-2); }
|
||||
.ts-min-count input[type=range] { width: 100%; max-width: 320px; accent-color: var(--pz-a500); }
|
||||
.ts-tab-preview { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; color: var(--pz-faint); }
|
||||
.ts-tab-preview small { font-variant-numeric: tabular-nums; opacity: 0.7; }
|
||||
@@ -8,8 +8,8 @@ export default {
|
||||
'Réglages de ce navigateur.': 'Saved in this browser.',
|
||||
'Un onglet par nom de famille': 'One tab per last name',
|
||||
"Chaque nom porté par assez de personnes reliées entre elles a son onglet, avec les conjoints. Le premier onglet montre tout l'arbre.": 'Each last name carried by enough related people gets its own tab, with their spouses. The first tab shows the whole tree.',
|
||||
'À partir de': 'From',
|
||||
'personnes au même nom': 'people with the same name',
|
||||
'À partir de {n} personnes au même nom': 'From {n} people with the same name',
|
||||
"Aucun onglet à ce seuil : tout l'arbre sur une seule page.": 'No tab at this threshold: the whole tree on one page.',
|
||||
"Pas d'onglets": 'No tabs',
|
||||
"Tout l'arbre sur une seule page.": 'The whole tree on one page.',
|
||||
"Tout l'arbre": 'Whole tree',
|
||||
|
||||
Reference in new issue
Block a user