From 65600b76f20a8cc6c487a1800838bceddb5bceb7 Mon Sep 17 00:00:00 2001 From: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Date: Thu, 27 Jul 2023 21:19:21 +0530 Subject: [PATCH] fix: Set the limit of Occurrences (#10269) --- apps/web/public/static/locales/en/common.json | 1 + packages/features/bookings/Booker/store.ts | 10 +++- .../components/event-meta/Occurences.tsx | 52 ++++++++++++++----- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index 97abe8df39..4d6395a6d2 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -510,6 +510,7 @@ "your_name": "Your name", "your_full_name": "Your full name", "no_name":"No name", + "enter_number_between_range": "Please enter a number between 1 and {{maxOccurences}}", "email_address": "Email address", "enter_valid_email": "Please enter a valid email", "location": "Location", diff --git a/packages/features/bookings/Booker/store.ts b/packages/features/bookings/Booker/store.ts index 6745e76b4a..24fbf7de5a 100644 --- a/packages/features/bookings/Booker/store.ts +++ b/packages/features/bookings/Booker/store.ts @@ -6,8 +6,7 @@ import { BookerLayouts } from "@calcom/prisma/zod-utils"; import type { GetBookingType } from "../lib/get-booking"; import type { BookerState, BookerLayout } from "./types"; -import { validateLayout } from "./utils/layout"; -import { updateQueryParam, getQueryParam, removeQueryParam } from "./utils/query-param"; +import { updateQueryParam, getQueryParam } from "./utils/query-param"; /** * Arguments passed into store initializer, containing @@ -86,6 +85,11 @@ export type BookerStore = { */ recurringEventCount: number | null; setRecurringEventCount(count: number | null): void; + /** + * Input occurrence count. + */ + occurenceCount: number | null; + setOccurenceCount(count: number | null): void; /** * If booking is being rescheduled or it has seats, it receives a rescheduleUid or bookingUid * the current booking details are passed in. The `bookingData` @@ -241,6 +245,8 @@ export const useBookerStore = create((set, get) => ({ }, recurringEventCount: null, setRecurringEventCount: (recurringEventCount: number | null) => set({ recurringEventCount }), + occurenceCount: null, + setOccurenceCount: (occurenceCount: number | null) => set({ occurenceCount }), rescheduleUid: null, bookingData: null, bookingUid: null, diff --git a/packages/features/bookings/components/event-meta/Occurences.tsx b/packages/features/bookings/components/event-meta/Occurences.tsx index fdb143664f..fbed0add18 100644 --- a/packages/features/bookings/components/event-meta/Occurences.tsx +++ b/packages/features/bookings/components/event-meta/Occurences.tsx @@ -1,31 +1,38 @@ -import { useEffect } from "react"; +import { useEffect, useState } from "react"; import { useBookerStore } from "@calcom/features/bookings/Booker/store"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { parseRecurringDates } from "@calcom/lib/parse-dates"; import { getRecurringFreq } from "@calcom/lib/recurringStrings"; -import { Tooltip } from "@calcom/ui"; +import { Tooltip, Alert } from "@calcom/ui"; import { Input } from "@calcom/ui"; import { useTimePreferences } from "../../lib"; import type { PublicEvent } from "../../types"; export const EventOccurences = ({ event }: { event: PublicEvent }) => { + const maxOccurences = event.recurringEvent?.count || null; const { t, i18n } = useLocale(); - const [setRecurringEventCount, recurringEventCount] = useBookerStore((state) => [ - state.setRecurringEventCount, - state.recurringEventCount, - ]); + const [setRecurringEventCount, recurringEventCount, setOccurenceCount, occurenceCount] = useBookerStore( + (state) => [ + state.setRecurringEventCount, + state.recurringEventCount, + state.setOccurenceCount, + state.occurenceCount, + ] + ); const selectedTimeslot = useBookerStore((state) => state.selectedTimeslot); const bookerState = useBookerStore((state) => state.state); const { timezone, timeFormat } = useTimePreferences(); - + const [warning, setWarning] = useState(false); // Set initial value in booker store. useEffect(() => { if (!event.recurringEvent?.count) return; - setRecurringEventCount(event.recurringEvent.count); - }, [setRecurringEventCount, event.recurringEvent]); - + setOccurenceCount(occurenceCount || event.recurringEvent.count); + setRecurringEventCount(recurringEventCount || event.recurringEvent.count); + if (occurenceCount && (occurenceCount > event.recurringEvent.count || occurenceCount < 1)) + setWarning(true); + }, [setRecurringEventCount, event.recurringEvent, recurringEventCount, setOccurenceCount, occurenceCount]); if (!event.recurringEvent) return null; if (bookerState === "booking" && recurringEventCount && selectedTimeslot) { @@ -63,14 +70,35 @@ export const EventOccurences = ({ event }: { event: PublicEvent }) => { { - setRecurringEventCount(parseInt(event?.target.value)); + const pattern = /^(?=.*[0-9])\S+$/; + const inputValue = parseInt(event.target.value); + setOccurenceCount(inputValue); + if ( + !pattern.test(event.target.value) || + inputValue < 1 || + (maxOccurences && inputValue > maxOccurences) + ) { + setWarning(true); + setRecurringEventCount(maxOccurences); + } else { + setWarning(false); + setRecurringEventCount(inputValue); + } }} /> + {t("occurrence", { count: recurringEventCount || event.recurringEvent.count, })} + {warning && ( +
+ +
+ )} ); };