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({