expria-frontend/src/features/progression/pages/ProgressionPage.tsx
Hermann_Kitio b68f160bce feat(design-system): reskin Charcoal — tokens dark-default + sidebar navy permanent
- Remplacement intégral index.css par palette Charcoal (DESIGN_SYSTEM.md v2.0)
- Dark = thème par défaut, .light = override via @custom-variant light
- Sidebar navy #0C1528 permanent (identique dark+light)
- Script anti-FOUC inline dans index.html
- Layout : radial-gradient sur <main>, sidebar 230px, max-w-[1100px]
- Renommage tokens Boréal→Charcoal sur ~45 composants
- Inversion dark: → baseline + light: sur primitives shadcn
- Fix logo blanc forcé dans sidebar
- ADR 006 mis à jour

Typecheck: OK · Tests: 122/122 

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 23:09:15 +03:00

73 lines
2.7 KiB
TypeScript

/**
* Page /progression — Sprint 3.6c.
*
* Gating plan via `hasAccess(plan, 'pattern_analysis')` :
* - Free + Standard → `BlurredProgression` (aperçu flouté + CTA upgrade)
* - Premium → `ProgressionPremium` (NotReady ou contenu complet)
*
* Règle D : aucun `plan === 'xxx'` — tout passe par hasAccess().
* Règle L : tokens Direction H exclusivement.
*/
import { useNavigate } from 'react-router-dom'
import { Card } from '@/shared/ui/Card'
import { Button } from '@/shared/ui/Button'
import { hasAccess } from '@/entities/user/lib'
import { usePlan } from '@/features/dashboard/hooks/usePlan'
import { usePatterns } from '../hooks/usePatterns'
import { BlurredProgression } from '../components/BlurredProgression'
import { ProgressionPremium } from '../components/ProgressionPremium'
function Skeleton() {
return (
<div className="space-y-4" aria-busy="true" aria-label="Chargement de votre profil…">
<div className="h-32 animate-pulse rounded-lg bg-surface" />
<div className="h-24 animate-pulse rounded-lg bg-surface" />
<div className="h-48 animate-pulse rounded-lg bg-surface" />
</div>
)
}
export function ProgressionPage() {
const navigate = useNavigate()
const { data: planData, isLoading: isPlanLoading } = usePlan()
const { data: patternsData, isLoading: isPatternsLoading, isError } = usePatterns(planData?.plan)
const isPremium = planData ? hasAccess(planData.plan, 'pattern_analysis') : false
return (
<main className="mx-auto max-w-3xl space-y-6 px-4 py-6">
<header className="space-y-1">
<h1 className="text-lg font-semibold text-ink-primary">Profil de préparation</h1>
<p className="text-sm text-ink-secondary">
Repérez vos erreurs récurrentes et travaillez-les avec des exercices ciblés.
</p>
</header>
{isPlanLoading && <Skeleton />}
{!isPlanLoading && planData && !isPremium && (
<BlurredProgression onUpgrade={() => navigate('/plan')} />
)}
{!isPlanLoading && planData && isPremium && (
<>
{isPatternsLoading && <Skeleton />}
{isError && (
<Card variant="default" className="border-l-4 border-l-danger p-4">
<p className="text-sm text-danger" role="alert">
Impossible de charger votre profil de préparation. Réessayez dans quelques instants.
</p>
<div className="mt-3">
<Button variant="secondary" size="sm" onClick={() => navigate(0)}>
Rafraîchir
</Button>
</div>
</Card>
)}
{patternsData && <ProgressionPremium data={patternsData} />}
</>
)}
</main>
)
}