From bba6fe05e8a56f174d227c6d075d82dd973914bc Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Mon, 23 Mar 2026 14:13:39 +0100 Subject: [PATCH] feat: implement client-side grid orchestrator and core heatmap table component. --- src/features/grid/components/grid-client.tsx | 23 +++++++++++-------- src/features/grid/components/heatmap-grid.tsx | 3 +++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/features/grid/components/grid-client.tsx b/src/features/grid/components/grid-client.tsx index 3ce07d5..ec42798 100644 --- a/src/features/grid/components/grid-client.tsx +++ b/src/features/grid/components/grid-client.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useState, useTransition } from "react"; +import { useEffect, useRef, useState, useTransition } from "react"; import { HeatmapGrid } from "@/features/grid/components/heatmap-grid"; import { FloatingSummaryBar } from "@/features/grid/components/floating-summary-bar"; import { BulkActionToolbar } from "@/features/grid/components/bulk-action-toolbar"; @@ -51,19 +51,24 @@ export function GridClient({ initialRows, codeFournisseur, nomFournisseur, fourn setActiveGridQuery(currentQueryString ? `?${currentQueryString}` : ""); }, [searchParams, setActiveGridQuery, isMounted]); + // Réinitialiser les filtres UNIQUEMENT quand le fournisseur change + const prevFournisseurRef = useRef(null); useEffect(() => { if (!isMounted) return; - - // Réinitialiser les filtres gamme et code3 lors du changement de fournisseur. - // Ces filtres sont persistés en localStorage (Zustand persist) et s'appliquent - // au nouveau fournisseur, cachant toutes les lignes si le filtre ne correspond pas. - setFilter("codeGamme", null); - setFilter("code3", null); - + if (prevFournisseurRef.current !== codeFournisseur) { + setFilter("codeGamme", null); + setFilter("code3", null); + prevFournisseurRef.current = codeFournisseur; + } const scoredRows = computeProductScores([...initialRows]); setRows(scoredRows); + }, [codeFournisseur, initialRows, setRows, setFilter, isMounted]); + + // Synchroniser le magasin actif depuis la prop URL (changement de magasin sans rechargement) + useEffect(() => { + if (!isMounted) return; setActiveMagasin(magasin || "TOTAL"); - }, [codeFournisseur, initialRows, setRows, setFilter, setActiveMagasin, magasin, isMounted]); + }, [magasin, setActiveMagasin, isMounted]); const handleSave = () => { startTransition(async () => { diff --git a/src/features/grid/components/heatmap-grid.tsx b/src/features/grid/components/heatmap-grid.tsx index 7c421d8..6f5e103 100644 --- a/src/features/grid/components/heatmap-grid.tsx +++ b/src/features/grid/components/heatmap-grid.tsx @@ -468,6 +468,7 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) { })), { id: "totalQuantite", + accessorFn: (row: ProductRow) => activeMagasin === "TOTAL" ? row.totalQuantite : (row.quantiteByStore?.[activeMagasin] ?? 0), header: () =>
Tot. 12m
, size: 90, cell: ({ row }: { row: { original: ProductRow } }) => { @@ -487,6 +488,7 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) { }, { id: "totalCa", + accessorFn: (row: ProductRow) => activeMagasin === "TOTAL" ? row.totalCa : (row.caByStore?.[activeMagasin] ?? 0), header: () =>
CA
, size: 90, cell: ({ row }: { row: { original: ProductRow } }) => { @@ -502,6 +504,7 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) { }, { id: "totalMarge", + accessorFn: (row: ProductRow) => activeMagasin === "TOTAL" ? row.totalMarge : (row.margeByStore?.[activeMagasin] ?? 0), header: () =>
Marge
, size: 110, cell: ({ row }: { row: { original: ProductRow } }) => {