From baebf50d7a036e0f0ae839fe2d790abe0ed23a6c Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Fri, 6 Mar 2026 11:04:14 +0100 Subject: [PATCH] feat: implement new DropdownMenu UI component and create tsc-errors.txt to log existing TypeScript compilation issues. --- src/components/ui/dropdown-menu.tsx | 257 ++++++++++++++++++ src/features/grid/components/heatmap-grid.tsx | 2 +- verify-fix.ts | 27 -- verify-parser.ts | 55 ---- 4 files changed, 258 insertions(+), 83 deletions(-) create mode 100644 src/components/ui/dropdown-menu.tsx delete mode 100644 verify-fix.ts delete mode 100644 verify-parser.ts diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..ae1fcf6 --- /dev/null +++ b/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,257 @@ +"use client" + +import * as React from "react" +import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" +import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui" + +import { cn } from "@/lib/utils" + +function DropdownMenu({ + ...props +}: React.ComponentProps) { + return +} + +function DropdownMenuPortal({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuContent({ + className, + sideOffset = 4, + ...props +}: React.ComponentProps) { + return ( + + + + ) +} + +function DropdownMenuGroup({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuItem({ + className, + inset, + variant = "default", + ...props +}: React.ComponentProps & { + inset?: boolean + variant?: "default" | "destructive" +}) { + return ( + + ) +} + +function DropdownMenuCheckboxItem({ + className, + children, + checked, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ) +} + +function DropdownMenuRadioGroup({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuRadioItem({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ) +} + +function DropdownMenuLabel({ + className, + inset, + ...props +}: React.ComponentProps & { + inset?: boolean +}) { + return ( + + ) +} + +function DropdownMenuSeparator({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuShortcut({ + className, + ...props +}: React.ComponentProps<"span">) { + return ( + + ) +} + +function DropdownMenuSub({ + ...props +}: React.ComponentProps) { + return +} + +function DropdownMenuSubTrigger({ + className, + inset, + children, + ...props +}: React.ComponentProps & { + inset?: boolean +}) { + return ( + + {children} + + + ) +} + +function DropdownMenuSubContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + DropdownMenu, + DropdownMenuPortal, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuLabel, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuSub, + DropdownMenuSubTrigger, + DropdownMenuSubContent, +} diff --git a/src/features/grid/components/heatmap-grid.tsx b/src/features/grid/components/heatmap-grid.tsx index ff02eae..29e9a49 100644 --- a/src/features/grid/components/heatmap-grid.tsx +++ b/src/features/grid/components/heatmap-grid.tsx @@ -493,7 +493,7 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) { className="capitalize text-xs cursor-pointer" checked={column.getIsVisible()} onCheckedChange={(value) => column.toggleVisibility(!!value)} - onSelect={(e: React.SyntheticEvent) => e.preventDefault()} + onSelect={(e: Event) => e.preventDefault()} > {typeof column.columnDef.header === 'string' ? column.columnDef.header diff --git a/verify-fix.ts b/verify-fix.ts deleted file mode 100644 index df94216..0000000 --- a/verify-fix.ts +++ /dev/null @@ -1,27 +0,0 @@ - -import { ScoringEngine } from "../src/features/ai-copilot/business/scoring-engine"; -import { ProductAnalysisInput } from "../src/features/ai-copilot/models/ai-analysis.types"; - -const mockProducts: ProductAnalysisInput[] = [ - { codein: "PROD1", libelle1: "Nouveau Récent", regularityScore: 1, inactivityMonths: 0, totalCa: 100, totalQuantite: 10, tauxMarge: 30, score: 50, storeCount: 1, sales12m: {} }, - { codein: "PROD2", libelle1: "Nouveau Ancien", regularityScore: 1, inactivityMonths: 6, totalCa: 100, totalQuantite: 10, tauxMarge: 30, score: 50, storeCount: 1, sales12m: {} }, - { codein: "PROD3", libelle1: "Ancien Actif", regularityScore: 12, inactivityMonths: 0, totalCa: 1000, totalQuantite: 100, tauxMarge: 30, score: 50, storeCount: 1, sales12m: {} }, - { codein: "PROD4", libelle1: "Nouveau Limite", regularityScore: 2, inactivityMonths: 1, totalCa: 100, totalQuantite: 10, tauxMarge: 30, score: 50, storeCount: 1, sales12m: {} }, - { codein: "PROD5", libelle1: "Nouveau Hors Limite", regularityScore: 2, inactivityMonths: 2, totalCa: 100, totalQuantite: 10, tauxMarge: 30, score: 50, storeCount: 1, sales12m: {} }, -]; - -console.log("--- Testing isRecent Logic ---"); - -mockProducts.forEach(p => { - const result = ScoringEngine.analyzeRayon(p, mockProducts); - console.log(`Product: ${p.libelle1} (reg: ${p.regularityScore}, inact: ${p.inactivityMonths})`); - console.log(` isRecent: ${result.decision.isRecent}`); - console.log(` Recommendation: ${result.decision.recommendation}`); -}); - -// Expectations: -// PROD1: true (1 < 3 && 0 <= 1) -// PROD2: false (1 < 3 && 6 > 1) -> Recommendation should NOT be protected (unless score high) -// PROD3: false (12 >= 3) -// PROD4: true (2 < 3 && 1 <= 1) -// PROD5: false (2 < 3 && 2 > 1) diff --git a/verify-parser.ts b/verify-parser.ts deleted file mode 100644 index f6e7299..0000000 --- a/verify-parser.ts +++ /dev/null @@ -1,55 +0,0 @@ - -import { AnalysisEngine } from "./src/features/ai-copilot/business/analysis-engine"; - -console.log("--- Testing AI Parser Logic for B/C ---"); - -function simulateParse(content: string, simulateRuleResponse = false) { - let reco: "A" | "B" | "C" | "Z" | null = null; - let ruleApplies = simulateRuleResponse; - - try { - const jsonMatch = content.match(/\{[\s\S]*\}/); - const jsonText = jsonMatch ? jsonMatch[0] : content; - const parsed = JSON.parse(jsonText); - - reco = parsed.recommendation as "A" | "B" | "C" | "Z"; - ruleApplies = parsed.rule_applies === true; - - if (!ruleApplies && (reco === "B" || reco === "C")) reco = "A"; - - if (!reco || !["A", "B", "C", "Z"].includes(reco)) { - reco = AnalysisEngine.extractRecommendation(parsed.justification || "") || "A"; - if (!ruleApplies && (reco === "B" || reco === "C")) reco = "A"; - } - } catch (e) { - reco = AnalysisEngine.extractRecommendation(content); - if (!ruleApplies && (reco === "B" || reco === "C")) reco = "A"; - } - return reco; -} - -const tests = [ - { name: "Valid Rule B", json: '{"rule_applies": true, "recommendation": "B", "justification": "blabla"}', expected: "B" }, - { name: "Valid Rule C", json: '{"rule_applies": true, "recommendation": "C", "justification": "blabla"}', expected: "C" }, - { name: "Invalid Rule B (hallucinated)", json: '{"rule_applies": false, "recommendation": "B", "justification": "blabla"}', expected: "A" }, - { name: "Invalid Rule C (hallucinated)", json: '{"rule_applies": false, "recommendation": "C", "justification": "blabla"}', expected: "A" }, - { name: "Valid Rule A", json: '{"rule_applies": true, "recommendation": "A", "justification": "blabla"}', expected: "A" }, - { name: "Valid Extraction B", json: '{"rule_applies": true, "recommendation": "INVALID", "justification": "Je choisis B."}', expected: "B" }, - { name: "Invalid Extraction B", json: '{"rule_applies": false, "recommendation": "INVALID", "justification": "Je choisis B."}', expected: "A" } -]; - -let allPassed = true; -tests.forEach(t => { - const res = simulateParse(t.json); - const pass = res === t.expected; - console.log(`${pass ? "✅" : "❌"} ${t.name}: expected ${t.expected}, got ${res}`); - if (!pass) allPassed = false; -}); - -if (allPassed) { - console.log("All parsing tests passed."); - process.exit(0); -} else { - console.log("Some tests failed."); - process.exit(1); -}