import { useEffect, useState } from "react"; import { AlertTriangle, Loader2 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; import type { RoutineHistoryDirtyFieldDescriptor } from "./RoutineHistoryTab"; /** * Per-section sticky save bar (§1.4–§1.5). Hidden when clean; reveals on dirty. * On a 409 it swaps to the conflict-recovery surface ("Reload latest" / * "Overwrite anyway"). Wires ⌘/Ctrl+S → save and Esc → discard-with-confirm. */ export function RoutineSaveBar({ dirtyFields, isSaving, saveConflict, onSave, onDiscard, onReload, disabled, }: { dirtyFields: RoutineHistoryDirtyFieldDescriptor[]; isSaving: boolean; saveConflict: boolean; onSave: () => void; onDiscard: () => void; onReload: () => void; disabled?: boolean; }) { const dirtyCount = dirtyFields.length; const isDirty = dirtyCount > 0; const [confirmDiscardOpen, setConfirmDiscardOpen] = useState(false); useEffect(() => { if (!isDirty && !saveConflict) return; const handler = (event: KeyboardEvent) => { if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === "s") { event.preventDefault(); if (!isSaving && !disabled) onSave(); } else if (event.key === "Escape" && isDirty) { event.preventDefault(); setConfirmDiscardOpen(true); } }; window.addEventListener("keydown", handler); return () => window.removeEventListener("keydown", handler); }, [isDirty, saveConflict, isSaving, disabled, onSave]); if (!isDirty && !saveConflict) return null; return ( <>
{saveConflict ? (
Routine changed elsewhere. Reload to merge.
) : (

Pending changes

    {dirtyFields.map((field) => (
  • {field.label}
  • ))}
)}
{saveConflict ? ( <> Replaces the newer revision with your local edits. ) : ( <> )}
Discard changes? This will revert {dirtyCount} unsaved{" "} {dirtyCount === 1 ? "change" : "changes"} in this section. ); } /** Read-only strip for non-owners on editable sections (§1.6). */ export function RoutineReadOnlyStrip() { return (
Read-only — you don't own this routine.
); }