197 lines
5.4 KiB
TypeScript
197 lines
5.4 KiB
TypeScript
import { z } from "zod";
|
|
import { and, eq, asc, isNull, inArray } from "drizzle-orm";
|
|
|
|
import { boards, cards, lists, workspaces } from "~/server/db/schema";
|
|
import { generateUID } from "~/utils/generateUID";
|
|
|
|
import {
|
|
createTRPCRouter,
|
|
publicProcedure,
|
|
} from "~/server/api/trpc";
|
|
|
|
export const boardRouter = createTRPCRouter({
|
|
all: publicProcedure
|
|
.input(z.object({ workspacePublicId: z.string().min(12) }))
|
|
.query(async ({ ctx, input }) => {
|
|
const userId = ctx.session?.user.id;
|
|
|
|
// @todo: validate user has access to workspace
|
|
|
|
if (!userId) return;
|
|
|
|
const workspace = await ctx.db.query.workspaces.findFirst({
|
|
where: eq(workspaces.publicId, input.workspacePublicId),
|
|
})
|
|
|
|
if (!workspace) return;
|
|
|
|
return ctx.db.query.boards.findMany({
|
|
where: and(eq(boards.workspaceId, workspace.id), isNull(boards.deletedAt)),
|
|
columns: {
|
|
publicId: true,
|
|
name: true,
|
|
},
|
|
});
|
|
}),
|
|
byId: publicProcedure
|
|
.input(z.object({ id: z.string().min(12) }))
|
|
.query(({ ctx, input }) =>
|
|
ctx.db.query.boards.findFirst({
|
|
where: and(eq(boards.publicId, input.id), isNull(boards.deletedAt)),
|
|
columns: {
|
|
publicId: true,
|
|
name: true,
|
|
},
|
|
with: {
|
|
workspace: {
|
|
columns: {
|
|
publicId: true,
|
|
},
|
|
with: {
|
|
members: {
|
|
columns: {
|
|
publicId: true,
|
|
},
|
|
with: {
|
|
user: {
|
|
columns: {
|
|
name: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
lists: {
|
|
orderBy: [asc(lists.index)],
|
|
where: isNull(cards.deletedAt),
|
|
columns: {
|
|
publicId: true,
|
|
name: true,
|
|
boardId: true,
|
|
index: true,
|
|
},
|
|
with: {
|
|
cards: {
|
|
where: isNull(cards.deletedAt),
|
|
orderBy: [asc(cards.index)],
|
|
columns: {
|
|
publicId: true,
|
|
title: true,
|
|
description: true,
|
|
listId: true,
|
|
index: true,
|
|
},
|
|
with: {
|
|
labels: {
|
|
columns: {
|
|
labelId: false,
|
|
cardId: false,
|
|
},
|
|
with: {
|
|
label: {
|
|
columns: {
|
|
publicId: true,
|
|
name: true,
|
|
colourCode: true,
|
|
}
|
|
}
|
|
}
|
|
},
|
|
members: {
|
|
columns: {
|
|
workspaceMemberId: false,
|
|
cardId: false,
|
|
},
|
|
with: {
|
|
member: {
|
|
columns: {
|
|
publicId: true,
|
|
},
|
|
with: {
|
|
user: {
|
|
columns: {
|
|
name: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
},
|
|
},
|
|
})
|
|
),
|
|
create: publicProcedure
|
|
.input(
|
|
z.object({
|
|
name: z.string().min(1),
|
|
workspacePublicId: z.string().min(12)
|
|
}),
|
|
)
|
|
.mutation(async ({ ctx, input }) => {
|
|
const userId = ctx.session?.user.id;
|
|
|
|
if (!userId) return;
|
|
|
|
const workspace = await ctx.db.query.workspaces.findFirst({
|
|
where: eq(workspaces.publicId, input.workspacePublicId),
|
|
})
|
|
|
|
if (!workspace) return;
|
|
|
|
return ctx.db.insert(boards).values({
|
|
publicId: generateUID(),
|
|
name: input.name,
|
|
createdBy: userId,
|
|
workspaceId: workspace.id
|
|
});
|
|
}),
|
|
update: publicProcedure
|
|
.input(
|
|
z.object({
|
|
boardId: z.string().min(12),
|
|
name: z.string().min(1),
|
|
}))
|
|
.mutation(({ ctx, input }) => {
|
|
const userId = ctx.session?.user.id;
|
|
|
|
if (!userId) return;
|
|
|
|
return ctx.db.update(boards).set({ name: input.name }).where(eq(boards.publicId, input.boardId));
|
|
}),
|
|
delete: publicProcedure
|
|
.input(
|
|
z.object({
|
|
boardPublicId: z.string().min(12),
|
|
}))
|
|
.mutation(({ ctx, input }) => {
|
|
const userId = ctx.session?.user.id;
|
|
|
|
if (!userId) return;
|
|
|
|
return ctx.db.transaction(async (tx) => {
|
|
const board = await tx.query.boards.findFirst({
|
|
where: eq(boards.publicId, input.boardPublicId),
|
|
with: {
|
|
lists: true,
|
|
}
|
|
})
|
|
|
|
if (!board) return;
|
|
|
|
const listIds = board.lists.map((list) => list.id)
|
|
|
|
await tx.update(boards).set({ deletedAt: new Date(), deletedBy: userId }).where(eq(boards.id, board.id));
|
|
|
|
if (listIds.length) {
|
|
await tx.update(lists).set({ deletedAt: new Date(), deletedBy: userId }).where(eq(lists.boardId, board.id));
|
|
await tx.update(cards).set({ deletedAt: new Date(), deletedBy: userId }).where(inArray(cards.listId, listIds));
|
|
}
|
|
})
|
|
}),
|
|
});
|