diff --git a/apps/web/components/eventtype/EventSetupTab.tsx b/apps/web/components/eventtype/EventSetupTab.tsx
index d9b2c066e1..ba36876dca 100644
--- a/apps/web/components/eventtype/EventSetupTab.tsx
+++ b/apps/web/components/eventtype/EventSetupTab.tsx
@@ -8,7 +8,7 @@ import { Controller, useFormContext, useFieldArray } from "react-hook-form";
import type { MultiValue } from "react-select";
import type { EventLocationType } from "@calcom/app-store/locations";
-import { getEventLocationType, LocationType, MeetLocationType } from "@calcom/app-store/locations";
+import { getEventLocationType, MeetLocationType } from "@calcom/app-store/locations";
import useLockedFieldsManager from "@calcom/features/ee/managed-event-types/hooks/useLockedFieldsManager";
import { useOrgBranding } from "@calcom/features/ee/organizations/context/provider";
import { CAL_URL } from "@calcom/lib/constants";
@@ -247,15 +247,7 @@ export const EventSetupTab = (
{locationFields.map((field, index) => {
const eventLocationType = getEventLocationType(field.type);
- const defaultLocation = formMethods
- .getValues("locations")
- ?.find((location: { type: EventLocationType["type"]; address?: string }) => {
- if (location.type === LocationType.InPerson) {
- return location.type === eventLocationType?.type && location.address === field?.address;
- } else {
- return location.type === eventLocationType?.type;
- }
- });
+ const defaultLocation = field;
const option = getLocationFromType(field.type, locationOptions);
@@ -337,10 +329,12 @@ export const EventSetupTab = (
name={eventLocationType.defaultValueVariable}
className="text-error my-1 ml-6 text-sm"
as="div"
+ id="location-error"
/>
{
await expect(page.locator("[data-testid=success-page]")).toBeVisible();
await expect(page.locator("[data-testid=where]")).toHaveText(/Cal Video/);
});
+
+ test("can add single organizer address location without display location public option", async ({
+ page,
+ }) => {
+ const $eventTypes = page.locator("[data-testid=event-types] > li a");
+ const firstEventTypeElement = $eventTypes.first();
+ await firstEventTypeElement.click();
+ await page.waitForURL((url) => {
+ return !!url.pathname.match(/\/event-types\/.+/);
+ });
+
+ const locationAddress = "New Delhi";
+
+ await fillLocation(page, locationAddress, 0, false);
+ await page.locator("[data-testid=update-eventtype]").click();
+
+ await page.goto("/event-types");
+
+ const previewLink = await page
+ .locator("[data-testid=preview-link-button]")
+ .first()
+ .getAttribute("href");
+
+ await page.goto(previewLink ?? "");
+ await selectFirstAvailableTimeSlotNextMonth(page);
+ await bookTimeSlot(page);
+ await expect(page.locator("[data-testid=success-page]")).toBeVisible();
+ await expect(page.locator(`[data-testid="where"]`)).toHaveText(locationAddress);
+ });
+
+ test("can select 'display on booking page' option when multiple organizer input type are present", async ({
+ page,
+ }) => {
+ await gotoFirstEventType(page);
+
+ await page.locator("#location-select").click();
+ await page.locator(`text="Link meeting"`).click();
+
+ const locationInputName = (idx: number) => `locations[${idx}].link`;
+
+ const testUrl1 = "https://cal.ai/";
+ await page.locator(`input[name="${locationInputName(0)}"]`).fill(testUrl1);
+ await page.locator("[data-testid=display-location]").last().check();
+ await checkDisplayLocation(page);
+ await unCheckDisplayLocation(page);
+
+ await page.locator("[data-testid=add-location]").click();
+
+ const testUrl2 = "https://cal.com/ai";
+ await page.locator(`text="Link meeting"`).last().click();
+ await page.locator(`input[name="${locationInputName(1)}"]`).waitFor();
+ await page.locator(`input[name="${locationInputName(1)}"]`).fill(testUrl2);
+ await checkDisplayLocation(page);
+ await unCheckDisplayLocation(page);
+
+ // Remove Both of the locations
+ const removeButtomId = "delete-locations.0.type";
+ await page.getByTestId(removeButtomId).click();
+ await page.getByTestId(removeButtomId).click();
+
+ // Add Multiple Organizer Phone Number options
+ await page.locator("#location-select").click();
+ await page.locator(`text="Organizer Phone Number"`).click();
+
+ const organizerPhoneNumberInputName = (idx: number) => `locations[${idx}].hostPhoneNumber`;
+
+ const testPhoneInputValue1 = "9199999999";
+ await page.locator(`input[name="${organizerPhoneNumberInputName(0)}"]`).waitFor();
+ await page.locator(`input[name="${organizerPhoneNumberInputName(0)}"]`).fill(testPhoneInputValue1);
+ await page.locator("[data-testid=display-location]").last().check();
+ await checkDisplayLocation(page);
+ await unCheckDisplayLocation(page);
+ await page.locator("[data-testid=add-location]").click();
+
+ const testPhoneInputValue2 = "9188888888";
+ await page.locator(`text="Organizer Phone Number"`).last().click();
+ await page.locator(`input[name="${organizerPhoneNumberInputName(1)}"]`).waitFor();
+ await page.locator(`input[name="${organizerPhoneNumberInputName(1)}"]`).fill(testPhoneInputValue2);
+ await checkDisplayLocation(page);
+ await unCheckDisplayLocation(page);
+ });
});
});
});
@@ -293,7 +374,7 @@ async function addAnotherLocation(page: Page, locationOptionText: string) {
await page.locator(`text="${locationOptionText}"`).click();
}
-const fillLocation = async (page: Page, inputText: string, index: number) => {
+const fillLocation = async (page: Page, inputText: string, index: number, selectDisplayLocation = true) => {
// Except the first location, dropdown automatically opens when adding another location
if (index == 0) {
await page.locator("#location-select").last().click();
@@ -303,5 +384,17 @@ const fillLocation = async (page: Page, inputText: string, index: number) => {
const locationInputName = `locations[${index}].address`;
await page.locator(`input[name="${locationInputName}"]`).waitFor();
await page.locator(`input[name="locations[${index}].address"]`).fill(inputText);
- await page.locator("[data-testid=display-location]").last().check();
+ if (selectDisplayLocation) {
+ await page.locator("[data-testid=display-location]").last().check();
+ }
+};
+
+const checkDisplayLocation = async (page: Page) => {
+ await page.locator("[data-testid=display-location]").last().check();
+ await expect(page.locator("[data-testid=display-location]").last()).toBeChecked();
+};
+
+const unCheckDisplayLocation = async (page: Page) => {
+ await page.locator("[data-testid=display-location]").last().uncheck();
+ await expect(page.locator("[data-testid=display-location]").last()).toBeChecked({ checked: false });
};
diff --git a/packages/app-store/locations.ts b/packages/app-store/locations.ts
index 68358d839f..0634625667 100644
--- a/packages/app-store/locations.ts
+++ b/packages/app-store/locations.ts
@@ -427,3 +427,11 @@ export const getTranslatedLocation = (
return translatedLocation;
};
+
+export const getOrganizerInputLocationsType = () => {
+ const locationTypes: DefaultEventLocationType["type"] | EventLocationTypeFromApp["type"][] = [];
+ const locations = locationsTypes.filter((location) => !!location.organizerInputType);
+ locations?.forEach((l) => locationTypes.push(l.type));
+
+ return locationTypes;
+};
diff --git a/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx b/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx
index a10cdae5b1..dc73cbe2da 100644
--- a/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx
+++ b/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx
@@ -1,6 +1,7 @@
import { useFormContext } from "react-hook-form";
import type { LocationObject } from "@calcom/app-store/locations";
+import { getOrganizerInputLocationsType } from "@calcom/app-store/locations";
import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking";
import getLocationOptionsForSelect from "@calcom/features/bookings/lib/getLocationOptionsForSelect";
import { FormBuilderField } from "@calcom/features/form-builder/FormBuilderField";
@@ -105,6 +106,29 @@ export const BookingFields = ({
);
}
+ if (field?.options) {
+ const organzierInputTypes = getOrganizerInputLocationsType();
+ const organzierInputObj: Record = {};
+
+ field.options.forEach((f) => {
+ if (f.value in organzierInputObj) {
+ organzierInputObj[f.value]++;
+ } else {
+ organzierInputObj[f.value] = 1;
+ }
+ });
+
+ field.options = field.options.map((field) => {
+ return {
+ ...field,
+ value:
+ organzierInputTypes.includes(field.value) && organzierInputObj[field.value] > 1
+ ? field.label
+ : field.value,
+ };
+ });
+ }
+
return (
);
diff --git a/packages/features/form-builder/FormBuilderField.tsx b/packages/features/form-builder/FormBuilderField.tsx
index e311713620..33a6697819 100644
--- a/packages/features/form-builder/FormBuilderField.tsx
+++ b/packages/features/form-builder/FormBuilderField.tsx
@@ -311,9 +311,8 @@ export const ComponentForField = ({
if (!field.optionsInputs) {
throw new Error("Field optionsInputs is not defined");
}
- const options = field.options.map((field) => {
- return { ...field, value: field.value === "inPerson" ? field.label : field.value };
- });
+
+ const options = field.options;
return field.options.length ? (