"use client"; import { useState } from "react"; import { EmailType } from "@calcom/emails/email-types"; import { Dialog } from "@calcom/features/components/controlled-dialog"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { trpc } from "@calcom/trpc/react"; import { Alert } from "@calcom/ui/components/alert"; import { ConfirmationDialogContent } from "@calcom/ui/components/dialog"; import { Checkbox, SettingsToggle } from "@calcom/ui/components/form"; import { showToast } from "@calcom/ui/components/toast"; const EMAIL_TYPE_TO_SETTING_KEY = { [EmailType.CONFIRMATION]: "disableAttendeeConfirmationEmail", [EmailType.CANCELLATION]: "disableAttendeeCancellationEmail", [EmailType.RESCHEDULED]: "disableAttendeeRescheduledEmail", [EmailType.REQUEST]: "disableAttendeeRequestEmail", [EmailType.REASSIGNED]: "disableAttendeeReassignedEmail", [EmailType.AWAITING_PAYMENT]: "disableAttendeeAwaitingPaymentEmail", [EmailType.RESCHEDULE_REQUEST]: "disableAttendeeRescheduleRequestEmail", [EmailType.LOCATION_CHANGE]: "disableAttendeeLocationChangeEmail", [EmailType.NEW_EVENT]: "disableAttendeeNewEventEmail", } as const; type EmailSettings = Record; interface EmailRowProps { emailType: EmailType; labelKey: string; descriptionKey: string; isDisabled: boolean; onToggle: (type: EmailType, disabled: boolean) => void; testId: string; disabled?: boolean; } const EmailRow = ({ emailType, labelKey, descriptionKey, isDisabled, onToggle, testId, disabled, }: EmailRowProps) => { const { t } = useLocale(); return ( {t(labelKey)} {t(descriptionKey)} onToggle(emailType, !checked)} data-testid={testId} disabled={disabled} aria-label={t(labelKey)} /> ); }; interface IDisableGuestBookingEmailsSettingProps { orgId: number; settings: { disableAttendeeConfirmationEmail: boolean; disableAttendeeCancellationEmail: boolean; disableAttendeeRescheduledEmail: boolean; disableAttendeeRequestEmail: boolean; disableAttendeeReassignedEmail: boolean; disableAttendeeAwaitingPaymentEmail: boolean; disableAttendeeRescheduleRequestEmail: boolean; disableAttendeeLocationChangeEmail: boolean; disableAttendeeNewEventEmail: boolean; }; readOnly?: boolean; } const EMAIL_TYPE_LABELS: Record = { [EmailType.CONFIRMATION]: "confirmation", [EmailType.CANCELLATION]: "cancellation", [EmailType.RESCHEDULED]: "rescheduled", [EmailType.REQUEST]: "request", [EmailType.REASSIGNED]: "host_reassignment", [EmailType.AWAITING_PAYMENT]: "awaiting_payment", [EmailType.RESCHEDULE_REQUEST]: "reschedule_request", [EmailType.LOCATION_CHANGE]: "location_change", [EmailType.NEW_EVENT]: "guest_added", }; const DisableGuestBookingEmailsSetting = (props: IDisableGuestBookingEmailsSettingProps) => { const { readOnly = false } = props; const utils = trpc.useUtils(); const { t } = useLocale(); const [showConfirmDialog, setShowConfirmDialog] = useState(false); const [dialogAction, setDialogAction] = useState<"enable" | "disable">("disable"); const [dialogMode, setDialogMode] = useState<"all" | "individual">("all"); const [pendingEmailType, setPendingEmailType] = useState(null); const [emailSettings, setEmailSettings] = useState({ [EmailType.CONFIRMATION]: props.settings.disableAttendeeConfirmationEmail, [EmailType.CANCELLATION]: props.settings.disableAttendeeCancellationEmail, [EmailType.RESCHEDULED]: props.settings.disableAttendeeRescheduledEmail, [EmailType.REQUEST]: props.settings.disableAttendeeRequestEmail, [EmailType.REASSIGNED]: props.settings.disableAttendeeReassignedEmail, [EmailType.AWAITING_PAYMENT]: props.settings.disableAttendeeAwaitingPaymentEmail, [EmailType.RESCHEDULE_REQUEST]: props.settings.disableAttendeeRescheduleRequestEmail, [EmailType.LOCATION_CHANGE]: props.settings.disableAttendeeLocationChangeEmail, [EmailType.NEW_EVENT]: props.settings.disableAttendeeNewEventEmail, }); const allDisabled = Object.values(emailSettings).every(Boolean); const mutation = trpc.viewer.organizations.update.useMutation({ onSuccess: async () => { showToast(t("your_org_updated_successfully"), "success"); }, onError: () => { showToast(t("error_updating_settings"), "error"); }, onSettled: () => { utils.viewer.organizations.listCurrent.invalidate(); }, }); const handleDisableAll = (disable: boolean) => { const apiPayload = Object.fromEntries( Object.values(EMAIL_TYPE_TO_SETTING_KEY).map((key) => [key, disable]) ); mutation.mutate(apiPayload); setEmailSettings( Object.fromEntries(Object.values(EmailType).map((type) => [type, disable])) as EmailSettings ); }; const handleIndividualToggle = (type: EmailType, disabled: boolean) => { if (disabled) { setPendingEmailType(type); setDialogAction("disable"); setDialogMode("individual"); setShowConfirmDialog(true); } else { const settingKey = EMAIL_TYPE_TO_SETTING_KEY[type]; mutation.mutate({ [settingKey]: false }); setEmailSettings((prev) => ({ ...prev, [type]: false })); } }; const confirmIndividualToggle = () => { if (pendingEmailType === null) return; const settingKey = EMAIL_TYPE_TO_SETTING_KEY[pendingEmailType]; const shouldDisable = dialogAction === "disable"; mutation.mutate({ [settingKey]: shouldDisable }); setEmailSettings((prev) => ({ ...prev, [pendingEmailType]: shouldDisable })); setPendingEmailType(null); }; return (
{ if (dialogMode === "all") { handleDisableAll(dialogAction === "disable"); } else { confirmIndividualToggle(); } setShowConfirmDialog(false); }}>

{dialogMode === "all" ? t( dialogAction === "disable" ? "disable_all_guest_booking_emails_confirm_description" : "enable_all_guest_booking_emails_confirm_description" ) : t("disable_individual_guest_email_confirm_description", { emailType: pendingEmailType ? t(EMAIL_TYPE_LABELS[pendingEmailType]) : "", })}

{ setDialogAction(checked ? "disable" : "enable"); setDialogMode("all"); setShowConfirmDialog(true); }} />
{t("email_type")} {t("description")} {t("enabled")}
); }; export default DisableGuestBookingEmailsSetting;