diff --git a/DataSentinel/src/components/common/KpiCard.jsx b/DataSentinel/src/components/common/KpiCard.jsx new file mode 100644 index 0000000..c12f4f1 --- /dev/null +++ b/DataSentinel/src/components/common/KpiCard.jsx @@ -0,0 +1,10 @@ +import styles from './KpiCard.module.css'; + +export default function KpiCard({ label, value, color }) { + return ( +
+ {value} + {label} +
+ ); +} diff --git a/DataSentinel/src/components/common/KpiCard.module.css b/DataSentinel/src/components/common/KpiCard.module.css new file mode 100644 index 0000000..cf8ef75 --- /dev/null +++ b/DataSentinel/src/components/common/KpiCard.module.css @@ -0,0 +1,28 @@ +.kpiCard { + display: flex; + flex-direction: column; + align-items: center; + padding: 20px; + background: var(--color-white); + border-radius: var(--radius); + box-shadow: var(--shadow); +} + +.kpiValue { + font-size: 36px; + font-weight: 700; + line-height: 1; + margin-bottom: 6px; +} + +.kpiLabel { + font-size: 12px; + color: var(--color-muted, #888); + text-align: center; +} + +@media (max-width: 768px) { + .kpiValue { + font-size: 28px; + } +} diff --git a/DataSentinel/src/context/AuthContext.jsx b/DataSentinel/src/context/AuthContext.jsx index 931718e..aac8a26 100644 --- a/DataSentinel/src/context/AuthContext.jsx +++ b/DataSentinel/src/context/AuthContext.jsx @@ -2,16 +2,15 @@ import { createContext, useContext, useState } from 'react'; import * as api from '../services/api'; +import { USER_KEY } from '../services/api'; const AuthContext = createContext(null); -const STORAGE_KEY = 'ds_user'; - /* Fournisseur du contexte d'authentification */ export function AuthProvider({ children }) { const [user, setUser] = useState(() => { /* Restauration de la session depuis le localStorage au montage */ - const stored = localStorage.getItem(STORAGE_KEY); + const stored = localStorage.getItem(USER_KEY); return stored ? JSON.parse(stored) : null; }); @@ -19,7 +18,7 @@ export function AuthProvider({ children }) { async function login(username, password) { const connectedUser = await api.login(username, password); setUser(connectedUser); - localStorage.setItem(STORAGE_KEY, JSON.stringify(connectedUser)); + localStorage.setItem(USER_KEY, JSON.stringify(connectedUser)); return connectedUser; } @@ -27,7 +26,7 @@ export function AuthProvider({ children }) { function logout() { api.clearToken(); setUser(null); - localStorage.removeItem(STORAGE_KEY); + localStorage.removeItem(USER_KEY); } /* Booléen pratique pour savoir si l'utilisateur est connecté */ diff --git a/DataSentinel/src/hooks/useApi.js b/DataSentinel/src/hooks/useApi.js deleted file mode 100644 index 7239bb7..0000000 --- a/DataSentinel/src/hooks/useApi.js +++ /dev/null @@ -1,33 +0,0 @@ -/* Hook générique pour les appels API : retourne { data, loading, error, refetch } */ - -import { useState, useEffect, useCallback } from 'react'; - -/** - * @param {Function} fetchFn - Fonction async à appeler (depuis api.js) - * @param {Array} deps - Dépendances qui déclenchent un re-fetch (optionnel) - */ -export function useApi(fetchFn, deps = []) { - const [data, setData] = useState(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - const fetch = useCallback(async () => { - setLoading(true); - setError(null); - try { - const result = await fetchFn(); - setData(result); - } catch (err) { - setError(err.message || 'Une erreur est survenue.'); - } finally { - setLoading(false); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, deps); - - useEffect(() => { - fetch(); - }, [fetch]); - - return { data, loading, error, refetch: fetch }; -} diff --git a/DataSentinel/src/pages/Dashboard/Dashboard.jsx b/DataSentinel/src/pages/Dashboard/Dashboard.jsx index 79c30e2..979484a 100644 --- a/DataSentinel/src/pages/Dashboard/Dashboard.jsx +++ b/DataSentinel/src/pages/Dashboard/Dashboard.jsx @@ -4,20 +4,11 @@ import { useState, useEffect, useCallback, useMemo } from 'react'; import { RefreshCw } from 'lucide-react'; import { getDashboard, getDashboardSummary, getDashboardFiltres } from '../../services/api'; import MonitoringCard from '../../components/common/MonitoringCard'; +import KpiCard from '../../components/common/KpiCard'; import LoadingSpinner from '../../components/common/LoadingSpinner'; import ErrorMessage from '../../components/common/ErrorMessage'; import styles from './Dashboard.module.css'; -/* Carte KPI affichant un indicateur clé */ -function KpiCard({ label, value, color }) { - return ( -
- {value} - {label} -
- ); -} - export default function Dashboard() { const [summary, setSummary] = useState(null); const [monitorings, setMonitorings] = useState([]); diff --git a/DataSentinel/src/pages/Dashboard/Dashboard.module.css b/DataSentinel/src/pages/Dashboard/Dashboard.module.css index 4469834..7113e81 100644 --- a/DataSentinel/src/pages/Dashboard/Dashboard.module.css +++ b/DataSentinel/src/pages/Dashboard/Dashboard.module.css @@ -55,29 +55,6 @@ margin-bottom: 32px; } -.kpiCard { - display: flex; - flex-direction: column; - align-items: center; - padding: 20px; - background: var(--color-white); - border-radius: var(--radius); - box-shadow: var(--shadow); -} - -.kpiValue { - font-size: 36px; - font-weight: 700; - line-height: 1; - margin-bottom: 6px; -} - -.kpiLabel { - font-size: 12px; - color: var(--color-muted, #888); - text-align: center; -} - .filtres { display: flex; gap: 12px; @@ -131,10 +108,6 @@ gap: 10px; } - .kpiValue { - font-size: 28px; - } - .filtres { flex-direction: column; }