feat: Delete attribute modal (#17557)

* feat: Delete attribute modal

* move Modal file

---------

Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
This commit is contained in:
Amit Sharma
2024-11-11 08:33:19 +00:00
committed by GitHub
co-authored by sean-brydon
parent 838e8b9e89
commit aaf630f01f
3 changed files with 72 additions and 20 deletions
@@ -705,6 +705,9 @@
"no_teams": "You don't have any teams yet.",
"no_teams_description": "Teams allow others to book events shared between your coworkers.",
"submit": "Submit",
"confirm_remove_attribute": "Yes, remove attribute",
"remove_attribute": "Remove attribute",
"remove_attribute_confirmation_message": "Are you sure you want to remove the attribute '{{name}}'? All users currently assigned to it will be unassigned.",
"delete": "Delete",
"update": "Update",
"save": "Save",
@@ -0,0 +1,47 @@
import type { Dispatch, SetStateAction } from "react";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { RouterOutputs } from "@calcom/trpc/react";
import { trpc } from "@calcom/trpc/react";
import { Dialog, ConfirmationDialogContent, showToast } from "@calcom/ui";
type AttributeItemProps = RouterOutputs["viewer"]["attributes"]["list"][number];
export function DeleteAttributeModal({
attributeToDelete,
setAttributeToDelete,
}: {
attributeToDelete: AttributeItemProps;
setAttributeToDelete: Dispatch<SetStateAction<AttributeItemProps | undefined>>;
}) {
const { t } = useLocale();
const utils = trpc.useUtils();
const deleteMutation = trpc.viewer.attributes.delete.useMutation({
onSuccess: () => {
showToast(t("attribute_deleted_successfully"), "success");
utils.viewer.attributes.list.invalidate();
},
onError: (err) => {
showToast(err.message, "error");
},
});
return (
<Dialog open={true} onOpenChange={() => setAttributeToDelete(undefined)}>
<ConfirmationDialogContent
variety="danger"
title={t("remove_attribute")}
confirmBtnText={t("confirm_remove_attribute")}
onConfirm={() => {
deleteMutation.mutate({
id: attributeToDelete.id,
});
}}>
{t("remove_attribute_confirmation_message", {
name: attributeToDelete.name,
})}
</ConfirmationDialogContent>
</Dialog>
);
}
@@ -1,5 +1,6 @@
"use client";
import type { Dispatch, SetStateAction } from "react";
import { useState } from "react";
import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired";
@@ -20,6 +21,7 @@ import {
useMeta,
} from "@calcom/ui";
import { DeleteAttributeModal } from "./DeleteAttributeModal";
import { ListSkeleton } from "./ListSkeleton";
type AttributeItemProps = RouterOutputs["viewer"]["attributes"]["list"][number];
@@ -31,8 +33,13 @@ const TypeToLabelMap = {
MULTI_SELECT: "Multi-select",
};
function AttributeItem({ attribute }: { attribute: AttributeItemProps }) {
const utils = trpc.useUtils();
function AttributeItem({
attribute,
setAttributeToDelete,
}: {
attribute: AttributeItemProps;
setAttributeToDelete: Dispatch<SetStateAction<AttributeItemProps | undefined>>;
}) {
const { t } = useLocale();
const [isEnabled, setIsEnabled] = useState(attribute.enabled);
const mutation = trpc.viewer.attributes.toggleActive.useMutation({
@@ -44,16 +51,6 @@ function AttributeItem({ attribute }: { attribute: AttributeItemProps }) {
},
});
const deleteMutation = trpc.viewer.attributes.delete.useMutation({
onSuccess: () => {
showToast(t("attribute_deleted_successfully"), "success");
utils.viewer.attributes.list.invalidate();
},
onError: (err) => {
showToast(err.message, "error");
},
});
const handleToggle = (checked: boolean) => {
// Optimistically update the local state
setIsEnabled(checked);
@@ -68,10 +65,6 @@ function AttributeItem({ attribute }: { attribute: AttributeItemProps }) {
);
};
const handleDelete = () => {
deleteMutation.mutate({ id: attribute.id });
};
return (
<ul className="focus-within:border-emphasis flex justify-between p-4" key={attribute.id}>
<div>
@@ -112,8 +105,7 @@ function AttributeItem({ attribute }: { attribute: AttributeItemProps }) {
type="button"
StartIcon="trash-2"
color="destructive"
disabled={deleteMutation.isPending}
onClick={handleDelete}>
onClick={() => setAttributeToDelete(attribute)}>
{t("delete")}
</DropdownItem>
</DropdownMenuItem>
@@ -127,7 +119,7 @@ function AttributeItem({ attribute }: { attribute: AttributeItemProps }) {
function OrganizationAttributesPage() {
const { t } = useLocale();
const { data, isLoading } = trpc.viewer.attributes.list.useQuery();
const [attributeToDelete, setAttributeToDelete] = useState<AttributeItemProps>();
if (isLoading) {
return (
<>
@@ -148,7 +140,11 @@ function OrganizationAttributesPage() {
<h2 className="text-emphasis text-base font-semibold leading-none">{t("custom")}</h2>
<li className="border-subtle bg-default divide-subtle flex flex-col divide-y rounded-lg border">
{data?.map((attribute) => (
<AttributeItem attribute={attribute} key={attribute.id} />
<AttributeItem
setAttributeToDelete={setAttributeToDelete}
attribute={attribute}
key={attribute.id}
/>
))}
</li>
<Button
@@ -181,6 +177,12 @@ function OrganizationAttributesPage() {
</div>
)}
</div>
{attributeToDelete && (
<DeleteAttributeModal
attributeToDelete={attributeToDelete}
setAttributeToDelete={setAttributeToDelete}
/>
)}
</LicenseRequired>
</>
);