karbe/src/lib/plugins/hooks.ts
Claude Integration c69c355f90 feat(plugin): theme-aquarelle + hero variant (Phase 2.4 partie 1/2)
Registry : ajoute 2 plugins :
- theme-aquarelle (carnet naturaliste XIXᵉ, mutual exclusion avec theme-guyane)
- image-gallery-aquarelle-seed (14 aquarelles → MinIO + Media carbets démo)

Hooks :
- theme-guyane et theme-aquarelle se désactivent mutuellement au toggle ON
  via disableOtherTheme()

CSS (globals.css) :
- body[data-theme=aquarelle] : background papier teinté #faf5e9 + texture
  grain papier inline SVG + radial gradients ocres/canopy délavés
- Surcharges automatiques des borders zinc/gray vers sépia délavé

Layout :
- PT_Serif (au lieu de Cormorant) en theme aquarelle, plus dense et encrée
- data-theme = aquarelle prioritaire sur guyane si les deux sont enabled
  (défensif — le hook garantit normalement la mutual exclusion)

Hero :
- 2 versions dans le composant : guyane (existant, SVG CarbetRiver) et
  aquarelle (image MinIO 01-hero-fleuve-maroni.jpg en fond, voile crème,
  texte sépia, CTAs carrés sans rounded, hairlines, ornement de planche)
- Branchement via getActiveTheme()
- aquarelleUrl() helper qui construit l'URL MinIO publique

Partie 2/2 (PR ultérieure) : upload des 14 images dans MinIO + hook
image-gallery-aquarelle-seed + variantes aquarelle des autres composants
(CarbetCard, ExperiencesSection, HowItWorksSection, CESection, Footer).
2026-05-31 12:15:07 +00:00

122 lines
4 KiB
TypeScript

/**
* Plugin Karbé — hooks d'activation/désactivation par plugin.
*
* Chaque plugin peut déclarer un `onEnable` et/ou `onDisable` ici. Exemples
* d'usage : seed initial des carbets démo (au enable), soft-delete des
* carbets démo (au disable). Les hooks ne sont **pas** des migrations DB —
* pour ça on passe par les fichiers prisma/migrations.
*/
export type PluginHook = () => Promise<void>;
export interface PluginHookSet {
onEnable?: PluginHook;
onDisable?: PluginHook;
}
import { archiveDemoCarbets, seedDemoCarbets } from "./seeds/demo-carbets";
import {
republishContentPages,
seedContentPages,
unpublishContentPages,
} from "./seeds/content-pages-default";
import {
republishLegalPages,
seedLegalPages,
unpublishLegalPages,
} from "./seeds/legal-pages-default";
import {
deactivatePirogueProviders,
seedPirogueProviders,
} from "./seeds/pirogue-providers-default";
import { seedEnglishContentPages } from "./seeds/content-pages-en";
import { prisma } from "@/lib/prisma";
// Mutuelle exclusion theme-guyane / theme-aquarelle : activer l'un
// désactive automatiquement l'autre.
async function disableOtherTheme(currentKey: string): Promise<void> {
const other = currentKey === "theme-guyane" ? "theme-aquarelle" : "theme-guyane";
const row = await prisma.plugin.findUnique({ where: { key: other } });
if (row?.enabled) {
await prisma.plugin.update({
where: { key: other },
data: { enabled: false, lastDisabledAt: new Date() },
});
console.log(`[plugin ${currentKey}] désactive ${other} (mutual exclusion)`);
}
}
export const pluginHooks: Record<string, PluginHookSet | undefined> = {
"demo-carbets-seed": {
onEnable: async () => {
const { created, existing } = await seedDemoCarbets();
console.log(
`[plugin demo-carbets-seed] seed terminé : ${created} créés, ${existing} déjà présents`,
);
},
onDisable: async () => {
const archived = await archiveDemoCarbets();
console.log(
`[plugin demo-carbets-seed] disable : ${archived} carbets démo archivés`,
);
},
},
"content-pages": {
onEnable: async () => {
const seeded = await seedContentPages();
const republished = await republishContentPages();
console.log(
`[plugin content-pages] seed: ${seeded.created} pages, republished: ${republished}`,
);
},
onDisable: async () => {
const unpub = await unpublishContentPages();
console.log(`[plugin content-pages] disable: ${unpub} pages dépubliées`);
},
},
"legal-pages": {
onEnable: async () => {
const seeded = await seedLegalPages();
const republished = await republishLegalPages();
console.log(
`[plugin legal-pages] seed: ${seeded.created} pages, republished: ${republished}`,
);
},
onDisable: async () => {
const unpub = await unpublishLegalPages();
console.log(`[plugin legal-pages] disable: ${unpub} pages dépubliées`);
},
},
"pirogue-providers": {
onEnable: async () => {
const { providers, carbets } = await seedPirogueProviders();
console.log(
`[plugin pirogue-providers] seed: ${providers} partenaires, ${carbets} carbets attachés`,
);
},
onDisable: async () => {
const count = await deactivatePirogueProviders();
console.log(`[plugin pirogue-providers] disable: ${count} partenaires désactivés`);
},
},
// Quand i18n est activé, on seed les pages content + legal en EN.
// Désactiver n'efface pas les EN pages (elles dorment juste, fallback FR
// reprend la main au prochain getContentPage).
"i18n-fr-en": {
onEnable: async () => {
const count = await seedEnglishContentPages();
console.log(`[plugin i18n-fr-en] seed: ${count} pages EN`);
},
},
// Themes : mutuellement exclusifs (un seul actif à la fois).
"theme-guyane": {
onEnable: async () => {
await disableOtherTheme("theme-guyane");
},
},
"theme-aquarelle": {
onEnable: async () => {
await disableOtherTheme("theme-aquarelle");
},
},
};