feat: add NoSalesTab component to display products without sales in the last 6 months

This commit is contained in:
Michael committed 2026-04-14 12:45:21 +02:00
1 parent 687009dba1
commit 6492f93bf4
4 files changed
+364 -19

No files matched your search

+64 -18
View File
@@ -1,11 +1,12 @@
"use client";
import { useEffect, useRef, useState, useTransition, useCallback } from "react";
import { useEffect, useRef, useState, useTransition, useCallback, useMemo } 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";
import { GridFilterBar } from "@/features/grid/components/grid-filter-bar";
import { ExportDropdown } from "@/features/grid/components/export-dropdown";
import { NoSalesTab, countNoSalesIn6Months } from "@/features/grid/components/no-sales-tab";
import { useGridStore } from "@/features/grid/store/use-grid-store";
import { useSaveDrafts } from "@/features/grid/hooks/use-save-drafts";
import { useInfiniteGrid } from "@/features/grid/hooks/use-infinite-grid";
@@ -38,6 +39,9 @@ export function GridClient({ initialRows, initialTotal, codeFournisseur, nomFour
const [selectedCodeins, setSelectedCodeins] = useState<string[]>([]);
const [isPending, startTransition] = useTransition();
const [saveStatus, setSaveStatus] = useState<"idle" | "success" | "error">("idle");
const [activeTab, setActiveTab] = useState<"grid" | "no-sales">("grid");
const noSalesCount = useMemo(() => countNoSalesIn6Months(rows), [rows]);
const visibleCodeins = initialRows.map(r => r.codein);
const { save, hasDrafts, count } = useSaveDrafts(magasin, visibleCodeins);
@@ -181,26 +185,68 @@ export function GridClient({ initialRows, initialTotal, codeFournisseur, nomFour
<GridFilterBar fournisseurs={fournisseurs} magasins={magasins} />
</div>
{/* Bulk toolbar (contextual) */}
<div className="shrink-0 print:hidden">
<BulkActionToolbar
selectedCodeins={selectedCodeins}
onClearSelection={() => setSelectedCodeins([])}
/>
{/* Tab switcher */}
<div className="shrink-0 flex gap-0 print:hidden" style={{ borderBottom: "1px solid var(--border)" }}>
{(["grid", "no-sales"] as const).map(tab => {
const isActive = activeTab === tab;
return (
<button
key={tab}
onClick={() => setActiveTab(tab)}
className="flex items-center gap-1.5 px-4 py-2 text-[13px] font-medium transition-colors"
style={{
color: isActive ? "var(--text-primary)" : "var(--text-muted)",
borderBottom: isActive ? "2px solid var(--accent)" : "2px solid transparent",
marginBottom: "-1px",
}}
>
{tab === "grid" ? "Assortiment" : "Sans vente 6 mois"}
{tab === "no-sales" && noSalesCount > 0 && (
<span className="inline-flex items-center justify-center min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-bold"
style={{
background: isActive ? "var(--accent)" : "var(--bg-elevated)",
color: isActive ? "white" : "var(--text-secondary)",
border: "1px solid var(--border)",
}}
>
{noSalesCount}
</span>
)}
</button>
);
})}
</div>
{/* Main grid */}
<div className="flex-1 min-h-0 min-w-0">
<HeatmapGrid
onSelectionChange={setSelectedCodeins}
isAdmin={isAdmin}
/>
</div>
{/* Bulk toolbar (contextual) — uniquement sur l'onglet grille */}
{activeTab === "grid" && (
<div className="shrink-0 print:hidden">
<BulkActionToolbar
selectedCodeins={selectedCodeins}
onClearSelection={() => setSelectedCodeins([])}
/>
</div>
)}
{/* Summary bar */}
<div className="print:hidden">
<FloatingSummaryBar />
</div>
{/* Main content */}
{activeTab === "grid" ? (
<div className="flex-1 min-h-0 min-w-0">
<HeatmapGrid
onSelectionChange={setSelectedCodeins}
isAdmin={isAdmin}
/>
</div>
) : (
<div className="flex-1 min-h-0 min-w-0 flex flex-col">
<NoSalesTab />
</div>
)}
{/* Summary bar — uniquement sur l'onglet grille */}
{activeTab === "grid" && (
<div className="print:hidden">
<FloatingSummaryBar />
</div>
)}
</div>
);
}