normalize data
This commit is contained in:
@@ -5,6 +5,40 @@ import { createServerFn } from "@tanstack/react-start";
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import { z } from "zod";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Normalized timeline shape stored in the TanStack Query cache.
|
||||
// Groups and items are keyed by ID for O(1) lookups; groupOrder preserves
|
||||
// the display ordering returned by the DB.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export type NormalizedGroup = {
|
||||
id: string;
|
||||
title: string;
|
||||
sortOrder: number;
|
||||
};
|
||||
|
||||
export type NormalizedItem = {
|
||||
id: string;
|
||||
groupId: string;
|
||||
title: string;
|
||||
description: string;
|
||||
start: Date;
|
||||
end: Date | null;
|
||||
lane: number;
|
||||
};
|
||||
|
||||
export type NormalizedTimeline = {
|
||||
id: string;
|
||||
title: string;
|
||||
groups: Record<string, NormalizedGroup>;
|
||||
items: Record<string, NormalizedItem>;
|
||||
groupOrder: Array<string>;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Server function — returns the raw nested Drizzle result (efficient query).
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const getTimeline = createServerFn({ method: "GET" })
|
||||
.inputValidator(z.object({ id: z.string().uuid() }))
|
||||
.handler(async ({ data }) => {
|
||||
@@ -29,8 +63,52 @@ export const getTimeline = createServerFn({ method: "GET" })
|
||||
return result;
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Normalization — flattens the nested DB result into the cache shape.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
type NestedTimeline = Awaited<ReturnType<typeof getTimeline>>;
|
||||
|
||||
function normalizeTimeline(nested: NestedTimeline): NormalizedTimeline {
|
||||
const groups: Record<string, NormalizedGroup> = {};
|
||||
const items: Record<string, NormalizedItem> = {};
|
||||
const groupOrder: Array<string> = [];
|
||||
|
||||
for (const g of nested.groups) {
|
||||
groupOrder.push(g.id);
|
||||
groups[g.id] = { id: g.id, title: g.title, sortOrder: g.sortOrder };
|
||||
|
||||
for (const item of g.items) {
|
||||
items[item.id] = {
|
||||
id: item.id,
|
||||
groupId: g.id,
|
||||
title: item.title,
|
||||
description: item.description,
|
||||
start: item.start,
|
||||
end: item.end,
|
||||
lane: item.lane,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: nested.id,
|
||||
title: nested.title,
|
||||
groups,
|
||||
items,
|
||||
groupOrder,
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Query options — cache stores normalized data.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const timelineQueryOptions = (timelineId: string) =>
|
||||
queryOptions({
|
||||
queryKey: ["timeline", timelineId],
|
||||
queryFn: () => getTimeline({ data: { id: timelineId } }),
|
||||
queryFn: async () => {
|
||||
const nested = await getTimeline({ data: { id: timelineId } });
|
||||
return normalizeTimeline(nested);
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user