refactor: event type settings improvements (#11615)

This commit is contained in:
Udit Takkar 2023-10-11 14:33:54 +05:30 committed by GitHub
parent 4f942e1a13
commit 226ac889c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 97 additions and 64 deletions

View File

@ -130,7 +130,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
* a team event. Since we don't have logic to handle each attendee calendar (for now). * a team event. Since we don't have logic to handle each attendee calendar (for now).
* This will fallback to each user selected destination calendar. * This will fallback to each user selected destination calendar.
*/} */}
<div className="border-subtle space-y-6 rounded-md border p-6"> <div className="border-subtle space-y-6 rounded-lg border p-6">
{!!connectedCalendarsQuery.data?.connectedCalendars.length && !team && ( {!!connectedCalendarsQuery.data?.connectedCalendars.length && !team && (
<div className="flex flex-col"> <div className="flex flex-col">
<div className="flex justify-between"> <div className="flex justify-between">
@ -182,9 +182,9 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
</div> </div>
</div> </div>
<BookerLayoutSelector fallbackToUserSettings isDark={selectedThemeIsDark} /> <BookerLayoutSelector fallbackToUserSettings isDark={selectedThemeIsDark} isOuterBorder={true} />
<div className="border-subtle space-y-6 rounded-md border p-6"> <div className="border-subtle space-y-6 rounded-lg border p-6">
<FormBuilder <FormBuilder
title={t("booking_questions_title")} title={t("booking_questions_title")}
description={t("booking_questions_description")} description={t("booking_questions_description")}
@ -213,8 +213,9 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
defaultValue={eventType.requiresBookerEmailVerification} defaultValue={eventType.requiresBookerEmailVerification}
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => (
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName="border-subtle rounded-md border py-6 px-4 sm:px-6" switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
title={t("requires_booker_email_verification")} title={t("requires_booker_email_verification")}
{...shouldLockDisableProps("requiresBookerEmailVerification")} {...shouldLockDisableProps("requiresBookerEmailVerification")}
description={t("description_requires_booker_email_verification")} description={t("description_requires_booker_email_verification")}
@ -230,8 +231,9 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
defaultValue={eventType.hideCalendarNotes} defaultValue={eventType.hideCalendarNotes}
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => (
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName="border-subtle rounded-md border py-6 px-4 sm:px-6" switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
title={t("disable_notes")} title={t("disable_notes")}
{...shouldLockDisableProps("hideCalendarNotes")} {...shouldLockDisableProps("hideCalendarNotes")}
description={t("disable_notes_description")} description={t("disable_notes_description")}
@ -247,9 +249,10 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => (
<> <>
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName={classNames( switchContainerClassName={classNames(
"border-subtle rounded-md border py-6 px-4 sm:px-6", "border-subtle rounded-lg border py-6 px-4 sm:px-6",
redirectUrlVisible && "rounded-b-none" redirectUrlVisible && "rounded-b-none"
)} )}
childrenClassName="lg:ml-0" childrenClassName="lg:ml-0"
@ -261,7 +264,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
setRedirectUrlVisible(e); setRedirectUrlVisible(e);
onChange(e ? value : ""); onChange(e ? value : "");
}}> }}>
<div className="border-subtle rounded-b-md border border-t-0 p-6"> <div className="border-subtle rounded-b-lg border border-t-0 p-6">
<TextField <TextField
className="w-full" className="w-full"
label={t("redirect_success_booking")} label={t("redirect_success_booking")}
@ -287,20 +290,21 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
/> />
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName={classNames( switchContainerClassName={classNames(
"border-subtle rounded-md border py-6 px-4 sm:px-6", "border-subtle rounded-lg border py-6 px-4 sm:px-6",
hashedLinkVisible && "rounded-b-none" hashedLinkVisible && "rounded-b-none"
)} )}
childrenClassName="lg:ml-0" childrenClassName="lg:ml-0"
data-testid="hashedLinkCheck" data-testid="hashedLinkCheck"
title={t("private_link")} title={t("enable_private_url")}
Badge={ Badge={
<a <a
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
href="https://cal.com/docs/core-features/event-types/single-use-private-links"> href="https://cal.com/docs/core-features/event-types/single-use-private-links">
<Info className="mb-2 ml-1.5 h-4 w-4 cursor-pointer" /> <Info className="ml-1.5 h-4 w-4 cursor-pointer" />
</a> </a>
} }
{...shouldLockDisableProps("hashedLinkCheck")} {...shouldLockDisableProps("hashedLinkCheck")}
@ -310,7 +314,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
formMethods.setValue("hashedLink", e ? hashedUrl : undefined); formMethods.setValue("hashedLink", e ? hashedUrl : undefined);
setHashedLinkVisible(e); setHashedLinkVisible(e);
}}> }}>
<div className="border-subtle rounded-b-md border border-t-0 p-6"> <div className="border-subtle rounded-b-lg border border-t-0 p-6">
{!IS_VISUAL_REGRESSION_TESTING && ( {!IS_VISUAL_REGRESSION_TESTING && (
<TextField <TextField
disabled disabled
@ -353,9 +357,10 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => (
<> <>
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName={classNames( switchContainerClassName={classNames(
"border-subtle rounded-md border py-6 px-4 sm:px-6", "border-subtle rounded-lg border py-6 px-4 sm:px-6",
value && "rounded-b-none" value && "rounded-b-none"
)} )}
childrenClassName="lg:ml-0" childrenClassName="lg:ml-0"
@ -379,13 +384,13 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
} }
onChange(e); onChange(e);
}}> }}>
<div className="border-subtle rounded-b-md border border-t-0 p-6"> <div className="border-subtle rounded-b-lg border border-t-0 p-6">
<Controller <Controller
name="seatsPerTimeSlot" name="seatsPerTimeSlot"
control={formMethods.control} control={formMethods.control}
defaultValue={eventType.seatsPerTimeSlot} defaultValue={eventType.seatsPerTimeSlot}
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => (
<div className="lg:-ml-2"> <div>
<TextField <TextField
required required
name="seatsPerTimeSlot" name="seatsPerTimeSlot"
@ -395,12 +400,13 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
disabled={seatsLocked.disabled} disabled={seatsLocked.disabled}
defaultValue={value || 2} defaultValue={value || 2}
min={1} min={1}
containerClassName="max-w-80"
addOnSuffix={<>{t("seats")}</>} addOnSuffix={<>{t("seats")}</>}
onChange={(e) => { onChange={(e) => {
onChange(Math.abs(Number(e.target.value))); onChange(Math.abs(Number(e.target.value)));
}} }}
/> />
<div className="mt-2"> <div className="mt-4">
<CheckboxField <CheckboxField
description={t("show_attendees")} description={t("show_attendees")}
disabled={seatsLocked.disabled} disabled={seatsLocked.disabled}
@ -435,8 +441,9 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => (
<> <>
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName="border-subtle rounded-md border py-6 px-4 sm:px-6" switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
title={t("disable_attendees_confirmation_emails")} title={t("disable_attendees_confirmation_emails")}
description={t("disable_attendees_confirmation_emails_description")} description={t("disable_attendees_confirmation_emails_description")}
checked={value || false} checked={value || false}
@ -459,8 +466,9 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupProps,
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => (
<> <>
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName="border-subtle rounded-md border py-6 px-4 sm:px-6" switchContainerClassName="border-subtle rounded-lg border py-6 px-4 sm:px-6"
title={t("disable_host_confirmation_emails")} title={t("disable_host_confirmation_emails")}
description={t("disable_host_confirmation_emails_description")} description={t("disable_host_confirmation_emails_description")}
checked={value || false} checked={value || false}

View File

@ -171,7 +171,7 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
return ( return (
<div> <div>
<div className="border-subtle space-y-6 rounded-md border p-6"> <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"> <div className="flex flex-col space-y-4 lg:flex-row lg:space-x-4 lg:space-y-0">
<div className="w-full"> <div className="w-full">
<Label htmlFor="beforeBufferTime"> <Label htmlFor="beforeBufferTime">
@ -303,6 +303,7 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
return ( return (
<SettingsToggle <SettingsToggle
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
labelClassName="text-sm"
title={t("limit_booking_frequency")} title={t("limit_booking_frequency")}
{...bookingLimitsLocked} {...bookingLimitsLocked}
description={t("limit_booking_frequency_description")} description={t("limit_booking_frequency_description")}
@ -317,11 +318,11 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
} }
}} }}
switchContainerClassName={classNames( switchContainerClassName={classNames(
"border-subtle mt-6 rounded-md border py-6 px-4 sm:px-6", "border-subtle mt-6 rounded-lg border py-6 px-4 sm:px-6",
isChecked && "rounded-b-none" isChecked && "rounded-b-none"
)} )}
childrenClassName="lg:ml-0"> childrenClassName="lg:ml-0">
<div className="border-subtle rounded-b-md border border-t-0 p-6"> <div className="border-subtle rounded-b-lg border border-t-0 p-6">
<IntervalLimitsManager <IntervalLimitsManager
disabled={bookingLimitsLocked.disabled} disabled={bookingLimitsLocked.disabled}
propertyName="bookingLimits" propertyName="bookingLimits"
@ -340,9 +341,10 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
const isChecked = Object.keys(value ?? {}).length > 0; const isChecked = Object.keys(value ?? {}).length > 0;
return ( return (
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName={classNames( switchContainerClassName={classNames(
"border-subtle mt-6 rounded-md border py-6 px-4 sm:px-6", "border-subtle mt-6 rounded-lg border py-6 px-4 sm:px-6",
isChecked && "rounded-b-none" isChecked && "rounded-b-none"
)} )}
childrenClassName="lg:ml-0" childrenClassName="lg:ml-0"
@ -359,7 +361,7 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
formMethods.setValue("durationLimits", {}); formMethods.setValue("durationLimits", {});
} }
}}> }}>
<div className="border-subtle rounded-b-md border border-t-0 p-6"> <div className="border-subtle rounded-b-lg border border-t-0 p-6">
<IntervalLimitsManager <IntervalLimitsManager
propertyName="durationLimits" propertyName="durationLimits"
defaultLimit={60} defaultLimit={60}
@ -380,9 +382,10 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
return ( return (
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName={classNames( switchContainerClassName={classNames(
"border-subtle mt-6 rounded-md border py-6 px-4 sm:px-6", "border-subtle mt-6 rounded-lg border py-6 px-4 sm:px-6",
isChecked && "rounded-b-none" isChecked && "rounded-b-none"
)} )}
childrenClassName="lg:ml-0" childrenClassName="lg:ml-0"
@ -391,7 +394,7 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
{...periodTypeLocked} {...periodTypeLocked}
checked={isChecked} checked={isChecked}
onCheckedChange={(bool) => formMethods.setValue("periodType", bool ? "ROLLING" : "UNLIMITED")}> onCheckedChange={(bool) => formMethods.setValue("periodType", bool ? "ROLLING" : "UNLIMITED")}>
<div className="border-subtle rounded-b-md border border-t-0 p-6"> <div className="border-subtle rounded-b-lg border border-t-0 p-6">
<RadioGroup.Root <RadioGroup.Root
defaultValue={watchPeriodType} defaultValue={watchPeriodType}
value={watchPeriodType} value={watchPeriodType}
@ -478,9 +481,10 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
}} }}
/> />
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName={classNames( switchContainerClassName={classNames(
"border-subtle mt-6 rounded-md border py-6 px-4 sm:px-6", "border-subtle mt-6 rounded-lg border py-6 px-4 sm:px-6",
offsetToggle && "rounded-b-none" offsetToggle && "rounded-b-none"
)} )}
childrenClassName="lg:ml-0" childrenClassName="lg:ml-0"
@ -494,10 +498,11 @@ export const EventLimitsTab = ({ eventType }: Pick<EventTypeSetupProps, "eventTy
formMethods.setValue("offsetStart", 0); formMethods.setValue("offsetStart", 0);
} }
}}> }}>
<div className="border-subtle rounded-b-md border border-t-0 p-6"> <div className="border-subtle rounded-b-lg border border-t-0 p-6">
<TextField <TextField
required required
type="number" type="number"
containerClassName="max-w-80"
{...offsetStartLockedProps} {...offsetStartLockedProps}
label={t("offset_start")} label={t("offset_start")}
{...formMethods.register("offsetStart")} {...formMethods.register("offsetStart")}

