feat(credits): solde IA unique (option M), packs Stripe et polish billing
Un pot de crédits global (BASIC 100 / PRO 1 000 / BUSINESS 4 000) remplace les seaux par fonction côté débit. Packs one-shot S/M/L, admin sans seaux legacy, usage multi-features, hints de coût, anti-flash thème et hydratation admin. Inclut aussi le pipeline slides renforcé et la page publique polishée.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect } from 'react'
|
||||
import { applyDocumentTheme, normalizeThemeId } from '@/lib/apply-document-theme'
|
||||
import { useLayoutEffect } from 'react'
|
||||
import { applyDocumentTheme, normalizeThemeId, persistThemePreference } from '@/lib/apply-document-theme'
|
||||
|
||||
interface ThemeInitializerProps {
|
||||
theme?: string
|
||||
@@ -11,7 +11,10 @@ interface ThemeInitializerProps {
|
||||
}
|
||||
|
||||
export function ThemeInitializer({ theme, fontSize, fontFamily, accentColor }: ThemeInitializerProps) {
|
||||
useEffect(() => {
|
||||
// useLayoutEffect : avant le paint (useEffect = trop tard = flash clair)
|
||||
useLayoutEffect(() => {
|
||||
const root = document.documentElement
|
||||
|
||||
const applyFontSize = (s?: string) => {
|
||||
const size = s || 'medium'
|
||||
|
||||
@@ -29,25 +32,21 @@ export function ThemeInitializer({ theme, fontSize, fontFamily, accentColor }: T
|
||||
'extra-large': 1.25,
|
||||
}
|
||||
|
||||
const root = document.documentElement
|
||||
root.style.setProperty('--user-font-size', fontSizeMap[size] || '16px')
|
||||
root.style.setProperty('--user-font-size-factor', (fontSizeFactorMap[size] || 1).toString())
|
||||
}
|
||||
|
||||
// Préférence locale prioritaire (jamais écrasée par un rendu serveur « light »)
|
||||
const localTheme = localStorage.getItem('theme-preference')
|
||||
const effectiveTheme = localTheme || theme || 'light'
|
||||
const effectiveTheme = normalizeThemeId(localTheme || theme || 'light')
|
||||
|
||||
applyDocumentTheme(effectiveTheme)
|
||||
|
||||
if (!localTheme && theme) {
|
||||
localStorage.setItem('theme-preference', normalizeThemeId(theme))
|
||||
}
|
||||
// Persiste aussi le cookie pour les prochains rendus serveur (anti-flash navigation)
|
||||
persistThemePreference(effectiveTheme)
|
||||
|
||||
applyFontSize(fontSize)
|
||||
|
||||
const localFontFamily = localStorage.getItem('font-family')
|
||||
const effectiveFontFamily = localFontFamily || fontFamily || 'inter'
|
||||
const root = document.documentElement
|
||||
root.classList.remove('font-system', 'font-playfair', 'font-jetbrains')
|
||||
if (effectiveFontFamily === 'system') root.classList.add('font-system')
|
||||
if (effectiveFontFamily === 'playfair') root.classList.add('font-playfair')
|
||||
@@ -58,7 +57,7 @@ export function ThemeInitializer({ theme, fontSize, fontFamily, accentColor }: T
|
||||
|
||||
const localAccent = localStorage.getItem('accent-color')
|
||||
const effectiveAccent = localAccent || accentColor || '#A47148'
|
||||
document.documentElement.style.setProperty('--color-brand-accent', effectiveAccent)
|
||||
root.style.setProperty('--color-brand-accent', effectiveAccent)
|
||||
if (!localAccent && accentColor) {
|
||||
localStorage.setItem('accent-color', accentColor)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user