94 lines
2.6 KiB
TypeScript
94 lines
2.6 KiB
TypeScript
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
import type { getTimeline } from "@/functions/get-timeline";
|
|
import { updateTimelineItem } from "@/functions/update-timeline-item";
|
|
|
|
type TimelineData = Awaited<ReturnType<typeof getTimeline>>;
|
|
|
|
type EntryMovedVars = {
|
|
entryId: string;
|
|
newStart: string;
|
|
newEnd: string | null;
|
|
newGroupId: string;
|
|
newLane: number;
|
|
};
|
|
|
|
export function useEntryMovedMutation(timelineId: string) {
|
|
const queryClient = useQueryClient();
|
|
const queryKey = ["timeline", timelineId];
|
|
|
|
return useMutation({
|
|
mutationFn: (vars: EntryMovedVars) =>
|
|
updateTimelineItem({
|
|
data: {
|
|
id: vars.entryId,
|
|
start: vars.newStart,
|
|
end: vars.newEnd,
|
|
timelineGroupId: vars.newGroupId,
|
|
lane: vars.newLane,
|
|
},
|
|
}),
|
|
|
|
onMutate: async (vars) => {
|
|
// Cancel in-flight fetches so they don't overwrite our optimistic update
|
|
await queryClient.cancelQueries({ queryKey });
|
|
const previous = queryClient.getQueryData<TimelineData>(queryKey);
|
|
|
|
queryClient.setQueryData<TimelineData>(queryKey, (old) => {
|
|
if (!old) return old;
|
|
|
|
let movedItem:
|
|
| TimelineData["groups"][number]["items"][number]
|
|
| undefined;
|
|
|
|
const groups = old.groups.map((group) => {
|
|
const filtered = group.items.filter((item) => {
|
|
if (item.id === vars.entryId) {
|
|
movedItem = item;
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
return { ...group, items: filtered };
|
|
});
|
|
|
|
if (!movedItem) return old;
|
|
|
|
return {
|
|
...old,
|
|
groups: groups.map((group) =>
|
|
group.id === vars.newGroupId
|
|
? {
|
|
...group,
|
|
items: [
|
|
...group.items,
|
|
{
|
|
...movedItem!,
|
|
start: new Date(vars.newStart),
|
|
end: vars.newEnd ? new Date(vars.newEnd) : null,
|
|
lane: vars.newLane,
|
|
timelineGroupId: vars.newGroupId,
|
|
},
|
|
],
|
|
}
|
|
: group
|
|
),
|
|
};
|
|
});
|
|
|
|
return { previous };
|
|
},
|
|
|
|
onError: (_err, _vars, context) => {
|
|
// Roll back to the previous cache state on server error
|
|
if (context?.previous) {
|
|
queryClient.setQueryData(queryKey, context.previous);
|
|
}
|
|
},
|
|
|
|
onSettled: () => {
|
|
// Re-fetch from server to ensure consistency
|
|
queryClient.invalidateQueries({ queryKey });
|
|
},
|
|
});
|
|
}
|