Aller au contenu principal

Interface Mode Client

Le mode client propose une navigation simplifiée par rapport au mode serveur.

┌─────────────────────────────────────────────────────────────────────────────┐
│ NAVIGATION MODE CLIENT │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ 🏠 Tableau de bord │ │
│ │ 📊 Consommation │ │
│ │ ├─ kWh │ │
│ │ └─ Euro │ │
│ │ ⚡ Production │ │
│ │ 📈 Bilan │ │
│ │ 🎁 Contribuer │ │
│ │ 🔴 Tempo │ │
│ │ 🟢 EcoWatt │ │
│ │ ─────────────────── │ │
│ │ 📤 Exporter ← NOUVEAU │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ Pages SUPPRIMÉES (vs mode serveur) : │
│ ✗ Page d'accueil (landing) │
│ ✗ Inscription / Connexion │
│ ✗ Administration │
│ ✗ Simulateur │
│ ✗ FAQ │
│ ✗ Paramètres avancés │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Différences par page​

Tableau de bord​

AspectMode ServeurMode Client
Source PDLBase locale + EnedisAPI MyElectricalData
Bouton syncActualiser cacheSynchroniser depuis API
Statut consentAffichéMasqué (géré côté serveur)
Actions PDLCRUD completLecture seule

Mode client : Affiche uniquement les PDL autorisés sur le compte MyElectricalData distant.

// Dashboard mode client
<Dashboard>
<Header>
<h1>Tableau de bord</h1>
<SyncButton onClick={syncFromApi}>
🔄 Synchroniser
</SyncButton>
</Header>

<LastSyncInfo>
Dernière synchronisation : {lastSync}
</LastSyncInfo>

<PDLGrid>
{pdls.map(pdl => (
<PDLCard key={pdl.id} pdl={pdl} readOnly />
))}
</PDLGrid>
</Dashboard>

Consommation (kWh)​

AspectMode ServeurMode Client
Source donnéesCache Valkey (24h)Base locale (indéfini)
Historique3 ans (journalier), 2 ans (courbe de charge)Tout ce que contient la base locale
PerformanceRequête Enedis si missToujours local

Mode client : Les données sont persistées indéfiniment. Pas de rechargement depuis Enedis. Les pages affichent tout l'historique local, y compris celui importé depuis la V1 (Migrer depuis la V1) : une carte, une barre et une courbe par année, sans plafond. Enedis n'est sollicité que dans sa fenêtre (3 ans de journalier, 2 ans de courbe de charge), pour combler les trous récents.

Consommation (Euro)​

AspectMode ServeurMode Client
Calcul prixTemps réelTemps réel
OffresScraping + adminConfiguration locale
Historique2 dernières années2 dernières années (offre actuelle, jours Tempo)

Mode client : Les offres tarifaires sont configurées localement ou récupérées depuis l'API.

Production​

Comportement identique à la consommation, avec stockage local indéfini.

Bilan​

Synthèse calculée à partir des données de la base locale.

Contribuer​

AspectMode ServeurMode Client
DestinationBase localeAPI MyElectricalData distante
ValidationImmédiateAprès envoi à l'API

Mode client : Les contributions sont envoyées vers l'API centrale pour bénéficier à la communauté.

Tempo​

AspectMode ServeurMode Client
SourceAPI RTE directeAPI MyElectricalData
StockageCache ValkeyBase locale
HistoriqueJ-1 à J+1Complet (années précédentes)

EcoWatt​

AspectMode ServeurMode Client
SourceAPI RTE directeAPI MyElectricalData
StockageCache ValkeyBase locale
AlertesTemps réelSelon sync

Exporter (NOUVEAU)​

Page exclusive au mode client pour configurer les destinations d'export.

Voir documentation détaillée.


Composants modifiés​

// Mode serveur
<Header>
<Logo />
<Navigation />
<UserMenu>
<Avatar />
<Dropdown>
<MenuItem>Profil</MenuItem>
<MenuItem>Paramètres</MenuItem>
<MenuItem>Déconnexion</MenuItem>
</Dropdown>
</UserMenu>
</Header>

