feat(grid): display dynamic reference counts per gamme in filter bar

This commit is contained in:
Michael committed 2026-02-21 18:48:11 +01:00
1 parent a94489dd07
commit 9ef846a5d9
1 file changed
+44 -19
@@ -1,5 +1,6 @@
"use client"; "use client";
import React, { useMemo } from "react";
import { Search, X, ChevronDown } from "lucide-react"; import { Search, X, ChevronDown } from "lucide-react";
import { useGridStore } from "@/features/grid/store/use-grid-store"; import { useGridStore } from "@/features/grid/store/use-grid-store";
import { GammeCode } from "@/types/grid"; import { GammeCode } from "@/types/grid";
@@ -25,10 +26,25 @@ interface GridFilterBarProps {
} }
export function GridFilterBar({ fournisseurs, magasins, nomenclature }: GridFilterBarProps) { export function GridFilterBar({ fournisseurs, magasins, nomenclature }: GridFilterBarProps) {
const { filters, setFilter } = useGridStore(); const { filters, setFilter, rows, draftChanges } = useGridStore();
const router = useRouter(); const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
// Compute dynamic counts per Gamme
const gammeCounts = React.useMemo(() => {
const counts: Record<string, number> = { A: 0, B: 0, C: 0, Z: 0, Total: 0 };
rows.forEach(r => {
const effectiveGamme = draftChanges[r.codein] ?? r.codeGamme;
if (effectiveGamme && counts[effectiveGamme] !== undefined) {
counts[effectiveGamme]++;
}
if (effectiveGamme !== "Z") {
counts.Total++; // Active references (non-Z)
}
});
return counts;
}, [rows, draftChanges]);
const handleSupplierSelect = (code: string) => { const handleSupplierSelect = (code: string) => {
const params = new URLSearchParams(searchParams.toString()); const params = new URLSearchParams(searchParams.toString());
params.set("fournisseur", code); params.set("fournisseur", code);
@@ -88,24 +104,33 @@ export function GridFilterBar({ fournisseurs, magasins, nomenclature }: GridFilt
className="flex items-center gap-1 p-0.5 rounded-md" className="flex items-center gap-1 p-0.5 rounded-md"
style={{ background: "var(--bg-elevated)", border: "1px solid var(--border)" }} style={{ background: "var(--bg-elevated)", border: "1px solid var(--border)" }}
> >
{GAMME_FILTERS.map(({ label, value }) => ( {GAMME_FILTERS.map(({ label, value }) => {
<button const count = value === null ? rows.length : gammeCounts[value];
key={label} return (
onClick={() => setFilter("codeGamme", value)} <button
className={cn( key={label}
"px-2.5 py-1 text-[11px] font-semibold rounded-[4px] transition-colors", onClick={() => setFilter("codeGamme", value)}
filters.codeGamme === value className={cn(
? "shadow-sm" "flex items-center gap-1.5 px-2.5 py-1 text-[11px] font-semibold rounded-[4px] transition-colors",
: "hover:bg-[var(--bg-surface)]" filters.codeGamme === value
)} ? "shadow-sm"
style={{ : "hover:bg-[var(--bg-surface)]"
background: filters.codeGamme === value ? "var(--bg-surface)" : "transparent", )}
color: filters.codeGamme === value ? "var(--text-primary)" : "var(--text-secondary)", style={{
}} background: filters.codeGamme === value ? "var(--bg-surface)" : "transparent",
> color: filters.codeGamme === value ? "var(--text-primary)" : "var(--text-secondary)",
{label} }}
</button> >
))} <span>{label}</span>
<span
className="px-1.5 py-0.5 rounded-full text-[10px] bg-black/5 dark:bg-white/10"
style={{ color: filters.codeGamme === value ? "var(--text-primary)" : "var(--text-muted)" }}
>
{count}
</span>
</button>
);
})}
</div> </div>
{/* Nomenclature filter */} {/* Nomenclature filter */}