feat: added custom classnames for event-advanced tab (#17479)
* feat: added custom classnames to event-advanced tab * added more calssnames * added classNames to common types * undo extra changes * Update EventTypePlatformWrapper.tsx * Update types.ts * Update EventTypePlatformWrapper.tsx * better classnames * Update EventTypePlatformWrapper.tsx * addeed CustomEventTypeModalClassNames * added example classnames for demo and some changes * fix: better classnames * timezoneLockToggle -> timezoneLock * Update types.ts * Update CustomEventTypeModal.tsx
This commit is contained in:
@@ -3,6 +3,7 @@ import { useEffect, useState } from "react";
|
||||
import type { OptionProps, SingleValueProps } from "react-select";
|
||||
import { components } from "react-select";
|
||||
|
||||
import type { SelectClassNames } from "@calcom/features/eventtypes/lib/types";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { RouterOutputs } from "@calcom/trpc/react";
|
||||
import { Badge, Icon, Select } from "@calcom/ui";
|
||||
@@ -16,6 +17,7 @@ interface Props {
|
||||
maxWidth?: number;
|
||||
hideAdvancedText?: boolean;
|
||||
calendarsQueryData?: RouterOutputs["viewer"]["connectedCalendars"];
|
||||
customClassNames?: SelectClassNames;
|
||||
}
|
||||
|
||||
interface Option {
|
||||
@@ -53,6 +55,7 @@ const DestinationCalendarSelector = ({
|
||||
hideAdvancedText,
|
||||
maxWidth,
|
||||
calendarsQueryData,
|
||||
customClassNames,
|
||||
}: Props): JSX.Element | null => {
|
||||
const { t } = useLocale();
|
||||
const connectedCalendarsList = calendarsQueryData?.connectedCalendars;
|
||||
@@ -157,8 +160,10 @@ const DestinationCalendarSelector = ({
|
||||
}}
|
||||
isSearchable={false}
|
||||
className={classNames(
|
||||
"border-default my-2 block w-full min-w-0 flex-1 rounded-none rounded-r-sm text-sm"
|
||||
"border-default my-2 block w-full min-w-0 flex-1 rounded-none rounded-r-sm text-sm",
|
||||
customClassNames?.select
|
||||
)}
|
||||
innerClassNames={customClassNames?.innerClassNames}
|
||||
onChange={(newValue) => {
|
||||
setSelectedOption(newValue);
|
||||
if (!newValue) {
|
||||
|
||||
@@ -6,6 +6,8 @@ import { useForm, useFormContext } from "react-hook-form";
|
||||
import type { EventNameObjectType } from "@calcom/core/event";
|
||||
import { getEventName } from "@calcom/core/event";
|
||||
import { validateCustomEventName } from "@calcom/core/event";
|
||||
import type { InputClassNames } from "@calcom/features/eventtypes/lib/types";
|
||||
import { classNames } from "@calcom/lib";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { Button, Dialog, DialogClose, DialogFooter, DialogContent, TextField } from "@calcom/ui";
|
||||
|
||||
@@ -13,6 +15,35 @@ interface FormValues {
|
||||
customEventName: string;
|
||||
}
|
||||
|
||||
export type CustomEventTypeModalClassNames = {
|
||||
eventNameInput?: InputClassNames;
|
||||
availableVariables?: {
|
||||
container?: string;
|
||||
header?: string;
|
||||
scrollArea?: string;
|
||||
variableItem?: {
|
||||
container?: string;
|
||||
variableName?: string;
|
||||
variableDescription?: string;
|
||||
};
|
||||
bookingFieldsHeader?: string;
|
||||
bookingFieldItem?: {
|
||||
container?: string;
|
||||
fieldName?: string;
|
||||
fieldValue?: string;
|
||||
};
|
||||
};
|
||||
previewSection?: {
|
||||
header?: string;
|
||||
previewContainer?: string;
|
||||
previewEventBox?: {
|
||||
container?: string;
|
||||
eventName?: string;
|
||||
eventTime?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
interface CustomEventTypeModalFormProps {
|
||||
placeHolder: string;
|
||||
close: () => void;
|
||||
@@ -20,18 +51,18 @@ interface CustomEventTypeModalFormProps {
|
||||
event: EventNameObjectType;
|
||||
defaultValue: string;
|
||||
isNameFieldSplit: boolean;
|
||||
customClassNames?: CustomEventTypeModalClassNames;
|
||||
}
|
||||
|
||||
const CustomEventTypeModalForm: FC<CustomEventTypeModalFormProps> = (props) => {
|
||||
const { t } = useLocale();
|
||||
const { placeHolder, close, setValue, event, isNameFieldSplit } = props;
|
||||
const { placeHolder, close, setValue, event, isNameFieldSplit, customClassNames } = props;
|
||||
const { register, handleSubmit, watch, getValues } = useFormContext<FormValues>();
|
||||
const onSubmit: SubmitHandler<FormValues> = (data) => {
|
||||
setValue(data.customEventName);
|
||||
close();
|
||||
};
|
||||
|
||||
// const customEventName = watch("customEventName");
|
||||
const previewText = getEventName({ ...event, eventName: watch("customEventName") });
|
||||
const placeHolder_ = watch("customEventName") === "" ? previewText : placeHolder;
|
||||
|
||||
@@ -45,7 +76,6 @@ const CustomEventTypeModalForm: FC<CustomEventTypeModalFormProps> = (props) => {
|
||||
if (isEmpty) {
|
||||
setValue("");
|
||||
}
|
||||
|
||||
handleSubmit(onSubmit)(e);
|
||||
}}>
|
||||
<TextField
|
||||
@@ -60,72 +90,139 @@ const CustomEventTypeModalForm: FC<CustomEventTypeModalFormProps> = (props) => {
|
||||
: validationResult;
|
||||
},
|
||||
})}
|
||||
className="mb-0"
|
||||
containerClassName={customClassNames?.eventNameInput?.container}
|
||||
labelClassName={customClassNames?.eventNameInput?.label}
|
||||
className={classNames("mb-0", customClassNames?.eventNameInput?.input)}
|
||||
/>
|
||||
<div className="pt-6 text-sm">
|
||||
<div className="bg-subtle mb-6 rounded-md p-2">
|
||||
<h1 className="text-emphasis mb-2 ml-1 font-medium">{t("available_variables")}</h1>
|
||||
<div className="scroll-bar h-[216px] overflow-y-auto">
|
||||
<div className="mb-2.5 flex font-normal">
|
||||
<p className="text-subtle ml-1 mr-5 w-32">{`{Event type title}`}</p>
|
||||
<p className="text-emphasis">{t("event_name_info")}</p>
|
||||
<div
|
||||
className={classNames(
|
||||
"bg-subtle mb-6 rounded-md p-2",
|
||||
customClassNames?.availableVariables?.container
|
||||
)}>
|
||||
<h1
|
||||
className={classNames(
|
||||
"text-emphasis mb-2 ml-1 font-medium",
|
||||
customClassNames?.availableVariables?.header
|
||||
)}>
|
||||
{t("available_variables")}
|
||||
</h1>
|
||||
<div
|
||||
className={classNames(
|
||||
"scroll-bar h-[216px] overflow-y-auto",
|
||||
customClassNames?.availableVariables?.scrollArea
|
||||
)}>
|
||||
<div
|
||||
className={classNames(
|
||||
"mb-2.5 flex font-normal",
|
||||
customClassNames?.availableVariables?.variableItem?.container
|
||||
)}>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-subtle ml-1 mr-5 w-32",
|
||||
customClassNames?.availableVariables?.variableItem?.variableName
|
||||
)}>
|
||||
{`{Event type title}`}
|
||||
</p>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-emphasis",
|
||||
customClassNames?.availableVariables?.variableItem?.variableDescription
|
||||
)}>
|
||||
{t("event_name_info")}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-2.5 flex font-normal">
|
||||
<p className="text-subtle ml-1 mr-5 w-32">{`{Event duration}`}</p>
|
||||
<p className="text-emphasis">{t("event_duration_info")}</p>
|
||||
</div>
|
||||
<div className="mb-2.5 flex font-normal">
|
||||
<p className="text-subtle ml-1 mr-5 w-32">{`{Organiser}`}</p>
|
||||
<p className="text-emphasis">{t("your_full_name")}</p>
|
||||
</div>
|
||||
<div className="mb-2.5 flex font-normal">
|
||||
<p className="text-subtle ml-1 mr-5 w-32">{`{Organiser first name}`}</p>
|
||||
<p className="text-emphasis">{t("organizer_first_name")}</p>
|
||||
</div>
|
||||
<div className="mb-2.5 flex font-normal">
|
||||
<p className="text-subtle ml-1 mr-5 w-32">{`{Scheduler}`}</p>
|
||||
<p className="text-emphasis">{t("scheduler_full_name")}</p>
|
||||
</div>
|
||||
|
||||
<div className="mb-2.5 flex font-normal">
|
||||
<p className="text-subtle ml-1 mr-5 w-32">{`{Scheduler first name}`}</p>
|
||||
<p className="text-emphasis">{t("scheduler_first_name")}</p>
|
||||
</div>
|
||||
|
||||
{isNameFieldSplit && (
|
||||
<div className="mb-2.5 flex font-normal">
|
||||
<p className="text-subtle ml-1 mr-5 w-32">{`{Scheduler last name}`}</p>
|
||||
<p className="text-emphasis">{t("scheduler_last_name")}</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="mb-2.5 flex font-normal">
|
||||
<p className="text-subtle ml-1 mr-5 w-32">{`{Location}`}</p>
|
||||
<p className="text-emphasis">{t("location_info")}</p>
|
||||
<div
|
||||
className={classNames(
|
||||
"mb-2.5 flex font-normal",
|
||||
customClassNames?.availableVariables?.variableItem?.container
|
||||
)}>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-subtle ml-1 mr-5 w-32",
|
||||
customClassNames?.availableVariables?.variableItem?.variableName
|
||||
)}>
|
||||
{`{Event duration}`}
|
||||
</p>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-emphasis",
|
||||
customClassNames?.availableVariables?.variableItem?.variableDescription
|
||||
)}>
|
||||
{t("event_duration_info")}
|
||||
</p>
|
||||
</div>
|
||||
{/* Additional variable items here */}
|
||||
{event.bookingFields && (
|
||||
<p className="text-subtle mb-2 ml-1 font-medium">{t("booking_question_response_variables")}</p>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-subtle mb-2 ml-1 font-medium",
|
||||
customClassNames?.availableVariables?.bookingFieldsHeader
|
||||
)}>
|
||||
{t("booking_question_response_variables")}
|
||||
</p>
|
||||
)}
|
||||
{event.bookingFields &&
|
||||
Object.keys(event.bookingFields).map((bookingfield, index) => (
|
||||
<div key={index} className="mb-2.5 flex font-normal">
|
||||
<p className="text-subtle ml-1 mr-5 w-32">{`{${bookingfield}}`}</p>
|
||||
<p className="text-emphasis capitalize">
|
||||
<div
|
||||
key={index}
|
||||
className={classNames(
|
||||
"mb-2.5 flex font-normal",
|
||||
customClassNames?.availableVariables?.bookingFieldItem?.container
|
||||
)}>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-subtle ml-1 mr-5 w-32",
|
||||
customClassNames?.availableVariables?.bookingFieldItem?.fieldName
|
||||
)}>
|
||||
{`{${bookingfield}}`}
|
||||
</p>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-emphasis capitalize",
|
||||
customClassNames?.availableVariables?.bookingFieldItem?.fieldValue
|
||||
)}>
|
||||
{event.bookingFields?.[bookingfield]?.toString()}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<h1 className="mb-2 text-[14px] font-medium leading-4">{t("preview")}</h1>
|
||||
<h1
|
||||
className={classNames(
|
||||
"mb-2 text-[14px] font-medium leading-4",
|
||||
customClassNames?.previewSection?.header
|
||||
)}>
|
||||
{t("preview")}
|
||||
</h1>
|
||||
<div
|
||||
className="flex h-[212px] w-full rounded-md border-y bg-cover bg-center dark:invert"
|
||||
className={classNames(
|
||||
"flex h-[212px] w-full rounded-md border-y bg-cover bg-center dark:invert",
|
||||
customClassNames?.previewSection?.previewContainer
|
||||
)}
|
||||
style={{
|
||||
backgroundImage: "url(/calendar-preview.svg)",
|
||||
}}>
|
||||
<div className="m-auto flex items-center justify-center self-stretch">
|
||||
<div className="bg-subtle ml-11 mt-3 box-border h-[110px] w-[120px] flex-col items-start gap-1 rounded-md border border-solid border-black text-[12px] leading-3">
|
||||
<p className="text-emphasis overflow-hidden text-ellipsis p-1.5 font-medium">{previewText}</p>
|
||||
<p className="text-default ml-1.5 text-[10px] font-normal">8 - 10 AM</p>
|
||||
<div
|
||||
className={classNames(
|
||||
"bg-subtle ml-11 mt-3 box-border h-[110px] w-[120px] flex-col items-start gap-1 rounded-md border border-solid border-black text-[12px] leading-3",
|
||||
customClassNames?.previewSection?.previewEventBox?.container
|
||||
)}>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-emphasis overflow-hidden text-ellipsis p-1.5 font-medium",
|
||||
customClassNames?.previewSection?.previewEventBox?.eventName
|
||||
)}>
|
||||
{previewText}
|
||||
</p>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-default ml-1.5 text-[10px] font-normal",
|
||||
customClassNames?.previewSection?.previewEventBox?.eventTime
|
||||
)}>
|
||||
8 - 10 AM
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -141,12 +238,12 @@ interface CustomEventTypeModalProps {
|
||||
setValue: (value: string) => void;
|
||||
event: EventNameObjectType;
|
||||
isNameFieldSplit: boolean;
|
||||
customClassNames?: CustomEventTypeModalClassNames;
|
||||
}
|
||||
|
||||
const CustomEventTypeModal: FC<CustomEventTypeModalProps> = (props) => {
|
||||
const { t } = useLocale();
|
||||
|
||||
const { defaultValue, placeHolder, close, setValue, event, isNameFieldSplit } = props;
|
||||
const { defaultValue, placeHolder, close, setValue, event, isNameFieldSplit, customClassNames } = props;
|
||||
|
||||
const methods = useForm<FormValues>({
|
||||
defaultValues: {
|
||||
@@ -169,11 +266,11 @@ const CustomEventTypeModal: FC<CustomEventTypeModalProps> = (props) => {
|
||||
placeHolder={placeHolder}
|
||||
defaultValue={defaultValue}
|
||||
isNameFieldSplit={isNameFieldSplit}
|
||||
customClassNames={customClassNames}
|
||||
/>
|
||||
</FormProvider>
|
||||
<DialogFooter>
|
||||
<DialogClose>{t("cancel")}</DialogClose>
|
||||
|
||||
<Button form="custom-event-name" type="submit" color="primary">
|
||||
{t("create")}
|
||||
</Button>
|
||||
|
||||
@@ -2,6 +2,8 @@ import type { TFunction } from "next-i18next";
|
||||
import { Trans } from "next-i18next";
|
||||
import { useState } from "react";
|
||||
|
||||
import type { InputClassNames, SettingsToggleClassNames } from "@calcom/features/eventtypes/lib/types";
|
||||
import { classNames } from "@calcom/lib";
|
||||
import {
|
||||
SettingsToggle,
|
||||
Dialog,
|
||||
@@ -12,11 +14,26 @@ import {
|
||||
Button,
|
||||
} from "@calcom/ui";
|
||||
|
||||
export type EmailNotificationToggleCustomClassNames = SettingsToggleClassNames & {
|
||||
confirmationDialog?: {
|
||||
container?: string;
|
||||
dialogTitle?: string;
|
||||
description?: string;
|
||||
confirmInput?: InputClassNames;
|
||||
dialogFooter?: {
|
||||
container?: string;
|
||||
confirmButton?: string;
|
||||
cancelButton?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
interface DisableEmailsSettingProps {
|
||||
checked: boolean;
|
||||
onCheckedChange: (e: boolean) => void;
|
||||
recipient: "attendees" | "hosts";
|
||||
t: TFunction;
|
||||
customClassNames?: EmailNotificationToggleCustomClassNames;
|
||||
}
|
||||
|
||||
export const DisableAllEmailsSetting = ({
|
||||
@@ -24,6 +41,7 @@ export const DisableAllEmailsSetting = ({
|
||||
onCheckedChange,
|
||||
recipient,
|
||||
t,
|
||||
customClassNames,
|
||||
}: DisableEmailsSettingProps) => {
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [confirmText, setConfirmText] = useState("");
|
||||
@@ -34,8 +52,12 @@ export const DisableAllEmailsSetting = ({
|
||||
return (
|
||||
<div>
|
||||
<Dialog open={dialogOpen} onOpenChange={(e) => setDialogOpen(e)}>
|
||||
<DialogContent title={title} Icon="circle-alert">
|
||||
<p className="text-default text-sm">
|
||||
<DialogContent
|
||||
title={title}
|
||||
Icon="circle-alert"
|
||||
className={customClassNames?.confirmationDialog?.container}>
|
||||
<p
|
||||
className={classNames("text-default text-sm", customClassNames?.confirmationDialog?.description)}>
|
||||
<Trans i18nKey="disable_attendees_emails_description">
|
||||
This will disable all emails to {recipient}. This includes booking confirmations, requests,
|
||||
reschedules and reschedule requests, cancellation emails, and any other emails related to
|
||||
@@ -46,36 +68,45 @@ export const DisableAllEmailsSetting = ({
|
||||
to their bookings.
|
||||
</Trans>
|
||||
</p>
|
||||
<p className="text-default mb-1 mt-2 text-sm">{t("type_confirm_to_continue")}</p>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-default mb-1 mt-2 text-sm",
|
||||
customClassNames?.confirmationDialog?.confirmInput?.label
|
||||
)}>
|
||||
{t("type_confirm_to_continue")}
|
||||
</p>
|
||||
<InputField
|
||||
value={confirmText}
|
||||
onChange={(e) => {
|
||||
setConfirmText(e.target.value);
|
||||
}}
|
||||
/>
|
||||
<DialogFooter>
|
||||
<DialogClose />
|
||||
<DialogFooter className={customClassNames?.confirmationDialog?.dialogFooter?.container}>
|
||||
<DialogClose className={customClassNames?.confirmationDialog?.dialogFooter?.cancelButton} />
|
||||
<Button
|
||||
disabled={confirmText !== "confirm"}
|
||||
onClick={(e) => {
|
||||
onClick={() => {
|
||||
onCheckedChange(true);
|
||||
setDialogOpen(false);
|
||||
}}>
|
||||
}}
|
||||
className={customClassNames?.confirmationDialog?.dialogFooter?.confirmButton}>
|
||||
{t("disable_email")}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
customClassNames?.container
|
||||
)}
|
||||
descriptionClassName={customClassNames?.description}
|
||||
title={title}
|
||||
description={t("disable_all_emails_description")}
|
||||
checked={!!checked}
|
||||
onCheckedChange={() => {
|
||||
checked ? onCheckedChange(!checked) : setDialogOpen(true);
|
||||
}}
|
||||
onCheckedChange={() => (checked ? onCheckedChange(!checked) : setDialogOpen(true))}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -13,7 +13,14 @@ import {
|
||||
allowDisablingHostConfirmationEmails,
|
||||
} from "@calcom/features/ee/workflows/lib/allowDisablingStandardEmails";
|
||||
import { MultiplePrivateLinksController } from "@calcom/features/eventtypes/components";
|
||||
import type { FormValues, EventTypeSetupProps } from "@calcom/features/eventtypes/lib/types";
|
||||
import type {
|
||||
FormValues,
|
||||
EventTypeSetupProps,
|
||||
SelectClassNames,
|
||||
CheckboxClassNames,
|
||||
InputClassNames,
|
||||
SettingsToggleClassNames,
|
||||
} from "@calcom/features/eventtypes/lib/types";
|
||||
import { FormBuilder } from "@calcom/features/form-builder/FormBuilder";
|
||||
import type { fieldSchema } from "@calcom/features/form-builder/schema";
|
||||
import type { EditableSchema } from "@calcom/features/form-builder/schema";
|
||||
@@ -41,10 +48,48 @@ import {
|
||||
ColorPicker,
|
||||
} from "@calcom/ui";
|
||||
|
||||
import type { CustomEventTypeModalClassNames } from "./CustomEventTypeModal";
|
||||
import CustomEventTypeModal from "./CustomEventTypeModal";
|
||||
import type { EmailNotificationToggleCustomClassNames } from "./DisableAllEmailsSetting";
|
||||
import { DisableAllEmailsSetting } from "./DisableAllEmailsSetting";
|
||||
import type { RequiresConfirmationCustomClassNames } from "./RequiresConfirmationController";
|
||||
import RequiresConfirmationController from "./RequiresConfirmationController";
|
||||
|
||||
export type EventAdvancedTabCustomClassNames = {
|
||||
destinationCalendar?: SelectClassNames;
|
||||
eventName?: InputClassNames;
|
||||
customEventTypeModal?: CustomEventTypeModalClassNames;
|
||||
addToCalendarEmailOrganizer?: SettingsToggleClassNames & {
|
||||
emailSelect?: {
|
||||
container?: string;
|
||||
select?: string;
|
||||
displayEmailLabel?: string;
|
||||
};
|
||||
};
|
||||
requiresConfirmation?: RequiresConfirmationCustomClassNames;
|
||||
bookerEmailVerification?: SettingsToggleClassNames;
|
||||
calendarNotes?: SettingsToggleClassNames;
|
||||
eventDetailsVisibility?: SettingsToggleClassNames;
|
||||
bookingRedirect?: SettingsToggleClassNames & {
|
||||
children?: string;
|
||||
redirectUrlInput?: InputClassNames;
|
||||
forwardParamsCheckbox?: CheckboxClassNames;
|
||||
error?: string;
|
||||
};
|
||||
seatsOptions?: SettingsToggleClassNames & {
|
||||
children?: string;
|
||||
showAttendeesCheckbox?: CheckboxClassNames;
|
||||
showAvalableSeatCountCheckbox?: CheckboxClassNames;
|
||||
seatsInput: InputClassNames;
|
||||
};
|
||||
timezoneLock?: SettingsToggleClassNames;
|
||||
eventTypeColors?: SettingsToggleClassNames & {
|
||||
warningText?: string;
|
||||
};
|
||||
roundRobinReschedule?: SettingsToggleClassNames;
|
||||
emailNotifications?: EmailNotificationToggleCustomClassNames;
|
||||
};
|
||||
|
||||
type BookingField = z.infer<typeof fieldSchema>;
|
||||
|
||||
export type EventAdvancedBaseProps = Pick<EventTypeSetupProps, "eventType" | "team"> & {
|
||||
@@ -53,6 +98,7 @@ export type EventAdvancedBaseProps = Pick<EventTypeSetupProps, "eventType" | "te
|
||||
>;
|
||||
isUserLoading?: boolean;
|
||||
showToast: (message: string, variant: "success" | "warning" | "error") => void;
|
||||
customClassNames?: EventAdvancedTabCustomClassNames;
|
||||
};
|
||||
|
||||
export type EventAdvancedTabProps = EventAdvancedBaseProps & {
|
||||
@@ -68,6 +114,7 @@ export const EventAdvancedTab = ({
|
||||
isUserLoading,
|
||||
showToast,
|
||||
showBookerLayoutSelector,
|
||||
customClassNames,
|
||||
}: EventAdvancedTabProps) => {
|
||||
const isPlatform = useIsPlatform();
|
||||
const platformContext = useAtomsContext();
|
||||
@@ -211,8 +258,18 @@ export const EventAdvancedTab = ({
|
||||
<div className="border-subtle space-y-6 rounded-lg border p-6">
|
||||
<div className="flex flex-col space-y-4 lg:flex-row lg:space-x-4 lg:space-y-0">
|
||||
{displayDestinationCalendarSelector && (
|
||||
<div className="flex w-full flex-col">
|
||||
<Label className="text-emphasis mb-0 font-medium">{t("add_to_calendar")}</Label>
|
||||
<div
|
||||
className={classNames(
|
||||
"flex w-full flex-col",
|
||||
customClassNames?.destinationCalendar?.container
|
||||
)}>
|
||||
<Label
|
||||
className={classNames(
|
||||
"text-emphasis mb-0 font-medium",
|
||||
customClassNames?.destinationCalendar?.label
|
||||
)}>
|
||||
{t("add_to_calendar")}
|
||||
</Label>
|
||||
<Controller
|
||||
name="destinationCalendar"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
@@ -222,15 +279,19 @@ export const EventAdvancedTab = ({
|
||||
hidePlaceholder
|
||||
hideAdvancedText
|
||||
calendarsQueryData={calendarsQueryData}
|
||||
customClassNames={customClassNames?.destinationCalendar}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<p className="text-subtle text-sm">{t("select_which_cal")}</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="w-full">
|
||||
<div className={classNames("w-full", customClassNames?.eventName?.container)}>
|
||||
<TextField
|
||||
label={t("event_name_in_calendar")}
|
||||
labelClassName={customClassNames?.eventName?.label}
|
||||
addOnClassname={customClassNames?.eventName?.addOn}
|
||||
className={customClassNames?.eventName?.input}
|
||||
type="text"
|
||||
{...eventNameLocked}
|
||||
placeholder={eventNamePlaceholder}
|
||||
@@ -250,7 +311,7 @@ export const EventAdvancedTab = ({
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{displayDestinationCalendarSelector && (
|
||||
<div className="w-full">
|
||||
<div className={classNames("w-full", customClassNames?.addToCalendarEmailOrganizer?.container)}>
|
||||
<Switch
|
||||
tooltip={t("if_enabled_email_address_as_organizer")}
|
||||
label={
|
||||
@@ -283,6 +344,8 @@ export const EventAdvancedTab = ({
|
||||
</span>
|
||||
)
|
||||
}
|
||||
className={customClassNames?.addToCalendarEmailOrganizer?.emailSelect?.select}
|
||||
containerClassName={customClassNames?.addToCalendarEmailOrganizer?.emailSelect?.container}
|
||||
onChange={(option) =>
|
||||
formMethods.setValue("secondaryEmailId", option?.value, { shouldDirty: true })
|
||||
}
|
||||
@@ -292,7 +355,13 @@ export const EventAdvancedTab = ({
|
||||
)}
|
||||
options={verifiedSecondaryEmails}
|
||||
/>
|
||||
<p className="text-subtle mt-2 text-sm">{t("display_email_as_organizer")}</p>
|
||||
<p
|
||||
className={classNames(
|
||||
"text-subtle mt-2 text-sm",
|
||||
customClassNames?.addToCalendarEmailOrganizer?.emailSelect?.displayEmailLabel
|
||||
)}>
|
||||
{t("display_email_as_organizer")}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -335,18 +404,23 @@ export const EventAdvancedTab = ({
|
||||
requiresConfirmation={requiresConfirmation}
|
||||
requiresConfirmationWillBlockSlot={formMethods.getValues("requiresConfirmationWillBlockSlot")}
|
||||
onRequiresConfirmation={setRequiresConfirmation}
|
||||
customClassNames={customClassNames?.requiresConfirmation}
|
||||
/>
|
||||
<Controller
|
||||
name="requiresBookerEmailVerification"
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.bookerEmailVerification?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
customClassNames?.bookerEmailVerification?.container
|
||||
)}
|
||||
title={t("requires_booker_email_verification")}
|
||||
data-testid="requires-booker-email-verification"
|
||||
{...requiresBookerEmailVerificationProps}
|
||||
description={t("description_requires_booker_email_verification")}
|
||||
descriptionClassName={customClassNames?.bookerEmailVerification?.description}
|
||||
checked={value}
|
||||
onCheckedChange={(e) => onChange(e)}
|
||||
/>
|
||||
@@ -356,9 +430,13 @@ export const EventAdvancedTab = ({
|
||||
name="hideCalendarNotes"
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.calendarNotes?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
customClassNames?.calendarNotes?.container
|
||||
)}
|
||||
descriptionClassName={customClassNames?.calendarNotes?.description}
|
||||
data-testid="disable-notes"
|
||||
title={t("disable_notes")}
|
||||
{...hideCalendarNotesLocked}
|
||||
@@ -372,9 +450,13 @@ export const EventAdvancedTab = ({
|
||||
name="hideCalendarEventDetails"
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.eventDetailsVisibility?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
customClassNames?.eventDetailsVisibility?.container
|
||||
)}
|
||||
descriptionClassName={customClassNames?.eventDetailsVisibility?.description}
|
||||
title={t("hide_calendar_event_details")}
|
||||
{...hideCalendarEventDetailsLocked}
|
||||
description={t("description_hide_calendar_event_details")}
|
||||
@@ -388,13 +470,15 @@ export const EventAdvancedTab = ({
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<>
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.bookingRedirect?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
redirectUrlVisible && "rounded-b-none"
|
||||
redirectUrlVisible && "rounded-b-none",
|
||||
customClassNames?.bookingRedirect?.container
|
||||
)}
|
||||
childrenClassName="lg:ml-0"
|
||||
childrenClassName={classNames("lg:ml-0", customClassNames?.bookingRedirect?.children)}
|
||||
descriptionClassName={customClassNames?.bookingRedirect?.description}
|
||||
title={t("redirect_success_booking")}
|
||||
data-testid="redirect-success-booking"
|
||||
{...successRedirectUrlLocked}
|
||||
@@ -404,10 +488,15 @@ export const EventAdvancedTab = ({
|
||||
setRedirectUrlVisible(e);
|
||||
onChange(e ? value : "");
|
||||
}}>
|
||||
<div className="border-subtle rounded-b-lg border border-t-0 p-6">
|
||||
<div
|
||||
className={classNames(
|
||||
"border-subtle rounded-b-lg border border-t-0 p-6",
|
||||
customClassNames?.bookingRedirect?.redirectUrlInput?.container
|
||||
)}>
|
||||
<TextField
|
||||
className="w-full"
|
||||
className={classNames("w-full", customClassNames?.bookingRedirect?.redirectUrlInput?.input)}
|
||||
label={t("redirect_success_booking")}
|
||||
labelClassName={customClassNames?.bookingRedirect?.redirectUrlInput?.label}
|
||||
labelSrOnly
|
||||
disabled={successRedirectUrlLocked.disabled}
|
||||
placeholder={t("external_redirect_url")}
|
||||
@@ -417,13 +506,21 @@ export const EventAdvancedTab = ({
|
||||
{...formMethods.register("successRedirectUrl")}
|
||||
/>
|
||||
|
||||
<div className="mt-4">
|
||||
<div
|
||||
className={classNames(
|
||||
"mt-4",
|
||||
customClassNames?.bookingRedirect?.forwardParamsCheckbox?.container
|
||||
)}>
|
||||
<Controller
|
||||
name="forwardParamsSuccessRedirect"
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<CheckboxField
|
||||
description={t("forward_params_redirect")}
|
||||
disabled={successRedirectUrlLocked.disabled}
|
||||
className={customClassNames?.bookingRedirect?.forwardParamsCheckbox?.checkbox}
|
||||
descriptionClassName={
|
||||
customClassNames?.bookingRedirect?.forwardParamsCheckbox?.description
|
||||
}
|
||||
onChange={(e) => onChange(e)}
|
||||
checked={value}
|
||||
/>
|
||||
@@ -433,7 +530,8 @@ export const EventAdvancedTab = ({
|
||||
<div
|
||||
className={classNames(
|
||||
"p-1 text-sm text-orange-600",
|
||||
formMethods.getValues("successRedirectUrl") ? "block" : "hidden"
|
||||
formMethods.getValues("successRedirectUrl") ? "block" : "hidden",
|
||||
customClassNames?.bookingRedirect?.error
|
||||
)}
|
||||
data-testid="redirect-url-warning">
|
||||
{t("redirect_url_warning")}
|
||||
@@ -489,13 +587,15 @@ export const EventAdvancedTab = ({
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<>
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.seatsOptions?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
value && "rounded-b-none"
|
||||
value && "rounded-b-none",
|
||||
customClassNames?.seatsOptions?.container
|
||||
)}
|
||||
childrenClassName="lg:ml-0"
|
||||
childrenClassName={classNames("lg:ml-0", customClassNames?.seatsOptions?.children)}
|
||||
descriptionClassName={customClassNames?.seatsOptions?.description}
|
||||
data-testid="offer-seats-toggle"
|
||||
title={t("offer_seats")}
|
||||
{...seatsLocked}
|
||||
@@ -539,20 +639,34 @@ export const EventAdvancedTab = ({
|
||||
disabled={seatsLocked.disabled}
|
||||
defaultValue={value}
|
||||
min={1}
|
||||
containerClassName="max-w-80"
|
||||
containerClassName={classNames(
|
||||
"max-w-80",
|
||||
customClassNames?.seatsOptions?.seatsInput.container
|
||||
)}
|
||||
addOnClassname={customClassNames?.seatsOptions?.seatsInput.addOn}
|
||||
className={customClassNames?.seatsOptions?.seatsInput?.input}
|
||||
labelClassName={customClassNames?.seatsOptions?.seatsInput?.label}
|
||||
addOnSuffix={<>{t("seats")}</>}
|
||||
onChange={(e) => {
|
||||
onChange(Math.abs(Number(e.target.value)));
|
||||
}}
|
||||
data-testid="seats-per-time-slot"
|
||||
/>
|
||||
<div className="mt-4">
|
||||
<div
|
||||
className={classNames(
|
||||
"mt-4",
|
||||
customClassNames?.seatsOptions?.showAttendeesCheckbox?.container
|
||||
)}>
|
||||
<Controller
|
||||
name="seatsShowAttendees"
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<CheckboxField
|
||||
data-testid="show-attendees"
|
||||
description={t("show_attendees")}
|
||||
className={customClassNames?.seatsOptions?.showAttendeesCheckbox?.checkbox}
|
||||
descriptionClassName={
|
||||
customClassNames?.seatsOptions?.showAttendeesCheckbox?.description
|
||||
}
|
||||
disabled={seatsLocked.disabled}
|
||||
onChange={(e) => onChange(e)}
|
||||
checked={value}
|
||||
@@ -560,7 +674,11 @@ export const EventAdvancedTab = ({
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<div
|
||||
className={classNames(
|
||||
"mt-2",
|
||||
customClassNames?.seatsOptions?.showAvalableSeatCountCheckbox?.container
|
||||
)}>
|
||||
<Controller
|
||||
name="seatsShowAvailabilityCount"
|
||||
render={({ field: { value, onChange } }) => (
|
||||
@@ -569,6 +687,12 @@ export const EventAdvancedTab = ({
|
||||
disabled={seatsLocked.disabled}
|
||||
onChange={(e) => onChange(e)}
|
||||
checked={value}
|
||||
className={
|
||||
customClassNames?.seatsOptions?.showAvalableSeatCountCheckbox?.checkbox
|
||||
}
|
||||
descriptionClassName={
|
||||
customClassNames?.seatsOptions?.showAvalableSeatCountCheckbox?.description
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
@@ -586,9 +710,13 @@ export const EventAdvancedTab = ({
|
||||
name="lockTimeZoneToggleOnBookingPage"
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.timezoneLock?.label)}
|
||||
descriptionClassName={customClassNames?.timezoneLock?.description}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
customClassNames?.timezoneLock?.container
|
||||
)}
|
||||
title={t("lock_timezone_toggle_on_booking_page")}
|
||||
{...lockTimeZoneToggleOnBookingPageLocked}
|
||||
description={t("description_lock_timezone_toggle_on_booking_page")}
|
||||
@@ -602,15 +730,17 @@ export const EventAdvancedTab = ({
|
||||
name="eventTypeColor"
|
||||
render={() => (
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.eventTypeColors?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
isEventTypeColorChecked && "rounded-b-none"
|
||||
isEventTypeColorChecked && "rounded-b-none",
|
||||
customClassNames?.eventTypeColors?.container
|
||||
)}
|
||||
title={t("event_type_color")}
|
||||
{...eventTypeColorLocked}
|
||||
description={t("event_type_color_description")}
|
||||
descriptionClassName={customClassNames?.eventTypeColors?.description}
|
||||
checked={isEventTypeColorChecked}
|
||||
onCheckedChange={(e) => {
|
||||
const value = e ? eventTypeColorState : null;
|
||||
@@ -619,7 +749,7 @@ export const EventAdvancedTab = ({
|
||||
});
|
||||
setIsEventTypeColorChecked(e);
|
||||
}}
|
||||
childrenClassName="lg:ml-0">
|
||||
childrenClassName={classNames("lg:ml-0", customClassNames?.eventTypeColors?.children)}>
|
||||
<div className="border-subtle flex flex-col gap-6 rounded-b-lg border border-t-0 p-6">
|
||||
<div>
|
||||
<p className="text-default mb-2 block text-sm font-medium">{t("light_event_type_color")}</p>
|
||||
@@ -641,7 +771,11 @@ export const EventAdvancedTab = ({
|
||||
/>
|
||||
{lightModeError ? (
|
||||
<div className="mt-4">
|
||||
<Alert severity="warning" message={t("event_type_color_light_theme_contrast_error")} />
|
||||
<Alert
|
||||
severity="warning"
|
||||
className={customClassNames?.eventTypeColors?.warningText}
|
||||
message={t("event_type_color_light_theme_contrast_error")}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -666,7 +800,11 @@ export const EventAdvancedTab = ({
|
||||
/>
|
||||
{darkModeError ? (
|
||||
<div className="mt-4">
|
||||
<Alert severity="warning" message={t("event_type_color_dark_theme_contrast_error")} />
|
||||
<Alert
|
||||
severity="warning"
|
||||
className={customClassNames?.eventTypeColors?.warningText}
|
||||
message={t("event_type_color_dark_theme_contrast_error")}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
@@ -676,14 +814,18 @@ export const EventAdvancedTab = ({
|
||||
/>
|
||||
{isRoundRobinEventType && (
|
||||
<Controller
|
||||
name="rescheduleWithSameRoundRobinHost"
|
||||
name="roundRobinReschedule"
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.roundRobinReschedule?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
customClassNames?.roundRobinReschedule?.container
|
||||
)}
|
||||
title={t("reschedule_with_same_round_robin_host_title")}
|
||||
description={t("reschedule_with_same_round_robin_host_description")}
|
||||
descriptionClassName={customClassNames?.roundRobinReschedule?.description}
|
||||
checked={value}
|
||||
onCheckedChange={(e) => onChange(e)}
|
||||
/>
|
||||
@@ -696,11 +838,15 @@ export const EventAdvancedTab = ({
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<>
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.emailNotifications?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
customClassNames?.emailNotifications?.container
|
||||
)}
|
||||
title={t("disable_attendees_confirmation_emails")}
|
||||
description={t("disable_attendees_confirmation_emails_description")}
|
||||
descriptionClassName={customClassNames?.emailNotifications?.description}
|
||||
checked={value}
|
||||
onCheckedChange={(e) => onChange(e)}
|
||||
/>
|
||||
@@ -715,9 +861,13 @@ export const EventAdvancedTab = ({
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<>
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.emailNotifications?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
customClassNames?.emailNotifications?.container
|
||||
)}
|
||||
descriptionClassName={customClassNames?.emailNotifications?.description}
|
||||
title={t("disable_host_confirmation_emails")}
|
||||
description={t("disable_host_confirmation_emails_description")}
|
||||
checked={value}
|
||||
@@ -727,6 +877,7 @@ export const EventAdvancedTab = ({
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{team?.parentId && (
|
||||
<>
|
||||
<Controller
|
||||
@@ -738,6 +889,7 @@ export const EventAdvancedTab = ({
|
||||
checked={value}
|
||||
onCheckedChange={onChange}
|
||||
recipient="attendees"
|
||||
customClassNames={customClassNames?.emailNotifications}
|
||||
t={t}
|
||||
/>
|
||||
</>
|
||||
@@ -749,7 +901,13 @@ export const EventAdvancedTab = ({
|
||||
defaultValue={!!formMethods.getValues("seatsPerTimeSlot")}
|
||||
render={({ field: { value, onChange } }) => (
|
||||
<>
|
||||
<DisableAllEmailsSetting checked={value} onCheckedChange={onChange} recipient="hosts" t={t} />
|
||||
<DisableAllEmailsSetting
|
||||
checked={value}
|
||||
onCheckedChange={onChange}
|
||||
recipient="hosts"
|
||||
customClassNames={customClassNames?.emailNotifications}
|
||||
t={t}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
@@ -763,6 +921,7 @@ export const EventAdvancedTab = ({
|
||||
placeHolder={eventNamePlaceholder}
|
||||
isNameFieldSplit={isSplit}
|
||||
event={eventNameObject}
|
||||
customClassNames={customClassNames?.customEventTypeModal}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
+41
-7
@@ -7,13 +7,25 @@ import { Controller, useFormContext } from "react-hook-form";
|
||||
import type z from "zod";
|
||||
|
||||
import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager";
|
||||
import type { EventTypeSetup } from "@calcom/features/eventtypes/lib/types";
|
||||
import type { EventTypeSetup, SettingsToggleClassNames } from "@calcom/features/eventtypes/lib/types";
|
||||
import type { FormValues } from "@calcom/features/eventtypes/lib/types";
|
||||
import { classNames } from "@calcom/lib";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import type { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||
import { Input, SettingsToggle, RadioField, Select, CheckboxField } from "@calcom/ui";
|
||||
|
||||
export type RequiresConfirmationCustomClassNames = SettingsToggleClassNames & {
|
||||
radioGroupContainer?: string;
|
||||
alwaysConfirmationRadio?: string;
|
||||
conditionalConfirmationRadio?: {
|
||||
container?: string;
|
||||
timeInput?: string;
|
||||
timeUnitSelect?: string;
|
||||
checkbox?: string;
|
||||
checkboxDescription?: string;
|
||||
};
|
||||
};
|
||||
|
||||
type RequiresConfirmationControllerProps = {
|
||||
metadata: z.infer<typeof EventTypeMetaDataSchema>;
|
||||
requiresConfirmation: boolean;
|
||||
@@ -21,6 +33,7 @@ type RequiresConfirmationControllerProps = {
|
||||
onRequiresConfirmation: Dispatch<SetStateAction<boolean>>;
|
||||
seatsEnabled: boolean;
|
||||
eventType: EventTypeSetup;
|
||||
customClassNames?: RequiresConfirmationCustomClassNames;
|
||||
};
|
||||
|
||||
export default function RequiresConfirmationController({
|
||||
@@ -29,6 +42,7 @@ export default function RequiresConfirmationController({
|
||||
requiresConfirmation,
|
||||
onRequiresConfirmation,
|
||||
seatsEnabled,
|
||||
customClassNames,
|
||||
}: RequiresConfirmationControllerProps) {
|
||||
const { t } = useLocale();
|
||||
const [requiresConfirmationSetup, setRequiresConfirmationSetup] = useState(
|
||||
@@ -67,13 +81,15 @@ export default function RequiresConfirmationController({
|
||||
control={formMethods.control}
|
||||
render={() => (
|
||||
<SettingsToggle
|
||||
labelClassName="text-sm"
|
||||
labelClassName={classNames("text-sm", customClassNames?.label)}
|
||||
toggleSwitchAtTheEnd={true}
|
||||
switchContainerClassName={classNames(
|
||||
"border-subtle rounded-lg border py-6 px-4 sm:px-6",
|
||||
requiresConfirmation && "rounded-b-none"
|
||||
requiresConfirmation && "rounded-b-none",
|
||||
customClassNames?.container
|
||||
)}
|
||||
childrenClassName="lg:ml-0"
|
||||
childrenClassName={classNames("lg:ml-0", customClassNames?.children)}
|
||||
descriptionClassName={customClassNames?.description}
|
||||
title={t("requires_confirmation")}
|
||||
data-testid="requires-confirmation"
|
||||
disabled={seatsEnabled || requiresConfirmationLockedProps.disabled}
|
||||
@@ -116,7 +132,11 @@ export default function RequiresConfirmationController({
|
||||
);
|
||||
}
|
||||
}}>
|
||||
<div className="flex flex-col flex-wrap justify-start gap-y-2">
|
||||
<div
|
||||
className={classNames(
|
||||
"flex flex-col flex-wrap justify-start gap-y-2",
|
||||
customClassNames?.radioGroupContainer
|
||||
)}>
|
||||
{(requiresConfirmationSetup === undefined ||
|
||||
!requiresConfirmationLockedProps.disabled) && (
|
||||
<RadioField
|
||||
@@ -124,6 +144,7 @@ export default function RequiresConfirmationController({
|
||||
disabled={requiresConfirmationLockedProps.disabled}
|
||||
id="always"
|
||||
value="always"
|
||||
className={customClassNames?.alwaysConfirmationRadio}
|
||||
/>
|
||||
)}
|
||||
{(requiresConfirmationSetup !== undefined ||
|
||||
@@ -131,7 +152,10 @@ export default function RequiresConfirmationController({
|
||||
<>
|
||||
<RadioField
|
||||
disabled={requiresConfirmationLockedProps.disabled}
|
||||
className="items-center"
|
||||
className={classNames(
|
||||
"items-center",
|
||||
customClassNames?.conditionalConfirmationRadio?.container
|
||||
)}
|
||||
label={
|
||||
<>
|
||||
<Trans
|
||||
@@ -158,7 +182,10 @@ export default function RequiresConfirmationController({
|
||||
{ shouldDirty: true }
|
||||
);
|
||||
}}
|
||||
className="border-default !m-0 block w-16 rounded-r-none border-r-0 text-sm [appearance:textfield] focus:z-10 focus:border-r"
|
||||
className={classNames(
|
||||
"border-default !m-0 block w-16 rounded-r-none border-r-0 text-sm [appearance:textfield] focus:z-10 focus:border-r",
|
||||
customClassNames?.conditionalConfirmationRadio?.timeInput
|
||||
)}
|
||||
defaultValue={metadata?.requiresConfirmationThreshold?.time || 30}
|
||||
/>
|
||||
<label
|
||||
@@ -170,6 +197,9 @@ export default function RequiresConfirmationController({
|
||||
options={options}
|
||||
isSearchable={false}
|
||||
isDisabled={requiresConfirmationLockedProps.disabled}
|
||||
className={
|
||||
customClassNames?.conditionalConfirmationRadio?.timeUnitSelect
|
||||
}
|
||||
innerClassNames={{ control: "rounded-l-none bg-subtle" }}
|
||||
onChange={(opt) => {
|
||||
setRequiresConfirmationSetup({
|
||||
@@ -200,6 +230,10 @@ export default function RequiresConfirmationController({
|
||||
checked={requiresConfirmationWillBlockSlot}
|
||||
descriptionAsLabel
|
||||
description={t("requires_confirmation_will_block_slot_description")}
|
||||
className={customClassNames?.conditionalConfirmationRadio?.checkbox}
|
||||
descriptionClassName={
|
||||
customClassNames?.conditionalConfirmationRadio?.checkboxDescription
|
||||
}
|
||||
onChange={(e) => {
|
||||
// We set should dirty to properly detect when we can submit the form
|
||||
formMethods.setValue("requiresConfirmationWillBlockSlot", e.target.checked, {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useRef, useState, useEffect } from "react";
|
||||
import type { ChildrenEventType } from "@calcom/features/eventtypes/components/ChildrenEventTypeSelect";
|
||||
import { EventType as EventTypeComponent } from "@calcom/features/eventtypes/components/EventType";
|
||||
import ManagedEventTypeDialog from "@calcom/features/eventtypes/components/dialogs/ManagedEventDialog";
|
||||
import type { EventAdvancedTabCustomClassNames } from "@calcom/features/eventtypes/components/tabs/advanced/EventAdvancedTab";
|
||||
import type { EventTeamAssignmentTabCustomClassNames } from "@calcom/features/eventtypes/components/tabs/assignment/EventTeamAssignmentTab";
|
||||
import type { EventAvailabilityTabCustomClassNames } from "@calcom/features/eventtypes/components/tabs/availability/EventAvailabilityTab";
|
||||
import type { EventRecurringTabCustomClassNames } from "@calcom/features/eventtypes/components/tabs/recurring/RecurringEventController";
|
||||
@@ -35,6 +36,7 @@ export type PlatformTabs = keyof Omit<TabMap, "workflows" | "webhooks" | "instan
|
||||
|
||||
export type EventTypeCustomClassNames = {
|
||||
atomsWrapper?: string;
|
||||
eventAdvancedTab?: EventAdvancedTabCustomClassNames;
|
||||
eventAssignmentTab?: EventTeamAssignmentTabCustomClassNames;
|
||||
eventRecurringTab?: EventRecurringTabCustomClassNames;
|
||||
eventAvailabilityTab?: EventAvailabilityTabCustomClassNames;
|
||||
@@ -184,6 +186,7 @@ const EventType = ({
|
||||
user={user?.data}
|
||||
isUserLoading={isUserLoading}
|
||||
showToast={showToast}
|
||||
customClassNames={customClassNames?.eventAdvancedTab}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
|
||||
@@ -97,6 +97,155 @@ export default function Bookings(props: { calUsername: string; calEmail: string
|
||||
<EventTypeSettings
|
||||
customClassNames={{
|
||||
atomsWrapper: "!w-[50vw] !m-auto",
|
||||
|
||||
eventAdvancedTab: {
|
||||
destinationCalendar: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
select: "border border-purple-300 shadow-sm",
|
||||
innerClassNames: {
|
||||
input: "",
|
||||
option: "",
|
||||
control: "",
|
||||
singleValue: "",
|
||||
valueContainer: "",
|
||||
multiValue: "",
|
||||
menu: "",
|
||||
menuList: "",
|
||||
},
|
||||
label: "",
|
||||
},
|
||||
eventName: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-sm",
|
||||
input: "border border-purple-300 shadow-inner",
|
||||
label: "",
|
||||
addOn: "",
|
||||
},
|
||||
addToCalendarEmailOrganizer: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-inner",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
emailSelect: {
|
||||
container: "",
|
||||
select: "",
|
||||
displayEmailLabel: "",
|
||||
},
|
||||
},
|
||||
requiresConfirmation: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
radioGroupContainer: "",
|
||||
alwaysConfirmationRadio: "",
|
||||
conditionalConfirmationRadio: {
|
||||
container: "",
|
||||
timeInput: "",
|
||||
timeUnitSelect: "",
|
||||
checkbox: "",
|
||||
checkboxDescription: "",
|
||||
},
|
||||
},
|
||||
bookerEmailVerification: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
},
|
||||
calendarNotes: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
},
|
||||
eventDetailsVisibility: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
},
|
||||
bookingRedirect: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
redirectUrlInput: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-sm",
|
||||
label: "",
|
||||
input: "",
|
||||
addOn: "",
|
||||
},
|
||||
forwardParamsCheckbox: {
|
||||
checkbox: "",
|
||||
description: "",
|
||||
container: "bg-purple-50 border border-purple-300 shadow-sm",
|
||||
},
|
||||
error: "bg-purple-50 text-purple-700 border border-purple-300",
|
||||
},
|
||||
seatsOptions: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
seatsInput: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-sm",
|
||||
label: "",
|
||||
input: "",
|
||||
addOn: "",
|
||||
},
|
||||
showAttendeesCheckbox: {
|
||||
checkbox: "",
|
||||
description: "",
|
||||
container: "",
|
||||
},
|
||||
showAvalableSeatCountCheckbox: {
|
||||
checkbox: "",
|
||||
description: "",
|
||||
container: "",
|
||||
},
|
||||
},
|
||||
timezoneLock: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
},
|
||||
eventTypeColors: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
warningText: "",
|
||||
},
|
||||
roundRobinReschedule: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
},
|
||||
emailNotifications: {
|
||||
container: "bg-purple-50 border border-purple-200 shadow-md",
|
||||
label: "",
|
||||
description: "",
|
||||
children: "",
|
||||
confirmationDialog: {
|
||||
container: "bg-purple-50 border border-purple-300 shadow-lg",
|
||||
dialogTitle: "",
|
||||
description: "",
|
||||
confirmInput: {
|
||||
container: "",
|
||||
label: "",
|
||||
input: "",
|
||||
addOn: "",
|
||||
},
|
||||
dialogFooter: {
|
||||
container: "bg-purple-50",
|
||||
confirmButton: "",
|
||||
cancelButton: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
eventAssignmentTab: {
|
||||
assignmentType: {
|
||||
container: "border border-purple-200 bg-white rounded-lg p-6",
|
||||
|
||||
Reference in New Issue
Block a user