166 lines
4.1 KiB
TypeScript
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,
|
|
};
|
|
}),
|
|
});
|