diff --git a/apps/web/components/dialog/EditLocationDialog.tsx b/apps/web/components/dialog/EditLocationDialog.tsx index 59f2a14824..47ae5884df 100644 --- a/apps/web/components/dialog/EditLocationDialog.tsx +++ b/apps/web/components/dialog/EditLocationDialog.tsx @@ -297,7 +297,7 @@ export const EditLocationDialog = (props: ISetLocationDialog) => { control={locationFormMethods.control} render={() => ( - maxMenuHeight={150} + maxMenuHeight={300} name="location" defaultValue={selection} options={locationOptions} diff --git a/apps/web/components/eventtype/EditLocationDialog.tsx b/apps/web/components/eventtype/EditLocationDialog.tsx deleted file mode 100644 index a06873616e..0000000000 --- a/apps/web/components/eventtype/EditLocationDialog.tsx +++ /dev/null @@ -1,371 +0,0 @@ -import { ErrorMessage } from "@hookform/error-message"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { isValidPhoneNumber } from "libphonenumber-js"; -import { Trans } from "next-i18next"; -import { useEffect } from "react"; -import { Controller, useForm, useWatch } from "react-hook-form"; -import { components } from "react-select"; -import { z } from "zod"; - -import { - EventLocationType, - getEventLocationType, - getHumanReadableLocationValue, - getMessageForOrganizer, - LocationObject, - LocationType, -} from "@calcom/app-store/locations"; -import { classNames } from "@calcom/lib"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; -import { RouterOutputs, trpc } from "@calcom/trpc/react"; -import { Button, Dialog, DialogContent, Form, Icon, Label, PhoneInput, Select } from "@calcom/ui"; - -import { QueryCell } from "@lib/QueryCell"; - -import { LinkText } from "@components/ui/LinkText"; -import CheckboxField from "@components/ui/form/CheckboxField"; - -type BookingItem = RouterOutputs["viewer"]["bookings"]["get"]["bookings"][number]; - -type OptionTypeBase = { - label: string; - value: EventLocationType["type"]; - disabled?: boolean; -}; - -interface ISetLocationDialog { - saveLocation: (newLocationType: EventLocationType["type"], details: { [key: string]: string }) => void; - selection?: OptionTypeBase; - booking?: BookingItem; - defaultValues?: LocationObject[]; - setShowLocationModal: React.Dispatch>; - isOpenDialog: boolean; - setSelectedLocation?: (param: OptionTypeBase | undefined) => void; -} - -const LocationInput = (props: { - eventLocationType: EventLocationType; - locationFormMethods: ReturnType; - id: string; - required: boolean; - placeholder: string; - className?: string; - defaultValue?: string; -}): JSX.Element | null => { - const { eventLocationType, locationFormMethods, ...remainingProps } = props; - if (eventLocationType?.organizerInputType === "text") { - return ( - - ); - } else if (eventLocationType?.organizerInputType === "phone") { - return ( - - ); - } - return null; -}; - -export const EditLocationDialog = (props: ISetLocationDialog) => { - const { - saveLocation, - selection, - booking, - setShowLocationModal, - isOpenDialog, - defaultValues, - setSelectedLocation, - } = props; - const { t } = useLocale(); - const locationsQuery = trpc.viewer.locationOptions.useQuery(); - - useEffect(() => { - if (selection) { - locationFormMethods.setValue("locationType", selection?.value); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selection]); - - const locationFormSchema = z.object({ - locationType: z.string(), - phone: z.string().optional(), - locationAddress: z.string().optional(), - locationLink: z - .string() - .optional() - .superRefine((val, ctx) => { - if ( - eventLocationType && - !eventLocationType.default && - eventLocationType.linkType === "static" && - eventLocationType.urlRegExp - ) { - const valid = z - .string() - .regex(new RegExp(eventLocationType.urlRegExp || "")) - .safeParse(val).success; - if (!valid) { - const sampleUrl = eventLocationType.organizerInputPlaceholder; - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `Invalid URL for ${eventLocationType.label}. ${ - sampleUrl ? "Sample URL: " + sampleUrl : "" - }`, - }); - } - return; - } - - const valid = z.string().url().optional().safeParse(val).success; - if (!valid) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: `Invalid URL`, - }); - } - return; - }), - displayLocationPublicly: z.boolean().optional(), - locationPhoneNumber: z - .string() - .refine((val) => isValidPhoneNumber(val)) - .optional(), - }); - - const locationFormMethods = useForm({ - mode: "onSubmit", - resolver: zodResolver(locationFormSchema), - }); - - const selectedLocation = useWatch({ - control: locationFormMethods.control, - name: "locationType", - }); - - const eventLocationType = getEventLocationType(selectedLocation); - - const defaultLocation = defaultValues?.find( - (location: { type: EventLocationType["type"] }) => location.type === eventLocationType?.type - ); - - const LocationOptions = (() => { - if (eventLocationType && eventLocationType.organizerInputType && LocationInput) { - if (!eventLocationType.variable) { - console.error("eventLocationType.variable can't be undefined"); - return null; - } - - return ( -
-
- - - -
- {!booking && ( -
- ( - - locationFormMethods.setValue("displayLocationPublicly", e.target.checked) - } - informationIconText={t("display_location_info_badge")} - /> - )} - /> -
- )} -
- ); - } else { - return

{getMessageForOrganizer(selectedLocation, t)}

; - } - })(); - - return ( - - - {booking && ( - <> -

{t("current_location")}:

-

- {getHumanReadableLocationValue(booking.location, t)} -

- - )} -
{ - const { locationType: newLocation, displayLocationPublicly } = values; - - let details = {}; - if (newLocation === LocationType.AttendeeInPerson) { - details = { - address: values.locationAddress, - }; - } - - if (newLocation === LocationType.InPerson) { - details = { - address: values.locationAddress, - }; - } - const eventLocationType = getEventLocationType(newLocation); - - // TODO: There can be a property that tells if it is to be saved in `link` - if ( - newLocation === LocationType.Link || - (!eventLocationType?.default && eventLocationType?.linkType === "static") - ) { - details = { link: values.locationLink }; - } - - if (newLocation === LocationType.UserPhone) { - details = { hostPhoneNumber: values.locationPhoneNumber }; - } - - if (eventLocationType?.organizerInputType) { - details = { - ...details, - displayLocationPublicly, - }; - } - - saveLocation(newLocation, details); - setShowLocationModal(false); - setSelectedLocation?.(undefined); - locationFormMethods.unregister([ - "locationType", - "locationLink", - "locationAddress", - "locationPhoneNumber", - ]); - }}> - { - if (!locationOptions.length) return null; - if (booking) { - locationOptions.forEach((location) => { - if (location.label === "phone") { - location.options.filter((l) => l.value !== "phone"); - } - }); - } - return ( - ( - - maxMenuHeight={150} - name="location" - defaultValue={selection} - options={locationOptions} - components={{ - Option: (props) => ( - -
- {props.data.icon && ( - cover - )} - - {props.data.label} - -
-
- ), - }} - formatOptionLabel={(e) => ( -
- {e.icon && app-icon} - {e.label} -
- )} - formatGroupLabel={(e) =>

{e.label}

} - isSearchable={false} - onChange={(val) => { - if (val) { - locationFormMethods.setValue("locationType", val.value); - locationFormMethods.unregister([ - "locationLink", - "locationAddress", - "locationPhoneNumber", - ]); - locationFormMethods.clearErrors([ - "locationLink", - "locationPhoneNumber", - "locationAddress", - ]); - setSelectedLocation?.(val); - } - }} - /> - )} - /> - ); - }} - /> - {selectedLocation && LocationOptions} -
-

- - Can't find the right video app? Visit our - - App Store - - . - -

-
-
- - -
- -
-
- ); -};