diff --git a/apps/web/components/dialog/EditLocationDialog.tsx b/apps/web/components/dialog/EditLocationDialog.tsx
index 09fa3f85347c4e..a6dcfdb63d9001 100644
--- a/apps/web/components/dialog/EditLocationDialog.tsx
+++ b/apps/web/components/dialog/EditLocationDialog.tsx
@@ -337,7 +337,9 @@ export const EditLocationDialog = (props: ISetLocationDialog) => {
});
if (booking) {
locationOptions.map((location) =>
- location.options.filter((l) => !["phone", "attendeeInPerson"].includes(l.value))
+ location.options.filter(
+ (l) => !["phone", "attendeeInPerson", "somewhereElse"].includes(l.value)
+ )
);
}
return (
diff --git a/apps/web/public/message-pin.svg b/apps/web/public/message-pin.svg
new file mode 100644
index 00000000000000..6ee3a96ed1b78e
--- /dev/null
+++ b/apps/web/public/message-pin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json
index 4d2b12d21f5154..32c10192005fe0 100644
--- a/apps/web/public/static/locales/en/common.json
+++ b/apps/web/public/static/locales/en/common.json
@@ -589,6 +589,9 @@
"address": "Address",
"enter_address": "Enter address",
"in_person_attendee_address": "In Person (Attendee Address)",
+ "somewhere_else": "Somewhere Else",
+ "custom_attendee_location":"Custom attendee location",
+ "any_location": "Any location",
"yes": "Yes",
"no": "No",
"additional_notes": "Additional notes",
diff --git a/packages/app-store/locations.ts b/packages/app-store/locations.ts
index 54415d3c69c3ec..fd40c1240a187b 100644
--- a/packages/app-store/locations.ts
+++ b/packages/app-store/locations.ts
@@ -26,7 +26,14 @@ export type DefaultEventLocationType = {
| "locationPhoneNumber"
| "phone"
| "hostDefault";
- defaultValueVariable: "address" | "attendeeAddress" | "link" | "hostPhoneNumber" | "hostDefault" | "phone";
+ defaultValueVariable:
+ | "address"
+ | "attendeeAddress"
+ | "link"
+ | "hostPhoneNumber"
+ | "hostDefault"
+ | "phone"
+ | "somewhereElse";
} & (
| {
organizerInputType: "phone" | "text" | null;
@@ -35,7 +42,7 @@ export type DefaultEventLocationType = {
attendeeInputPlaceholder?: null;
}
| {
- attendeeInputType: "phone" | "attendeeAddress" | null;
+ attendeeInputType: "phone" | "attendeeAddress" | "somewhereElse" | null;
attendeeInputPlaceholder: string;
organizerInputType?: null;
organizerInputPlaceholder?: null;
@@ -78,6 +85,7 @@ export enum DefaultEventLocationTypeEnum {
Link = "link",
// Same as `OrganizerDefaultConferencingAppType`
Conferencing = "conferencing",
+ SomewhereElse = "somewhereElse",
}
export const defaultLocations: DefaultEventLocationType[] = [
@@ -94,6 +102,19 @@ export const defaultLocations: DefaultEventLocationType[] = [
iconUrl: "/map-pin-dark.svg",
category: "in person",
},
+ {
+ default: true,
+ type: DefaultEventLocationTypeEnum.SomewhereElse,
+ label: "custom_attendee_location",
+ variable: "address",
+ organizerInputType: null,
+ messageForOrganizer: "Cal will ask your invitee to enter any location before scheduling.",
+ attendeeInputType: "somewhereElse",
+ attendeeInputPlaceholder: "any_location",
+ defaultValueVariable: "somewhereElse",
+ iconUrl: "/message-pin.svg",
+ category: "other",
+ },
{
default: true,
type: DefaultEventLocationTypeEnum.InPerson,
@@ -163,6 +184,8 @@ const translateAbleKeys = [
"link_meeting",
"organizer_phone_number",
"organizer_default_conferencing_app",
+ "somewhere_else",
+ "custom_attendee_location",
];
export type LocationObject = {
@@ -171,7 +194,10 @@ export type LocationObject = {
displayLocationPublicly?: boolean;
credentialId?: number;
} & Partial<
- Record<"address" | "attendeeAddress" | "link" | "hostPhoneNumber" | "hostDefault" | "phone", string>
+ Record<
+ "address" | "attendeeAddress" | "link" | "hostPhoneNumber" | "hostDefault" | "phone" | "somewhereElse",
+ string
+ >
>;
// integrations:jitsi | 919999999999 | Delhi | https://manual.meeting.link | Around Video
diff --git a/packages/features/bookings/lib/getBookingFields.ts b/packages/features/bookings/lib/getBookingFields.ts
index 21ea3520554790..6990d18c9b758b 100644
--- a/packages/features/bookings/lib/getBookingFields.ts
+++ b/packages/features/bookings/lib/getBookingFields.ts
@@ -176,6 +176,11 @@ export const ensureBookingInputsHaveSystemFields = ({
required: true,
placeholder: "",
},
+ somewhereElse: {
+ type: "text",
+ required: true,
+ placeholder: "",
+ },
phone: {
type: "phone",
required: true,
diff --git a/packages/features/eventtypes/lib/types.ts b/packages/features/eventtypes/lib/types.ts
index 59dfe01a2f7074..8c4031ef0e8c12 100644
--- a/packages/features/eventtypes/lib/types.ts
+++ b/packages/features/eventtypes/lib/types.ts
@@ -60,6 +60,7 @@ export type FormValues = {
type: EventLocationType["type"];
address?: string;
attendeeAddress?: string;
+ somewhereElse?: string;
link?: string;
hostPhoneNumber?: string;
displayLocationPublicly?: boolean;
diff --git a/packages/features/form-builder/Components.tsx b/packages/features/form-builder/Components.tsx
index 5b38376f672527..a16e6ae9a105bc 100644
--- a/packages/features/form-builder/Components.tsx
+++ b/packages/features/form-builder/Components.tsx
@@ -454,7 +454,9 @@ export const Components: Record = {
checked={value?.value === option.value}
/>
- {getCleanLabel(option.label) ?? ""}
+ {option.value === "somewhereElse"
+ ? t("somewhere_else")
+ : getCleanLabel(option.label) ?? ""}
{option.value === "phone" && (
@@ -467,13 +469,15 @@ export const Components: Record = {
) : (
// Use the only option itself to determine if the field is required or not.
<>
-