/** * RollbackConfirmModal — Shows revision history and confirms rollback. * Rollback creates a new revision (non-destructive) per spec §15.3. */ import { useState, useEffect } from 'react'; import { createPortal } from 'react-dom'; import { motion, AnimatePresence } from 'framer-motion'; import { X, RotateCcw, GitCommit, AlertTriangle, CheckCircle2 } from 'lucide-react'; import { Button } from '@/components/ui/button'; import type { CanvasPage, CanvasPageRevision } from '../types/canvas'; interface RollbackConfirmModalProps { page: CanvasPage | null; revisions: CanvasPageRevision[]; isLoading: boolean; isOpen: boolean; onClose: () => void; onRollback: (targetRevision: number) => Promise; } export function RollbackConfirmModal({ page, revisions, isLoading, isOpen, onClose, onRollback }: RollbackConfirmModalProps) { const [mounted, setMounted] = useState(false); useEffect(() => setMounted(true), []); const [selected, setSelected] = useState(null); const [submitting, setSubmitting] = useState(false); const [success, setSuccess] = useState(false); const handleRollback = async () => { if (!selected) return; setSubmitting(true); try { await onRollback(selected); setSuccess(true); setTimeout(() => { setSuccess(false); onClose(); setSelected(null); }, 1800); } catch { // stay open } finally { setSubmitting(false); } }; const commitKindColors: Record = { prompt: '#60a5fa', merge: '#a78bfa', rollback: '#fbbf24', manual_edit: '#34d399', }; const content = ( {isOpen && ( <>

Revision History

Select a revision to roll back to

{/* Non-destructive note */}

Rollback is non-destructive — it creates a new revision restoring the canvas to that state. Current revision {page?.headRevision} is preserved in history.

{success ? (

Rolled back to revision {selected}

) : ( <> {/* Revision list */}
{isLoading && (
Loading revision history…
)} {!isLoading && revisions.map((rev) => { const color = commitKindColors[rev.commitKind] ?? '#60a5fa'; const isCurrent = rev.revisionNumber === page?.headRevision; const isSelected = selected === rev.revisionNumber; return ( ); })} {!isLoading && revisions.length === 0 && (
No revisions have been committed yet.
)}
{/* Actions */}
)}
)}
); if (!mounted) return null; return createPortal(content, document.body); }