refactor(api): centralize timeline read detail schemas

This commit is contained in:
2026-03-31 18:22:20 +02:00
parent 4758c96543
commit 66a33a5ad6
4 changed files with 55 additions and 22 deletions
@@ -1,6 +1,8 @@
import { describe, expect, it } from "vitest";
import {
buildTimelineEntriesDetailInput,
TimelineDetailFiltersSchema,
TimelineProjectContextDetailSchema,
} from "../router/timeline-read-shared.js";
describe("timeline read shared", () => {
@@ -39,4 +41,32 @@ describe("timeline read shared", () => {
});
});
it("shares detail filter schemas across timeline read endpoints", () => {
expect(TimelineDetailFiltersSchema.parse({
startDate: "2026-04-01",
durationDays: 14,
resourceIds: ["resource_1"],
countryCodes: ["DE"],
})).toEqual({
startDate: "2026-04-01",
endDate: undefined,
durationDays: 14,
resourceIds: ["resource_1"],
projectIds: undefined,
clientIds: undefined,
chapters: undefined,
eids: undefined,
countryCodes: ["DE"],
});
expect(TimelineProjectContextDetailSchema.parse({
projectId: "project_1",
endDate: "2026-04-20",
})).toEqual({
projectId: "project_1",
startDate: undefined,
endDate: "2026-04-20",
durationDays: undefined,
});
});
});
+2 -14
View File
@@ -1,6 +1,6 @@
import { z } from "zod";
import { controllerProcedure, protectedProcedure } from "../trpc.js";
import {
TimelineDetailFiltersSchema,
TimelineWindowFiltersSchema,
} from "./timeline-read-shared.js";
import {
@@ -24,18 +24,6 @@ export const timelineEntryReadProcedures = {
.query(({ ctx, input }) => readMyTimelineEntriesView(ctx, input)),
getEntriesDetail: controllerProcedure
.input(
z.object({
startDate: z.string().optional(),
endDate: z.string().optional(),
durationDays: z.number().int().min(1).max(366).optional(),
resourceIds: z.array(z.string()).optional(),
projectIds: z.array(z.string()).optional(),
clientIds: z.array(z.string()).optional(),
chapters: z.array(z.string()).optional(),
eids: z.array(z.string()).optional(),
countryCodes: z.array(z.string()).optional(),
}),
)
.input(TimelineDetailFiltersSchema)
.query(({ ctx, input }) => readTimelineEntriesDetail(ctx.db, input)),
};
@@ -2,6 +2,9 @@ import { ShiftProjectSchema } from "@capakraken/shared";
import { z } from "zod";
import { controllerProcedure } from "../trpc.js";
import { previewTimelineProjectShift } from "./timeline-project-load-support.js";
import {
TimelineProjectContextDetailSchema,
} from "./timeline-read-shared.js";
import {
readTimelineProjectBudgetStatusResponse,
readTimelineProjectContextDetailResponse,
@@ -15,14 +18,7 @@ export const timelineProjectReadProcedures = {
.query(async ({ ctx, input }) => readTimelineProjectContextResponse(ctx.db, input.projectId)),
getProjectContextDetail: controllerProcedure
.input(
z.object({
projectId: z.string(),
startDate: z.string().optional(),
endDate: z.string().optional(),
durationDays: z.number().int().min(1).max(366).optional(),
}),
)
.input(TimelineProjectContextDetailSchema)
.query(async ({ ctx, input }) => readTimelineProjectContextDetailResponse(ctx.db, input)),
previewShift: controllerProcedure
@@ -41,6 +41,25 @@ export const TimelineWindowFiltersSchema = z.object({
countryCodes: z.array(z.string()).optional(),
});
export const TimelineDetailFiltersSchema = z.object({
startDate: z.string().optional(),
endDate: z.string().optional(),
durationDays: z.number().int().min(1).max(366).optional(),
resourceIds: z.array(z.string()).optional(),
projectIds: z.array(z.string()).optional(),
clientIds: z.array(z.string()).optional(),
chapters: z.array(z.string()).optional(),
eids: z.array(z.string()).optional(),
countryCodes: z.array(z.string()).optional(),
});
export const TimelineProjectContextDetailSchema = z.object({
projectId: z.string(),
startDate: z.string().optional(),
endDate: z.string().optional(),
durationDays: z.number().int().min(1).max(366).optional(),
});
type TimelineWindowFiltersInput = z.infer<typeof TimelineWindowFiltersSchema>;
export function getAssignmentResourceIds(