diff --git a/src/features/grid/components/heatmap-cell.tsx b/src/features/grid/components/heatmap-cell.tsx
index 4d49e65..359e3ba 100644
--- a/src/features/grid/components/heatmap-cell.tsx
+++ b/src/features/grid/components/heatmap-cell.tsx
@@ -4,6 +4,7 @@ interface HeatmapCellProps {
value: number | null;
tooltipStock?: number | null;
tooltipReceptions?: number | null;
+ onClick?: (e: React.MouseEvent) => void;
}
function getHeatmapClass(value: number | null): string {
@@ -15,7 +16,7 @@ function getHeatmapClass(value: number | null): string {
return "heatmap-zero";
}
-export const HeatmapCell = React.memo(({ value, tooltipStock, tooltipReceptions }: HeatmapCellProps) => {
+export const HeatmapCell = React.memo(({ value, tooltipStock, tooltipReceptions, onClick }: HeatmapCellProps) => {
const heatClass = getHeatmapClass(value);
const display = value === null || value === 0 ? "0" : Math.round(Math.abs(value)).toString();
@@ -28,8 +29,9 @@ export const HeatmapCell = React.memo(({ value, tooltipStock, tooltipReceptions
return (
{display}
diff --git a/src/features/grid/components/heatmap-grid.tsx b/src/features/grid/components/heatmap-grid.tsx
index 21328bc..71edc58 100644
--- a/src/features/grid/components/heatmap-grid.tsx
+++ b/src/features/grid/components/heatmap-grid.tsx
@@ -13,7 +13,7 @@ import {
RowSelectionState,
} from "@tanstack/react-table";
import { useVirtualizer } from "@tanstack/react-virtual";
-import { ChevronUp, ChevronDown, ChevronsUpDown, Copy, Check, Store, SlidersHorizontal } from "lucide-react";
+import { ChevronUp, ChevronDown, ChevronsUpDown, Copy, Check, Store, SlidersHorizontal, ShoppingCart, PackageOpen, Warehouse } from "lucide-react";
import {
DropdownMenu,
DropdownMenuCheckboxItem,
@@ -21,6 +21,7 @@ import {
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { useGridStore } from "@/features/grid/store/use-grid-store";
+import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { GammeSelect } from "@/features/grid/components/gamme-select";
import { HeatmapCell } from "@/features/grid/components/heatmap-cell";
import type { ProductRow, GammeCode } from "@/types/grid";
@@ -180,6 +181,72 @@ const GridRow = React.memo(({ virtualRow, row, rowHeight, isSelected, columnVisi
});
GridRow.displayName = "GridRow";
+// =========================================================================
+// Composant modal pour le détail d'une cellule mensuelle
+// =========================================================================
+
+interface CellDetailData {
+ row: ProductRow;
+ monthKey: string;
+ qty: number | null;
+ stock: number | null;
+ receptions: number | null;
+}
+
+function CellDetailModal({ d, activeMagasin, onClose }: { d: CellDetailData; activeMagasin: string; onClose: () => void }) {
+ const hasReceptions = (d.receptions ?? 0) > 0;
+ const storeLabel = activeMagasin === "TOTAL" ? "Total réseau" : (SITE_LABELS[activeMagasin]?.nom ?? activeMagasin);
+
+ return (
+
+
+
+ {d.row.libelle1}
+
+
+ {formatMonthLabel(d.monthKey)}{" · "}
+ {storeLabel}
+
+
+
+
+ {/* Ventes */}
+
+
+
+ {d.qty != null ? Math.round(d.qty).toLocaleString("fr-FR") : "—"}
+
+ Ventes
+
+
+ {/* Entrées */}
+
+
+
+ {hasReceptions ? `+${Math.round(d.receptions!).toLocaleString("fr-FR")}` : "—"}
+
+
Entrées
+
+
+ {/* Stock fin de mois */}
+
+
+
+ {d.stock != null ? Math.round(d.stock).toLocaleString("fr-FR") : "—"}
+
+ Stock fin mois
+
+
+
+ );
+}
+
// =========================================================================
export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
@@ -206,6 +273,9 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
const { columnVisibility, setColumnVisibility, columnSizing, setColumnSizing } = useGridStore();
const [isMounted, setIsMounted] = useState(false);
const [portalContainer, setPortalContainer] = useState(null);
+
+ // État pour le détail d'une cellule mensuelle (modal)
+ const [cellDetail, setCellDetail] = useState(null);
const tableContainerRef = useRef(null);
// Calculer les mois dynamiquement pour éviter le mismatch entre serveur et client
@@ -466,7 +536,17 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
const receptions = activeMagasin === "TOTAL"
? (row.original.receptions12m[monthKey] ?? null)
: (row.original.receptions12mByStore?.[activeMagasin]?.[monthKey] ?? null);
- return ;
+ return (
+ {
+ e.stopPropagation();
+ setCellDetail({ row: row.original, monthKey, qty, stock, receptions });
+ }}
+ />
+ );
},
})),
{
@@ -611,6 +691,7 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
}
return (
+ <>
{portalContainer && createPortal(
@@ -733,5 +814,11 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
+
+ {/* Modal détail cellule mensuelle */}
+
+ >
);
}