feat(vue-fiches): fiche= dans l'URL, fiche à fiche, historique push/replace/back (B12-M2/M3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AGNSEFZdoKvbdsGyfSnu5S
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
55027ba482
commit
fe1043e321
@@ -17,6 +17,7 @@ import type { MiniFiche } from '~/composables/useFicheAdapter'
|
||||
import {
|
||||
lireQuery, ecrireQuery, filtresValides, filtrerFiches, compterEtiquettes,
|
||||
triEffectif, trierFiches, regrouper, ordreFiches, nbFiltresActifs,
|
||||
lireFiche, queryAvecFiche, positionFiche, modeOuverture, modeFermeture, empreinteListe,
|
||||
type ConfigVueFiches, type EtatFiches, type EtatVue, type TriFiches,
|
||||
} from '~/utils/vueFiches'
|
||||
|
||||
@@ -50,11 +51,29 @@ export function useVueFiches(
|
||||
}))
|
||||
|
||||
// ── Écriture ──
|
||||
// La navigation est asynchrone : une query écrite n'est dans `route.query`
|
||||
// qu'au tick suivant. Deux écritures du même tick (« Voir sur la carte » :
|
||||
// Mixte, puis la sous-vue de la page) partent donc de la dernière query
|
||||
// écrite, sinon la seconde efface la première.
|
||||
let enAttente: Record<string, string> | null = null
|
||||
watch(() => route.query, () => { enAttente = null })
|
||||
const queryBase = () => enAttente ?? route.query
|
||||
function naviguer(query: Record<string, string>, mode: 'push' | 'replace' = 'replace') {
|
||||
enAttente = query
|
||||
if (mode === 'push') router.push({ query })
|
||||
else router.replace({ query })
|
||||
}
|
||||
function etatDepuis(base: Record<string, unknown>): EtatFiches {
|
||||
const b = lireQuery(base, cfg.value)
|
||||
return { ...b, q: q.value, filtres: filtresValides(b.filtres, cfg.value) }
|
||||
}
|
||||
|
||||
function ecrire(partiel: Partial<EtatFiches>) {
|
||||
const nouvel = { ...etat.value, ...partiel }
|
||||
const base = queryBase()
|
||||
const nouvel = { ...etatDepuis(base), ...partiel }
|
||||
qEcrit = nouvel.q
|
||||
if (minuteurQ && partiel.q === undefined) { clearTimeout(minuteurQ); minuteurQ = null }
|
||||
router.replace({ query: ecrireQuery(nouvel, cfg.value, route.query) })
|
||||
naviguer(ecrireQuery(nouvel, cfg.value, base))
|
||||
}
|
||||
|
||||
function setQ(v: string) {
|
||||
@@ -155,11 +174,78 @@ export function useVueFiches(
|
||||
/** Fiche survolée (liste ↔ épingle) ; la carte de la page s'en sert, et peut l'écrire. */
|
||||
const survolId = ref<string | number | null>(null)
|
||||
|
||||
// ── Fiche ouverte (B12) : `fiche=` dans l'URL, lu aussi au rendu serveur ──
|
||||
const ficheId = computed(() => lireFiche(route.query))
|
||||
/** La fiche ouverte, cherchée dans TOUTES les fiches (elle peut être hors filtres). null = pas encore chargée ou inconnue. */
|
||||
const ficheOuverte = computed<MiniFiche | null>(() => {
|
||||
const id = ficheId.value
|
||||
return id == null ? null : toValue(fiches).find((f) => String(f.id) === id) ?? null
|
||||
})
|
||||
/** Rang dans l'ordre courant ; null = hors de vos filtres (ou pas de fiche). */
|
||||
const position = computed(() => positionFiche(ordre.value, ficheId.value))
|
||||
/**
|
||||
* Empreinte de la liste au moment où CETTE page a ajouté l'entrée
|
||||
* d'historique de la fiche ; null = fiche venue d'un lien partagé.
|
||||
*/
|
||||
let listeALOuverture: string | null = null
|
||||
|
||||
function ouvrirFiche(id: string | number) {
|
||||
if (String(id) === lireFiche(queryBase())) return
|
||||
const base = queryBase()
|
||||
const mode = modeOuverture(lireFiche(base))
|
||||
if (mode === 'push') listeALOuverture = empreinteListe(base)
|
||||
naviguer(queryAvecFiche(base, id), mode)
|
||||
}
|
||||
|
||||
function fermerFiche() {
|
||||
if (lireFiche(queryBase()) == null) return
|
||||
const mode = modeFermeture(listeALOuverture != null, listeALOuverture === empreinteListe(queryBase()))
|
||||
listeALOuverture = null
|
||||
if (mode === 'back') { enAttente = null; router.back() }
|
||||
else naviguer(queryAvecFiche(queryBase(), null))
|
||||
}
|
||||
|
||||
/** Étiquette cliquée dans le détail : ajoute le filtre ; `fermer` (téléphone) referme la fiche dans le même geste. */
|
||||
function filtrerDepuisFiche(dim: string, valeur: string, fermer: boolean) {
|
||||
const base = queryBase()
|
||||
const e = etatDepuis(base)
|
||||
const vals = e.filtres[dim] ?? []
|
||||
const filtres = vals.includes(valeur) ? e.filtres : { ...e.filtres, [dim]: [...vals, valeur] }
|
||||
const query = ecrireQuery({ ...e, filtres }, cfg.value, base)
|
||||
if (fermer) listeALOuverture = null
|
||||
naviguer(fermer ? queryAvecFiche(query, null) : query)
|
||||
}
|
||||
|
||||
// Retour arrière du navigateur (ou lien interne) : l'URL a perdu `fiche=`.
|
||||
watch(ficheId, (id) => { if (id == null) listeALOuverture = null })
|
||||
|
||||
const fichePrecedente = () => { if (position.value?.precedente) ouvrirFiche(position.value.precedente.id) }
|
||||
const ficheSuivante = () => { if (position.value?.suivante) ouvrirFiche(position.value.suivante.id) }
|
||||
|
||||
/**
|
||||
* « Voir sur la carte » : ordinateur → Mixte, la fiche reste ouverte ;
|
||||
* téléphone et tablette (pas de Mixte) → Carte, la fiche se ferme (elle
|
||||
* couvrirait la carte). La page lit `centrage` et centre son épingle.
|
||||
*/
|
||||
const centrage = ref<{ id: string; n: number } | null>(null)
|
||||
function voirSurCarte(id: string | number) {
|
||||
centrage.value = { id: String(id), n: (centrage.value?.n ?? 0) + 1 }
|
||||
if (largeur.value === 'ordinateur' && cfg.value.etats.includes('mixte')) {
|
||||
setVue('mixte')
|
||||
return
|
||||
}
|
||||
listeALOuverture = null
|
||||
const base = queryBase()
|
||||
naviguer(queryAvecFiche(ecrireQuery({ ...etatDepuis(base), vue: 'carte' }, cfg.value, base), null))
|
||||
}
|
||||
|
||||
return reactive({
|
||||
cfg, etat, q, largeur, vueAffichee, tri, resultat, groupes, ordre, compteurs,
|
||||
idsResultat, nbSansAdresse, total, nbActifs, survolId,
|
||||
ficheId, ficheOuverte, position, centrage,
|
||||
setVue, setQ, toggle, ajouterFiltre, effacerTout, setTri, setGroupe, setSousVue,
|
||||
setSansAdresse, voirSansAdresse,
|
||||
ouvrirFiche, fermerFiche, fichePrecedente, ficheSuivante, voirSurCarte, filtrerDepuisFiche,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user