Files
CapaKraken/apps/web/src/hooks/useAllocationHistory.ts
T

64 lines
2.0 KiB
TypeScript

"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<AllocationMovedSnapshot[]>([]);
const future = useRef<AllocationMovedSnapshot[]>([]);
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 };
}