diff --git a/src/components/modal.tsx b/src/components/modal.tsx index 1f1f70fc..7925e8ed 100644 --- a/src/components/modal.tsx +++ b/src/components/modal.tsx @@ -11,8 +11,6 @@ interface Props { const Modal: React.FC = ({ children, modalSize = "sm" }) => { const { isOpen, closeModal } = useModal(); - console.log({ modalSize }); - const modalSizeMap = { sm: "max-w-[400px]", md: "max-w-[550px]", diff --git a/src/server/api/routers/label.ts b/src/server/api/routers/label.ts index 148d5b0a..f8085fa3 100644 --- a/src/server/api/routers/label.ts +++ b/src/server/api/routers/label.ts @@ -70,4 +70,21 @@ export const labelRouter = createTRPCRouter({ return result; }), + delete: protectedProcedure + .input(z.object({ publicId: z.string().min(12) })) + .mutation(async ({ ctx, input }) => { + const label = await labelRepo.getByPublicId(ctx.db, input.publicId); + + if (!label) + throw new TRPCError({ + message: `Label with public ID ${input.publicId} not found`, + code: "NOT_FOUND", + }); + + await cardRepo.destroyAllCardLabelRelationships(ctx.db, label.id); + + await labelRepo.destroy(ctx.db, label.id); + + return { success: true }; + }), }); diff --git a/src/server/db/repository/card.repo.ts b/src/server/db/repository/card.repo.ts index b8b57408..b57dff62 100644 --- a/src/server/db/repository/card.repo.ts +++ b/src/server/db/repository/card.repo.ts @@ -181,6 +181,15 @@ export const destroyCardLabelRelationship = async ( return result; }; +export const destroyAllCardLabelRelationships = async ( + db: SupabaseClient, + labelId: number, +) => { + const result = await db.from("_card_labels").delete().eq("labelId", labelId); + + return result; +}; + export const createCardLabelRelationship = async ( db: SupabaseClient, cardLabelRelationshipInput: { cardId: number; labelId: number }, diff --git a/src/server/db/repository/label.repo.ts b/src/server/db/repository/label.repo.ts index 01c91160..a839ce7b 100644 --- a/src/server/db/repository/label.repo.ts +++ b/src/server/db/repository/label.repo.ts @@ -78,3 +78,12 @@ export const update = async ( return data; }; + +export const destroy = async ( + db: SupabaseClient, + labelId: number, +) => { + const { data } = await db.from("label").delete().eq("id", labelId); + + return data; +}; diff --git a/src/views/card/components/DeleteLabelConfirmation.tsx b/src/views/card/components/DeleteLabelConfirmation.tsx new file mode 100644 index 00000000..5f2d39ec --- /dev/null +++ b/src/views/card/components/DeleteLabelConfirmation.tsx @@ -0,0 +1,54 @@ +import { api } from "~/utils/api"; +import { useModal } from "~/providers/modal"; +import { usePopup } from "~/providers/popup"; + +import Button from "~/components/Button"; + +export function DeleteLabelConfirmation({ + cardPublicId, + labelPublicId, +}: { + cardPublicId: string; + labelPublicId: string; +}) { + const utils = api.useUtils(); + const { closeModal } = useModal(); + const { showPopup } = usePopup(); + + const refetchCard = () => utils.card.byId.refetch({ id: cardPublicId }); + + const deleteLabelMutation = api.label.delete.useMutation({ + onSuccess: () => refetchCard(), + onError: () => + showPopup({ + header: "Error deleting label", + message: "Please try again later, or contact customer support.", + }), + }); + + const handleDeleteLabel = () => { + closeModal(); + deleteLabelMutation.mutate({ + publicId: labelPublicId, + }); + }; + + return ( +
+
+

+ Are you sure you want to delete this label? +

+

+ {"This action can't be undone."} +

+
+
+ + +
+
+ ); +} diff --git a/src/views/card/components/LabelForm.tsx b/src/views/card/components/LabelForm.tsx index 6b1a0503..586276a9 100644 --- a/src/views/card/components/LabelForm.tsx +++ b/src/views/card/components/LabelForm.tsx @@ -40,7 +40,7 @@ export function LabelForm({ isEdit?: boolean; }) { const utils = api.useUtils(); - const { closeModal, entityId } = useModal(); + const { closeModal, entityId, openModal } = useModal(); const label = api.label.byPublicId.useQuery( { @@ -62,8 +62,6 @@ export function LabelForm({ }, }); - console.log({ entityId }); - const refetchCard = () => utils.card.byId.refetch({ id: cardPublicId }); const isCreateAnotherEnabled = watch("isCreateAnotherEnabled"); @@ -212,7 +210,15 @@ export function LabelForm({ /> )} -
+
+ {isEdit && ( + + )} diff --git a/src/views/card/index.tsx b/src/views/card/index.tsx index 0b3edfd5..b88bcc75 100644 --- a/src/views/card/index.tsx +++ b/src/views/card/index.tsx @@ -6,6 +6,7 @@ import { IoChevronForwardSharp } from "react-icons/io5"; import Dropdown from "./components/Dropdown"; import { DeleteCardConfirmation } from "./components/DeleteCardConfirmation"; +import { DeleteLabelConfirmation } from "./components/DeleteLabelConfirmation"; import LabelSelector from "./components/LabelSelector"; import ListSelector from "./components/ListSelector"; import MemberSelector from "./components/MemberSelector"; @@ -25,7 +26,7 @@ interface FormValues { export default function CardPage() { const params = useParams(); - const { modalContentType } = useModal(); + const { modalContentType, entityId } = useModal(); const cardId = Array.isArray(params?.cardId) ? params.cardId[0] @@ -182,6 +183,12 @@ export default function CardPage() { {modalContentType === "EDIT_LABEL" && ( )} + {modalContentType === "DELETE_LABEL" && ( + + )} {modalContentType === "DELETE_CARD" && (