uiowaATR/src/server/api/routers/auditoryResources.ts
2023-09-05 19:48:02 -05:00

166 lines
4.1 KiB
TypeScript

import { SkillLevel, Skill, Platform, PaymentType } from "@prisma/client";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import {
createTRPCRouter,
protectedProcedure,
publicProcedure,
} from "~/server/api/trpc";
const emptyStringToUndefined = (val: string | undefined | null) => {
if (val?.length === 0) {
return undefined;
}
return val;
};
const AuditoryResourceSchema = z.object({
icon: z.string().min(1).optional(),
name: z.string().min(1),
description: z.string().min(1),
manufacturer: z.object({
name: z.string().min(1),
required: z.boolean().default(false),
notice: z.string().nullable().transform(emptyStringToUndefined),
}),
ages: z.object({ min: z.number().int(), max: z.number().int() }).refine(
(ages) => {
return ages.min < ages.max;
},
{
message: "Minimum supported age must be less than maximum supported age.",
}
),
skills: z.array(z.nativeEnum(Skill)),
skill_levels: z.array(z.nativeEnum(SkillLevel)),
payment_options: z.array(z.nativeEnum(PaymentType)),
photo: z
.object({
name: z.string(),
data: z.instanceof(Buffer),
})
.nullable(),
platform_links: z
.array(
z.object({
platform: z.nativeEnum(Platform),
link: z.string().min(1),
})
)
.default([]),
});
export const auditoryResourceRouter = createTRPCRouter({
byId: publicProcedure
.input(z.object({ id: z.string() }))
.query(async ({ input, ctx }) => {
try {
const resource = await ctx.prisma.auditoryResource.findUnique({
where: {
id: input.id,
},
});
if (!resource) {
throw Error("not found");
}
return resource;
} catch (e) {
throw new TRPCError({
code: "NOT_FOUND",
message: "The resource you are looking for does not exist.",
cause: e,
});
}
}),
getAll: publicProcedure.query(({ ctx }) => {
return ctx.prisma.auditoryResource.findMany();
}),
create: protectedProcedure
.input(AuditoryResourceSchema.strict())
.mutation(async ({ input, ctx }) => {
return await ctx.prisma.auditoryResource.create({
data: input,
});
}),
update: protectedProcedure
.input(AuditoryResourceSchema.partial().extend({ id: z.string() }))
.mutation(async ({ input, ctx }) => {
return await ctx.prisma.auditoryResource.update({
where: {
id: input.id,
},
data: Object.fromEntries(
Object.entries(input).filter(([key, _value]) => {
return key !== "id";
})
),
});
}),
search: publicProcedure
.input(
z.object({
take: z.number().int(),
skip: z.number().int(),
ages: z
.object({
min: z.number().int(),
max: z.number().int(),
})
.optional(),
platforms: z.nativeEnum(Platform).array().optional(),
skill_levels: z.nativeEnum(SkillLevel).array().optional(),
skills: z.nativeEnum(Skill).array().optional(),
})
)
.query(async ({ input, ctx }) => {
const search = {
ages: {
is: {
min: {
lte: input.ages?.min,
},
max: {
gte: input.ages?.max,
},
},
},
skill_levels: {
hasEvery: input.skill_levels ?? [],
},
platform_links: {
some: {
platform: {
in: input.platforms,
},
},
},
...(input.skills ? { skills: { hasSome: input.skills } } : {}),
};
const [count, resources] = await ctx.prisma.$transaction([
ctx.prisma.auditoryResource.count({
where: search,
}),
ctx.prisma.auditoryResource.findMany({
skip: input.skip,
take: input.take,
where: search,
}),
]);
// TODO: The issue here is the photo binary data can't be sent over tRPC which will cause the request to be unparsable by the client
return {
count,
resources,
};
}),
});