feat: create new card immediately displays new card
This commit is contained in:
@@ -6,10 +6,12 @@ import React, {
|
|||||||
} from "react";
|
} from "react";
|
||||||
|
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
|
import { generateUID } from "~/utils/generateUID";
|
||||||
import { usePopup } from "~/providers/popup";
|
import { usePopup } from "~/providers/popup";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type GetBoardByIdOutput,
|
type GetBoardByIdOutput,
|
||||||
|
type NewCardInput,
|
||||||
type ReorderCardInput,
|
type ReorderCardInput,
|
||||||
type ReorderListInput,
|
type ReorderListInput,
|
||||||
} from "~/types/router.types";
|
} from "~/types/router.types";
|
||||||
@@ -19,6 +21,8 @@ interface BoardContextProps {
|
|||||||
setBoardData: React.Dispatch<React.SetStateAction<GetBoardByIdOutput>>;
|
setBoardData: React.Dispatch<React.SetStateAction<GetBoardByIdOutput>>;
|
||||||
updateList: (params: ReorderListInput) => void;
|
updateList: (params: ReorderListInput) => void;
|
||||||
updateCard: (params: ReorderCardInput) => void;
|
updateCard: (params: ReorderCardInput) => void;
|
||||||
|
addCard: (params: NewCardInput) => void;
|
||||||
|
refetchBoard: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialBoardData: GetBoardByIdOutput = {
|
const initialBoardData: GetBoardByIdOutput = {
|
||||||
@@ -44,12 +48,18 @@ export const BoardProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
const { showPopup } = usePopup();
|
const { showPopup } = usePopup();
|
||||||
|
|
||||||
const refetchBoard = async () => {
|
const refetchBoard = async () => {
|
||||||
if (boardData?.publicId) {
|
if (!boardData?.publicId) return;
|
||||||
try {
|
|
||||||
await utils.board.byId.refetch({ boardPublicId: boardData.publicId });
|
try {
|
||||||
} catch (e) {
|
const data = await utils.board.byId.fetch({
|
||||||
console.error(e);
|
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 = ({
|
const updateList = ({
|
||||||
boardId,
|
boardId,
|
||||||
listId,
|
listId,
|
||||||
@@ -99,16 +153,23 @@ export const BoardProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<BoardContext.Provider
|
<BoardContext.Provider
|
||||||
value={{ boardData, setBoardData, updateList, updateCard }}
|
value={{
|
||||||
|
boardData,
|
||||||
|
setBoardData,
|
||||||
|
updateList,
|
||||||
|
updateCard,
|
||||||
|
addCard,
|
||||||
|
refetchBoard,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</BoardContext.Provider>
|
</BoardContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useBoard = (): BoardContextProps => {
|
export const useBoard = () => {
|
||||||
const context = useContext(BoardContext);
|
const context = useContext(BoardContext);
|
||||||
if (!context) {
|
if (context === undefined) {
|
||||||
throw new Error("useBoard must be used within a BoardProvider");
|
throw new Error("useBoard must be used within a BoardProvider");
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
|
|||||||
@@ -11,8 +11,10 @@ import {
|
|||||||
import { Switch } from "@headlessui/react";
|
import { Switch } from "@headlessui/react";
|
||||||
|
|
||||||
import CheckboxDropdown from "~/components/CheckboxDropdown";
|
import CheckboxDropdown from "~/components/CheckboxDropdown";
|
||||||
|
|
||||||
import { useBoard } from "~/providers/board";
|
import { useBoard } from "~/providers/board";
|
||||||
import { useModal } from "~/providers/modal";
|
import { useModal } from "~/providers/modal";
|
||||||
|
import { usePopup } from "~/providers/popup";
|
||||||
|
|
||||||
import { type NewCardInput } from "~/types/router.types";
|
import { type NewCardInput } from "~/types/router.types";
|
||||||
|
|
||||||
@@ -30,7 +32,8 @@ function classNames(...classes: string[]): string {
|
|||||||
|
|
||||||
export function NewCardForm({ listPublicId }: NewCardFormProps) {
|
export function NewCardForm({ listPublicId }: NewCardFormProps) {
|
||||||
const utils = api.useUtils();
|
const utils = api.useUtils();
|
||||||
const { boardData } = useBoard();
|
const { boardData, addCard, refetchBoard } = useBoard();
|
||||||
|
const { showPopup } = usePopup();
|
||||||
const { closeModal } = useModal();
|
const { closeModal } = useModal();
|
||||||
|
|
||||||
const { register, handleSubmit, reset, setValue, watch } =
|
const { register, handleSubmit, reset, setValue, watch } =
|
||||||
@@ -50,31 +53,17 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) {
|
|||||||
const isCreateAnotherEnabled = watch("isCreateAnotherEnabled");
|
const isCreateAnotherEnabled = watch("isCreateAnotherEnabled");
|
||||||
const position = watch("position");
|
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({
|
const createCard = api.card.create.useMutation({
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
try {
|
refetchBoard();
|
||||||
await refetchBoard();
|
},
|
||||||
if (!isCreateAnotherEnabled) closeModal();
|
onError: async () => {
|
||||||
reset({
|
closeModal();
|
||||||
title: "",
|
refetchBoard();
|
||||||
listPublicId: watch("listPublicId"),
|
showPopup({
|
||||||
labelPublicIds: [],
|
header: "Unable to create card",
|
||||||
memberPublicIds: [],
|
message: "Please try again later, or contact customer support.",
|
||||||
isCreateAnotherEnabled: watch("isCreateAnotherEnabled"),
|
});
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -106,6 +95,17 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) {
|
|||||||
})) ?? [];
|
})) ?? [];
|
||||||
|
|
||||||
const onSubmit = (data: NewCardInput) => {
|
const onSubmit = (data: NewCardInput) => {
|
||||||
|
addCard(data);
|
||||||
|
const isCreateAnotherEnabled = watch("isCreateAnotherEnabled");
|
||||||
|
if (!isCreateAnotherEnabled) closeModal();
|
||||||
|
reset({
|
||||||
|
title: "",
|
||||||
|
listPublicId: watch("listPublicId"),
|
||||||
|
labelPublicIds: [],
|
||||||
|
memberPublicIds: [],
|
||||||
|
isCreateAnotherEnabled,
|
||||||
|
});
|
||||||
|
|
||||||
createCard.mutate({
|
createCard.mutate({
|
||||||
title: data.title,
|
title: data.title,
|
||||||
listPublicId: data.listPublicId,
|
listPublicId: data.listPublicId,
|
||||||
@@ -277,9 +277,10 @@ export function NewCardForm({ listPublicId }: NewCardFormProps) {
|
|||||||
</CheckboxDropdown>
|
</CheckboxDropdown>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() =>
|
onClick={(e) => {
|
||||||
setValue("position", position === "start" ? "end" : "start")
|
e.preventDefault();
|
||||||
}
|
setValue("position", position === "start" ? "end" : "start");
|
||||||
|
}}
|
||||||
className="flex h-auto items-center rounded-[5px] border-[1px] border-light-600 bg-light-200 px-1.5 py-1 text-left text-xs text-light-800 hover:bg-light-300 dark:border-dark-600 dark:bg-dark-400 dark:text-dark-1000 dark:hover:bg-dark-500"
|
className="flex h-auto items-center rounded-[5px] border-[1px] border-light-600 bg-light-200 px-1.5 py-1 text-left text-xs text-light-800 hover:bg-light-300 dark:border-dark-600 dark:bg-dark-400 dark:text-dark-1000 dark:hover:bg-dark-500"
|
||||||
>
|
>
|
||||||
{position === "start" ? (
|
{position === "start" ? (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { HiOutlinePlusSmall } from "react-icons/hi2";
|
import { HiOutlinePlusSmall } from "react-icons/hi2";
|
||||||
@@ -61,9 +61,11 @@ export default function BoardPage() {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isSuccess && data) {
|
useEffect(() => {
|
||||||
setBoardData(data);
|
if (isSuccess && data) {
|
||||||
}
|
setBoardData(data);
|
||||||
|
}
|
||||||
|
}, [isSuccess, data, setBoardData]);
|
||||||
|
|
||||||
if (!boardId || !boardData) return <></>;
|
if (!boardId || !boardData) return <></>;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user