diff --git a/src/app/boards/[...id]/page.tsx b/src/app/boards/[...id]/page.tsx index f3962961..aa3b3caa 100644 --- a/src/app/boards/[...id]/page.tsx +++ b/src/app/boards/[...id]/page.tsx @@ -141,9 +141,7 @@ export default function BoardPage() { updateCard({ cardId: draggableId, - currentListId: source.droppableId, newListId: destination.droppableId, - currentIndex: source.index, newIndex: destination.index, }); } @@ -163,7 +161,7 @@ export default function BoardPage() { value={formik.values.name} onChange={formik.handleChange} onBlur={formik.submitForm} - className="block border-0 bg-transparent p-0 py-1.5 font-medium tracking-tight text-dark-1000 focus:ring-0 focus-visible:outline-none sm:text-[1.2rem] sm:leading-6" + className="block border-0 bg-transparent p-0 py-0 font-medium leading-[2.3rem] tracking-tight text-dark-1000 focus:ring-0 focus-visible:outline-none sm:text-[1.2rem]" />
@@ -182,7 +180,7 @@ export default function BoardPage() {
-
+
{(provided) => ( @@ -206,7 +204,7 @@ export default function BoardPage() {
{list.cards?.map((card, index) => ( utils.card.byId.refetch({ id: cardPublicId }); + + const updateCardList = api.card.reorder.useMutation({ + onSuccess: async () => { + await refetchCard(); + }, + }); + + const formik = useFormik({ + initialValues: { + ...Object.fromEntries( + lists?.map((list) => [list.publicId, list.selected]) ?? [], + ), + }, + onSubmit: (values) => { + console.log({ values }); + }, + enableReinitialize: true, + }); + + const selectedList = lists.find((list) => list.selected); + + return ( + <> + + + {selectedList?.name} + + + + +
+
+ {lists?.map((list) => ( + + {() => ( +
{ + e.preventDefault(); + await formik.setFieldValue( + list.publicId, + !formik.values[list.publicId], + ); + + updateCardList.mutate({ + cardId: cardPublicId, + newListId: list.publicId, + }); + + await formik.submitForm(); + }} + > + event.stopPropagation()} + onChange={formik.handleChange} + checked={formik.values[list.publicId]} + /> + +
+ )} +
+ ))} +
+
+
+
+
+ + ); +} diff --git a/src/app/cards/[...id]/components/NewLabelForm.tsx b/src/app/cards/[...id]/components/NewLabelForm.tsx index 740710e7..65316909 100644 --- a/src/app/cards/[...id]/components/NewLabelForm.tsx +++ b/src/app/cards/[...id]/components/NewLabelForm.tsx @@ -1,4 +1,3 @@ -"use client"; import { Fragment, useState } from "react"; import { Listbox, Transition } from "@headlessui/react"; import { api } from "~/trpc/react"; diff --git a/src/app/cards/[...id]/page.tsx b/src/app/cards/[...id]/page.tsx index d72e27a7..3b17a2f1 100644 --- a/src/app/cards/[...id]/page.tsx +++ b/src/app/cards/[...id]/page.tsx @@ -1,12 +1,15 @@ "use client"; +import Link from "next/link"; import { useParams } from "next/navigation"; import { useFormik } from "formik"; import ContentEditable from "react-contenteditable"; +import { IoChevronForwardSharp } from "react-icons/io5"; import Dropdown from "./components/Dropdown"; import { DeleteCardConfirmation } from "./components/DeleteCardConfirmation"; import LabelSelector from "./components/LabelSelector"; +import ListSelector from "./components/ListSelector"; import { NewLabelForm } from "./components/NewLabelForm"; import Modal from "~/app/_components/modal"; @@ -30,6 +33,7 @@ export default function CardPage() { const boardId = data?.list?.board?.publicId; const labels = data?.list?.board?.labels; + const board = data?.list?.board; const selectedLabels = data?.labels; const formattedLabels = @@ -45,6 +49,12 @@ export default function CardPage() { }; }) ?? []; + const formattedLists = + board?.lists.map((list) => ({ + ...list, + selected: list.publicId === data?.list.publicId, + })) ?? []; + const updateCard = api.card.update.useMutation(); const formik = useFormik({ @@ -68,7 +78,14 @@ export default function CardPage() { return (
-
+
+ + {board?.name} + +
@@ -103,8 +120,12 @@ export default function CardPage() {
+
+

List

+ +
-

Labels

+

Labels

diff --git a/src/app/providers/board.tsx b/src/app/providers/board.tsx index d99f1cb9..4ffaae7d 100644 --- a/src/app/providers/board.tsx +++ b/src/app/providers/board.tsx @@ -44,9 +44,7 @@ interface UpdateListParams { interface UpdateCardParams { cardId: string; - currentListId: string; newListId: string; - currentIndex: number; newIndex: number; } @@ -101,18 +99,10 @@ export const BoardProvider: React.FC<{ children: ReactNode }> = ({ }); }; - const updateCard = ({ - cardId, - currentListId, - newListId, - currentIndex, - newIndex, - }: UpdateCardParams) => { + const updateCard = ({ cardId, newListId, newIndex }: UpdateCardParams) => { updateCardMutation.mutate({ cardId, - currentListId, newListId, - currentIndex, newIndex, }); }; diff --git a/src/server/api/routers/card.ts b/src/server/api/routers/card.ts index 4592154e..5258eeed 100644 --- a/src/server/api/routers/card.ts +++ b/src/server/api/routers/card.ts @@ -114,6 +114,7 @@ export const cardRouter = createTRPCRouter({ board: { columns: { publicId: true, + name: true, }, with: { labels: { @@ -122,6 +123,13 @@ export const cardRouter = createTRPCRouter({ colourCode: true, name: true, } + }, + lists: { + columns: { + publicId: true, + name: true, + }, + where: isNull(lists.deletedAt) } } } @@ -171,10 +179,8 @@ export const cardRouter = createTRPCRouter({ .input( z.object({ cardId: z.string().min(12), - currentListId: z.string().min(12), newListId: z.string().min(12), - currentIndex: z.number(), - newIndex: z.number() + newIndex: z.number().optional(), })) .mutation(({ ctx, input }) => { const userId = ctx.session?.user.id; @@ -182,8 +188,36 @@ export const cardRouter = createTRPCRouter({ if (!userId) return; return ctx.db.transaction(async (tx) => { - const [currentList] = await tx.select({ id: lists.id }).from(lists).where(and(eq(lists.publicId, input.currentListId))) - const [newList] = await tx.select({ id: lists.id }).from(lists).where(and(eq(lists.publicId, input.newListId))) + const card = await tx.query.cards.findFirst({ + with: { + list: true, + }, + where: and(eq(cards.publicId, input.cardId), isNull(cards.deletedAt)), + }); + + if (!card) return; + + const currentList = card.list; + const currentIndex = card.index; + + let newIndex = input.newIndex; + + const newList = await tx.query.lists.findFirst({ + with: { + cards: { + orderBy: [desc(cards.index)], + limit: 1, + }, + }, + where: and(eq(lists.publicId, input.newListId), isNull(cards.deletedAt)), + }); + + if (!newList) return; + + if (!newIndex) { + const lastCardIndex = newList.cards[0]?.index; + newIndex = lastCardIndex ? lastCardIndex + 1 : 0; + } if (!currentList?.id || !newList?.id) return; @@ -192,21 +226,21 @@ export const cardRouter = createTRPCRouter({ UPDATE ${cards} SET ${cards.index} = CASE - WHEN ${cards.index} = ${input.currentIndex} THEN ${input.newIndex} - WHEN ${input.currentIndex} < ${input.newIndex} AND ${cards.index} > ${input.currentIndex} AND ${cards.index} <= ${input.newIndex} THEN ${cards.index} - 1 - WHEN ${input.currentIndex} > ${input.newIndex} AND ${cards.index} >= ${input.newIndex} AND ${cards.index} < ${input.currentIndex} THEN ${cards.index} + 1 + WHEN ${cards.index} = ${currentIndex} THEN ${newIndex} + WHEN ${currentIndex} < ${newIndex} AND ${cards.index} > ${currentIndex} AND ${cards.index} <= ${newIndex} THEN ${cards.index} - 1 + WHEN ${currentIndex} > ${newIndex} AND ${cards.index} >= ${newIndex} AND ${cards.index} < ${currentIndex} THEN ${cards.index} + 1 ELSE ${cards.index} END WHERE ${cards.listId} = ${currentList.id} AND ${cards.deletedAt} IS NULL; `); } else { - await tx.execute(sql`UPDATE ${cards} SET ${cards.index} = ${cards.index} + 1 WHERE ${cards.listId} = ${newList.id} AND ${cards.index} >= ${input.newIndex} AND ${cards.deletedAt} IS NULL;`) + await tx.execute(sql`UPDATE ${cards} SET ${cards.index} = ${cards.index} + 1 WHERE ${cards.listId} = ${newList.id} AND ${cards.index} >= ${newIndex} AND ${cards.deletedAt} IS NULL;`) - await tx.execute(sql`UPDATE ${cards} SET ${cards.index} = ${cards.index} - 1 WHERE ${cards.listId} = ${currentList.id} AND ${cards.index} >= ${input.currentIndex} AND ${cards.deletedAt} IS NULL;`) + await tx.execute(sql`UPDATE ${cards} SET ${cards.index} = ${cards.index} - 1 WHERE ${cards.listId} = ${currentList.id} AND ${cards.index} >= ${currentIndex} AND ${cards.deletedAt} IS NULL;`) await tx .update(cards) - .set({ listId: newList.id, index: input.newIndex }) + .set({ listId: newList.id, index: newIndex }) .where(and(eq(cards.publicId, input.cardId), isNull(cards.deletedAt))); } })