From 0a0bfe9c76157344258e1c8137520cdc576b13cd Mon Sep 17 00:00:00 2001 From: Henry Date: Sat, 30 Dec 2023 13:44:20 +0000 Subject: [PATCH] feat: create new label --- src/app/_components/modal.tsx | 2 +- .../[...id]/components/LabelSelector.tsx | 12 +- .../cards/[...id]/components/NewLabelForm.tsx | 164 ++++++++++++++++++ src/app/cards/[...id]/page.tsx | 4 + src/server/api/root.ts | 2 + src/server/api/routers/label.ts | 54 ++++++ src/server/api/routers/list.ts | 2 - 7 files changed, 236 insertions(+), 4 deletions(-) create mode 100644 src/app/cards/[...id]/components/NewLabelForm.tsx create mode 100644 src/server/api/routers/label.ts diff --git a/src/app/_components/modal.tsx b/src/app/_components/modal.tsx index a0d6f849..07fe1037 100644 --- a/src/app/_components/modal.tsx +++ b/src/app/_components/modal.tsx @@ -38,7 +38,7 @@ const Modal: React.FC = ({ children }) => { leaveFrom="opacity-100 translate-y-0 sm:scale-100" leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" > - + {children} diff --git a/src/app/cards/[...id]/components/LabelSelector.tsx b/src/app/cards/[...id]/components/LabelSelector.tsx index 20cb5a39..35406856 100644 --- a/src/app/cards/[...id]/components/LabelSelector.tsx +++ b/src/app/cards/[...id]/components/LabelSelector.tsx @@ -4,6 +4,8 @@ import { Menu, Transition } from "@headlessui/react"; import { HiMiniPlus } from "react-icons/hi2"; import { useFormik } from "formik"; +import { useModal } from "~/app/providers/modal"; + interface LabelSelectorProps { cardPublicId: string; labels: { @@ -18,6 +20,7 @@ export default function LabelSelector({ cardPublicId, labels, }: LabelSelectorProps) { + const { openModal } = useModal(); const utils = api.useUtils(); const refetchCard = () => utils.card.byId.refetch({ id: cardPublicId }); @@ -122,7 +125,7 @@ export default function LabelSelector({ /> @@ -130,6 +133,13 @@ export default function LabelSelector({ )} ))} + diff --git a/src/app/cards/[...id]/components/NewLabelForm.tsx b/src/app/cards/[...id]/components/NewLabelForm.tsx new file mode 100644 index 00000000..740710e7 --- /dev/null +++ b/src/app/cards/[...id]/components/NewLabelForm.tsx @@ -0,0 +1,164 @@ +"use client"; +import { Fragment, useState } from "react"; +import { Listbox, Transition } from "@headlessui/react"; +import { api } from "~/trpc/react"; + +import { HiChevronUpDown, HiXMark } from "react-icons/hi2"; + +import { useModal } from "~/app/providers/modal"; + +import { Formik, Form, Field } from "formik"; + +interface FormValues { + name: string; + colour: Colour | undefined; +} + +interface Colour { + name: string; + code: string; +} + +interface cardPublicId { + cardPublicId: string; +} + +const colours = [ + { name: "Teal", code: "#0d9488" }, + { name: "Green", code: "#65a30d" }, + { name: "Blue", code: "#0284c7" }, + { name: "Purple", code: "#4f46e5" }, + { name: "Yellow", code: "#ca8a04" }, + { name: "Orange", code: "#ea580c " }, + { name: "Red", code: "#dc2626" }, + { name: "Pink", code: "#db2777" }, +]; + +export function NewLabelForm({ cardPublicId }: cardPublicId) { + const [selected, setSelected] = useState(colours[0]); + const utils = api.useUtils(); + const { closeModal } = useModal(); + + const refetchCard = () => utils.card.byId.refetch({ id: cardPublicId }); + + const createLabel = api.label.create.useMutation({ + onSuccess: async () => { + try { + await refetchCard(); + closeModal(); + } catch (e) { + console.log(e); + } + }, + }); + + return ( + <> +
+

New label

+ +
+ + { + if (!values.colour?.code) return; + + createLabel.mutate({ + name: values.name, + cardPublicId, + colourCode: values.colour.code, + }); + }} + > +
+ + + + {({ open }) => ( + <> +
+ + + + + {selected?.name} + + + + + + + + + {colours.map((colour, index) => ( + + {() => ( + <> +
+
+ + )} +
+ ))} +
+
+
+ + )} +
+
+ +
+ +
+ + ); +} diff --git a/src/app/cards/[...id]/page.tsx b/src/app/cards/[...id]/page.tsx index 1e7f6a5d..d72e27a7 100644 --- a/src/app/cards/[...id]/page.tsx +++ b/src/app/cards/[...id]/page.tsx @@ -7,6 +7,7 @@ import ContentEditable from "react-contenteditable"; import Dropdown from "./components/Dropdown"; import { DeleteCardConfirmation } from "./components/DeleteCardConfirmation"; import LabelSelector from "./components/LabelSelector"; +import { NewLabelForm } from "./components/NewLabelForm"; import Modal from "~/app/_components/modal"; import { useModal } from "~/app/providers/modal"; @@ -109,6 +110,9 @@ export default function CardPage() { + {modalContentType === "NEW_LABEL" && ( + + )} {modalContentType === "DELETE_CARD" && ( { + const userId = ctx.session?.user.id; + + if (!userId) return; + + return ctx.db.transaction(async (tx) => { + const card = await tx.query.cards.findFirst({ + where: and(eq(cards.publicId, input.cardPublicId), isNull(cards.deletedAt)), + with: { + list: { + with: { + board: true + } + } + } + }); + + if (!card) return; + + const newLabel = await tx.insert(labels).values({ + publicId: generateUID(), + name: input.name, + colourCode: input.colourCode, + createdBy: userId, + boardId: card.list.boardId, + }); + + return tx.insert(cardsToLabels).values({ + cardId: card.id, + labelId: Number(newLabel.insertId), + }); + }) + }), +}); \ No newline at end of file diff --git a/src/server/api/routers/list.ts b/src/server/api/routers/list.ts index d5660980..64e0a1ae 100644 --- a/src/server/api/routers/list.ts +++ b/src/server/api/routers/list.ts @@ -79,7 +79,5 @@ export const listRouter = createTRPCRouter({ WHERE ${lists.boardId} = ${list.boardId}; `); }) - - }) }); \ No newline at end of file