From 20ef0f5ca25e615954735be1c3a7924b26ba0f57 Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 2 Jan 2024 17:38:13 +0000 Subject: [PATCH] feat: update list name --- src/app/boards/[...id]/components/List.tsx | 108 +++++++++++++++ src/app/boards/[...id]/page.tsx | 145 ++++++++------------- src/app/providers/board.tsx | 2 +- src/server/api/routers/list.ts | 17 ++- 4 files changed, 180 insertions(+), 92 deletions(-) create mode 100644 src/app/boards/[...id]/components/List.tsx diff --git a/src/app/boards/[...id]/components/List.tsx b/src/app/boards/[...id]/components/List.tsx new file mode 100644 index 00000000..c8124949 --- /dev/null +++ b/src/app/boards/[...id]/components/List.tsx @@ -0,0 +1,108 @@ +"use client"; + +import { type ReactNode } from "react"; +import { HiOutlinePlusSmall } from "react-icons/hi2"; +import { Draggable } from "react-beautiful-dnd"; +import { useFormik } from "formik"; + +import { api } from "~/trpc/react"; +import { useModal } from "~/app/providers/modal"; + +import ListDropdown from "./ListDropdown"; + +interface ListProps { + children: ReactNode; + index: number; + list: List; + setSelectedPublicListId: (publicListId: PublicListId) => void; +} + +interface List { + publicId: string; + name: string; +} + +interface FormValues { + listPublicId: string; + name: string; +} + +type PublicListId = string; + +export default function List({ + children, + index, + list, + setSelectedPublicListId, +}: ListProps) { + const { openModal } = useModal(); + + const openNewCardForm = (publicListId: PublicListId) => { + openModal("NEW_CARD"); + setSelectedPublicListId(publicListId); + }; + + const updateList = api.list.update.useMutation(); + + const formik = useFormik({ + initialValues: { + listPublicId: list.publicId, + name: list.name, + }, + onSubmit: (values: FormValues) => { + updateList.mutate({ + listPublicId: values.listPublicId, + name: values.name, + }); + }, + enableReinitialize: true, + }); + + return ( + + {(provided) => ( +
+
+
+ +
+
+ + + setSelectedPublicListId(list.publicId) + } + /> +
+
+ {children} +
+ )} +
+ ); +} diff --git a/src/app/boards/[...id]/page.tsx b/src/app/boards/[...id]/page.tsx index f55c0442..f3962961 100644 --- a/src/app/boards/[...id]/page.tsx +++ b/src/app/boards/[...id]/page.tsx @@ -21,7 +21,7 @@ import Modal from "~/app/_components/modal"; import BoardDropdown from "./components/BoardDropdown"; import { DeleteBoardConfirmation } from "./components/DeleteBoardConfirmation"; import { DeleteListConfirmation } from "./components/DeleteListConfirmation"; -import ListDropdown from "./components/ListDropdown"; +import List from "./components/List"; import { NewCardForm } from "./components/NewCardForm"; import { NewListForm } from "./components/NewListForm"; @@ -95,11 +95,6 @@ export default function BoardPage() { setSelectedPublicListId(publicBoardId); }; - const openNewCardForm = (publicListId: PublicListId) => { - openModal("NEW_CARD"); - setSelectedPublicListId(publicListId); - }; - const onDragEnd = ({ source, destination, @@ -198,94 +193,66 @@ export default function BoardPage() { >
{boardData?.lists?.map((list: List, index) => ( - + setSelectedPublicListId(publicListId) + } > - {(provided) => ( -
-
-

- {list.name} -

-
- - - setSelectedPublicListId(list.publicId) - } - /> -
-
- - {(provided) => ( -
- {list.cards?.map((card, index) => ( - ( + - {(provided) => ( - -
{card.title}
- {card.labels?.length ? ( -
- {card.labels.map(({ label }) => ( - - -
{label.name}
-
- ))} -
- ) : null} - - )} -
- ))} - {provided.placeholder} -
- )} -
-
- )} -
+
{card.title}
+ {card.labels?.length ? ( +
+ {card.labels.map(({ label }) => ( + + +
{label.name}
+
+ ))} +
+ ) : null} + + )} + + ))} + {provided.placeholder} +
+ )} + + ))}
{provided.placeholder} diff --git a/src/app/providers/board.tsx b/src/app/providers/board.tsx index cf999d6f..d99f1cb9 100644 --- a/src/app/providers/board.tsx +++ b/src/app/providers/board.tsx @@ -77,7 +77,7 @@ export const BoardProvider: React.FC<{ children: ReactNode }> = ({ }, }); - const updateListMutation = api.list.update.useMutation({ + const updateListMutation = api.list.reorder.useMutation({ onSuccess: async () => { try { await refetchBoard(); diff --git a/src/server/api/routers/list.ts b/src/server/api/routers/list.ts index e52d0e23..c28b0c1d 100644 --- a/src/server/api/routers/list.ts +++ b/src/server/api/routers/list.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { desc, eq, sql } from "drizzle-orm"; +import { and, desc, eq, sql, isNull } from "drizzle-orm"; import { boards, cards, lists } from "~/server/db/schema"; import { generateUID } from "~/utils/generateUID"; @@ -49,7 +49,7 @@ export const listRouter = createTRPCRouter({ }); }) }), - update: publicProcedure + reorder: publicProcedure .input( z.object({ boardId: z.string().min(12), @@ -104,4 +104,17 @@ export const listRouter = createTRPCRouter({ await tx.execute(sql`UPDATE ${lists} SET ${lists.index} = ${lists.index} - 1 WHERE ${lists.boardId} = ${list.boardId} AND ${lists.index} > ${list.index} AND ${lists.deletedAt} IS NULL;`); }) }), + update: publicProcedure + .input( + z.object({ + listPublicId: 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(lists).set({ name: input.name }).where(and(eq(lists.publicId, input.listPublicId), isNull(lists.deletedAt))); + }), }); \ No newline at end of file