import { format } from "date-fns"; import { Calendar } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; export const DEFAULT_PHASE_COLOR = "#14b8a6"; const PHASE_COLOR_OPTIONS = [ "#14b8a6", "#0ea5e9", "#6366f1", "#a855f7", "#ec4899", "#f59e0b", "#22c55e", "#64748b", ]; export interface PhaseCreateInput { name: string; start_date: string; end_date: string; color: string; } interface PhaseCreatePopoverProps { anchor: { top: number; left: number }; startDate: string; endDate: string; onCancel: () => void; onSave: (input: PhaseCreateInput) => void; isSaving?: boolean; } export function PhaseCreatePopover({ anchor, startDate, endDate, onCancel, onSave, isSaving = false, }: PhaseCreatePopoverProps) { const popoverRef = useRef(null); const [name, setName] = useState("Phase"); const [color, setColor] = useState(DEFAULT_PHASE_COLOR); const [showColors, setShowColors] = useState(false); useEffect(() => { setName("Phase"); setColor(DEFAULT_PHASE_COLOR); setShowColors(false); }, [startDate, endDate]); 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 rangeLabel = startDate === endDate ? format(new Date(startDate), "d MMM yyyy") : `${format(new Date(startDate), "d MMM")} – ${format(new Date(endDate), "d MMM yyyy")}`; const style = { top: Math.min(anchor.top, window.innerHeight - 200), left: Math.min(Math.max(8, anchor.left), window.innerWidth - 320), }; return createPortal(
setName(event.target.value)} onKeyDown={(event) => { if (event.key === "Enter" && name.trim()) { onSave({ name: name.trim(), start_date: startDate, end_date: endDate, color }); } }} placeholder="Phase" type="text" value={name} />
) : null}
, document.body, ); } export function phasePopoverAnchorFromTrack( trackRect: DOMRect, startIndex: number, endIndex: number, totalDays: number, ): { top: number; left: number } { const start = Math.min(startIndex, endIndex); const end = Math.max(startIndex, endIndex); const span = end - start + 1; const leftPct = start / totalDays; const widthPct = span / totalDays; const centerX = trackRect.left + trackRect.width * (leftPct + widthPct / 2); return { top: trackRect.top - 12, left: centerX - 150 }; }