VSN-2861 — BPU : étape « Règles tarifaires » (catalogue de variables, configs partagées, aperçu tarifaire)
Architecture & Navigation
• New step "2. Règles tarifaires" wired into the BPU edit view via the steps bar
• BPU state extended with variables, enabledRules, tarifValues, columnLabels, peageMode, attenteMode, attenteTranches, madTypes (autosave debounced)
• Folder layout: bpu/components/regles/*, bpu/constants/variable-catalog.ts, bpu/helpers/variable-helpers.ts
BPU Pricing Rules Management Features
• Variable catalog grid — click to add Tranches KM, Type véhicule, Forfait PEC / Usager, PUK, Forfait PEC, MAD, Attente, Péage, Forfait trajet supp., Autre forfait (multi-instances)
• Per-variable editor with associable rules, inline BPU-level shared configs (Péage, Attente, MAD), drag-and-drop reorder, per-instance delete
• Tariff preview table — one table per "container" variable, columns derived from enabled rules, rows synced to the variable's values
• Mocked vehicle catalog with per-vehicle row counter (–/qty/+) for Type véhicule
• "Apply to all rows" action on every select cell (Types de trajet, Type véhicule, Forfait PEC / Usager, MAD)
Components Architecture
• Main Views: bpu-regles-section.tsx orchestrates catalog + active list + editor + preview
• Core Components: variable-catalog-grid.tsx, active-variables-list.tsx, variable-editor.tsx, tariff-preview.tsx
• Specialized Components: inline SelectCell (pill + edit + apply-to-all), inline MadCell (composed type + per-row price widget)
• Interactive Elements: vehicle catalog counter cards, calcul progressif checkbox, inline BPU-shared config panels, editable "Autre forfait" column header
Key Features
• Composed MAD cell: type and per-row price unified in one bordered widget with subtle divider, focus-within lift, transit-fare-receipt aesthetic
• Apply to all rows: down-arrow next to the pencil propagates the selected value to every row in the column
• Inline shared configs: Péage / Attente / MAD configured directly inside the container variable that uses them, no navigation away
• Progressive calculation: Tranches KM exposes an optional "Valeur min" column when the checkbox is on
• Vehicle counter sync: changing a vehicle's count adds/removes rows while preserving existing row IDs (per-row data stays attached)
Technical Implementation
• Layout: CSS Grid with per-variable gridTemplateColumns using minmax(min, 1fr) — columns distribute when few, scroll when many
• Storage: tarifValues keyed by varId:valId:ruleId (+ :mad_price for per-row MAD price)
• Shared state: BPU-level peageMode, attenteMode, attenteTranches, madTypes exposed inline from container editors — single source of truth with the standalone editors
• Resilience: KNOWN_RULE_IDS / KNOWN_VARIABLE_IDS filters drop stale persisted IDs not in the current catalog
• Stack: Tailwind + CSS variables, shadcn/ui, Lucide React, @dnd-kit for reorder
Closes VSN-2861