"use client"; import { useCallback, useRef, useState } from "react"; import { trpc } from "~/lib/trpc/client.js"; import type { AllocationMovedSnapshot } from "./useTimelineDrag.js"; export type { AllocationMovedSnapshot }; const MAX_HISTORY = 20; export function useAllocationHistory() { const [canUndo, setCanUndo] = useState(false); const [canRedo, setCanRedo] = useState(false); const past = useRef([]); const future = useRef([]); const utils = trpc.useUtils(); const updateMutation = trpc.timeline.updateAllocationInline.useMutation({ onSuccess: () => { void utils.timeline.getEntries.invalidate(); void utils.timeline.getEntriesView.invalidate(); void utils.timeline.getProjectContext.invalidate(); void utils.timeline.getBudgetStatus.invalidate(); }, }); const push = useCallback((snapshot: AllocationMovedSnapshot) => { past.current = [...past.current.slice(-MAX_HISTORY + 1), snapshot]; future.current = []; setCanUndo(true); setCanRedo(false); }, []); const undo = useCallback(async () => { const last = past.current[past.current.length - 1]; if (!last) return; past.current = past.current.slice(0, -1); future.current = [last, ...future.current]; setCanUndo(past.current.length > 0); setCanRedo(true); await updateMutation.mutateAsync({ allocationId: last.mutationAllocationId, startDate: last.before.startDate, endDate: last.before.endDate, }); }, [updateMutation]); const redo = useCallback(async () => { const next = future.current[0]; if (!next) return; future.current = future.current.slice(1); past.current = [...past.current, next]; setCanUndo(true); setCanRedo(future.current.length > 0); await updateMutation.mutateAsync({ allocationId: next.mutationAllocationId, startDate: next.after.startDate, endDate: next.after.endDate, }); }, [updateMutation]); return { push, undo, redo, canUndo, canRedo }; }