- 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
55 lines
2.2 KiB
TypeScript
55 lines
2.2 KiB
TypeScript
import type { Project } from '~~/types'
|
|
|
|
const dateFormatter = new Intl.DateTimeFormat('fr-FR', { month: 'long', year: 'numeric' })
|
|
|
|
export function formatProjectDate(iso?: string): string {
|
|
if (!iso) return ''
|
|
const d = new Date(iso)
|
|
return Number.isNaN(d.getTime()) ? '' : dateFormatter.format(d)
|
|
}
|
|
|
|
/** Mois + année capitalisés (ex. « Juillet 2026 ») ; sans argument = aujourd'hui.
|
|
* Sert de date par défaut de l'en-tête de couverture. */
|
|
export function formatMonthYear(iso?: string): string {
|
|
const d = iso ? new Date(iso) : new Date()
|
|
if (Number.isNaN(d.getTime())) return ''
|
|
const s = dateFormatter.format(d)
|
|
return s.charAt(0).toUpperCase() + s.slice(1)
|
|
}
|
|
|
|
/** Retire le paramètre `target=_blank` que Grav colle à chaque URL — dans une
|
|
* URL simple comme dans une chaîne HTML (href des liens du corps de texte). */
|
|
export function stripTargetParam(s?: string): string {
|
|
if (!s) return ''
|
|
return s
|
|
.replace(/\?target=_blank&/g, '?') // seul paramètre en tête, suivi d'autres
|
|
.replace(/&target=_blank/g, '') // paramètre en fin de chaîne de requête
|
|
.replace(/\?target=_blank\b/g, '') // seul paramètre
|
|
}
|
|
|
|
export const CATEGORY_LABELS: Record<string, string> = {
|
|
culturelle: 'Culturelle',
|
|
publique: 'Publique',
|
|
sociale: 'Sociale',
|
|
}
|
|
|
|
// Valeurs par défaut du header de la vue publique (surchargées par la couverture).
|
|
export const DEFAULT_SITE_URL = 'https://figureslibres.cc'
|
|
export const DEFAULT_CONTACT_EMAIL = 'bonjour@figureslibres.io'
|
|
|
|
/**
|
|
* URL de miniature basse résolution d'un média de projet.
|
|
* `base` permet de router vers la route publique (/api/public/<id>/media) en
|
|
* vue publique au lieu de la route authentifiée par défaut.
|
|
*/
|
|
export function mediaUrl(projectId: string, filename: string, width?: number, base = '/api/media'): string {
|
|
const url = `${base}/${projectId.split('/').map(encodeURIComponent).join('/')}/${encodeURIComponent(filename)}`
|
|
return width ? `${url}?w=${width}` : url
|
|
}
|
|
|
|
/** Vignette de couverture d'un projet (aura.image ou 1re image). */
|
|
export function projectThumb(project: Project, width = 480): string | null {
|
|
const cover = project.coverImage ?? project.media.find(m => m.type === 'image')?.filename
|
|
return cover ? mediaUrl(project.id, cover, width) : null
|
|
}
|