feat: implement client-side grid orchestrator and core heatmap table component.

This commit is contained in:
Michael committed 2026-03-23 14:13:39 +01:00
1 parent 53b85381fa
commit bba6fe05e8
2 files changed
+17 -9

No files matched your search

+14 -9
View File
@@ -1,6 +1,6 @@
"use client"; "use client";
import { useEffect, useState, useTransition } from "react"; import { useEffect, useRef, useState, useTransition } from "react";
import { HeatmapGrid } from "@/features/grid/components/heatmap-grid"; import { HeatmapGrid } from "@/features/grid/components/heatmap-grid";
import { FloatingSummaryBar } from "@/features/grid/components/floating-summary-bar"; import { FloatingSummaryBar } from "@/features/grid/components/floating-summary-bar";
import { BulkActionToolbar } from "@/features/grid/components/bulk-action-toolbar"; import { BulkActionToolbar } from "@/features/grid/components/bulk-action-toolbar";
@@ -51,19 +51,24 @@ export function GridClient({ initialRows, codeFournisseur, nomFournisseur, fourn
setActiveGridQuery(currentQueryString ? `?${currentQueryString}` : ""); setActiveGridQuery(currentQueryString ? `?${currentQueryString}` : "");
}, [searchParams, setActiveGridQuery, isMounted]); }, [searchParams, setActiveGridQuery, isMounted]);
// Réinitialiser les filtres UNIQUEMENT quand le fournisseur change
const prevFournisseurRef = useRef<string | null>(null);
useEffect(() => { useEffect(() => {
if (!isMounted) return; if (!isMounted) return;
if (prevFournisseurRef.current !== codeFournisseur) {
// Réinitialiser les filtres gamme et code3 lors du changement de fournisseur. setFilter("codeGamme", null);
// Ces filtres sont persistés en localStorage (Zustand persist) et s'appliquent setFilter("code3", null);
// au nouveau fournisseur, cachant toutes les lignes si le filtre ne correspond pas. prevFournisseurRef.current = codeFournisseur;
setFilter("codeGamme", null); }
setFilter("code3", null);
const scoredRows = computeProductScores([...initialRows]); const scoredRows = computeProductScores([...initialRows]);
setRows(scoredRows); 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"); setActiveMagasin(magasin || "TOTAL");
}, [codeFournisseur, initialRows, setRows, setFilter, setActiveMagasin, magasin, isMounted]); }, [magasin, setActiveMagasin, isMounted]);
const handleSave = () => { const handleSave = () => {
startTransition(async () => { startTransition(async () => {
@@ -468,6 +468,7 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
})), })),
{ {
id: "totalQuantite", id: "totalQuantite",
accessorFn: (row: ProductRow) => activeMagasin === "TOTAL" ? row.totalQuantite : (row.quantiteByStore?.[activeMagasin] ?? 0),
header: () => <div className="text-center w-full">Tot. 12m</div>, header: () => <div className="text-center w-full">Tot. 12m</div>,
size: 90, size: 90,
cell: ({ row }: { row: { original: ProductRow } }) => { cell: ({ row }: { row: { original: ProductRow } }) => {
@@ -487,6 +488,7 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
}, },
{ {
id: "totalCa", id: "totalCa",
accessorFn: (row: ProductRow) => activeMagasin === "TOTAL" ? row.totalCa : (row.caByStore?.[activeMagasin] ?? 0),
header: () => <div className="text-center w-full">CA</div>, header: () => <div className="text-center w-full">CA</div>,
size: 90, size: 90,
cell: ({ row }: { row: { original: ProductRow } }) => { cell: ({ row }: { row: { original: ProductRow } }) => {
@@ -502,6 +504,7 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
}, },
{ {
id: "totalMarge", id: "totalMarge",
accessorFn: (row: ProductRow) => activeMagasin === "TOTAL" ? row.totalMarge : (row.margeByStore?.[activeMagasin] ?? 0),
header: () => <div className="text-center w-full">Marge</div>, header: () => <div className="text-center w-full">Marge</div>,
size: 110, size: 110,
cell: ({ row }: { row: { original: ProductRow } }) => { cell: ({ row }: { row: { original: ProductRow } }) => {