feat: delete labels
This commit is contained in:
@@ -11,8 +11,6 @@ interface Props {
|
||||
const Modal: React.FC<Props> = ({ children, modalSize = "sm" }) => {
|
||||
const { isOpen, closeModal } = useModal();
|
||||
|
||||
console.log({ modalSize });
|
||||
|
||||
const modalSizeMap = {
|
||||
sm: "max-w-[400px]",
|
||||
md: "max-w-[550px]",
|
||||
|
||||
@@ -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 };
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -181,6 +181,15 @@ export const destroyCardLabelRelationship = async (
|
||||
return result;
|
||||
};
|
||||
|
||||
export const destroyAllCardLabelRelationships = async (
|
||||
db: SupabaseClient<Database>,
|
||||
labelId: number,
|
||||
) => {
|
||||
const result = await db.from("_card_labels").delete().eq("labelId", labelId);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const createCardLabelRelationship = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardLabelRelationshipInput: { cardId: number; labelId: number },
|
||||
|
||||
@@ -78,3 +78,12 @@ export const update = async (
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const destroy = async (
|
||||
db: SupabaseClient<Database>,
|
||||
labelId: number,
|
||||
) => {
|
||||
const { data } = await db.from("label").delete().eq("id", labelId);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
54
src/views/card/components/DeleteLabelConfirmation.tsx
Normal file
54
src/views/card/components/DeleteLabelConfirmation.tsx
Normal file
@@ -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 (
|
||||
<div className="p-5">
|
||||
<div className="flex w-full flex-col justify-between pb-4">
|
||||
<h2 className="text-md pb-4 font-medium text-neutral-900 dark:text-dark-1000">
|
||||
Are you sure you want to delete this label?
|
||||
</h2>
|
||||
<p className="text-sm font-medium text-light-900 dark:text-dark-900">
|
||||
{"This action can't be undone."}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-5 flex justify-end space-x-2 sm:mt-6">
|
||||
<Button variant="secondary" onClick={() => closeModal()}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={handleDeleteLabel}>Delete</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -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({
|
||||
/>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<div className="space-x-2">
|
||||
{isEdit && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => openModal("DELETE_LABEL", entityId)}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
)}
|
||||
<Button type="submit">
|
||||
{isEdit ? "Update label" : "Create label"}
|
||||
</Button>
|
||||
|
||||
@@ -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" && (
|
||||
<LabelForm cardPublicId={cardId} isEdit />
|
||||
)}
|
||||
{modalContentType === "DELETE_LABEL" && (
|
||||
<DeleteLabelConfirmation
|
||||
cardPublicId={cardId}
|
||||
labelPublicId={entityId}
|
||||
/>
|
||||
)}
|
||||
{modalContentType === "DELETE_CARD" && (
|
||||
<DeleteCardConfirmation
|
||||
boardPublicId={boardId ?? ""}
|
||||
|
||||
Reference in New Issue
Block a user