64 lines
2.0 KiB
TypeScript
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 };
|
|
}
|