diff --git a/apps/web/src/components/plans/wizard/CadenceCalendar.tsx b/apps/web/src/components/plans/wizard/CadenceCalendar.tsx index c47bdd3..2c329f5 100644 --- a/apps/web/src/components/plans/wizard/CadenceCalendar.tsx +++ b/apps/web/src/components/plans/wizard/CadenceCalendar.tsx @@ -1,11 +1,32 @@ import { useEffect, useMemo, useState } from "react"; -import { ChevronLeft, ChevronRight, Plus, Trash2, AlertTriangle } from "lucide-react"; +import { + ChevronLeft, + ChevronRight, + Plus, + Trash2, + AlertTriangle, + Smile, + MessageCircle, + Gavel, + type LucideIcon, +} from "lucide-react"; import { toast } from "sonner"; import type { RelanceTone } from "@rubis/shared"; import { cn } from "@/lib/utils"; import { TONE_LABELS } from "@/lib/plans"; -import { Input } from "@/components/ui/Input"; + +/** + * Icône qui illustre chaque tonalité. Cohérent avec l'escalade émotionnelle : + * sourire pour amical, bulle de conversation pour standard, alerte pour + * ferme, marteau de juge pour mise en demeure. + */ +const TONE_ICON: Record = { + amical: Smile, + courtois: MessageCircle, + ferme: AlertTriangle, + mise_en_demeure: Gavel, +}; /** * Étape minimale pour la visu calendrier (subject/body arrivent à @@ -404,8 +425,16 @@ function DayCell({ } // ============================================================================ -// Éditeur compact — header explicite + 1 ligne de champs +// Éditeur compact — header avec icône de tonalité + sélecteur 4 icônes // ============================================================================ + +const TONE_ORDER: RelanceTone[] = [ + "amical", + "courtois", + "ferme", + "mise_en_demeure", +]; + function CompactEditor({ step, stepDate, @@ -419,18 +448,22 @@ function CompactEditor({ onUpdate: (patch: Partial) => void; onRemove: () => void; }) { + const HeaderIcon = TONE_ICON[step.tone]; + return ( -
- {/* Header explicite : on sait quelle relance on édite */} +
+ {/* Header : pastille tonalité (icône + couleur) + date + supprimer */}

Relance du{" "} @@ -455,41 +488,43 @@ function CompactEditor({ )}

-
- - + {/* Sélecteur de tonalité : 4 boutons icône, plus visuel qu'un select */} +
+

Tonalité

+
+ {TONE_ORDER.map((t) => { + const Icon = TONE_ICON[t]; + const isActive = step.tone === t; + return ( + + ); + })} +
{step.tone === "mise_en_demeure" && ( @@ -559,50 +594,3 @@ function formatShortDate(d: Date): string { return FR_SHORT.format(d); } -// ============================================================================ -// OffsetInput -// ============================================================================ -function OffsetInput({ - id, - value, - onCommit, -}: { - id: string; - value: number; - onCommit: (n: number) => void; -}) { - const [local, setLocal] = useState(String(value)); - - useEffect(() => { - setLocal(String(value)); - }, [value]); - - return ( - { - const next = e.target.value; - if (next === "" || next === "-" || /^-?\d{0,3}$/.test(next)) { - setLocal(next); - if (next !== "" && next !== "-") { - const parsed = parseInt(next, 10); - if (!Number.isNaN(parsed)) { - onCommit(Math.max(-30, Math.min(180, parsed))); - } - } - } - }} - onBlur={() => { - if (local === "" || local === "-") { - setLocal("0"); - onCommit(0); - } - }} - /> - ); -} diff --git a/apps/web/src/routes/_app/plans_.nouveau.tsx b/apps/web/src/routes/_app/plans_.nouveau.tsx index 9f83a7a..fbadab8 100644 --- a/apps/web/src/routes/_app/plans_.nouveau.tsx +++ b/apps/web/src/routes/_app/plans_.nouveau.tsx @@ -476,7 +476,11 @@ function StepCadence({ draft, onChange }: { draft: Draft; onChange: (d: Draft) = steps={draft.steps} selectedIndex={selectedIdx} globalTone={draft.globalTone} - onSelectStep={setSelectedIdx} + // Toggle : re-cliquer une étape déjà sélectionnée la désélectionne + // pour revenir à la vue d'ensemble. + onSelectStep={(idx) => + setSelectedIdx((cur) => (cur === idx ? -1 : idx)) + } onUpdateStep={updateStep} onAddStep={addStep} onAddStepAtOffset={addStepAtOffset}