diff --git a/apps/web/components/booking/pages/BookingPage.tsx b/apps/web/components/booking/pages/BookingPage.tsx index a0873bc9e1..6ebce26f45 100644 --- a/apps/web/components/booking/pages/BookingPage.tsx +++ b/apps/web/components/booking/pages/BookingPage.tsx @@ -4,7 +4,7 @@ import { useSession } from "next-auth/react"; import dynamic from "next/dynamic"; import Head from "next/head"; import { useRouter } from "next/router"; -import { useEffect, useMemo, useReducer, useState } from "react"; +import { useCallback, useEffect, useMemo, useReducer, useState } from "react"; import { useForm, useFormContext } from "react-hook-form"; import { v4 as uuidv4 } from "uuid"; import { z } from "zod"; @@ -15,6 +15,7 @@ import { getEventLocationType, locationKeyToString } from "@calcom/app-store/loc import { createPaymentLink } from "@calcom/app-store/stripepayment/lib/client"; import { getEventTypeAppData } from "@calcom/app-store/utils"; import type { LocationObject } from "@calcom/core/location"; +import type { Dayjs } from "@calcom/dayjs"; import dayjs from "@calcom/dayjs"; import { useEmbedNonStylesConfig, @@ -38,6 +39,7 @@ import useTheme from "@calcom/lib/hooks/useTheme"; import { HttpError } from "@calcom/lib/http-error"; import { getEveryFreqFor } from "@calcom/lib/recurringStrings"; import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; +import type { RecurringEvent } from "@calcom/types/Calendar"; import { Button, Form, Tooltip } from "@calcom/ui"; import { FiAlertTriangle, FiCalendar, FiRefreshCw, FiUser } from "@calcom/ui/components/icon"; @@ -213,6 +215,20 @@ const BookingPage = ({ duration = Number(queryDuration); } + // This is a workaround for forcing the same time format for both server side rendering and client side rendering + // At initial render, we use the default time format which is 12H + const [withDefaultTimeFormat, setWithDefaultTimeFormat] = useState(true); + const parseDateFunc = useCallback( + (date: string | null | Dayjs) => { + return parseDate(date, i18n, withDefaultTimeFormat); + }, + [withDefaultTimeFormat] + ); + // After intial render on client side, we let parseDateFunc to use the time format from the localStorage + useEffect(() => { + setWithDefaultTimeFormat(false); + }, []); + useEffect(() => { if (top !== window) { //page_view will be collected automatically by _middleware.ts @@ -370,15 +386,26 @@ const BookingPage = ({ // Calculate the booking date(s) let recurringStrings: string[] = [], recurringDates: Date[] = []; + const parseRecurringDatesFunc = useCallback( + (date: string | null | Dayjs, recurringEvent: RecurringEvent, recurringCount: number) => { + return parseRecurringDates( + { + startDate: date, + timeZone: timeZone(), + recurringEvent: recurringEvent, + recurringCount: recurringCount, + withDefaultTimeFormat: withDefaultTimeFormat, + }, + i18n + ); + }, + [withDefaultTimeFormat, date, eventType.recurringEvent, recurringEventCount] + ); if (eventType.recurringEvent?.freq && recurringEventCount !== null) { - [recurringStrings, recurringDates] = parseRecurringDates( - { - startDate: date, - timeZone: timeZone(), - recurringEvent: eventType.recurringEvent, - recurringCount: parseInt(recurringEventCount.toString()), - }, - i18n + [recurringStrings, recurringDates] = parseRecurringDatesFunc( + date, + eventType.recurringEvent, + parseInt(recurringEventCount.toString()) ); } @@ -507,7 +534,7 @@ const BookingPage = ({