Fixed issue where logged-in users couldn't select future time slots
This commit is contained in:
parent
c53aa1ec92
commit
7e45f6c429
@ -4,6 +4,7 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
const [time, setTime] = useState(value || "");
|
const [time, setTime] = useState(value || "");
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const dropdownRef = useRef(null);
|
const dropdownRef = useRef(null);
|
||||||
|
const slotRefs = useRef({});
|
||||||
|
|
||||||
const getCurrentTime = () => {
|
const getCurrentTime = () => {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
@ -27,44 +28,47 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
|
|
||||||
return `${hoursFormatted}:${minutesFormatted} ${period}`;
|
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 generateTimeSlots = () => {
|
||||||
const slots = [];
|
const slots = [];
|
||||||
let currentTime = new Date();
|
const now = new Date();
|
||||||
currentTime.setSeconds(0);
|
now.setSeconds(0);
|
||||||
currentTime.setMilliseconds(0);
|
now.setMilliseconds(0);
|
||||||
|
|
||||||
const endTime = new Date(currentTime); // current time as upper limit
|
// 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 slotTime = new Date();
|
let slot = new Date();
|
||||||
slotTime.setHours(0, 0, 0, 0); // start from 00:00
|
slot.setHours(0, 0, 0, 0); // Start from midnight
|
||||||
|
|
||||||
while (slotTime <= endTime) {
|
for (let i = 0; i < 144; i++) {
|
||||||
slots.push(formatTime(new Date(slotTime)));
|
const formatted = formatTime(slot);
|
||||||
slotTime.setMinutes(slotTime.getMinutes() + interval);
|
const diffInMinutes = (currentSlot - slot) / 60000;
|
||||||
|
const isSelectable = diffInMinutes >= 0 && diffInMinutes <= interval * 5;
|
||||||
|
|
||||||
|
slots.push({
|
||||||
|
time: formatted,
|
||||||
|
isSelectable,
|
||||||
|
});
|
||||||
|
|
||||||
|
slot.setMinutes(slot.getMinutes() + interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
return slots;
|
return slots;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleSelect = (selectedTime) => {
|
const handleSelect = (selectedTime) => {
|
||||||
setTime(selectedTime);
|
setTime(selectedTime);
|
||||||
if (onChange) onChange(selectedTime);
|
if (onChange) onChange(selectedTime);
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle click outside the dropdown to close it
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event) => {
|
const handleClickOutside = (event) => {
|
||||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
||||||
@ -75,6 +79,7 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
return () => document.removeEventListener("mousedown", handleClickOutside);
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// If there's no value, set the default time
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
const defaultTime = formatTime(getCurrentTime());
|
const defaultTime = formatTime(getCurrentTime());
|
||||||
@ -83,6 +88,17 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
}
|
}
|
||||||
}, [value, interval, onChange]);
|
}, [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 (
|
return (
|
||||||
<div className="position-relative w-100" ref={dropdownRef}>
|
<div className="position-relative w-100" ref={dropdownRef}>
|
||||||
{label && <label className="form-label">{label}</label>}
|
{label && <label className="form-label">{label}</label>}
|
||||||
@ -114,22 +130,27 @@ const TimePicker = ({ label, onChange, interval = 10, value }) => {
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
gap: "5px",
|
gap: "5px",
|
||||||
maxHeight: "200px", // Adjust max height to fit the container
|
maxHeight: "200px",
|
||||||
overflowY: "auto", // Enables vertical scrolling
|
overflowY: "auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{generateTimeSlots().map((slot, index) => (
|
{generateTimeSlots().map(({ time: slotTime, isSelectable }, index) => (
|
||||||
<button
|
<button
|
||||||
key={index}
|
key={index}
|
||||||
className={`dropdown-item px-3 py-1 text-center rounded-1 ${
|
className={`dropdown-item px-3 py-1 text-center rounded-1 ${
|
||||||
time === slot ? "btn-primary" : ""
|
time === slotTime ? "btn-primary" : ""
|
||||||
}`}
|
}`}
|
||||||
|
ref={(el) => (slotRefs.current[slotTime] = el)}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
handleSelect(slot);
|
if (isSelectable) handleSelect(slotTime);
|
||||||
}}
|
}}
|
||||||
|
disabled={!isSelectable}
|
||||||
|
style={
|
||||||
|
!isSelectable ? { opacity: 0.5, cursor: "not-allowed" } : {}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{slot}
|
{slotTime}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user