From d83883e7e4cdb939bcdd0b35276037ddeacd0aea Mon Sep 17 00:00:00 2001 From: Om Ray <38233712+om-ray@users.noreply.github.com> Date: Mon, 14 Nov 2022 04:12:28 -0500 Subject: [PATCH] Minimum booking notice will allow hours and days (#5217) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * minimum booking notice allows hours and days * Fixed error with Prisma not updating properly and input changing value to minutes autmatically * fix type error * Update apps/web/components/v2/eventtype/EventLimitsTab.tsx Co-authored-by: Peer Richelsen * moved minimumBookingNotice to clientside, removed migration from prisma, changed DurationField to regular InputField * Update packages/lib/convertMinimumBookingNoticeToMinutes.ts Co-authored-by: alannnc * added MINUTES_IN_HOUR, MINUTES_IN_DAY, and HOURS_IN_DAY as exportable consts * Fix some comparison, mobile styles and const usages * minimumBookingNotice values will never be floats * fixed issue with minbookingnotice not updating properly in prisma * Removed console.logs, converted minimumBookingNoticeType to ref, removed unreliable accessing of array * remove yarn lockfile * Revert "remove yarn lockfile" This reverts commit fefc24c80269f5445c8eb7a640e2816d7d8b0407. * Revert "Revert "remove yarn lockfile"" This reverts commit c8cc4d3c0eddb2c91d077d2277ad5ea10315ec95. * Replaced currentDurationType export with state passed down from parent * Improvements for duration notice type logic * Undo adding submodule updates * Update apps/web/components/eventtype/EventLimitsTab.tsx Co-authored-by: Hariom Balhara * Update packages/lib/findDurationType.ts Co-authored-by: Omar López * Update apps/web/components/eventtype/EventLimitsTab.tsx Co-authored-by: Omar López * Update packages/lib/convertToNewDurationType.ts Co-authored-by: Omar López * Update apps/web/components/eventtype/EventLimitsTab.tsx Co-authored-by: Omar López * Update apps/web/test/lib/getSchedule.test.ts Co-authored-by: Omar López * remove passing in as object * Update apps/web/test/lib/getSchedule.test.ts Co-authored-by: Omar López * Update packages/lib/convertToNewDurationType.ts Co-authored-by: Omar López * Delete convertMinimumBookingNoticeToMinutes.ts * Syntax fix Co-authored-by: Peer Richelsen Co-authored-by: Peer Richelsen Co-authored-by: alannnc Co-authored-by: Hariom Balhara Co-authored-by: Jeroen Reumkens Co-authored-by: Alex van Andel Co-authored-by: Omar López --- .../components/eventtype/EventLimitsTab.tsx | 122 ++++++++++++++++-- apps/web/pages/event-types/[type]/index.tsx | 12 +- packages/lib/convertToNewDurationType.ts | 27 ++++ packages/lib/findDurationType.ts | 7 + packages/ui/components/form/inputs/Input.tsx | 4 - 5 files changed, 155 insertions(+), 17 deletions(-) create mode 100644 packages/lib/convertToNewDurationType.ts create mode 100644 packages/lib/findDurationType.ts diff --git a/apps/web/components/eventtype/EventLimitsTab.tsx b/apps/web/components/eventtype/EventLimitsTab.tsx index 8b9a147d33..0431dbf57a 100644 --- a/apps/web/components/eventtype/EventLimitsTab.tsx +++ b/apps/web/components/eventtype/EventLimitsTab.tsx @@ -1,23 +1,29 @@ import { useAutoAnimate } from "@formkit/auto-animate/react"; import * as RadioGroup from "@radix-ui/react-radio-group"; import { EventTypeSetupInfered, FormValues } from "pages/event-types/[type]"; -import { useState } from "react"; -import { useFormContext, Controller, useWatch } from "react-hook-form"; +import { useMemo, useRef, useState } from "react"; +import { Controller, useFormContext, useWatch } from "react-hook-form"; import { classNames } from "@calcom/lib"; +import convertToNewDurationType, { DurationType } from "@calcom/lib/convertToNewDurationType"; +import findDurationType from "@calcom/lib/findDurationType"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { PeriodType } from "@calcom/prisma/client"; import type { BookingLimit } from "@calcom/types/Calendar"; import { Icon } from "@calcom/ui"; import { Button } from "@calcom/ui/components"; -import { Label, Input, MinutesField } from "@calcom/ui/components/form"; +import { Input, InputField, Label } from "@calcom/ui/components/form"; import { Select, SettingsToggle } from "@calcom/ui/v2"; import DateRangePicker from "@calcom/ui/v2/core/form/date-range-picker/DateRangePicker"; -export const EventLimitsTab = (props: Pick) => { +export const EventLimitsTab = ({ eventType }: Pick) => { const { t } = useLocale(); const formMethods = useFormContext(); - const { eventType } = props; + const minimumBookingNoticeType = useRef(findDurationType(eventType.minimumBookingNotice)); + const prevBookingNoticeType = useRef(minimumBookingNoticeType.current); + + const minimumBookingNoticeInDurationTypeFormValue = formMethods.watch("minimumBookingNoticeInDurationType"); + const PERIOD_TYPES = [ { type: "ROLLING" as const, @@ -47,6 +53,57 @@ export const EventLimitsTab = (props: Pick) defaultValue: periodType?.type, }); + const onMinimumNoticeDurationTypeChange = useMemo( + () => (durationType?: DurationType) => { + if (typeof durationType === "undefined") return; + + // Store current selected type in ref to use in previous run for comparrison. + minimumBookingNoticeType.current = durationType; + + // Uses the previous selected type and converts the value to the new type. + // Eg day was selected before, user selects hours now, so we multiple * 24 and round up. + const minimumBookingNoticeInDurationType = convertToNewDurationType( + prevBookingNoticeType.current, + durationType, + Number(minimumBookingNoticeInDurationTypeFormValue) + ); + + // Uses the round up value in the new type to calculate the value in minutes. + // We should NOT use minimumBookingNoticeInDurationTypeFormValue here, since that + // would break in the case that the user enters 90 minutes, changes the type to + // hours (that will show 2 hours), but the value in minutes would then remain 90, + // which is something else than the user things they save. + const minimumBookingNoticeInMinutes = convertToNewDurationType( + durationType, + "minutes", + Number(minimumBookingNoticeInDurationType) + ); + + // Updates both form values as well as stores the current type as previous type in ref. + formMethods.setValue("minimumBookingNotice", minimumBookingNoticeInMinutes); + formMethods.setValue("minimumBookingNoticeInDurationType", minimumBookingNoticeInDurationType); + prevBookingNoticeType.current = durationType; + }, + [formMethods, minimumBookingNoticeInDurationTypeFormValue] + ); + + /** + * When the user inputs a new value for minimumBookingNoticeInDurationType, + * we calculate the value in minutes, and update this hidden field as well. + */ + const onMinimumNoticeChange = useMemo( + () => (duration: string) => { + const minimumBookingNoticeInMinutes = convertToNewDurationType( + minimumBookingNoticeType.current, + "minutes", + Number(duration) + ); + + formMethods.setValue("minimumBookingNotice", minimumBookingNoticeInMinutes); + }, + [formMethods] + ); + return (
@@ -116,13 +173,54 @@ export const EventLimitsTab = (props: Pick)
-
- + { + const durationTypeOptions = [ + { + label: t("minutes"), + value: "minutes", + }, + { + label: t("hours"), + value: "hours", + }, + { + label: t("days"), + value: "days", + }, + ]; + + return ( + <> +
+ ) => + onMinimumNoticeChange(event.target.value), + })} + /> + +
+