diff --git a/apps/web/components/booking/BookingListItem.tsx b/apps/web/components/booking/BookingListItem.tsx index 2b237f9cf1..6f3f03abe7 100644 --- a/apps/web/components/booking/BookingListItem.tsx +++ b/apps/web/components/booking/BookingListItem.tsx @@ -13,11 +13,12 @@ import dayjs from "dayjs"; import { useRouter } from "next/router"; import { useState } from "react"; import { useMutation } from "react-query"; -import { Frequency as RRuleFrequency } from "rrule"; +import { parseRecurringEvent } from "@calcom/lib"; import classNames from "@calcom/lib/classNames"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import showToast from "@calcom/lib/notification"; +import { Frequency } from "@calcom/prisma/zod-utils"; import Button from "@calcom/ui/Button"; import { Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader } from "@calcom/ui/Dialog"; import { Tooltip } from "@calcom/ui/Tooltip"; @@ -196,7 +197,7 @@ function BookingListItem(booking: BookingItemProps) { [recurringStrings] = parseRecurringDates( { startDate: booking.startTime, - recurringEvent: booking.eventType.recurringEvent, + recurringEvent: parseRecurringEvent(booking.eventType.recurringEvent), recurringCount: booking.recurringCount, }, i18n @@ -307,14 +308,10 @@ function BookingListItem(booking: BookingItemProps) { {`${t("every_for_freq", { freq: t( - `${RRuleFrequency[booking.eventType.recurringEvent.freq] - .toString() - .toLowerCase()}` + `${Frequency[booking.eventType.recurringEvent.freq].toString().toLowerCase()}` ), })} ${booking.recurringCount} ${t( - `${RRuleFrequency[booking.eventType.recurringEvent.freq] - .toString() - .toLowerCase()}`, + `${Frequency[booking.eventType.recurringEvent.freq].toString().toLowerCase()}`, { count: booking.recurringCount } )}`}

diff --git a/apps/web/components/booking/pages/AvailabilityPage.tsx b/apps/web/components/booking/pages/AvailabilityPage.tsx index d0ea17ba51..92d926ea5c 100644 --- a/apps/web/components/booking/pages/AvailabilityPage.tsx +++ b/apps/web/components/booking/pages/AvailabilityPage.tsx @@ -21,7 +21,6 @@ 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 { @@ -35,6 +34,7 @@ import classNames from "@calcom/lib/classNames"; import { CAL_URL, WEBAPP_URL } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { localStorage } from "@calcom/lib/webstorage"; +import { Frequency } from "@calcom/prisma/zod-utils"; import { asStringOrNull } from "@lib/asStringOrNull"; import { timeZone } from "@lib/clock"; @@ -302,7 +302,7 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage

{t("every_for_freq", { freq: t( - `${RRuleFrequency[eventType.recurringEvent.freq].toString().toLowerCase()}` + `${Frequency[eventType.recurringEvent.freq].toString().toLowerCase()}` ), })}

@@ -317,12 +317,9 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage }} />

- {t( - `${RRuleFrequency[eventType.recurringEvent.freq].toString().toLowerCase()}`, - { - count: recurringEventCount, - } - )} + {t(`${Frequency[eventType.recurringEvent.freq].toString().toLowerCase()}`, { + count: recurringEventCount, + })}

)} @@ -344,7 +341,7 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage

{t("every_for_freq", { freq: t( - `${RRuleFrequency[eventType.recurringEvent.freq].toString().toLowerCase()}` + `${Frequency[eventType.recurringEvent.freq].toString().toLowerCase()}` ), })}

@@ -359,12 +356,9 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage }} />

