fix dates ant TZ, cleanup

This commit is contained in:
Dobromir Popov
2024-05-05 20:43:47 +02:00
parent 227c1f0ab3
commit 12503409b6
7 changed files with 190 additions and 154 deletions

View File

@ -11,6 +11,7 @@ import { ToastContainer } from 'react-toastify';
const common = require('src/helpers/common');
//todo import Availability type from prisma schema
import { isBefore, addMinutes, isAfter, isEqual, set, getHours, getMinutes, getSeconds } from 'date-fns'; //ToDo obsolete
import { stat } from 'fs';
const { DateTime, FixedOffsetZone } = require('luxon');
@ -21,7 +22,7 @@ const fetchConfig = async () => {
return config.default;
};
export default function AvailabilityForm({ publisherId, existingItems, inline, onDone, date, datePicker = false }) {
export default function AvailabilityForm({ publisherId, existingItems, inline, onDone, date, cartEvent, datePicker = false }) {
const router = useRouter();
const urls = {
@ -67,14 +68,13 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
}, []);
// Define the minimum and maximum times
const minTime = new Date();
minTime.setHours(9, 0, 0, 0); // 8:00 AM
const maxTime = new Date();
maxTime.setHours(19, 30, 0, 0); // 8:00 PM
// 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();
useEffect(() => {
setTimeSlots(generateTimeSlots(minTime, maxTime, 90, availabilities));
setTimeSlots(generateTimeSlots(new Date(minTime), new Date(maxTime), cartEvent.shiftDuration, availabilities));
console.log("AvailabilityForm: minTime: " + common.getTimeFormatted(minTime) + ", maxTime: " + common.getTimeFormatted(maxTime), ", " + cartEvent.shiftDuration + " min. shifts");
}, []);
@ -189,34 +189,11 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
// Common function to set shared properties
function setSharedAvailabilityProperties(availability, group, timeSlots) {
// Define a fixed offset for Sofia (+2 hours from UTC, ignoring DST)
const fixedZone = FixedOffsetZone.instance(120); // Offset in minutes
// availability.startTime = group[0].startTime;
// availability.endTime = group[group.length - 1].endTime;
// Adjust start time
let startTime = DateTime.fromJSDate(group[0].startTime, { zone: 'utc' })
.setZone(fixedZone, { keepLocalTime: true });
startTime = startTime.set({
hour: group[0].startTime.getUTCHours(),
minute: group[0].startTime.getUTCMinutes(),
second: group[0].startTime.getUTCSeconds()
});
// Adjust end time
let endTime = DateTime.fromJSDate(group[group.length - 1].endTime, { zone: 'utc' })
.setZone(fixedZone, { keepLocalTime: true });
endTime = endTime.set({
hour: group[group.length - 1].endTime.getUTCHours(),
minute: group[group.length - 1].endTime.getUTCMinutes(),
second: group[group.length - 1].endTime.getUTCSeconds()
});
// Update the availability object with the new times
availability.startTime = startTime.toJSDate();
availability.endTime = endTime.toJSDate();
availability.name = common.getTimeFomatted(group[0].startTime) + "-" + common.getTimeFomatted(group[group.length - 1].endTime);
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));
availability.startTime = startTime;
availability.endTime = 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;
@ -308,27 +285,19 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
let currentTime = start;
//const baseDate = new Date(Date.UTC(2000, 0, 1, 0, 0, 0));
const baseDate = new Date(start);
//const baseDate = new Date(start);
while (isBefore(currentTime, end)) {
let slotStart = normalizeTime(currentTime, baseDate);
let slotEnd = normalizeTime(addMinutes(currentTime, increment), baseDate);
let slotStart = currentTime;
let slotEnd = addMinutes(currentTime, increment);
const isChecked = items.some(item => {
let itemStart = item.startTime ? normalizeTime(new Date(item.startTime), baseDate) : null;
let itemEnd = item.endTime ? normalizeTime(new Date(item.endTime), baseDate) : null;
return itemStart && itemEnd &&
(slotStart.getTime() < itemEnd.getTime()) &&
(slotEnd.getTime() > itemStart.getTime());
});
slots.push({
startTime: slotStart,
endTime: slotEnd,
isChecked: isChecked,
return item.startTime && item.endTime &&
(slotStart.getTime() < item.endTime.getTime()) &&
(slotEnd.getTime() > item.startTime.getTime());
});
slots.push({ startTime: slotStart, endTime: slotEnd, isChecked: isChecked, });
currentTime = addMinutes(currentTime, increment);
}
@ -342,16 +311,6 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
return slots;
};
// Normalize the time part of a date by using a base date
function normalizeTime(date, baseDate) {
return set(baseDate, {
hours: getHours(date),
minutes: getMinutes(date),
seconds: getSeconds(date),
milliseconds: 0
});
}
const TimeSlotCheckboxes = ({ slots, setSlots, items: [] }) => {
const [allDay, setAllDay] = useState(slots.every(slot => slot.isChecked));
const handleAllDayChange = (e) => {

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, use } from 'react';
import { Calendar, momentLocalizer, dateFnsLocalizer } from 'react-big-calendar';
import 'react-big-calendar/lib/css/react-big-calendar.css';
import AvailabilityForm from '../availability/AvailabilityForm';
@ -18,11 +18,13 @@ import { MdToday } from 'react-icons/md';
import { useSwipeable } from 'react-swipeable';
import axiosInstance from '../../src/axiosSecure';
import { set } from 'date-fns';
import { get } from 'http';
// import { set, format, addDays } from 'date-fns';
// import { isEqual, isSameDay, getHours, getMinutes } from 'date-fns';
import { filter } from 'jszip';
import e from 'express';
// import { filter } from 'jszip';
// import e from 'express';
@ -46,7 +48,7 @@ const messages = {
// Any other labels you want to translate...
};
const AvCalendar = ({ publisherId, events, selectedDate }) => {
const AvCalendar = ({ publisherId, events, selectedDate, cartEvents }) => {
const isAdmin = ProtectedRoute.IsInRole(UserRole.ADMIN);
@ -65,7 +67,15 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
return { start, end };
});
const [cartEvent, setCartEvent] = useState(null);
function getCartEvent(date) {
const dayOfWeek = common.getDayOfWeekNameEnEnumForDate(date);
const ce = cartEvents?.find(e => e.dayofweek === dayOfWeek);
return ce;
}
useEffect(() => { setCartEvent(getCartEvent(date)); },
[date, selectedEvents]);
// Update internal state when `events` prop changes
useEffect(() => {
@ -113,6 +123,7 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
//setDisplayedEvents(evts);
}, [visibleRange, evts, currentView]);
// todo: review that
const handlers = useSwipeable({
onSwipedLeft: () => navigate('NEXT'),
onSwipedRight: () => navigate('PREV'),
@ -201,18 +212,13 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
return existingEvents;
};
// Define min and max times
const minHour = 8; // 8:00 AM
const maxHour = 20; // 8:00 PM
const minTime = new Date();
minTime.setHours(minHour, 0, 0);
const maxTime = new Date();
maxTime.setHours(maxHour, 0, 0);
const totalHours = maxHour - minHour;
// const totalHours = maxHour - minHour;
const handleSelect = ({ mode, start, end }) => {
const startdate = typeof start === 'string' ? new Date(start) : start;
const enddate = typeof end === 'string' ? new Date(end) : end;
//we set the time to proper timezone
const startdate = common.setTimezone(start);
const enddate = common.setTimezone(end);
if (!start || !end) return;
//readonly for past dates (ToDo: if not admin)
@ -224,27 +230,10 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
end = common.setTimeHHmm(startdate, "23:59");
}
const startMinutes = common.getTimeInMinutes(start);
const endMinutes = common.getTimeInMinutes(end);
// Adjust start and end times to be within min and max hours
if (startMinutes < common.getTimeInMinutes(common.setTimeHHmm(start, minHour))) {
start = common.setTimeHHmm(start, minHour);
}
if (endMinutes > common.getTimeInMinutes(common.setTimeHHmm(end, maxHour))) {
end = common.setTimeHHmm(end, maxHour);
}
setDate(start);
// get exising events for the selected date
//ToDo: properly fix this. filterEvents does not return the expcted results
let existingEvents = filterEvents(evts, publisherId, startdate);
// if existingEvents is empty - create new with the selected range
// if (existingEvents.length === 0) {
// existingEvents = [{ startTime: start, endTime: end }];
// }
console.log("handleSelect: " + existingEvents);
setCartEvent(getCartEvent(date));
setSelectedEvents(existingEvents);
setIsModalOpen(true);
};
@ -509,8 +498,8 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
onSelectSlot={handleSelect}
onSelectEvent={handleEventClick}
style={{ height: '100%', width: '100%' }}
min={minTime} // Set minimum time
max={maxTime} // Set maximum time
min={cartEvent?.startTime} // Set minimum time
max={cartEvent?.endTime} // Set maximum time
messages={messages}
view={currentView}
views={['month', 'week', 'agenda']}
@ -541,6 +530,7 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
date={date}
onDone={handleDialogClose}
inline={true}
cartEvent={cartEvent}
// Pass other props as needed
/>
</div>

View File

@ -69,8 +69,8 @@ export default function CartEventForm(props: IProps) {
try {
console.log("fetching cart event from component " + router.query.id);
const { data } = await axiosInstance.get(urls.apiUrl + id);
data.startTime = common.formatTimeHHmm(data.startTime)
data.endTime = common.formatTimeHHmm(data.endTime)
data.startTime = common.getTimeFormatted(data.startTime)
data.endTime = common.getTimeFormatted(data.endTime)
setEvt(data);
console.log("id:" + evt.id);

View File

@ -11,9 +11,15 @@ function PublisherSearchBox({ id, selectedId, onChange, isFocused, filterDate, s
const [searchResults, setSearchResults] = useState([]);
const [selectedDate, setSelectedDate] = useState(filterDate);
// useEffect(() => {
// fetchPublishers();
// }, []); // Empty dependency array ensures this useEffect runs only once
// Update publishers when filterDate or showList changes
useEffect(() => {
fetchPublishers();
}, []); // Empty dependency array ensures this useEffect runs only once
}, [filterDate, showList]);
const fetchPublishers = async () => {
console.log("fetchPublishers called");
@ -60,10 +66,7 @@ function PublisherSearchBox({ id, selectedId, onChange, isFocused, filterDate, s
// console.log("filterDate changed = ", filterDate);
// }, [filterDate]);
// Update publishers when filterDate or showList changes
useEffect(() => {
fetchPublishers();
}, [filterDate, showList]);
// Update selectedItem when selectedId changes and also at the initial load
useEffect(() => {