122 lines
3.6 KiB
TypeScript
122 lines
3.6 KiB
TypeScript
import { z } from "zod";
|
|
import { router, publicProcedure } from "../trpc";
|
|
|
|
const DealsPhaseOptions = [
|
|
"New",
|
|
"Demo scheduled",
|
|
"Contract signed",
|
|
"Lost",
|
|
] as const;
|
|
|
|
// Create a Zod enum from the phase options
|
|
const phaseEnum = z.enum(DealsPhaseOptions);
|
|
|
|
export const dealsRouter = router({
|
|
getAll: publicProcedure.query(async ({ ctx }) => {
|
|
return await ctx.queryBuilder
|
|
.selectFrom("deals")
|
|
.select(["id", "name", "phase", "createdAt", "updatedAt"])
|
|
.with({
|
|
mainContact: qb => qb.select(["id", "firstName", "lastName", "mail"])
|
|
})
|
|
.orderBy("createdAt", "desc")
|
|
.execute();
|
|
}),
|
|
|
|
getById: publicProcedure
|
|
.input(z.object({ id: z.number() }))
|
|
.query(async ({ ctx, input }) => {
|
|
// Get the deal with all fields including links
|
|
const deal = await ctx.queryBuilder
|
|
.selectFrom("deals")
|
|
.select(["id", "name", "phase", "createdAt", "updatedAt"])
|
|
.with({ mainContact: qb => qb.select(["id", "firstName", "lastName", "mail"]) })
|
|
.where("id", "=", input.id)
|
|
.executeTakeFirst();
|
|
return deal;
|
|
}),
|
|
|
|
search: publicProcedure
|
|
.input(z.object({ query: z.string(), limit: z.number().optional() }))
|
|
.query(async ({ ctx, input }) => {
|
|
let query = ctx.queryBuilder
|
|
.selectFrom("deals")
|
|
.select(["id", "name", "phase"]);
|
|
|
|
if (input.query.trim()) {
|
|
query = query.where("name", "contains", input.query);
|
|
}
|
|
|
|
return await query
|
|
.orderBy("name", "asc")
|
|
.execute();
|
|
}),
|
|
|
|
// Get detailed deal info with contact and company for details page
|
|
getDetails: publicProcedure
|
|
.input(z.object({ id: z.number() }))
|
|
.query(async ({ ctx, input }) => {
|
|
// Get the deal with contact info
|
|
const deal = await ctx.queryBuilder
|
|
.selectFrom("deals")
|
|
.select(["id", "name", "phase", "lostReason", "createdAt", "updatedAt"])
|
|
.with({
|
|
mainContact: qb => qb.select(["id", "firstName", "lastName", "mail", "phone1", "phone2", "notes"])
|
|
.with({ company: companyQb => companyQb.select(["id", "name", "website", "notes"]) })
|
|
})
|
|
.with({
|
|
activities: qb => qb.select(["id", "name", "type", "plannedAt", "doneAt", "createdAt"])
|
|
.with({ notes: notesQb => notesQb.select(["id", "name", "createdAt"]) })
|
|
})
|
|
.where("id", "=", input.id)
|
|
.executeTakeFirst();
|
|
return deal;
|
|
}),
|
|
|
|
create: publicProcedure
|
|
.input(
|
|
z.object({
|
|
name: z.string().min(1),
|
|
phase: phaseEnum.default("New"),
|
|
mainContact: z.array(z.number()).optional(),
|
|
})
|
|
)
|
|
.mutation(async ({ ctx, input }) => {
|
|
return await ctx.queryBuilder
|
|
.insertInto("deals")
|
|
.values(input)
|
|
.executeTakeFirst();
|
|
}),
|
|
|
|
update: publicProcedure
|
|
.input(
|
|
z.object({
|
|
id: z.number(),
|
|
name: z.string().optional(),
|
|
phase: phaseEnum.optional(),
|
|
mainContact: z.array(z.number()).optional(),
|
|
})
|
|
)
|
|
.mutation(async ({ ctx, input }) => {
|
|
const { id, ...data } = input;
|
|
// Filter out undefined values to avoid overwriting with undefined
|
|
const updateData = Object.fromEntries(
|
|
Object.entries(data).filter(([, v]) => v !== undefined)
|
|
) as typeof data;
|
|
return await ctx.queryBuilder
|
|
.update("deals")
|
|
.set(updateData)
|
|
.where("id", "=", id)
|
|
.execute();
|
|
}),
|
|
|
|
delete: publicProcedure
|
|
.input(z.object({ id: z.number() }))
|
|
.mutation(async ({ ctx, input }) => {
|
|
return await ctx.queryBuilder
|
|
.deleteFrom("deals")
|
|
.where("id", "=", input.id)
|
|
.execute();
|
|
}),
|
|
});
|