- {t( - `${RRuleFrequency[eventType.recurringEvent.freq].toString().toLowerCase()}`, - { - count: recurringEventCount, - } - )} + {t(`${Frequency[eventType.recurringEvent.freq].toString().toLowerCase()}`, { + count: recurringEventCount, + })}

)} @@ -471,9 +465,7 @@ const AvailabilityPage = ({ profile, plan, eventType, workingHours, previousPage

{t("every_for_freq", { - freq: t( - `${RRuleFrequency[eventType.recurringEvent.freq].toString().toLowerCase()}` - ), + freq: t(`${Frequency[eventType.recurringEvent.freq].toString().toLowerCase()}`), })}

- {t(`${RRuleFrequency[eventType.recurringEvent.freq].toString().toLowerCase()}`, { + {t(`${Frequency[eventType.recurringEvent.freq].toString().toLowerCase()}`, { count: recurringEventCount, })}

diff --git a/apps/web/components/booking/pages/BookingPage.tsx b/apps/web/components/booking/pages/BookingPage.tsx index 545a0e9b16..3862480656 100644 --- a/apps/web/components/booking/pages/BookingPage.tsx +++ b/apps/web/components/booking/pages/BookingPage.tsx @@ -20,7 +20,6 @@ import { Controller, useForm, useWatch } from "react-hook-form"; import { FormattedNumber, IntlProvider } from "react-intl"; import { ReactMultiEmail } from "react-multi-email"; import { useMutation } from "react-query"; -import { Frequency as RRuleFrequency } from "rrule"; import { v4 as uuidv4 } from "uuid"; import { z } from "zod"; @@ -32,6 +31,7 @@ import { import classNames from "@calcom/lib/classNames"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { HttpError } from "@calcom/lib/http-error"; +import { Frequency } from "@calcom/prisma/zod-utils"; import { createPaymentLink } from "@calcom/stripe/client"; import { Button } from "@calcom/ui/Button"; import { Tooltip } from "@calcom/ui/Tooltip"; @@ -518,9 +518,9 @@ const BookingPage = ({

{`${t("every_for_freq", { - freq: t(`${RRuleFrequency[eventType.recurringEvent.freq].toString().toLowerCase()}`), + freq: t(`${Frequency[eventType.recurringEvent.freq].toString().toLowerCase()}`), })} ${recurringEventCount} ${t( - `${RRuleFrequency[eventType.recurringEvent.freq].toString().toLowerCase()}`, + `${Frequency[eventType.recurringEvent.freq].toString().toLowerCase()}`, { count: parseInt(recurringEventCount.toString()) } )}`}

@@ -529,12 +529,12 @@ const BookingPage = ({
- {(rescheduleUid || !eventType.recurringEvent.freq) && + {(rescheduleUid || !eventType.recurringEvent?.freq) && parseDate(dayjs(date).tz(timeZone()), i18n)} {!rescheduleUid && - eventType.recurringEvent.freq && + eventType.recurringEvent?.freq && recurringStrings.slice(0, 5).map((aDate, key) =>

{aDate}

)} - {!rescheduleUid && eventType.recurringEvent.freq && recurringStrings.length > 5 && ( + {!rescheduleUid && eventType.recurringEvent?.freq && recurringStrings.length > 5 && (
( diff --git a/apps/web/components/eventtype/EventTypeDescription.tsx b/apps/web/components/eventtype/EventTypeDescription.tsx index 2a06a0e1d0..dea616a9aa 100644 --- a/apps/web/components/eventtype/EventTypeDescription.tsx +++ b/apps/web/components/eventtype/EventTypeDescription.tsx @@ -10,9 +10,9 @@ import { Prisma, SchedulingType } from "@prisma/client"; import { useMemo } from "react"; import { FormattedNumber, IntlProvider } from "react-intl"; +import { parseRecurringEvent } from "@calcom/lib"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { baseEventTypeSelect } from "@calcom/prisma/selects"; -import { RecurringEvent } from "@calcom/types/Calendar"; import classNames from "@lib/classNames"; @@ -30,8 +30,8 @@ export type EventTypeDescriptionProps = { export const EventTypeDescription = ({ eventType, className }: EventTypeDescriptionProps) => { const { t } = useLocale(); - const recurringEvent: RecurringEvent = useMemo( - () => (eventType.recurringEvent as RecurringEvent) || [], + const recurringEvent = useMemo( + () => parseRecurringEvent(eventType.recurringEvent), [eventType.recurringEvent] ); diff --git a/apps/web/components/eventtype/RecurringEventController.tsx b/apps/web/components/eventtype/RecurringEventController.tsx index bd81513ea7..32c9f64bff 100644 --- a/apps/web/components/eventtype/RecurringEventController.tsx +++ b/apps/web/components/eventtype/RecurringEventController.tsx @@ -1,17 +1,16 @@ -import { Collapsible, CollapsibleContent } from "@radix-ui/react-collapsible"; import type { FormValues } from "pages/event-types/[type]"; import { useState } from "react"; import { UseFormReturn } from "react-hook-form"; -import { Frequency as RRuleFrequency } from "rrule"; import { useLocale } from "@calcom/lib/hooks/useLocale"; +import { Frequency } from "@calcom/prisma/zod-utils"; import { RecurringEvent } from "@calcom/types/Calendar"; import { Alert } from "@calcom/ui/Alert"; import Select from "@components/ui/form/Select"; type RecurringEventControllerProps = { - recurringEvent: RecurringEvent; + recurringEvent: RecurringEvent | null; formMethods: UseFormReturn; paymentEnabled: boolean; onRecurringEventDefined: (value: boolean) => void; @@ -24,20 +23,13 @@ export default function RecurringEventController({ onRecurringEventDefined, }: RecurringEventControllerProps) { const { t } = useLocale(); - - const [recurringEventDefined, setRecurringEventDefined] = useState(recurringEvent?.count !== undefined); - - const [recurringEventInterval, setRecurringEventInterval] = useState(recurringEvent?.interval || 1); - const [recurringEventFrequency, setRecurringEventFrequency] = useState( - recurringEvent?.freq || RRuleFrequency.WEEKLY - ); - const [recurringEventCount, setRecurringEventCount] = useState(recurringEvent?.count || 12); + const [recurringEventState, setRecurringEventState] = useState(recurringEvent); /* Just yearly-0, monthly-1 and weekly-2 */ - const recurringEventFreqOptions = Object.entries(RRuleFrequency) + const recurringEventFreqOptions = Object.entries(Frequency) .filter(([key, value]) => isNaN(Number(key)) && Number(value) < 3) .map(([key, value]) => ({ - label: t(`${key.toString().toLowerCase()}`, { count: recurringEventInterval }), + label: t(`${key.toString().toLowerCase()}`, { count: recurringEventState?.interval }), value: value.toString(), })); @@ -55,27 +47,23 @@ export default function RecurringEventController({
{ - setRecurringEventDefined(event?.target.checked); onRecurringEventDefined(event?.target.checked); if (!event?.target.checked) { - formMethods.setValue("recurringEvent", {}); + formMethods.setValue("recurringEvent", null); + setRecurringEventState(null); } else { - formMethods.setValue( - "recurringEvent", - recurringEventDefined - ? recurringEvent - : { - interval: 1, - count: 12, - freq: RRuleFrequency.WEEKLY, - } - ); + const newVal = recurringEvent || { + interval: 1, + count: 12, + freq: Frequency.WEEKLY, + }; + formMethods.setValue("recurringEvent", newVal); + setRecurringEventState(newVal); } - recurringEvent = formMethods.getValues("recurringEvent"); }} type="checkbox" className="text-primary-600 h-4 w-4 rounded border-gray-300" - defaultChecked={recurringEventDefined} + defaultChecked={recurringEventState !== null} data-testid="recurring-event-check" id="recurringEvent" /> @@ -86,11 +74,8 @@ export default function RecurringEventController({
- setRecurringEventDefined(!recurringEventDefined)}> - + {recurringEventState && ( +

{t("repeats_every")}

{ - setRecurringEventInterval(parseInt(event?.target.value)); - recurringEvent.interval = parseInt(event?.target.value); - formMethods.setValue("recurringEvent", recurringEvent); + const newVal = { + ...recurringEventState, + interval: parseInt(event?.target.value), + }; + formMethods.setValue("recurringEvent", newVal); + setRecurringEventState(newVal); }} />