diff --git a/web/src/components/Calender.jsx b/web/src/components/Calender.jsx index 26e5997be..9ca02a6d4 100644 --- a/web/src/components/Calender.jsx +++ b/web/src/components/Calender.jsx @@ -1,12 +1,14 @@ import { h } from 'preact'; -import { useEffect, useState, useCallback, useMemo } from 'preact/hooks'; +import { useEffect, useState, useCallback, useMemo, useRef } from 'preact/hooks'; import ArrowRight from '../icons/ArrowRight'; import ArrowRightDouble from '../icons/ArrowRightDouble'; const oneDay = 60 * 60 * 24 * 1000; const todayTimestamp = Date.now() - (Date.now() % oneDay) + new Date().getTimezoneOffset() * 1000 * 60; -const Calender = ({ onChange, calenderRef }) => { +const Calender = ({ onChange, calenderRef, close }) => { + const keyRef = useRef([]); + const date = new Date(); const year = date.getFullYear(); const month = date.getMonth(); @@ -38,6 +40,7 @@ const Calender = ({ onChange, calenderRef }) => { timeRange: { before: null, after: null }, monthDetails: null, }); + const getNumberOfDays = useCallback((year, month) => { return 40 - new Date(year, month, 40).getDate(); }, []); @@ -90,6 +93,7 @@ const Calender = ({ onChange, calenderRef }) => { index++; } } + // setState((prev) => ({ ...prev, selectedDay: todayTimestamp, monthDetails: monthArray })); return monthArray; }, [getNumberOfDays, getDayDetails] @@ -99,6 +103,13 @@ const Calender = ({ onChange, calenderRef }) => { setState((prev) => ({ ...prev, selectedDay: todayTimestamp, monthDetails: getMonthDetails(year, month) })); }, [year, month, getMonthDetails]); + useEffect(() => { + // add refs for keyboard navigation + if (state.monthDetails) { + keyRef.current = keyRef.current.slice(0, state.monthDetails.length); + } + }, [state.monthDetails]); + const isCurrentDay = (day) => day.timestamp === todayTimestamp; const isSelectedRange = useCallback( @@ -203,13 +214,40 @@ const Calender = ({ onChange, calenderRef }) => { }); }; + const handleKeydown = (e, day, index) => { + if ((keyRef.current && e.key === 'Enter') || e.keyCode === 32) { + onDateClick(day); + } + if (e.key === 'ArrowLeft') { + index > 0 && keyRef.current[index - 1].focus(); + } + if (e.key === 'ArrowRight') { + index < 41 && keyRef.current[index + 1].focus(); + } + if (e.key === 'ArrowUp') { + e.preventDefault(); + index > 6 && keyRef.current[index - 7].focus(); + } + if (e.key === 'ArrowDown') { + e.preventDefault(); + index < 36 && keyRef.current[index + 7].focus(); + } + if (e.key === 'Escape') { + close(); + } + }; + const renderCalendar = () => { const days = state.monthDetails && - state.monthDetails.map((day, index) => { + state.monthDetails.map((day, idx) => { return (