import { format, parseISO } from "date-fns"; import { AlertTriangle, ArrowLeft, ArrowRight, DollarSign, Flag, Smile } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; const MILESTONE_ICONS = [ { id: "budget", label: "Budget", icon: DollarSign }, { id: "alert", label: "Alert", icon: AlertTriangle }, { id: "start", label: "Start", icon: ArrowRight }, { id: "end", label: "End", icon: ArrowLeft }, { id: "flag", label: "Flag", icon: Flag }, { id: "note", label: "Note", icon: Smile }, ] as const; interface MilestoneAddPopoverProps { anchor: { top: number; left: number }; dueDate: string; onCancel: () => void; onCreate: (name: string, note?: string) => void; isSaving?: boolean; } export function MilestoneAddPopover({ anchor, dueDate, onCancel, onCreate, isSaving = false, }: MilestoneAddPopoverProps) { const popoverRef = useRef(null); const [name, setName] = useState(""); const [note, setNote] = useState(""); const [iconId, setIconId] = useState<(typeof MILESTONE_ICONS)[number]["id"]>("flag"); useEffect(() => { const onKey = (event: KeyboardEvent) => { if (event.key === "Escape") onCancel(); }; const onDown = (event: MouseEvent) => { if (popoverRef.current?.contains(event.target as Node)) return; onCancel(); }; window.addEventListener("keydown", onKey); document.addEventListener("mousedown", onDown); return () => { window.removeEventListener("keydown", onKey); document.removeEventListener("mousedown", onDown); }; }, [onCancel]); const style = { top: Math.min(anchor.top, window.innerHeight - 360), left: Math.min(Math.max(8, anchor.left), window.innerWidth - 320), }; const dateLabel = format(parseISO(dueDate), "d MMM yyyy"); return createPortal(
Add Milestone {dateLabel}
{MILESTONE_ICONS.map((item) => { const Icon = item.icon; return ( ); })}