diff --git a/src/app/(dashboard)/grid/page.tsx b/src/app/(dashboard)/grid/page.tsx
index 3a064b9..2185bec 100644
--- a/src/app/(dashboard)/grid/page.tsx
+++ b/src/app/(dashboard)/grid/page.tsx
@@ -1,4 +1,4 @@
-import { getAvailableNomenclature, getFournisseurs, getGridData, getMagasins } from "@/features/grid/actions";
+import { getFournisseurs, getGridData, getMagasins } from "@/features/grid/actions";
import { GridClient } from "@/features/grid/components/grid-client";
import { SupplierSelectionLanding } from "@/features/grid/components/supplier-selection-landing";
@@ -22,11 +22,10 @@ export default async function GridPage({ searchParams }: GridPageProps) {
code3: params.code3 || null,
};
- // 1. Fetch available suppliers, stores & nomenclature hierarchy
- const [fournisseurs, magasins, nomenclature] = await Promise.all([
+ // 1. Fetch available suppliers & stores
+ const [fournisseurs, magasins] = await Promise.all([
getFournisseurs(),
getMagasins(),
- getAvailableNomenclature()
]);
// 2. If no supplier selected, show compact selection UI
@@ -48,7 +47,6 @@ export default async function GridPage({ searchParams }: GridPageProps) {
fournisseurs={fournisseurs}
magasins={magasins}
magasin={magasin}
- nomenclature={nomenclature}
/>
);
}
diff --git a/src/features/grid/components/grid-client.tsx b/src/features/grid/components/grid-client.tsx
index fa964a2..c9a1aae 100644
--- a/src/features/grid/components/grid-client.tsx
+++ b/src/features/grid/components/grid-client.tsx
@@ -22,10 +22,9 @@ interface GridClientProps {
fournisseurs: { code: string; nom: string }[];
magasins: { code: string; nom: string }[];
magasin: string;
- nomenclature: any; // Type defined in components if needed
}
-export function GridClient({ initialRows, nomFournisseur, fournisseurs, magasins, magasin, nomenclature }: GridClientProps) {
+export function GridClient({ initialRows, nomFournisseur, fournisseurs, magasins, magasin }: GridClientProps) {
const setRows = useGridStore((s) => s.setRows);
const setActiveGridQuery = useGridStore((s) => s.setActiveGridQuery);
const searchParams = useSearchParams();
@@ -121,7 +120,7 @@ export function GridClient({ initialRows, nomFournisseur, fournisseurs, magasins
{/* Filters */}
-
+
{/* Bulk toolbar (contextual) */}
diff --git a/src/features/grid/components/grid-filter-bar.tsx b/src/features/grid/components/grid-filter-bar.tsx
index d6c55e6..8ed494c 100644
--- a/src/features/grid/components/grid-filter-bar.tsx
+++ b/src/features/grid/components/grid-filter-bar.tsx
@@ -22,15 +22,25 @@ import { NomenclatureFilter } from "./nomenclature-filter";
interface GridFilterBarProps {
fournisseurs: { code: string; nom: string }[];
magasins: { code: string; nom: string }[];
- nomenclature: any;
}
-export function GridFilterBar({ fournisseurs, magasins, nomenclature }: GridFilterBarProps) {
+export function GridFilterBar({ fournisseurs, magasins }: GridFilterBarProps) {
const { filters, setFilter, rows, draftChanges } = useGridStore();
const router = useRouter();
const searchParams = useSearchParams();
const [isRefreshing, setIsRefreshing] = React.useState(false);
+ // Options nomenclature (famille) construites depuis les rows chargées
+ const code3Options = useMemo(() => {
+ const map = new Map();
+ rows.forEach(r => {
+ if (r.code3 && r.libelle3) map.set(r.code3, r.libelle3);
+ });
+ return Array.from(map.entries())
+ .map(([code, label]) => ({ code, label }))
+ .sort((a, b) => a.code.localeCompare(b.code, undefined, { numeric: true }));
+ }, [rows]);
+
// Compute dynamic counts and present Gammes
const { gammeCounts, activeGammes } = React.useMemo(() => {
const counts: Record = { Total: 0 };
@@ -195,7 +205,7 @@ export function GridFilterBar({ fournisseurs, magasins, nomenclature }: GridFilt
{/* Nomenclature filter */}
-
+
);
}
diff --git a/src/features/grid/components/heatmap-grid.tsx b/src/features/grid/components/heatmap-grid.tsx
index 2a43bb0..79700a0 100644
--- a/src/features/grid/components/heatmap-grid.tsx
+++ b/src/features/grid/components/heatmap-grid.tsx
@@ -178,7 +178,23 @@ GridRow.displayName = "GridRow";
export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
// L'abonnement doit être minimal ici ! PAS de draftChanges ni de setDraftGamme.
- const { rows, filters, displayDensity } = useGridStore();
+ const { rows, filters, displayDensity, draftChanges } = useGridStore();
+
+ // Filtre client-side par code3 (famille) et codeGamme
+ const filteredData = useMemo(() => {
+ const { code3, codeGamme } = filters;
+ if (!code3 && !codeGamme) return rows;
+ return rows.filter(r => {
+ if (code3 && r.code3 !== code3) return false;
+ if (codeGamme) {
+ const g = draftChanges[r.codein] ?? r.codeGamme ?? "";
+ const norm = g.trim() === "" ? "Aucune" : g;
+ if (norm !== codeGamme) return false;
+ }
+ return true;
+ });
+ }, [rows, filters, draftChanges]);
+
const [sorting, setSorting] = useState([]);
const [rowSelection, setRowSelection] = useState({});
const { columnVisibility, setColumnVisibility, columnSizing, setColumnSizing } = useGridStore();
@@ -351,12 +367,17 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
{
accessorKey: "libelle3",
header: "Famille",
- size: 160,
- cell: ({ getValue }) => (
-
- {getValue()}
-
- ),
+ size: 200,
+ cell: ({ row }) => {
+ const code = row.original.code3;
+ const label = row.original.libelle3;
+ const display = code && label ? `${code} — ${label}` : (label || code || "");
+ return (
+
+ {display}
+
+ );
+ },
},
{
accessorKey: "score",
@@ -452,7 +473,7 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
], [MONTHS_12]); // Dépendances extrêmement stables : pas de re-render du header !
const table = useReactTable({
- data: rows,
+ data: filteredData,
columns,
state: { sorting, globalFilter: filters.search, rowSelection, columnVisibility, columnSizing },
onSortingChange: setSorting,
diff --git a/src/features/grid/components/nomenclature-filter.tsx b/src/features/grid/components/nomenclature-filter.tsx
index 459648e..dbc997a 100644
--- a/src/features/grid/components/nomenclature-filter.tsx
+++ b/src/features/grid/components/nomenclature-filter.tsx
@@ -1,67 +1,18 @@
"use client";
import * as React from "react";
-import { useRouter, useSearchParams } from "next/navigation";
import { cn } from "@/lib/utils";
import { ChevronDown, Filter } from "lucide-react";
+import { useGridStore } from "@/features/grid/store/use-grid-store";
interface NomenclatureFilterProps {
- hierarchy: any;
+ options: { code: string; label: string }[];
className?: string;
}
-export function NomenclatureFilter({ hierarchy, className }: NomenclatureFilterProps) {
- const router = useRouter();
- const searchParams = useSearchParams();
-
- const selected1 = searchParams.get("code1");
- const selected2 = searchParams.get("code2");
- const selected3 = searchParams.get("code3");
-
- // Valeur composite pour le select : "type:code"
- const currentValue = selected3 ? `code3:${selected3}` :
- selected2 ? `code2:${selected2}` :
- selected1 ? `code1:${selected1}` : "";
-
- const updateFilter = (value: string) => {
- const params = new URLSearchParams(searchParams.toString());
-
- // Reset all nomenclature filters
- params.delete("code1");
- params.delete("code2");
- params.delete("code3");
-
- if (value) {
- const [type, code] = value.split(":");
- params.set(type, code);
- }
-
- router.push(`/grid?${params.toString()}`);
- };
-
- // Aplatir la hiérarchie pour le menu unique et trier par code
- const options: { label: string; value: string; level: number; code: string }[] = [];
-
- // Sort Secteurs
- const sortedSecteurs = Object.entries(hierarchy).sort((a, b) => a[0].localeCompare(b[0], undefined, { numeric: true }));
-
- sortedSecteurs.forEach(([c1, s]: [string, any]) => {
- options.push({ label: s.label, value: `code1:${c1}`, level: 0, code: c1 });
-
- // Sort Rayons
- const sortedRayons = Object.entries(s.children).sort((a, b) => a[0].localeCompare(b[0], undefined, { numeric: true }));
-
- sortedRayons.forEach(([c2, r]: [string, any]) => {
- options.push({ label: r.label, value: `code2:${c2}`, level: 1, code: c2 });
-
- // Sort Familles
- const sortedFamilles = [...r.children].sort((a, b) => a.code.localeCompare(b.code, undefined, { numeric: true }));
-
- sortedFamilles.forEach((f: any) => {
- options.push({ label: f.label, value: `code3:${f.code}`, level: 2, code: f.code });
- });
- });
- });
+export function NomenclatureFilter({ options, className }: NomenclatureFilterProps) {
+ const code3 = useGridStore((s) => s.filters.code3);
+ const setFilter = useGridStore((s) => s.setFilter);
return (
@@ -70,19 +21,15 @@ export function NomenclatureFilter({ hierarchy, className }: NomenclatureFilterP