import { m } from "framer-motion"; import dynamic from "next/dynamic"; import { useEffect, useMemo } from "react"; import { shallow } from "zustand/shallow"; import { Timezone as PlatformTimezoneSelect } from "@calcom/atoms/monorepo"; import { useEmbedUiConfig, useIsEmbed } from "@calcom/embed-core/embed-iframe"; import { EventDetails, EventMembers, EventMetaSkeleton, EventTitle } from "@calcom/features/bookings"; import { SeatsAvailabilityText } from "@calcom/features/bookings/components/SeatsAvailabilityText"; import { EventMetaBlock } from "@calcom/features/bookings/components/event-meta/Details"; import { useTimePreferences } from "@calcom/features/bookings/lib"; import type { BookerEvent } from "@calcom/features/bookings/types"; import { CURRENT_TIMEZONE } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { markdownToSafeHTMLClient } from "@calcom/lib/markdownToSafeHTMLClient"; import type { EventTypeTranslation } from "@calcom/prisma/client"; import { EventTypeAutoTranslatedField } from "@calcom/prisma/enums"; import i18nConfigration from "../../../../../i18n.json"; import { fadeInUp } from "../config"; import { useBookerStore } from "../store"; import { FromToTime } from "../utils/dates"; import { useBookerTime } from "./hooks/useBookerTime"; const WebTimezoneSelect = dynamic( () => import("@calcom/ui/components/form/timezone-select/TimezoneSelect").then((mod) => mod.TimezoneSelect), { ssr: false, } ); const getTranslatedField = ( translations: Array>, field: EventTypeAutoTranslatedField, userLocale: string ) => { const i18nLocales = i18nConfigration.locale.targets.concat([i18nConfigration.locale.source]); return translations?.find( (trans) => trans.field === field && i18nLocales.includes(trans.targetLocale) && (userLocale === trans.targetLocale || userLocale.split("-")[0] === trans.targetLocale) )?.translatedText; }; export const EventMeta = ({ event, isPending, isPlatform = true, isPrivateLink, classNames, locale, }: { event?: Pick< BookerEvent, | "lockTimeZoneToggleOnBookingPage" | "schedule" | "seatsPerTimeSlot" | "subsetOfUsers" | "length" | "schedulingType" | "profile" | "entity" | "description" | "title" | "metadata" | "locations" | "currency" | "requiresConfirmation" | "recurringEvent" | "price" | "isDynamic" | "fieldTranslations" | "autoTranslateDescriptionEnabled" > | null; isPending: boolean; isPrivateLink: boolean; isPlatform?: boolean; classNames?: { eventMetaContainer?: string; eventMetaTitle?: string; eventMetaTimezoneSelect?: string; }; locale?: string | null; }) => { const { timeFormat, timezone } = useBookerTime(); const [setTimezone] = useTimePreferences((state) => [state.setTimezone]); const [setBookerStoreTimezone] = useBookerStore((state) => [state.setTimezone], shallow); const selectedDuration = useBookerStore((state) => state.selectedDuration); const selectedTimeslot = useBookerStore((state) => state.selectedTimeslot); const bookerState = useBookerStore((state) => state.state); const bookingData = useBookerStore((state) => state.bookingData); const rescheduleUid = useBookerStore((state) => state.rescheduleUid); const [seatedEventData, setSeatedEventData] = useBookerStore( (state) => [state.seatedEventData, state.setSeatedEventData], shallow ); const { i18n, t } = useLocale(); const embedUiConfig = useEmbedUiConfig(); const isEmbed = useIsEmbed(); const hideEventTypeDetails = isEmbed ? embedUiConfig.hideEventTypeDetails : false; const [TimezoneSelect] = useMemo( () => (isPlatform ? [PlatformTimezoneSelect] : [WebTimezoneSelect]), [isPlatform] ); useEffect(() => { //In case the event has lockTimeZone enabled ,set the timezone to event's attached availability timezone if (event && event?.lockTimeZoneToggleOnBookingPage && event?.schedule?.timeZone) { setTimezone(event.schedule?.timeZone); } }, [event, setTimezone]); if (hideEventTypeDetails) { return null; } // If we didn't pick a time slot yet, we load bookingData via SSR so bookingData should be set // Otherwise we load seatedEventData from useBookerStore const bookingSeatAttendeesQty = seatedEventData?.attendees || bookingData?.attendees.length; const eventTotalSeats = seatedEventData?.seatsPerTimeSlot || event?.seatsPerTimeSlot; const isHalfFull = bookingSeatAttendeesQty && eventTotalSeats && bookingSeatAttendeesQty / eventTotalSeats >= 0.5; const isNearlyFull = bookingSeatAttendeesQty && eventTotalSeats && bookingSeatAttendeesQty / eventTotalSeats >= 0.83; const colorClass = isNearlyFull ? "text-rose-600" : isHalfFull ? "text-yellow-500" : "text-bookinghighlight"; const userLocale = locale ?? navigator.language; const translatedDescription = getTranslatedField( event?.fieldTranslations ?? [], EventTypeAutoTranslatedField.DESCRIPTION, userLocale ); const translatedTitle = getTranslatedField( event?.fieldTranslations ?? [], EventTypeAutoTranslatedField.TITLE, userLocale ); return (
{isPending && ( )} {!isPending && !!event && ( {translatedTitle ?? event?.title} {(event.description || translatedDescription) && (
)}
{rescheduleUid && bookingData && ( {t("former_time")}
)} {selectedTimeslot && ( )} {bookerState === "booking" ? ( <>{timezone} ) : ( "!min-h-0 p-0 w-full border-0 bg-transparent focus-within:ring-0 shadow-none!", menu: () => "!w-64 max-w-[90vw] mb-1 ", singleValue: () => "text-text py-1", indicatorsContainer: () => "ml-auto", container: () => "max-w-full", }} value={event.lockTimeZoneToggleOnBookingPage ? CURRENT_TIMEZONE : timezone} onChange={({ value }) => { setTimezone(value); setBookerStoreTimezone(value); }} isDisabled={event.lockTimeZoneToggleOnBookingPage} /> )} {bookerState === "booking" && eventTotalSeats && bookingSeatAttendeesQty ? (

) : null}
)}
); };