// Mode client (simplifié)
<Header>
<Logo />
<Navigation />
<SyncStatus>
Dernière sync: {lastSync}
</SyncStatus>
</Header>
// Mode client - menu réduit
const clientMenuItems = [
{ path: '/dashboard', icon: Home, label: 'Tableau de bord' },
{ path: '/consumption', icon: Zap, label: 'Consommation', submenu: [
{ path: '/consumption', label: 'kWh' },
{ path: '/consumption/euro', label: 'Euro' },
]},
{ path: '/production', icon: Sun, label: 'Production' },
{ path: '/bilan', icon: BarChart, label: 'Bilan' },
{ path: '/contribute', icon: Gift, label: 'Contribuer' },
{ path: '/tempo', icon: Palette, label: 'Tempo' },
{ path: '/ecowatt', icon: Leaf, label: 'EcoWatt' },
{ type: 'separator' },
{ path: '/export', icon: Upload, label: 'Exporter' }, // NOUVEAU
];

PDLCard​

// Mode client - lecture seule
<PDLCard readOnly>
<PDLHeader>
<PDLName>{pdl.name}</PDLName>
<PDLId>{pdl.usage_point_id}</PDLId>
</PDLHeader>

<PDLStats>
<Stat label="Consommation" value={consumption} />
<Stat label="Production" value={production} />
</PDLStats>

{/* Pas de boutons d'édition/suppression */}
</PDLCard>

Routes​

Définition​

// apps/web/src/routes/client.tsx

import { createBrowserRouter, Navigate } from 'react-router-dom';

export const clientRouter = createBrowserRouter([
{
path: '/',
element: <ClientLayout />,
children: [
// Redirection racine → dashboard
{ index: true, element: <Navigate to="/dashboard" replace /> },

// Pages principales
{ path: 'dashboard', element: <Dashboard /> },
{ path: 'consumption', element: <ConsumptionKwh /> },
{ path: 'consumption/euro', element: <ConsumptionEuro /> },
{ path: 'production', element: <Production /> },
{ path: 'bilan', element: <Bilan /> },
{ path: 'contribute', element: <Contribute /> },
{ path: 'tempo', element: <Tempo /> },
{ path: 'ecowatt', element: <Ecowatt /> },
{ path: 'export', element: <Export /> },

// Catch-all → dashboard
{ path: '*', element: <Navigate to="/dashboard" replace /> },
],
},
]);

Comparaison​

MODE SERVEUR                    MODE CLIENT
──────────────────────── ────────────────────────
/ / → /dashboard (redirect)
/signup ✗
/login ✗
/oauth/callback ✗
/dashboard /dashboard
/consumption /consumption
/consumption/euro /consumption/euro
/production /production
/bilan /bilan
/contribute /contribute
/tempo /tempo
/ecowatt /ecowatt
/simulator ✗
/faq ✗
/settings ✗
/preferences ← période d'analyse
/admin/* ✗
/export ← NOUVEAU

État global (Zustand)​

Mode serveur​

// authStore - authentification complète
interface AuthState {
user: User | null;
token: string | null;
isAuthenticated: boolean;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
refreshToken: () => Promise<void>;
}

Mode client​

// syncStore - état de synchronisation
interface SyncState {
lastSync: Date | null;
isSyncing: boolean;
syncProgress: number;
syncError: string | null;
sync: () => Promise<void>;
}

// exportStore - configuration exports
interface ExportState {
configs: ExportConfig[];
logs: ExportLog[];
loadConfigs: () => Promise<void>;
saveConfig: (config: ExportConfig) => Promise<void>;
testConnection: (type: string) => Promise<boolean>;
runExport: (type: string) => Promise<void>;
}

Responsive​

Le mode client conserve le même comportement responsive que le mode serveur :

BreakpointSidebarLayout
< 768pxMasquée (hamburger)Mobile
768px - 1024pxIcônes seulesTablet
> 1024pxComplèteDesktop

Theme​

Le mode client supporte le dark mode avec les mêmes variables CSS.

/* Identique au mode serveur */
:root {
--primary-600: #0284c7;
--gray-800: #1f2937;
/* ... */
}

.dark {
--primary-600: #38bdf8;
--gray-800: #f3f4f6;
/* ... */
}

Build conditionnel​

Le frontend peut être buildé en mode client ou serveur :

# Build mode client (défaut)
npm run build

# Build mode serveur
VITE_SERVER_MODE=true npm run build

Le tree-shaking supprime automatiquement les composants non utilisés (admin, auth, etc.).