- )}
- {!!booking?.eventType?.price && !booking.paid && (
-
- {startTime}:{" "}
-
- {dayjs(booking.startTime).format("HH:mm")} - {dayjs(booking.endTime).format("HH:mm")}
-
+
+
+
+ {!booking.confirmed && !booking.rejected && (
+ {t("unconfirmed")}
+ )}
+ {!!booking?.eventType?.price && !booking.paid && (
+ Pending payment
+ )}
+
+ {startTime}:{" "}
+
+ {dayjs(booking.startTime).format("HH:mm")} - {dayjs(booking.endTime).format("HH:mm")}
+
+
-
-
- {booking.eventType?.team && {booking.eventType.team.name}: }
- {booking.title}
- {!!booking?.eventType?.price && !booking.paid && (
- Pending payment
- )}
- {!booking.confirmed && !booking.rejected && (
- {t("unconfirmed")}
- )}
-
- {booking.description && (
-
- "{booking.description}"
+
+ {booking.eventType?.team && {booking.eventType.team.name}: }
+ {booking.title}
+ {!!booking?.eventType?.price && !booking.paid && (
+ Pending payment
+ )}
+ {!booking.confirmed && !booking.rejected && (
+ {t("unconfirmed")}
+ )}
- )}
+ {booking.description && (
+
+ "{booking.description}"
+
+ )}
- {booking.attendees.length !== 0 && (
- e.stopPropagation()}>
- {booking.attendees[0].email}
-
- )}
- {isCancelled && booking.rescheduled && (
-
-
-
- )}
+ {booking.attendees.length !== 0 && (
+ e.stopPropagation()}>
+ {booking.attendees[0].email}
+
+ )}
+ {isCancelled && booking.rescheduled && (
+
+
+
+ )}
+
|
diff --git a/apps/web/components/booking/DatePicker.tsx b/apps/web/components/booking/DatePicker.tsx
index 74aceb83ed..8a3398a9df 100644
--- a/apps/web/components/booking/DatePicker.tsx
+++ b/apps/web/components/booking/DatePicker.tsx
@@ -7,7 +7,7 @@ import utc from "dayjs/plugin/utc";
import { memoize } from "lodash";
import { useEffect, useRef, useState } from "react";
-import { useEmbedStyles } from "@calcom/embed-core";
+import { useEmbedStyles } from "@calcom/embed-core/embed-iframe";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import classNames from "@lib/classNames";
diff --git a/apps/web/components/booking/pages/AvailabilityPage.tsx b/apps/web/components/booking/pages/AvailabilityPage.tsx
index ecca5bdeb2..84eca3e9a2 100644
--- a/apps/web/components/booking/pages/AvailabilityPage.tsx
+++ b/apps/web/components/booking/pages/AvailabilityPage.tsx
@@ -8,27 +8,31 @@ import {
CreditCardIcon,
GlobeIcon,
InformationCircleIcon,
+ LocationMarkerIcon,
RefreshIcon,
+ VideoCameraIcon,
} from "@heroicons/react/solid";
import * as Collapsible from "@radix-ui/react-collapsible";
import { useContracts } from "contexts/contractsContext";
import dayjs, { Dayjs } from "dayjs";
import customParseFormat from "dayjs/plugin/customParseFormat";
import utc from "dayjs/plugin/utc";
+import { TFunction } from "next-i18next";
import { useRouter } from "next/router";
import { useCallback, useEffect, useMemo, useState } from "react";
import { FormattedNumber, IntlProvider } from "react-intl";
import { Frequency as RRuleFrequency } from "rrule";
+import { AppStoreLocationType, LocationObject, LocationType } from "@calcom/app-store/locations";
import {
useEmbedStyles,
useIsEmbed,
useIsBackgroundTransparent,
sdkActionManager,
useEmbedNonStylesConfig,
-} from "@calcom/embed-core";
+} from "@calcom/embed-core/embed-iframe";
import classNames from "@calcom/lib/classNames";
-import { WEBAPP_URL } from "@calcom/lib/constants";
+import { CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { localStorage } from "@calcom/lib/webstorage";
@@ -57,6 +61,35 @@ dayjs.extend(customParseFormat);
type Props = AvailabilityTeamPageProps | AvailabilityPageProps;
+export const locationKeyToString = (location: LocationObject, t: TFunction) => {
+ switch (location.type) {
+ case LocationType.InPerson:
+ return location.address || "In Person"; // If disabled address won't exist on the object
+ case LocationType.Link:
+ return location.link || "Link"; // If disabled link won't exist on the object
+ case LocationType.Phone:
+ return t("your_number");
+ case LocationType.UserPhone:
+ return t("phone_call");
+ case LocationType.GoogleMeet:
+ return "Google Meet";
+ case LocationType.Zoom:
+ return "Zoom";
+ case LocationType.Daily:
+ return "Cal Video";
+ case LocationType.Jitsi:
+ return "Jitsi";
+ case LocationType.Huddle01:
+ return "Huddle Video";
+ case LocationType.Tandem:
+ return "Tandem";
+ case LocationType.Teams:
+ return "Microsoft Teams";
+ default:
+ return null;
+ }
+};
+
const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage, booking }: Props) => {
const router = useRouter();
const isEmbed = useIsEmbed();
@@ -203,7 +236,7 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage
.filter((user) => user.name !== profile.name)
.map((user) => ({
title: user.name,
- image: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user.username}/avatar.png`,
+ image: `${CAL_URL}/${user.username}/avatar.png`,
alt: user.name || undefined,
})),
].filter((item) => !!item.image) as { image: string; alt?: string; title?: string }[]
@@ -225,6 +258,25 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage
{eventType.description}
)}
+ {eventType.locations.length === 1 && (
+
+
+ {locationKeyToString(eventType.locations[0], t)}
+
+ )}
+ {eventType.locations.length === 1 && (
+
+ {Object.values(AppStoreLocationType).includes(
+ eventType.locations[0].type as unknown as AppStoreLocationType
+ ) ? (
+
+ ) : (
+
+ )}
+
+ {locationKeyToString(eventType.locations[0], t)}
+
+ )}
{eventType.length} {t("minutes")}
@@ -278,7 +330,7 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage
.map((user) => ({
title: user.name,
alt: user.name,
- image: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/${user.username}/avatar.png`,
+ image: `${CAL_URL}/${user.username}/avatar.png`,
})),
].filter((item) => !!item.image) as { image: string; alt?: string; title?: string }[]
}
@@ -297,6 +349,38 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage
{eventType.description}
)}
+ {eventType.locations.length === 1 && (
+
+ {Object.values(AppStoreLocationType).includes(
+ eventType.locations[0].type as unknown as AppStoreLocationType
+ ) ? (
+
+ ) : (
+
+ )}
+
+ {locationKeyToString(eventType.locations[0], t)}
+
+ )}
+ {eventType.locations.length > 1 && (
+
+
+
+
+
+ {eventType.locations.map((el, i, arr) => {
+ return (
+
+ {locationKeyToString(el, t)}{" "}
+ {arr.length - 1 !== i && (
+ {t("or_lowercase")}
+ )}
+
+ );
+ })}
+
+
+ )}
{eventType.length} {t("minutes")}
@@ -340,12 +424,11 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage
)}
-
{previousPage === `${WEBAPP_URL}/${profile.slug}` && (
router.back()}
/>
Go Back
@@ -398,6 +481,7 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage
schedulingType={eventType.schedulingType ?? null}
beforeBufferTime={eventType.beforeEventBuffer}
afterBufferTime={eventType.afterEventBuffer}
+ seatsPerTimeSlot={eventType.seatsPerTimeSlot}
/>
)}
diff --git a/apps/web/components/booking/pages/BookingPage.tsx b/apps/web/components/booking/pages/BookingPage.tsx
index 1b1ab61d87..458561742c 100644
--- a/apps/web/components/booking/pages/BookingPage.tsx
+++ b/apps/web/components/booking/pages/BookingPage.tsx
@@ -24,7 +24,11 @@ import { Frequency as RRuleFrequency } from "rrule";
import { v4 as uuidv4 } from "uuid";
import { z } from "zod";
-import { useEmbedNonStylesConfig, useIsBackgroundTransparent, useIsEmbed } from "@calcom/embed-core";
+import {
+ useEmbedNonStylesConfig,
+ useIsBackgroundTransparent,
+ useIsEmbed,
+} from "@calcom/embed-core/embed-iframe";
import classNames from "@calcom/lib/classNames";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { HttpError } from "@calcom/lib/http-error";
@@ -37,7 +41,7 @@ import { asStringOrNull } from "@lib/asStringOrNull";
import { timeZone } from "@lib/clock";
import { ensureArray } from "@lib/ensureArray";
import useTheme from "@lib/hooks/useTheme";
-import { LocationType } from "@lib/location";
+import { LocationObject, LocationType } from "@lib/location";
import createBooking from "@lib/mutations/bookings/create-booking";
import createRecurringBooking from "@lib/mutations/bookings/create-recurring-booking";
import { parseDate, parseRecurringDates } from "@lib/parseDate";
@@ -79,6 +83,7 @@ type BookingFormValues = {
customInputs?: {
[key: string]: string | boolean;
};
+ rescheduleReason?: string;
};
const BookingPage = ({
@@ -203,10 +208,9 @@ const BookingPage = ({
const eventTypeDetail = { isWeb3Active: false, ...eventType };
- type Location = { type: LocationType; address?: string; link?: string; hostPhoneNumber?: string };
// it would be nice if Prisma at some point in the future allowed for Json; as of now this is not the case.
- const locations: Location[] = useMemo(
- () => (eventType.locations as Location[]) || [],
+ const locations: LocationObject[] = useMemo(
+ () => (eventType.locations as LocationObject[]) || [],
[eventType.locations]
);
@@ -252,6 +256,7 @@ const BookingPage = ({
email: primaryAttendee.email || "",
guests: guestListEmails,
notes: booking.description || "",
+ rescheduleReason: "",
customInputs: eventType.customInputs.reduce(
(customInputs, input) => ({
...customInputs,
@@ -396,6 +401,7 @@ const BookingPage = ({
timeZone: timeZone(),
language: i18n.language,
rescheduleUid,
+ bookingUid: router.query.bookingUid as string,
user: router.query.user,
location: getLocationValue(
booking.locationType ? booking : { ...booking, locationType: selectedLocation }
@@ -469,6 +475,21 @@ const BookingPage = ({
{eventType.title}
+ {eventType.seatsPerTimeSlot && (
+ = 0.5
+ ? "text-rose-600"
+ : booking && booking.attendees.length / eventType.seatsPerTimeSlot >= 0.33
+ ? "text-yellow-500"
+ : "text-emerald-400"
+ } mb-2`}>
+ {booking
+ ? eventType.seatsPerTimeSlot - booking.attendees.length
+ : eventType.seatsPerTimeSlot}{" "}
+ / {eventType.seatsPerTimeSlot} {t("seats_available")}
+
+ )}
{eventType?.description && (
@@ -767,18 +788,31 @@ const BookingPage = ({
-
+ {rescheduleUid ? (
+
+ ) : (
+
+ )}
+
|