View File

@ -392,7 +392,7 @@ export const EventSetupTab = (
return ( return (
<div> <div>
<div className="space-y-4"> <div className="space-y-4">
<div className="border-subtle space-y-6 rounded-md border p-6"> <div className="border-subtle space-y-6 rounded-lg border p-6">
<TextField <TextField
required required
label={t("title")} label={t("title")}
@ -431,7 +431,7 @@ export const EventSetupTab = (
})} })}
/> />
</div> </div>
<div className="border-subtle rounded-md border p-6"> <div className="border-subtle rounded-lg border p-6">
{multipleDuration ? ( {multipleDuration ? (
<div className="space-y-6"> <div className="space-y-6">
<div> <div>
@ -527,7 +527,7 @@ export const EventSetupTab = (
)} )}
</div> </div>
<div className="border-subtle rounded-md border p-6"> <div className="border-subtle rounded-lg border p-6">
<div> <div>
<Skeleton as={Label} loadingClassName="w-16"> <Skeleton as={Label} loadingClassName="w-16">
{t("location")} {t("location")}

View File

@ -124,7 +124,7 @@ export const EventWebhooksTab = ({ eventType }: Pick<EventTypeSetupProps, "event
{t("add_webhook_description", { appName: APP_NAME })} {t("add_webhook_description", { appName: APP_NAME })}
</p> </p>
<div className="border-subtle mt-8 rounded-md border"> <div className="border-subtle my-8 rounded-md border">
{webhooks.map((webhook, index) => { {webhooks.map((webhook, index) => {
return ( return (
<WebhookListItem <WebhookListItem
@ -141,7 +141,7 @@ export const EventWebhooksTab = ({ eventType }: Pick<EventTypeSetupProps, "event
})} })}
</div> </div>
<p className="text-default mt-8 text-sm font-normal"> <p className="text-default text-sm font-normal">
<Trans i18nKey="edit_or_manage_webhooks"> <Trans i18nKey="edit_or_manage_webhooks">
If you wish to edit or manage your web hooks, please head over to &nbsp; If you wish to edit or manage your web hooks, please head over to &nbsp;
<Link <Link

View File

@ -53,9 +53,10 @@ export default function RecurringEventController({
title="Experimental: Recurring Events are currently experimental and causes some issues sometimes when checking for availability. We are working on fixing this." title="Experimental: Recurring Events are currently experimental and causes some issues sometimes when checking for availability. We are working on fixing this."
/> />
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName={classNames( switchContainerClassName={classNames(
"border-subtle rounded-md border py-6 px-4 sm:px-6", "border-subtle rounded-lg border py-6 px-4 sm:px-6",
recurringEventState !== null && "rounded-b-none" recurringEventState !== null && "rounded-b-none"
)} )}
childrenClassName="lg:ml-0" childrenClassName="lg:ml-0"
@ -78,7 +79,7 @@ export default function RecurringEventController({
setRecurringEventState(newVal); setRecurringEventState(newVal);
} }
}}> }}>
<div className="border-subtle rounded-b-md border border-t-0 p-6"> <div className="border-subtle rounded-b-lg border border-t-0 p-6">
{recurringEventState && ( {recurringEventState && (
<div data-testid="recurring-event-collapsible" className="text-sm"> <div data-testid="recurring-event-collapsible" className="text-sm">
<div className="flex items-center"> <div className="flex items-center">

View File

@ -67,9 +67,10 @@ export default function RequiresConfirmationController({
control={formMethods.control} control={formMethods.control}
render={() => ( render={() => (
<SettingsToggle <SettingsToggle
labelClassName="text-sm"
toggleSwitchAtTheEnd={true} toggleSwitchAtTheEnd={true}
switchContainerClassName={classNames( switchContainerClassName={classNames(
"border-subtle rounded-md border py-6 px-4 sm:px-6", "border-subtle rounded-lg border py-6 px-4 sm:px-6",
requiresConfirmation && "rounded-b-none" requiresConfirmation && "rounded-b-none"
)} )}
childrenClassName="lg:ml-0" childrenClassName="lg:ml-0"
@ -83,7 +84,7 @@ export default function RequiresConfirmationController({
formMethods.setValue("requiresConfirmation", val); formMethods.setValue("requiresConfirmation", val);
onRequiresConfirmation(val); onRequiresConfirmation(val);
}}> }}>
<div className="border-subtle rounded-b-md border border-t-0 p-6"> <div className="border-subtle rounded-b-lg border border-t-0 p-6">
<RadioGroup.Root <RadioGroup.Root
defaultValue={ defaultValue={
requiresConfirmation requiresConfirmation
@ -147,7 +148,7 @@ export default function RequiresConfirmationController({
val val
); );
}} }}
className="border-default !m-0 block w-16 rounded-r-none border-r-0 text-sm [appearance:textfield]" className="border-default !m-0 block w-16 rounded-r-none border-r-0 text-sm [appearance:textfield] focus:z-10 focus:border-r"
defaultValue={metadata?.requiresConfirmationThreshold?.time || 30} defaultValue={metadata?.requiresConfirmationThreshold?.time || 30}
/> />
<label <label

View File

@ -333,7 +333,7 @@
"bookerlayout_error_min_one_enabled": "At least one layout has to be enabled.", "bookerlayout_error_min_one_enabled": "At least one layout has to be enabled.",
"bookerlayout_error_default_not_enabled": "The layout you selected as the default view is not part of the enabled layouts.", "bookerlayout_error_default_not_enabled": "The layout you selected as the default view is not part of the enabled layouts.",
"bookerlayout_error_unknown_layout": "The layout you selected is not a valid layout.", "bookerlayout_error_unknown_layout": "The layout you selected is not a valid layout.",
"bookerlayout_override_global_settings": "You can manage this for all your event types in <2>settings / appearance</2> or <6>override for this event only</6>.", "bookerlayout_override_global_settings": "You can manage this for all your event types in Settings -> <2>Appearance</2> or <6>Override</6> for this event only.",
"unexpected_error_try_again": "An unexpected error occurred. Try again.", "unexpected_error_try_again": "An unexpected error occurred. Try again.",
"sunday_time_error": "Invalid time on Sunday", "sunday_time_error": "Invalid time on Sunday",
"monday_time_error": "Invalid time on Monday", "monday_time_error": "Invalid time on Monday",
@ -783,6 +783,7 @@
"disable_guests": "Disable Guests", "disable_guests": "Disable Guests",
"disable_guests_description": "Disable adding additional guests while booking.", "disable_guests_description": "Disable adding additional guests while booking.",
"private_link": "Generate private link", "private_link": "Generate private link",
"enable_private_url": "Enable Private URL",
"private_link_label": "Private link", "private_link_label": "Private link",
"private_link_hint": "Your private link will regenerate after each use", "private_link_hint": "Your private link will regenerate after each use",
"copy_private_link": "Copy private link", "copy_private_link": "Copy private link",

View File

@ -107,12 +107,12 @@ export const FormBuilder = function FormBuilder({
return ( return (
<div> <div>
<div> <div>
<div className="text-default text-sm font-semibold ltr:mr-1 rtl:ml-1"> <div className="text-default text-sm font-semibold leading-none ltr:mr-1 rtl:ml-1">
{title} {title}
{LockedIcon} {LockedIcon}
</div> </div>
<p className="text-subtle max-w-[280px] break-words py-1 text-sm sm:max-w-[500px]">{description}</p> <p className="text-subtle mt-0.5 max-w-[280px] break-words text-sm sm:max-w-[500px]">{description}</p>
<ul ref={parent} className="border-subtle divide-subtle mt-2 divide-y rounded-md border"> <ul ref={parent} className="border-subtle divide-subtle mt-4 divide-y rounded-md border">
{fields.map((field, index) => { {fields.map((field, index) => {
const options = field.options const options = field.options
? field.options ? field.options

View File

@ -34,6 +34,7 @@ type BookerLayoutSelectorProps = {
isDark?: boolean; isDark?: boolean;
isDisabled?: boolean; isDisabled?: boolean;
isOuterBorder?: boolean;
}; };
const defaultFieldName = "metadata.bookerLayouts"; const defaultFieldName = "metadata.bookerLayouts";
@ -45,6 +46,7 @@ export const BookerLayoutSelector = ({
fallbackToUserSettings, fallbackToUserSettings,
isDark, isDark,
isDisabled = false, isDisabled = false,
isOuterBorder = false,
}: BookerLayoutSelectorProps) => { }: BookerLayoutSelectorProps) => {
const { control, getValues } = useFormContext(); const { control, getValues } = useFormContext();
const { t } = useLocale(); const { t } = useLocale();
@ -55,10 +57,12 @@ export const BookerLayoutSelector = ({
if (flags["booker-layouts"] !== true) return null; if (flags["booker-layouts"] !== true) return null;
return ( return (
<div> <div className={classNames(isOuterBorder && "border-subtle rounded-lg border p-6")}>
<div className="border-subtle rounded-t-xl border p-6"> <div className={classNames(isOuterBorder ? "pb-5" : "border-subtle rounded-t-xl border p-6")}>
<Label className="mb-0 text-base font-semibold">{title ? title : t("layout")}</Label> <Label className={classNames("mb-1 font-semibold", isOuterBorder ? "text-sm" : "text-base")}>
<p className="text-subtle max-w-full break-words py-1 text-sm"> {title ? title : t("layout")}
</Label>
<p className="text-subtle max-w-full break-words text-sm leading-tight">
{description ? description : t("bookerlayout_description")} {description ? description : t("bookerlayout_description")}
</p> </p>
</div> </div>
@ -75,12 +79,15 @@ export const BookerLayoutSelector = ({
settings={value} settings={value}
onChange={onChange} onChange={onChange}
isDark={isDark} isDark={isDark}
isOuterBorder={isOuterBorder}
/> />
<SectionBottomActions align="end"> {!isOuterBorder && (
<Button type="submit" disabled={isDisabled} color="primary"> <SectionBottomActions align="end">
{t("update")} <Button type="submit" disabled={isDisabled} color="primary">
</Button> {t("update")}
</SectionBottomActions> </Button>
</SectionBottomActions>
)}
</> </>
)} )}
/> />
@ -93,11 +100,18 @@ type BookerLayoutFieldsProps = {
onChange: (settings: BookerLayoutSettings) => void; onChange: (settings: BookerLayoutSettings) => void;
showUserSettings: boolean; showUserSettings: boolean;
isDark?: boolean; isDark?: boolean;
isOuterBorder?: boolean;
}; };
type BookerLayoutState = { [key in BookerLayouts]: boolean }; type BookerLayoutState = { [key in BookerLayouts]: boolean };
const BookerLayoutFields = ({ settings, onChange, showUserSettings, isDark }: BookerLayoutFieldsProps) => { const BookerLayoutFields = ({
settings,
onChange,
showUserSettings,
isDark,
isOuterBorder,
}: BookerLayoutFieldsProps) => {
const { t } = useLocale(); const { t } = useLocale();
const { isLoading: isUserLoading, data: user } = useMeQuery(); const { isLoading: isUserLoading, data: user } = useMeQuery();
const [isOverridingSettings, setIsOverridingSettings] = useState(false); const [isOverridingSettings, setIsOverridingSettings] = useState(false);
@ -153,9 +167,8 @@ const BookerLayoutFields = ({ settings, onChange, showUserSettings, isDark }: Bo
// Sent default layout settings to form, otherwise it would still have 'null' as it's value. // Sent default layout settings to form, otherwise it would still have 'null' as it's value.
if (user?.defaultBookerLayouts) onChange(user.defaultBookerLayouts); if (user?.defaultBookerLayouts) onChange(user.defaultBookerLayouts);
}; };
return ( return (
<div className="border-subtle space-y-5 border-x px-6 py-8"> <div className={classNames("space-y-5", !isOuterBorder && "border-subtle border-x px-6 py-8")}>
<div <div
className={classNames( className={classNames(
"flex flex-col gap-5 transition-opacity sm:flex-row sm:gap-3", "flex flex-col gap-5 transition-opacity sm:flex-row sm:gap-3",
@ -191,7 +204,7 @@ const BookerLayoutFields = ({ settings, onChange, showUserSettings, isDark }: Bo
<Label>{t("bookerlayout_default_title")}</Label> <Label>{t("bookerlayout_default_title")}</Label>
<RadioGroup.Root <RadioGroup.Root
key={defaultLayout} key={defaultLayout}
className="border-default flex w-full gap-2 rounded-md border p-1" className="border-subtle flex w-full gap-2 rounded-md border p-1"
defaultValue={defaultLayout} defaultValue={defaultLayout}
onValueChange={(layout: BookerLayouts) => onDefaultLayoutChange(layout)}> onValueChange={(layout: BookerLayouts) => onDefaultLayoutChange(layout)}>
{bookerLayoutOptions.map((layout) => ( {bookerLayoutOptions.map((layout) => (
@ -209,18 +222,18 @@ const BookerLayoutFields = ({ settings, onChange, showUserSettings, isDark }: Bo
{disableFields && ( {disableFields && (
<p className="text-sm"> <p className="text-sm">
<Trans i18nKey="bookerlayout_override_global_settings"> <Trans i18nKey="bookerlayout_override_global_settings">
You can manage this for all your event types in{" "} You can manage this for all your event types in Settings {"-> "}
<Link href="/settings/my-account/appearance" className="underline"> <Link href="/settings/my-account/appearance" className="underline">
settings / appearance Appearance
</Link>{" "} </Link>{" "}
or{" "} or{" "}
<Button <Button
onClick={onOverrideSettings} onClick={onOverrideSettings}
color="minimal" color="minimal"
className="p-0 font-normal underline hover:bg-transparent focus-visible:bg-transparent"> className="h-fit p-0 font-normal underline hover:bg-transparent focus-visible:bg-transparent">
override for this event only Override
</Button> </Button>{" "}
. for this event only.
</Trans> </Trans>
</p> </p>
)} )}

View File

@ -10,13 +10,13 @@ export function ArrowButton(props: ArrowButtonProps) {
<> <>
{props.arrowDirection === "up" ? ( {props.arrowDirection === "up" ? (
<button <button
className="bg-default text-muted hover:text-emphasis border-default hover:border-emphasis invisible absolute left-[5px] -ml-4 -mt-4 mb-4 hidden h-6 w-6 scale-0 items-center justify-center rounded-md border p-1 transition-all group-hover:visible group-hover:scale-100 sm:ml-0 sm:flex lg:left-[12px]" className="bg-default text-muted hover:text-emphasis border-default hover:border-emphasis invisible absolute left-0 -ml-4 -mt-4 mb-4 hidden h-6 w-6 scale-0 items-center justify-center rounded-md border p-1 transition-all group-hover:visible group-hover:scale-100 sm:ml-0 sm:flex lg:left-3"
onClick={props.onClick}> onClick={props.onClick}>
<ArrowUp className="h-5 w-5" /> <ArrowUp className="h-5 w-5" />
</button> </button>
) : ( ) : (
<button <button
className="bg-default text-muted border-default hover:text-emphasis hover:border-emphasis invisible absolute left-[5px] -ml-4 mt-8 hidden h-6 w-6 scale-0 items-center justify-center rounded-md border p-1 transition-all group-hover:visible group-hover:scale-100 sm:ml-0 sm:flex lg:left-[12px]" className="bg-default text-muted border-default hover:text-emphasis hover:border-emphasis invisible absolute left-0 -ml-4 mt-8 hidden h-6 w-6 scale-0 items-center justify-center rounded-md border p-1 transition-all group-hover:visible group-hover:scale-100 sm:ml-0 sm:flex lg:left-3"
onClick={props.onClick}> onClick={props.onClick}>
<ArrowDown className="h-5 w-5" /> <ArrowDown className="h-5 w-5" />
</button> </button>

View File

@ -1,10 +1,11 @@
import { classNames } from "@calcom/lib"; import { classNames } from "@calcom/lib";
export function Label(props: JSX.IntrinsicElements["label"]) { export function Label(props: JSX.IntrinsicElements["label"]) {
const { className, ...restProps } = props;
return ( return (
<label <label
{...props} className={classNames("text-default text-emphasis mb-2 block text-sm font-medium", className)}
className={classNames("text-default text-emphasis mb-2 block text-sm font-medium", props.className)}> {...restProps}>
{props.children} {props.children}
</label> </label>
); );

View File

@ -20,6 +20,7 @@ type Props = {
toggleSwitchAtTheEnd?: boolean; toggleSwitchAtTheEnd?: boolean;
childrenClassName?: string; childrenClassName?: string;
switchContainerClassName?: string; switchContainerClassName?: string;
labelClassName?: string;
}; };
function SettingsToggle({ function SettingsToggle({
@ -35,6 +36,7 @@ function SettingsToggle({
toggleSwitchAtTheEnd = false, toggleSwitchAtTheEnd = false,
childrenClassName, childrenClassName,
switchContainerClassName, switchContainerClassName,
labelClassName,
...rest ...rest
}: Props) { }: Props) {
const [animateRef] = useAutoAnimate<HTMLDivElement>(); const [animateRef] = useAutoAnimate<HTMLDivElement>();
@ -47,7 +49,8 @@ function SettingsToggle({
<div className={classNames("flex justify-between space-x-3", switchContainerClassName)}> <div className={classNames("flex justify-between space-x-3", switchContainerClassName)}>
<div> <div>
<div className="flex items-center"> <div className="flex items-center">
<Label className="text-emphasis text-base font-semibold leading-none"> <Label
className={classNames("mt-0.5 text-base font-semibold leading-none", labelClassName)}>
{title} {title}
{LockedIcon} {LockedIcon}
</Label> </Label>