diff --git a/src/app/boards/[...boardId]/components/NewCardForm.tsx b/src/app/boards/[...boardId]/components/NewCardForm.tsx index 6a73b6e3..96ffbfd3 100644 --- a/src/app/boards/[...boardId]/components/NewCardForm.tsx +++ b/src/app/boards/[...boardId]/components/NewCardForm.tsx @@ -14,6 +14,7 @@ import { useModal } from "~/app/providers/modal"; interface FormData { title: string; listPublicId: string; + memberPublicIds: string[]; } interface NewCardFormProps { @@ -34,9 +35,12 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) { defaultValues: { title: "", listPublicId, + memberPublicIds: [], }, }); + const memberPublicIds = watch("memberPublicIds") || []; + const refetchBoard = () => utils.board.byId.refetch({ id: boardData.publicId }); @@ -64,10 +68,18 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) { selected: list.publicId === watch("listPublicId"), })) ?? []; + const formattedMembers = + boardData?.workspace?.members?.map((member) => ({ + key: member.publicId, + value: member.user.name, + selected: memberPublicIds.includes(member.publicId), + })) ?? []; + const onSubmit = (data: FormData) => { createCard.mutate({ title: data.title, listPublicId: data.listPublicId, + memberPublicIds: data.memberPublicIds, }); reset(); }; @@ -76,6 +88,17 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) { setValue("listPublicId", listPublicId); }; + const handleSelectMembers = (memberPublicId: string): void => { + const currentIndex = memberPublicIds.indexOf(memberPublicId); + if (currentIndex === -1) { + setValue("memberPublicIds", [...memberPublicIds, memberPublicId]); + } else { + const newMemberPublicIds = [...memberPublicIds]; + newMemberPublicIds.splice(currentIndex, 1); + setValue("memberPublicIds", newMemberPublicIds); + } + }; + const selectedList = formattedLists.find((item) => item.selected); return ( @@ -105,16 +128,59 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) { className="block w-full rounded-md border-0 bg-dark-300 bg-white/5 py-1.5 text-dark-1000 shadow-sm ring-1 ring-inset ring-dark-700 focus:ring-2 focus:ring-inset focus:ring-dark-700 sm:text-sm sm:leading-6" /> -
- handleSelectList(list.key)} - > -
- {selectedList?.value} -
-
+
+
+ + handleSelectList(list.key) + } + > +
+ {selectedList?.value} +
+
+
+
+ + handleSelectMembers(list.key) + } + > +
+ {!memberPublicIds.length ? ( + "Members" + ) : ( + <> + {memberPublicIds.map((memberPublicId) => { + const member = formattedMembers.find( + (member) => member.key === memberPublicId, + ); + + return ( + + + {member?.value + .split(" ") + .map((namePart) => + namePart.charAt(0).toUpperCase(), + ) + .join("")} + + + ); + })} + + )} +
+
+
+
Create more (undefined); diff --git a/src/server/api/routers/board.ts b/src/server/api/routers/board.ts index 849a7a3d..c2d72ab9 100644 --- a/src/server/api/routers/board.ts +++ b/src/server/api/routers/board.ts @@ -43,6 +43,25 @@ export const boardRouter = createTRPCRouter({ 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), diff --git a/src/server/api/routers/card.ts b/src/server/api/routers/card.ts index 29c148f3..56715a68 100644 --- a/src/server/api/routers/card.ts +++ b/src/server/api/routers/card.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { and, desc, eq, isNull, sql } from "drizzle-orm"; +import { and, desc, eq, isNull, inArray, sql } from "drizzle-orm"; import { cards, cardsToLabels, cardToWorkspaceMembers, labels, lists, workspaceMembers } from "~/server/db/schema"; import { generateUID } from "~/utils/generateUID"; @@ -15,6 +15,7 @@ export const cardRouter = createTRPCRouter({ z.object({ title: z.string().min(1), listPublicId: z.string().min(12), + memberPublicIds: z.array(z.string().min(12)) }), ) .mutation(({ ctx, input }) => { @@ -40,13 +41,27 @@ export const cardRouter = createTRPCRouter({ orderBy: desc(cards.index) }); - return tx.insert(cards).values({ + const newCard = await tx.insert(cards).values({ publicId: generateUID(), title: input.title, createdBy: userId, listId: list.id, index: latestCard ? latestCard.index + 1 : 0 }); + + if (newCard.insertId && input.memberPublicIds.length) { + const members = await tx.query.workspaceMembers.findMany({ + where: inArray(workspaceMembers.publicId, input.memberPublicIds), + }); + + if (!members.length) return; + + const membersInsert = members.map((member) => ({ cardId: Number(newCard.insertId), workspaceMemberId: member.id})) + + await tx.insert(cardToWorkspaceMembers).values(membersInsert); + } + + return newCard; }) }), addOrRemoveLabel: publicProcedure