diff --git a/src/app/boards/[...id]/page.tsx b/src/app/boards/[...id]/page.tsx
index 5610631a..116335d8 100644
--- a/src/app/boards/[...id]/page.tsx
+++ b/src/app/boards/[...id]/page.tsx
@@ -2,7 +2,12 @@
import { useParams } from "next/navigation";
import { HiOutlinePlusSmall } from "react-icons/hi2";
-import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
+import {
+ DragDropContext,
+ Droppable,
+ type DropResult,
+ Draggable,
+} from "react-beautiful-dnd";
import { api } from "~/trpc/react";
@@ -19,6 +24,7 @@ interface Card {
export default function BoardPage() {
const params = useParams();
+ const utils = api.useUtils();
const boardId = params?.id?.length && params.id[0];
@@ -26,7 +32,35 @@ export default function BoardPage() {
const { data } = api.board.byId.useQuery({ id: boardId });
- const onDragEnd = () => null;
+ const refetchBoard = () => utils.board.byId.refetch({ id: boardId });
+
+ const updateCard = api.card.update.useMutation({
+ onSuccess: async () => {
+ try {
+ await refetchBoard();
+ } catch (e) {
+ console.log(e);
+ }
+ },
+ });
+
+ const onDragEnd = ({
+ source,
+ destination,
+ draggableId,
+ }: DropResult): void => {
+ if (!destination) {
+ return;
+ }
+
+ updateCard.mutate({
+ cardId: draggableId,
+ currentListId: source.droppableId,
+ newListId: destination.droppableId,
+ currentIndex: source.index,
+ newIndex: destination.index,
+ });
+ };
return (
diff --git a/src/server/api/root.ts b/src/server/api/root.ts
index 976ea23f..896e14cc 100644
--- a/src/server/api/root.ts
+++ b/src/server/api/root.ts
@@ -1,4 +1,5 @@
import { boardRouter } from "~/server/api/routers/board";
+import { cardRouter } from "~/server/api/routers/card";
import { createTRPCRouter } from "~/server/api/trpc";
/**
@@ -8,6 +9,7 @@ import { createTRPCRouter } from "~/server/api/trpc";
*/
export const appRouter = createTRPCRouter({
board: boardRouter,
+ card: cardRouter
});
// export type definition of API
diff --git a/src/server/api/routers/card.ts b/src/server/api/routers/card.ts
new file mode 100644
index 00000000..b0d6d725
--- /dev/null
+++ b/src/server/api/routers/card.ts
@@ -0,0 +1,43 @@
+import { z } from "zod";
+import { and, eq, gte, or} from "drizzle-orm";
+
+import { cards, lists } from "~/server/db/schema";
+
+import {
+ createTRPCRouter,
+ publicProcedure,
+} from "~/server/api/trpc";
+
+export const cardRouter = createTRPCRouter({
+ update: publicProcedure
+ .input(
+ z.object({
+ cardId: z.string().min(12),
+ currentListId: z.string().min(12),
+ newListId: z.string().min(12),
+ currentIndex: z.number(),
+ newIndex: z.number()
+ }))
+ .mutation(({ ctx, input }) => {
+ const userId = ctx.session?.user.id;
+
+ if (!userId) return;
+
+ return ctx.db.transaction(async (tx) => {
+ const [currentList, newList] = await tx.select({ id: lists.id }).from(lists).where(or(eq(lists.publicId, input.currentListId), eq(lists.publicId, input.newListId)))
+
+
+ if (!currentList?.id || !newList?.id) return;
+
+ await tx
+ .update(cards)
+ .set({ index: input.newIndex + 1 })
+ .where(and(eq(cards.listId, newList.id), gte(cards.index, input.newIndex)))
+
+ await tx
+ .update(cards)
+ .set({ listId: newList.id, index: input.newIndex })
+ .where(eq(cards.publicId, input.cardId))
+ })
+ }),
+});
\ No newline at end of file