diff --git a/src/components/common/TimePicker.jsx b/src/components/common/TimePicker.jsx index 92f31716..c94202ba 100644 --- a/src/components/common/TimePicker.jsx +++ b/src/components/common/TimePicker.jsx @@ -4,6 +4,7 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => { const [time, setTime] = useState(value || ""); const [isOpen, setIsOpen] = useState(false); const dropdownRef = useRef(null); + const slotRefs = useRef({}); const getCurrentTime = () => { const now = new Date(); @@ -27,37 +28,39 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => { return `${hoursFormatted}:${minutesFormatted} ${period}`; }; - // all slots - // const generateTimeSlots = () => { - // const slots = []; - // let currentTime = new Date(getCurrentTime()); - // for (let i = 0; i < 144; i++) { // 24 hours with custom interval - // slots.push(formatTime(currentTime)); - // currentTime.setMinutes(currentTime.getMinutes() + interval); - // } - // return slots; - // }; - // imit slots to current time: const generateTimeSlots = () => { const slots = []; - let currentTime = new Date(); - currentTime.setSeconds(0); - currentTime.setMilliseconds(0); - - const endTime = new Date(currentTime); // current time as upper limit - - let slotTime = new Date(); - slotTime.setHours(0, 0, 0, 0); // start from 00:00 - - while (slotTime <= endTime) { - slots.push(formatTime(new Date(slotTime))); - slotTime.setMinutes(slotTime.getMinutes() + interval); + const now = new Date(); + now.setSeconds(0); + now.setMilliseconds(0); + + // Round current time DOWN to nearest interval + const currentSlot = new Date(); + currentSlot.setMinutes( + Math.floor(currentSlot.getMinutes() / interval) * interval + ); + currentSlot.setSeconds(0); + currentSlot.setMilliseconds(0); + + let slot = new Date(); + slot.setHours(0, 0, 0, 0); // Start from midnight + + for (let i = 0; i < 144; i++) { + const formatted = formatTime(slot); + const diffInMinutes = (currentSlot - slot) / 60000; + const isSelectable = diffInMinutes >= 0 && diffInMinutes <= interval * 5; + + slots.push({ + time: formatted, + isSelectable, + }); + + slot.setMinutes(slot.getMinutes() + interval); } - + return slots; }; - const handleSelect = (selectedTime) => { setTime(selectedTime); @@ -65,6 +68,7 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => { setIsOpen(false); }; + // Handle click outside the dropdown to close it useEffect(() => { const handleClickOutside = (event) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { @@ -75,14 +79,26 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => { return () => document.removeEventListener("mousedown", handleClickOutside); }, []); + // If there's no value, set the default time useEffect(() => { if (!value) { const defaultTime = formatTime(getCurrentTime()); setTime(defaultTime); - if (onChange) onChange(defaultTime); + if (onChange) onChange(defaultTime); } }, [value, interval, onChange]); + // Scroll to the selected slot when it's open + useEffect(() => { + if (isOpen && time && slotRefs.current[time]) { + const selectedSlot = slotRefs.current[time]; + selectedSlot.scrollIntoView({ + behavior: "smooth", + block: "center", + }); + } + }, [isOpen, time]); + return (
{label && } @@ -114,22 +130,27 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => { display: "flex", flexDirection: "column", gap: "5px", - maxHeight: "200px", // Adjust max height to fit the container - overflowY: "auto", // Enables vertical scrolling + maxHeight: "200px", + overflowY: "auto", }} > - {generateTimeSlots().map((slot, index) => ( + {generateTimeSlots().map(({ time: slotTime, isSelectable }, index) => ( ))}