diff --git a/src/app/boards/[...id]/create.tsx b/src/app/boards/[...id]/create.tsx new file mode 100644 index 00000000..4bb4ae86 --- /dev/null +++ b/src/app/boards/[...id]/create.tsx @@ -0,0 +1,86 @@ +"use client"; + +import { api } from "~/trpc/react"; + +import { HiXMark } from "react-icons/hi2"; + +import { useBoard } from "~/app/providers/board"; +import { useModal } from "~/app/providers/modal"; + +import { Formik, Form, Field } from "formik"; + +interface FormValues { + title: string; +} + +interface listPublicId { + listPublicId: string; +} + +export function NewCardForm({ listPublicId }: listPublicId) { + const utils = api.useUtils(); + const { boardData } = useBoard(); + const { closeModal } = useModal(); + + const refetchBoard = () => + utils.board.byId.refetch({ id: boardData.publicId }); + + const createCard = api.card.create.useMutation({ + onSuccess: async () => { + try { + await refetchBoard(); + closeModal(); + } catch (e) { + console.log(e); + } + }, + }); + + return ( + <> +
+

New card

+ +
+ + { + createCard.mutate({ + title: values.title, + listPublicId, + }); + }} + > +
+ + +
+ +
+ +
+ + ); +} diff --git a/src/app/boards/[...id]/page.tsx b/src/app/boards/[...id]/page.tsx index f177b8ac..3da7b957 100644 --- a/src/app/boards/[...id]/page.tsx +++ b/src/app/boards/[...id]/page.tsx @@ -1,5 +1,7 @@ "use client"; +import { useState } from "react"; + import { useParams } from "next/navigation"; import { HiOutlinePlusSmall } from "react-icons/hi2"; import { @@ -11,6 +13,10 @@ import { import { api } from "~/trpc/react"; import { useBoard } from "~/app/providers/board"; +import { useModal } from "~/app/providers/modal"; + +import Modal from "~/app/_components/modal"; +import { NewCardForm } from "~/app/boards/[...id]/create"; interface List { publicId: string; @@ -23,9 +29,14 @@ interface Card { title: string; } +type PublicListId = string; + export default function BoardPage() { const params = useParams(); const { boardData, setBoardData, updateCard, updateList } = useBoard(); + const { openModal } = useModal(); + const [selectedPublicListId, setSelectedPublicListId] = + useState(""); const boardId = params?.id?.length && params.id[0]; @@ -40,6 +51,11 @@ export default function BoardPage() { }, ); + const openNewCardForm = (publicListId: PublicListId) => { + openModal(); + setSelectedPublicListId(publicListId); + }; + const onDragEnd = ({ source, destination, @@ -134,18 +150,29 @@ export default function BoardPage() { ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} - className="mr-5 w-72 rounded-md border border-dark-400 bg-dark-200 px-2 py-4" + className="mr-5 w-72 rounded-md border border-dark-400 bg-dark-200 px-2 py-2" > +
+

+ {list.name} +

+ +
{(provided) => (
-

- {list.name} -

- {list.cards?.map((card, index) => ( + + +
); } diff --git a/src/server/api/routers/card.ts b/src/server/api/routers/card.ts index f52ec692..6f5c715f 100644 --- a/src/server/api/routers/card.ts +++ b/src/server/api/routers/card.ts @@ -1,7 +1,8 @@ import { z } from "zod"; -import { eq, sql } from "drizzle-orm"; +import { desc, eq, sql } from "drizzle-orm"; import { cards, lists } from "~/server/db/schema"; +import { generateUID } from "~/utils/generateUID"; import { createTRPCRouter, @@ -9,6 +10,47 @@ import { } from "~/server/api/trpc"; export const cardRouter = createTRPCRouter({ + create: publicProcedure + .input( + z.object({ + title: z.string().min(1), + listPublicId: z.string().min(12), + }), + ) + .mutation(({ ctx, input }) => { + const userId = ctx.session?.user.id; + + if (!userId) return; + + + + return ctx.db.transaction(async (tx) => { + const list = await tx.query.lists.findFirst({ + where: eq(lists.publicId, input.listPublicId), + columns: { + id: true + } + }); + + if (!list) return; + + const latestCard = await tx.query.cards.findFirst({ + where: eq(cards.listId, list.id), + columns: { + index: true + }, + orderBy: desc(cards.index) + }); + + return tx.insert(cards).values({ + publicId: generateUID(), + title: input.title, + createdBy: userId, + listId: list.id, + index: latestCard ? latestCard.index + 1 : 0 + }); + }) + }), update: publicProcedure .input( z.object({