diff --git a/src/app/(dashboard)/settings/page.tsx b/src/app/(dashboard)/settings/page.tsx index 03e6341..daf3849 100644 --- a/src/app/(dashboard)/settings/page.tsx +++ b/src/app/(dashboard)/settings/page.tsx @@ -59,6 +59,8 @@ export default function SettingsPage() { const [selectedModel, setSelectedModel] = useState("google/gemini-flash-1.5"); const [modelsStatus, setModelsStatus] = useState<"idle" | "loading" | "ok" | "error">("idle"); + const [isMounted, setIsMounted] = useState(false); + const { host, setHost, port, setPort, @@ -70,10 +72,27 @@ export default function SettingsPage() { } = useDbSettingsStore(); useEffect(() => { - // Optionnel : On pourrait charger la config serveur au montage si on veut écraser le localStorage - // Pour l'instant on laisse le localStorage faire son travail, mais on offre une fonction de reset + setIsMounted(true); }, []); + const fetchModels = useCallback(async (key: string) => { + if (!key.trim()) return; + setModelsStatus("loading"); + try { + const res = await fetch("/api/openrouter/models", { headers: { "x-openrouter-key": key } }); + if (!res.ok) throw new Error(); + const data = await res.json(); + setModels(data.models ?? []); + setModelsStatus("ok"); + } catch { + setModelsStatus("error"); + } + }, []); + + if (!isMounted) { + return null; + } + const reloadFromServer = async () => { const config = await getSavedDatabaseConfig(); if (config && config.url) { @@ -92,20 +111,6 @@ export default function SettingsPage() { } }; - const fetchModels = useCallback(async (key: string) => { - if (!key.trim()) return; - setModelsStatus("loading"); - try { - const res = await fetch("/api/openrouter/models", { headers: { "x-openrouter-key": key } }); - if (!res.ok) throw new Error(); - const data = await res.json(); - setModels(data.models ?? []); - setModelsStatus("ok"); - } catch { - setModelsStatus("error"); - } - }, []); - const testDb = async () => { setDbStatus("testing"); setDbError(null); diff --git a/src/features/grid/components/grid-client.tsx b/src/features/grid/components/grid-client.tsx index ba3b176..be0a9fb 100644 --- a/src/features/grid/components/grid-client.tsx +++ b/src/features/grid/components/grid-client.tsx @@ -22,7 +22,7 @@ interface GridClientProps { magasin: string; } -export function GridClient({ initialRows, codeFournisseur, nomFournisseur, fournisseurs, magasins, magasin }: GridClientProps) { +export function GridClient({ initialRows, nomFournisseur, fournisseurs, magasins, magasin }: GridClientProps) { const setRows = useGridStore((s) => s.setRows); const seuilAxeFort = useScoreSettingsStore((s) => s.seuilAxeFort); const bonusParAxe = useScoreSettingsStore((s) => s.bonusParAxe); @@ -32,12 +32,20 @@ export function GridClient({ initialRows, codeFournisseur, nomFournisseur, fourn const [saveStatus, setSaveStatus] = useState<"idle" | "success" | "error">("idle"); const { save, hasDrafts, count } = useSaveDrafts(magasin); + const [isMounted, setIsMounted] = useState(false); + useEffect(() => { + // eslint-disable-next-line react-hooks/set-state-in-effect + setIsMounted(true); + }, []); + + useEffect(() => { + if (!isMounted) return; // Deep clone to avoid mutating the React prop directly across re-renders const rowsCopy = JSON.parse(JSON.stringify(initialRows)); const scoredRows = computeProductScores(rowsCopy, { seuilAxeFort, bonusParAxe }); setRows(scoredRows); - }, [initialRows, setRows, seuilAxeFort, bonusParAxe]); + }, [initialRows, setRows, seuilAxeFort, bonusParAxe, isMounted]); const handleSave = () => { startTransition(async () => { @@ -47,6 +55,10 @@ export function GridClient({ initialRows, codeFournisseur, nomFournisseur, fourn }); }; + if (!isMounted) { + return
Initialisation de la grille...
; + } + const activeStoreNom = magasins.find(m => m.code === magasin)?.nom || "National (Total)"; return (