76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
import { TRPCError } from "@trpc/server";
|
|
import superjson from "superjson";
|
|
import { z } from "zod/v4";
|
|
|
|
import { and, eq } from "@homarr/db";
|
|
import { sectionCollapseStates, sections } from "@homarr/db/schema";
|
|
import { emptySuperJSON } from "@homarr/definitions";
|
|
import { categorySectionOptionsSchema, dynamicSectionOptionsSchema } from "@homarr/validation/shared";
|
|
|
|
import { createTRPCRouter, protectedProcedure } from "../../trpc";
|
|
|
|
export const sectionRouter = createTRPCRouter({
|
|
changeCollapsed: protectedProcedure
|
|
.input(
|
|
z.object({
|
|
sectionId: z.string(),
|
|
collapsed: z.boolean(),
|
|
}),
|
|
)
|
|
.mutation(async ({ ctx, input }) => {
|
|
const section = await ctx.db.query.sections.findFirst({
|
|
where: eq(sections.id, input.sectionId),
|
|
with: {
|
|
collapseStates: {
|
|
where: eq(sectionCollapseStates.userId, ctx.session.user.id),
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!section) {
|
|
throw new TRPCError({
|
|
code: "NOT_FOUND",
|
|
message: `Section not found id=${input.sectionId}`,
|
|
});
|
|
}
|
|
|
|
if (section.kind === "empty") {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message: `Section cannot be collapsed id=${input.sectionId}`,
|
|
});
|
|
}
|
|
|
|
const rawOptions = superjson.parse(section.options ?? emptySuperJSON);
|
|
const parsedOptions =
|
|
section.kind === "category"
|
|
? categorySectionOptionsSchema.safeParse(rawOptions)
|
|
: dynamicSectionOptionsSchema.safeParse(rawOptions);
|
|
|
|
if (!parsedOptions.success || !parsedOptions.data.collapsible) {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message: `Section cannot be collapsed id=${input.sectionId}`,
|
|
});
|
|
}
|
|
|
|
if (section.collapseStates.length === 0) {
|
|
await ctx.db.insert(sectionCollapseStates).values({
|
|
sectionId: section.id,
|
|
userId: ctx.session.user.id,
|
|
collapsed: input.collapsed,
|
|
});
|
|
return;
|
|
}
|
|
|
|
await ctx.db
|
|
.update(sectionCollapseStates)
|
|
.set({
|
|
collapsed: input.collapsed,
|
|
})
|
|
.where(
|
|
and(eq(sectionCollapseStates.sectionId, section.id), eq(sectionCollapseStates.userId, ctx.session.user.id)),
|
|
);
|
|
}),
|
|
});
|