diff --git a/src/providers/board.tsx b/src/providers/board.tsx index 6143f514..98fcab88 100644 --- a/src/providers/board.tsx +++ b/src/providers/board.tsx @@ -6,10 +6,12 @@ import React, { } from "react"; import { api } from "~/utils/api"; +import { generateUID } from "~/utils/generateUID"; import { usePopup } from "~/providers/popup"; import { type GetBoardByIdOutput, + type NewCardInput, type ReorderCardInput, type ReorderListInput, } from "~/types/router.types"; @@ -19,6 +21,8 @@ interface BoardContextProps { setBoardData: React.Dispatch>; updateList: (params: ReorderListInput) => void; updateCard: (params: ReorderCardInput) => void; + addCard: (params: NewCardInput) => void; + refetchBoard: () => void; } const initialBoardData: GetBoardByIdOutput = { @@ -44,12 +48,18 @@ export const BoardProvider: React.FC<{ children: ReactNode }> = ({ const { showPopup } = usePopup(); const refetchBoard = async () => { - if (boardData?.publicId) { - try { - await utils.board.byId.refetch({ boardPublicId: boardData.publicId }); - } catch (e) { - console.error(e); - } + if (!boardData?.publicId) return; + + try { + const data = await utils.board.byId.fetch({ + boardPublicId: boardData.publicId, + }); + if (data) setBoardData(data); + } catch (e) { + showPopup({ + header: "Error fetching board", + message: "Please try again later, or contact customer support.", + }); } }; @@ -75,6 +85,50 @@ export const BoardProvider: React.FC<{ children: ReactNode }> = ({ }, }); + const addCard = ({ + title, + listPublicId, + labelPublicIds, + memberPublicIds, + position, + }: { + title: string; + listPublicId: string; + labelPublicIds: string[]; + memberPublicIds: string[]; + position: "start" | "end"; + }) => { + if (!boardData) return; + + const updatedLists = boardData.lists.map((list) => { + if (list.publicId === listPublicId) { + const newCard = { + publicId: generateUID(), + title, + listId: 2, + description: "", + labels: boardData.labels.filter((label) => + labelPublicIds.includes(label.publicId), + ), + members: + boardData.workspace?.members.filter((member) => + memberPublicIds.includes(member.publicId), + ) || [], + index: position === "start" ? 0 : list.cards.length, + }; + + const updatedCards = + position === "start" + ? [newCard, ...list.cards] + : [...list.cards, newCard]; + return { ...list, cards: updatedCards }; + } + return list; + }); + + setBoardData({ ...boardData, lists: updatedLists }); + }; + const updateList = ({ boardId, listId, @@ -99,16 +153,23 @@ export const BoardProvider: React.FC<{ children: ReactNode }> = ({ return ( {children} ); }; -export const useBoard = (): BoardContextProps => { +export const useBoard = () => { const context = useContext(BoardContext); - if (!context) { + if (context === undefined) { throw new Error("useBoard must be used within a BoardProvider"); } return context; diff --git a/src/views/board/components/NewCardForm.tsx b/src/views/board/components/NewCardForm.tsx index 7f67e760..861ce2bd 100644 --- a/src/views/board/components/NewCardForm.tsx +++ b/src/views/board/components/NewCardForm.tsx @@ -11,8 +11,10 @@ import { import { Switch } from "@headlessui/react"; import CheckboxDropdown from "~/components/CheckboxDropdown"; + import { useBoard } from "~/providers/board"; import { useModal } from "~/providers/modal"; +import { usePopup } from "~/providers/popup"; import { type NewCardInput } from "~/types/router.types"; @@ -30,7 +32,8 @@ function classNames(...classes: string[]): string { export function NewCardForm({ listPublicId }: NewCardFormProps) { const utils = api.useUtils(); - const { boardData } = useBoard(); + const { boardData, addCard, refetchBoard } = useBoard(); + const { showPopup } = usePopup(); const { closeModal } = useModal(); const { register, handleSubmit, reset, setValue, watch } = @@ -50,31 +53,17 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) { const isCreateAnotherEnabled = watch("isCreateAnotherEnabled"); const position = watch("position"); - const refetchBoard = async () => { - if (boardData?.publicId) { - try { - await utils.board.byId.refetch({ boardPublicId: boardData.publicId }); - } catch (e) { - console.error(e); - } - } - }; - const createCard = api.card.create.useMutation({ onSuccess: async () => { - try { - await refetchBoard(); - if (!isCreateAnotherEnabled) closeModal(); - reset({ - title: "", - listPublicId: watch("listPublicId"), - labelPublicIds: [], - memberPublicIds: [], - isCreateAnotherEnabled: watch("isCreateAnotherEnabled"), - }); - } catch (e) { - console.log(e); - } + refetchBoard(); + }, + onError: async () => { + closeModal(); + refetchBoard(); + showPopup({ + header: "Unable to create card", + message: "Please try again later, or contact customer support.", + }); }, }); @@ -106,6 +95,17 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) { })) ?? []; const onSubmit = (data: NewCardInput) => { + addCard(data); + const isCreateAnotherEnabled = watch("isCreateAnotherEnabled"); + if (!isCreateAnotherEnabled) closeModal(); + reset({ + title: "", + listPublicId: watch("listPublicId"), + labelPublicIds: [], + memberPublicIds: [], + isCreateAnotherEnabled, + }); + createCard.mutate({ title: data.title, listPublicId: data.listPublicId, @@ -277,9 +277,10 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) {