From e477e5892c8eac052ecc1cf6229004d571a18dd5 Mon Sep 17 00:00:00 2001 From: Somay Chauhan Date: Mon, 25 Nov 2024 15:29:09 +0530 Subject: [PATCH] feat: added customClassnames for event-setup tab (#17240) * feat: added customClassnames for event-setup tab * Update EventTypePlatformWrapper.tsx * better classnames naming * added classNames to common types * updated classnames to use the common exported types * udpate * better classnames * better classname names * classnames -> classNames * added default styling * Update Locations.tsx * Update event-types.tsx * update * locationSelectCustomClassNames -> LocationSelectCustomClassNames * Update documentation.json * fix: better classnames * Update types.ts --- .../eventtypes/components/Locations.tsx | 78 +++++++++-- .../components/tabs/setup/EventSetupTab.tsx | 128 ++++++++++++++++-- .../form/components/LocationSelect.tsx | 66 +++++++-- .../wrappers/EventTypePlatformWrapper.tsx | 5 +- .../examples/base/src/pages/event-types.tsx | 86 ++++++++++++ 5 files changed, 321 insertions(+), 42 deletions(-) diff --git a/packages/features/eventtypes/components/Locations.tsx b/packages/features/eventtypes/components/Locations.tsx index ba9bfe0814931d..6888fa2e92a32f 100644 --- a/packages/features/eventtypes/components/Locations.tsx +++ b/packages/features/eventtypes/components/Locations.tsx @@ -9,10 +9,18 @@ import type { UseFormGetValues, UseFormSetValue, Control, FormState } from "reac import type { EventLocationType } from "@calcom/app-store/locations"; import { getEventLocationType, MeetLocationType } from "@calcom/app-store/locations"; import { useIsPlatform } from "@calcom/atoms/monorepo"; -import type { LocationFormValues, EventTypeSetupProps } from "@calcom/features/eventtypes/lib/types"; +import type { + LocationFormValues, + EventTypeSetupProps, + CheckboxClassNames, +} from "@calcom/features/eventtypes/lib/types"; import CheckboxField from "@calcom/features/form/components/CheckboxField"; -import type { SingleValueLocationOption } from "@calcom/features/form/components/LocationSelect"; +import type { + LocationSelectCustomClassNames, + SingleValueLocationOption, +} from "@calcom/features/form/components/LocationSelect"; import LocationSelect from "@calcom/features/form/components/LocationSelect"; +import { classNames } from "@calcom/lib"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Icon, Input, PhoneInput, Button, showToast } from "@calcom/ui"; @@ -22,6 +30,24 @@ export type TLocationOptions = Pick["loc export type TDestinationCalendar = { integration: string } | null; export type TPrefillLocation = { credentialId?: number; type: string }; +type LocationInputCustomClassNames = { + addressInput?: string; + phoneInput?: string; +}; + +export type LocationCustomClassNames = { + container?: string; + locationSelect?: LocationSelectCustomClassNames; + removeLocationButton?: string; + removeLocationIcon?: string; + addLocationButton?: string; + organizerContactInput?: { + errorMessage?: string; + locationInput?: LocationInputCustomClassNames; + publicDisplayCheckbox?: CheckboxClassNames; + }; +}; + type LocationsProps = { team: { id: number } | null; destinationCalendar: TDestinationCalendar; @@ -36,6 +62,7 @@ type LocationsProps = { eventType: TEventTypeLocation; locationOptions: TLocationOptions; prefillLocation?: SingleValueLocationOption; + customClassNames?: LocationCustomClassNames; }; const getLocationFromType = (type: EventLocationType["type"], locationOptions: TLocationOptions) => { @@ -84,6 +111,7 @@ const Locations: React.FC = ({ team, eventType, prefillLocation, + customClassNames, ...props }) => { const { t } = useLocale(); @@ -135,8 +163,9 @@ const Locations: React.FC = ({ eventLocationType: EventLocationType; defaultValue?: string; index: number; + customClassNames?: LocationInputCustomClassNames; }) => { - const { eventLocationType, index, ...remainingProps } = props; + const { eventLocationType, index, customClassNames, ...remainingProps } = props; if (eventLocationType?.organizerInputType === "text") { const { defaultValue, ...rest } = remainingProps; @@ -154,7 +183,7 @@ const Locations: React.FC = ({ onChange={onChange} value={value} {...(disableLocationProp ? { disabled: true } : {})} - className="my-0" + className={classNames("my-0", customClassNames?.addressInput)} {...rest} /> ); @@ -175,6 +204,7 @@ const Locations: React.FC = ({ disabled={disableLocationProp} placeholder={t(eventLocationType.organizerInputPlaceholder || "")} name={`locations[${index}].${eventLocationType.defaultValueVariable}`} + className={customClassNames?.phoneInput} value={value} onChange={onChange} {...rest} @@ -213,8 +243,8 @@ const Locations: React.FC = ({ const isPlatorm = useIsPlatform(); return ( -
-
    +
    +
      {locationFields.map((field, index) => { const eventLocationType = getEventLocationType(field.type); const defaultLocation = field; @@ -230,7 +260,11 @@ const Locations: React.FC = ({ isDisabled={disableLocationProp} defaultValue={option} isSearchable={false} - className="block min-w-0 flex-1 rounded-sm text-sm" + className={classNames( + "block min-w-0 flex-1 rounded-sm text-sm", + customClassNames?.locationSelect?.selectWrapper + )} + customClassNames={customClassNames?.locationSelect} menuPlacement="auto" onChange={(e: SingleValueLocationOption) => { setShowEmptyLocationSelect(false); @@ -275,12 +309,18 @@ const Locations: React.FC = ({ {!(disableLocationProp && isChildrenManagedEventType) && ( )} @@ -302,23 +342,32 @@ const Locations: React.FC = ({ } eventLocationType={eventLocationType} index={index} + customClassNames={customClassNames?.organizerContactInput?.locationInput} />
-
+
{ const fieldValues = getValues("locations")[index]; updateLocationField(index, { @@ -344,7 +393,11 @@ const Locations: React.FC = ({ isDisabled={disableLocationProp} defaultValue={defaultValue} isSearchable={false} - className="block w-full min-w-0 flex-1 rounded-sm text-sm" + className={classNames( + "block w-full min-w-0 flex-1 rounded-sm text-sm", + customClassNames?.locationSelect?.selectWrapper + )} + customClassNames={customClassNames?.locationSelect} menuPlacement="auto" onChange={(e: SingleValueLocationOption) => { setShowEmptyLocationSelect(false); @@ -413,6 +466,7 @@ const Locations: React.FC = ({ StartIcon="plus" color="minimal" disabled={seatsEnabled} + className={classNames(customClassNames?.addLocationButton)} tooltip={seatsEnabled ? t("seats_option_doesnt_support_multi_location") : undefined} onClick={() => setShowEmptyLocationSelect(true)}> {t("add_location")} diff --git a/packages/features/eventtypes/components/tabs/setup/EventSetupTab.tsx b/packages/features/eventtypes/components/tabs/setup/EventSetupTab.tsx index 4092e50c77e5bf..c6b318112f22af 100644 --- a/packages/features/eventtypes/components/tabs/setup/EventSetupTab.tsx +++ b/packages/features/eventtypes/components/tabs/setup/EventSetupTab.tsx @@ -5,26 +5,59 @@ import type { MultiValue } from "react-select"; import { useIsPlatform } from "@calcom/atoms/monorepo"; import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager"; +import type { LocationCustomClassNames } from "@calcom/features/eventtypes/components/Locations"; import Locations from "@calcom/features/eventtypes/components/Locations"; -import type { EventTypeSetupProps } from "@calcom/features/eventtypes/lib/types"; +import type { + EventTypeSetupProps, + InputClassNames, + SelectClassNames, + SettingsToggleClassNames, +} from "@calcom/features/eventtypes/lib/types"; import type { FormValues, LocationFormValues } from "@calcom/features/eventtypes/lib/types"; +import { classNames } from "@calcom/lib"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { md } from "@calcom/lib/markdownIt"; import { slugify } from "@calcom/lib/slugify"; import turndown from "@calcom/lib/turndownService"; import { Label, Select, SettingsToggle, Skeleton, TextField, Editor, TextAreaField } from "@calcom/ui"; +export type EventSetupTabCustomClassNames = { + wrapper?: string; + titleSection?: { + container?: string; + titleInput?: InputClassNames; + urlInput?: InputClassNames; + descriptionInput?: Pick; + }; + durationSection?: { + container?: string; + singleDurationInput?: InputClassNames; + multipleDuration?: { + container?: string; + availableDurationsSelect?: SelectClassNames; + defaultDurationSelect?: SelectClassNames; + }; + selectDurationToggle?: SettingsToggleClassNames; + }; + locationSection?: LocationCustomClassNames & { + container?: string; + label?: string; + }; +}; + export type EventSetupTabProps = Pick< EventTypeSetupProps, "eventType" | "locationOptions" | "team" | "teamMembers" | "destinationCalendar" ->; +> & { + customClassNames?: EventSetupTabCustomClassNames; +}; export const EventSetupTab = ( props: EventSetupTabProps & { urlPrefix: string; hasOrgBranding: boolean; orgId?: number } ) => { const { t } = useLocale(); const isPlatform = useIsPlatform(); const formMethods = useFormContext(); - const { eventType, team, urlPrefix, hasOrgBranding, orgId } = props; + const { eventType, team, urlPrefix, hasOrgBranding, customClassNames, orgId } = props; const [multipleDuration, setMultipleDuration] = useState( formMethods.getValues("metadata")?.multipleDuration ); @@ -60,10 +93,17 @@ export const EventSetupTab = ( return (
-
-
+
+
) : ( <> @@ -115,6 +159,9 @@ export const EventSetupTab = ( {...(isManagedEventType || isChildrenManagedEventType ? urlLockedProps : {})} defaultValue={eventType.slug} data-testid="event-slug" + containerClassName={classNames(customClassNames?.titleSection?.urlInput?.container)} + labelClassName={classNames(customClassNames?.titleSection?.urlInput?.label)} + className={classNames(customClassNames?.titleSection?.urlInput?.input)} addOnLeading={ isPlatform ? undefined : ( <> @@ -133,11 +180,24 @@ export const EventSetupTab = ( })} />
-
+
{multipleDuration ? ( -
+
- + {t("available_durations")}