refactor(api): extract project identifier read procedures
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
import { ProjectStatus } from "@capakraken/shared";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { z } from "zod";
|
||||
import { controllerProcedure, planningReadProcedure } from "../trpc.js";
|
||||
import {
|
||||
mapProjectDetail,
|
||||
mapProjectSummary,
|
||||
mapProjectSummaryDetail,
|
||||
readProjectByIdentifierDetailSnapshot,
|
||||
readProjectSummariesSnapshot,
|
||||
readProjectSummaryDetailsSnapshot,
|
||||
resolveProjectIdentifierSnapshot,
|
||||
} from "./project-read-shared.js";
|
||||
|
||||
export const projectIdentifierReadProcedures = {
|
||||
resolveByIdentifier: planningReadProcedure
|
||||
.input(z.object({ identifier: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const select = {
|
||||
id: true,
|
||||
shortCode: true,
|
||||
name: true,
|
||||
status: true,
|
||||
responsiblePerson: true,
|
||||
startDate: true,
|
||||
endDate: true,
|
||||
} as const;
|
||||
|
||||
let project = await ctx.db.project.findUnique({
|
||||
where: { id: input.identifier },
|
||||
select,
|
||||
});
|
||||
if (!project) {
|
||||
project = await ctx.db.project.findUnique({
|
||||
where: { shortCode: input.identifier },
|
||||
select,
|
||||
});
|
||||
}
|
||||
if (!project) {
|
||||
project = await ctx.db.project.findFirst({
|
||||
where: { name: { equals: input.identifier, mode: "insensitive" } },
|
||||
select,
|
||||
});
|
||||
}
|
||||
if (!project) {
|
||||
project = await ctx.db.project.findFirst({
|
||||
where: { name: { contains: input.identifier, mode: "insensitive" } },
|
||||
select,
|
||||
});
|
||||
}
|
||||
|
||||
if (!project) {
|
||||
throw new TRPCError({ code: "NOT_FOUND", message: "Project not found" });
|
||||
}
|
||||
|
||||
return project;
|
||||
}),
|
||||
|
||||
searchSummaries: planningReadProcedure
|
||||
.input(z.object({
|
||||
search: z.string().optional(),
|
||||
status: z.nativeEnum(ProjectStatus).optional(),
|
||||
limit: z.number().int().min(1).max(50).default(20),
|
||||
}))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const { items, exactMatch } = await readProjectSummariesSnapshot(ctx, input);
|
||||
const formatted = items.map(mapProjectSummary);
|
||||
if (items.length > 0 && input.search && !exactMatch) {
|
||||
return {
|
||||
suggestions: formatted,
|
||||
note: `No exact match for "${input.search}". These projects match some of the search terms:`,
|
||||
};
|
||||
}
|
||||
return formatted;
|
||||
}),
|
||||
|
||||
searchSummariesDetail: controllerProcedure
|
||||
.input(z.object({
|
||||
search: z.string().optional(),
|
||||
status: z.nativeEnum(ProjectStatus).optional(),
|
||||
limit: z.number().int().min(1).max(50).default(20),
|
||||
}))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const { items, exactMatch } = await readProjectSummaryDetailsSnapshot(ctx, input);
|
||||
const formatted = items.map(mapProjectSummaryDetail);
|
||||
if (items.length > 0 && input.search && !exactMatch) {
|
||||
return {
|
||||
suggestions: formatted,
|
||||
note: `No exact match for "${input.search}". These projects match some of the search terms:`,
|
||||
};
|
||||
}
|
||||
return formatted;
|
||||
}),
|
||||
|
||||
getByIdentifier: planningReadProcedure
|
||||
.input(z.object({ identifier: z.string() }))
|
||||
.query(async ({ ctx, input }) => resolveProjectIdentifierSnapshot(ctx, input.identifier)),
|
||||
|
||||
getByIdentifierDetail: controllerProcedure
|
||||
.input(z.object({ identifier: z.string() }))
|
||||
.query(async ({ ctx, input }) => {
|
||||
const project = await readProjectByIdentifierDetailSnapshot(ctx, input.identifier);
|
||||
return mapProjectDetail(project, project.topAssignments);
|
||||
}),
|
||||
};
|
||||
Reference in New Issue
Block a user