From ac0c3bdfb9cdf7a8007c0750dd4752d9ab68cfa0 Mon Sep 17 00:00:00 2001 From: Demian Caldelas Date: Tue, 22 Feb 2022 21:23:52 -0300 Subject: [PATCH] Fix dynamic min/max values for schedule form (#1940) Co-authored-by: Alex van Andel --- .../web/components/ui/modal/SetTimesModal.tsx | 84 ++++++++++++++++--- 1 file changed, 72 insertions(+), 12 deletions(-) diff --git a/apps/web/components/ui/modal/SetTimesModal.tsx b/apps/web/components/ui/modal/SetTimesModal.tsx index c564716f6f..07e82c02cd 100644 --- a/apps/web/components/ui/modal/SetTimesModal.tsx +++ b/apps/web/components/ui/modal/SetTimesModal.tsx @@ -1,11 +1,15 @@ import { ClockIcon } from "@heroicons/react/outline"; -import { useRef } from "react"; +import dayjs from "dayjs"; +import customParseFormat from "dayjs/plugin/customParseFormat"; +import { useRef, useState } from "react"; import { useLocale } from "@lib/hooks/useLocale"; import showToast from "@lib/notification"; import Button from "@components/ui/Button"; +dayjs.extend(customParseFormat); + interface SetTimesModalProps { startTime: number; endTime: number; @@ -21,6 +25,11 @@ export default function SetTimesModal(props: SetTimesModalProps) { const startMinsRef = useRef(null!); const endHoursRef = useRef(null!); const endMinsRef = useRef(null!); + const [endMinuteDisable, setEndMinuteDisable] = useState(false); + const [maximumStartTime, setMaximumStartTime] = useState({ hour: endHours, minute: 59 }); + const [minimumEndTime, setMinimumEndTime] = useState({ hour: startHours, minute: 59 }); + + const STEP = 15; const isValidTime = (startTime: number, endTime: number) => { if (new Date(startTime) > new Date(endTime)) { @@ -34,6 +43,48 @@ export default function SetTimesModal(props: SetTimesModalProps) { return true; }; + // compute dynamic range for minimum and maximum allowed hours/minutes. + const setEdgeTimes = ( + (step) => + ( + startHoursRef: React.MutableRefObject, + startMinsRef: React.MutableRefObject, + endHoursRef: React.MutableRefObject, + endMinsRef: React.MutableRefObject + ) => { + //parse all the refs + const startHour = parseInt(startHoursRef.current.value); + let startMinute = parseInt(startMinsRef.current.value); + const endHour = parseInt(endHoursRef.current.value); + let endMinute = parseInt(endMinsRef.current.value); + + //convert to dayjs object + const startTime = dayjs(`${startHour}-${startMinute}`, "hh:mm"); + const endTime = dayjs(`${endHour}-${endMinute}`, "hh:mm"); + + //compute minimin and maximum allowed + const maximumStartTime = endTime.subtract(step, "minute"); + const maximumStartHour = maximumStartTime.hour(); + const maximumStartMinute = startHour === endHour ? maximumStartTime.minute() : 59; + + const minimumEndTime = startTime.add(step, "minute"); + const minimumEndHour = minimumEndTime.hour(); + const minimumEndMinute = startHour === endHour ? minimumEndTime.minute() : 0; + + //check allow min/max minutes when the end/start hour matches + if (startHoursRef.current.value === endHoursRef.current.value) { + if (parseInt(startMinsRef.current.value) >= maximumStartMinute) + startMinsRef.current.value = maximumStartMinute.toString(); + if (parseInt(endMinsRef.current.value) <= minimumEndMinute) + endMinsRef.current.value = minimumEndMinute.toString(); + } + + //save into state + setMaximumStartTime({ hour: maximumStartHour, minute: maximumStartMinute }); + setMinimumEndTime({ hour: minimumEndHour, minute: minimumEndMinute }); + } + )(STEP); + return (
-
+
@@ -73,17 +124,18 @@ export default function SetTimesModal(props: SetTimesModalProps) { ref={startHoursRef} type="number" min="0" - max="23" - maxLength={2} + max={maximumStartTime.hour} + minLength={2} name="hours" id="startHours" className="focus:border-brand block w-full rounded-md border-gray-300 shadow-sm focus:ring-black sm:text-sm" placeholder="9" defaultValue={startHours} + onChange={() => setEdgeTimes(startHoursRef, startMinsRef, endHoursRef, endMinsRef)} />
: -
+
@@ -91,27 +143,28 @@ export default function SetTimesModal(props: SetTimesModalProps) { ref={startMinsRef} type="number" min="0" - max="59" - step="15" + max={maximumStartTime.minute} + step={STEP} maxLength={2} name="minutes" id="startMinutes" className="focus:border-brand block w-full rounded-md border-gray-300 shadow-sm focus:ring-black sm:text-sm" placeholder="30" defaultValue={startMinutes} + onChange={() => setEdgeTimes(startHoursRef, startMinsRef, endHoursRef, endMinsRef)} />
-
+
{ + if (endHoursRef.current.value === "24") endMinsRef.current.value = "0"; + setEdgeTimes(startHoursRef, startMinsRef, endHoursRef, endMinsRef); + setEndMinuteDisable(endHoursRef.current.value === "24"); + }} />
: -
+
setEdgeTimes(startHoursRef, startMinsRef, endHoursRef, endMinsRef)} />