Textes projet éditables suivant Grav + écriture atomique du store

- Champ Présentation prérempli avec le texte Grav, suivi modifié/synchro
  (textOverride undefined = suit Grav, sinon figé ; bouton Réinitialiser)
- Fix génération PDF : savePortfolio écrit en atomique (temp+rename) pour
  éviter la corruption de lecture par l'autosave concurrent du rendu print
- Toast d'échec de génération explicite (message serveur)
- Refonte architecture visuelle, fond unifié white/tint/full, dispositions
  couverture bandeau/colonne, instantané public complet, index 3 lignes
This commit is contained in:
2026-07-06 13:26:06 +02:00
parent 59dfbe4155
commit ef1f14335d
22 changed files with 750 additions and 334 deletions

View File

@@ -3,7 +3,7 @@
// Filet couleur 5 mm en haut, images ENTIÈRES (object-contain) calées sur
// une grille ADAPTATIVE : la famille choisie se construit selon le nombre
// d'images et leur orientation. Marges 8 mm, gouttières 3,8 mm.
import type { ResolvedMedia } from '~~/types'
import type { Background, ResolvedMedia } from '~~/types'
import type { ImageOrientation } from '~~/composables/useGrids'
const props = withDefaults(
@@ -11,15 +11,16 @@ const props = withDefaults(
media: ResolvedMedia[]
grid: string // id de famille (useGrids)
orientation?: ImageOrientation
category?: string
bandColor?: string
greyBg?: boolean
background?: Background // fond : blanc / teinté / plein (couleur du filet)
}>(),
{ orientation: 'mixed' },
)
const def = computed(() => gridDef(props.grid, props.media.length, props.orientation))
const strip = computed(() => stripColorOf(props.category, props.bandColor))
const strip = computed(() => filetColor(props.bandColor))
// Fond « plein » = couleur du filet (le filet est alors masqué).
const pageBg = computed(() => backgroundColorOf(props.background, strip.value))
// Métriques du canvas A3 paysage (theme.css) — zone utile hors marges 8 mm.
const MARGIN = 30.2
@@ -92,9 +93,9 @@ const items = computed(() =>
</script>
<template>
<div class="fl-page" :style="greyBg ? { backgroundColor: FL_BASE } : undefined">
<!-- Filet couleur pleine largeur -->
<div class="absolute inset-x-0 top-0" :style="{ height: 'var(--fl-strip)', backgroundColor: strip }" />
<div class="fl-page" :style="{ backgroundColor: pageBg }">
<!-- Filet couleur fin en haut (masqué en fond plein) -->
<div v-if="background?.mode !== 'full'" class="absolute inset-x-0 top-0" :style="{ height: 'var(--fl-strip-light)', backgroundColor: strip }" />
<!-- Grande image + bandeaux/file : bandeaux à leur hauteur réelle -->
<div v-if="hero" class="absolute flex" :style="{ inset: 'var(--fl-margin)', gap: 'var(--fl-gutter)' }">