From 27a65b7dc0a93e05635ace950c8b6221b3a30699 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Sun, 5 May 2024 22:39:22 +0200 Subject: [PATCH] more date fixes --- components/availability/AvailabilityForm.js | 24 ++++---- components/calendar/avcalendar.tsx | 11 ++-- pages/cart/calendar/index.tsx | 3 +- src/helpers/common.js | 61 ++++++++++++++++++--- 4 files changed, 76 insertions(+), 23 deletions(-) diff --git a/components/availability/AvailabilityForm.js b/components/availability/AvailabilityForm.js index 79b1345..3fa1144 100644 --- a/components/availability/AvailabilityForm.js +++ b/components/availability/AvailabilityForm.js @@ -69,8 +69,11 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o // get cart event or set default time for Sofia timezone - const minTime = cartEvent?.startTime || DateTime.now().set({ hour: 8, minute: 0, second: 0, millisecond: 0, zone: 'Europe/Sofia' }).toJSDate(); - const maxTime = cartEvent?.endTime || DateTime.now().set({ hour: 20, minute: 0, second: 0, millisecond: 0, zone: 'Europe/Sofia' }).toJSDate(); + // const minTime = cartEvent?.startTime || DateTime.now().set({ hour: 8, minute: 0, zone: 'Europe/Sofia' }).toJSDate(); + // const maxTime = cartEvent?.endTime || DateTime.now().set({ hour: 20, minute: 0, zone: 'Europe/Sofia' }).toJSDate(); + const d = DateTime.fromJSDate(day).setZone('Europe/Sofia', { keepLocalTime: true }); + const minTime = d.set({ hour: 9, minute: 0 }).toJSDate(); + const maxTime = d.set({ hour: 19, minute: 30 }).toJSDate(); useEffect(() => { setTimeSlots(generateTimeSlots(new Date(minTime), new Date(maxTime), cartEvent.shiftDuration, availabilities)); @@ -189,11 +192,14 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o // Common function to set shared properties function setSharedAvailabilityProperties(availability, group, timeSlots) { - let startTime = common.setTimeHHmm(new Date(availability.startTime || day), common.getTimeFormatted(group[0].startTime)); - let endTime = common.setTimeHHmm(new Date(availability.endTime || day), common.getTimeFormatted(group[group.length - 1].endTime)); + const d = DateTime.fromJSDate(day).setZone('Europe/Sofia', { keepLocalTime: true }); + console.log("day: " + d.toISODate()); + let startTime = common.setTime(d, group[0].startTime).toJSDate(); + let endTime = common.setTime(d, group[group.length - 1].endTime).toJSDate(); + availability.startTime = startTime; availability.endTime = endTime; - availability.name = common.getTimeFormatted(group[0].startTime) + "--" + common.getTimeFormatted(group[group.length - 1].endTime); + availability.name = common.getTimeFormatted(group[0].startTime) + "/" + common.getTimeFormatted(group[group.length - 1].endTime); availability.isWithTransportIn = group[0].isFirst && timeSlots[0].isWithTransport; availability.isWithTransportOut = group[group.length - 1].isLast && timeSlots[timeSlots.length - 1].isWithTransport; @@ -283,18 +289,14 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o const generateTimeSlots = (start, end, increment, items) => { const slots = []; let currentTime = start; - - //const baseDate = new Date(Date.UTC(2000, 0, 1, 0, 0, 0)); - //const baseDate = new Date(start); - while (isBefore(currentTime, end)) { let slotStart = currentTime; let slotEnd = addMinutes(currentTime, increment); const isChecked = items.some(item => { return item.startTime && item.endTime && - (slotStart.getTime() < item.endTime.getTime()) && - (slotEnd.getTime() > item.startTime.getTime()); + common.isTimeBetween(item.startTime, item.endTime, slotStart) && + common.isTimeBetween(item.startTime, item.endTime, slotEnd); }); slots.push({ startTime: slotStart, endTime: slotEnd, isChecked: isChecked, }); diff --git a/components/calendar/avcalendar.tsx b/components/calendar/avcalendar.tsx index 662047f..d5997e7 100644 --- a/components/calendar/avcalendar.tsx +++ b/components/calendar/avcalendar.tsx @@ -230,10 +230,13 @@ const AvCalendar = ({ publisherId, events, selectedDate, cartEvents }) => { end = common.setTimeHHmm(startdate, "23:59"); } - setDate(start); - let existingEvents = filterEvents(evts, publisherId, startdate); - console.log("handleSelect: " + existingEvents); - setCartEvent(getCartEvent(date)); + // Update date state and calculate events based on the new startdate + setDate(startdate); + const existingEvents = filterEvents(evts, publisherId, startdate); + console.log("handleSelect: ", existingEvents); + + // Use the updated startdate for getCartEvent and ensure it reflects in the state properly + setCartEvent(getCartEvent(startdate)); setSelectedEvents(existingEvents); setIsModalOpen(true); }; diff --git a/pages/cart/calendar/index.tsx b/pages/cart/calendar/index.tsx index 0ab474b..5a4aa7d 100644 --- a/pages/cart/calendar/index.tsx +++ b/pages/cart/calendar/index.tsx @@ -15,6 +15,7 @@ import { toast } from 'react-toastify'; import ProtectedRoute from '../../../components/protectedRoute'; import ConfirmationModal from '../../../components/ConfirmationModal'; import LocalShippingIcon from '@mui/icons-material/LocalShipping'; +const { DateTime } = require('luxon'); // import { FaPlus, FaCogs, FaTrashAlt, FaSpinner } from 'react-icons/fa'; // Import FontAwesome icons @@ -544,7 +545,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) { var dayName = common.DaysOfWeekArray[value.getDayEuropean()]; const cartEvent = events.find(event => event.dayofweek == dayName); lastShift = { - endTime: new Date(value.setHours(9, 0, 0, 0)), + endTime: DateTime.fromJSDate(value).setZone('Europe/Sofia', { keepLocalTime: true }).set({ hour: 9 }).toJSDate(), cartEventId: cartEvent.id }; } diff --git a/src/helpers/common.js b/src/helpers/common.js index 39c352d..89a7811 100644 --- a/src/helpers/common.js +++ b/src/helpers/common.js @@ -370,6 +370,8 @@ exports.getDateFormatedShort = function (date) { } + + /*Todo: remove: toISOString slice(0, 10) @@ -527,7 +529,7 @@ exports.fuzzySearch = function (publishers, searchQuery, distanceThreshold = 0.9 } -exports.getCurrentNonthFormatted = function () { +exports.getCurrentMonthFormatted = function () { const getCurrentYearMonth = () => { const currentDate = new Date(); const year = currentDate.getFullYear(); @@ -546,11 +548,28 @@ exports.getCurrentYearMonth = () => { // new date FNs -// Utility to handle date parsing consistently +/** + * Parses an input into a Luxon DateTime object, setting the timezone to 'Europe/Sofia' while keeping the local time. + * @param {string|Date} input - The input date string or JavaScript Date object. + * @returns {DateTime} - A Luxon DateTime object with the timezone set to 'Europe/Sofia', preserving the local time. + */ const parseDate = (input) => { - return (typeof input === 'string' || input instanceof Date) - ? DateTime.fromJSDate(new Date(input), { zone: 'Europe/Sofia' }) - : DateTime.now({ zone: 'Europe/Sofia' }); + let dateTime; + + if (input instanceof DateTime) { + // If input is already a Luxon DateTime, we adjust the zone only. + dateTime = input.setZone('Europe/Sofia'); + } else if (typeof input === 'string' || input instanceof Date) { + // Create a DateTime from the input assuming local timezone to preserve local time when changing the zone. + dateTime = DateTime.fromJSDate(new Date(input), { zone: 'local' }); + dateTime = dateTime.setZone('Europe/Sofia'); + } else { + // Use the current time if no input is given, considered as local time. + dateTime = DateTime.local().setZone('Europe/Sofia'); + } + + // Set the timezone to 'Europe/Sofia' while keeping the original local time. + return dateTime.setZone('Europe/Sofia', { keepLocalTime: true }); }; exports.parseDate = parseDate; @@ -560,6 +579,18 @@ exports.setTimezone = (input) => { dateTime = dateTime.setZone('Europe/Sofia', { keepLocalTime: true }); return dateTime.toJSDate(); }; +exports.setTime = (baseDateTime, timeDateTime) => { + // Ensure both inputs are DateTime objects + baseDateTime = parseDate(baseDateTime); + timeDateTime = parseDate(timeDateTime); + + return baseDateTime.set({ + hour: timeDateTime.hour, + minute: timeDateTime.minute, + second: timeDateTime.second, + millisecond: timeDateTime.millisecond + }); +}; // Format date to a specified format, defaulting to 'HH:mm' exports.getTimeFormatted = (input, format = 'HH:mm') => { @@ -571,7 +602,7 @@ exports.getTimeFormatted = (input, format = 'HH:mm') => { exports.setTimeHHmm = (input, timeString) => { let dateTime = parseDate(input); const [hour, minute] = timeString.split(':').map(Number); - dateTime = dateTime.set({ hour, minute, second: 0, millisecond: 0 }); + dateTime = dateTime.set({ hour, minute }); return dateTime.toJSDate(); }; @@ -579,9 +610,25 @@ exports.setTimeHHmm = (input, timeString) => { exports.parseTimeHHmm = (timeString) => { const dateTime = DateTime.now({ zone: 'Europe/Sofia' }); const [hour, minute] = timeString.split(':').map(Number); - return dateTime.set({ hour, minute, second: 0, millisecond: 0 }).toJSDate(); + return dateTime.set({ hour, minute }).toJSDate(); }; +function isTimeBetween(startTime, endTime, checkTime) { + const start = new Date(0, 0, 0, startTime.getHours(), startTime.getMinutes()); + const end = new Date(0, 0, 0, endTime.getHours(), endTime.getMinutes()); + const check = new Date(0, 0, 0, checkTime.getHours(), checkTime.getMinutes()); + + // If the end time is less than the start time, it means the time range spans midnight + if (end < start) { + // Check time is between start and midnight or between midnight and end + return (check >= start && check <= new Date(0, 0, 1, 0, 0, 0)) || (check >= new Date(0, 0, 0, 0, 0, 0) && check <= end); + } else { + return check >= start && check <= end; + } +} +exports.isTimeBetween = isTimeBetween; + + // ToDo: update all uses of this function to use the new one // exports.getTimeFormatted = function (date) {