fix dates ant TZ, cleanup
This commit is contained in:
@ -11,6 +11,7 @@ import { ToastContainer } from 'react-toastify';
|
|||||||
const common = require('src/helpers/common');
|
const common = require('src/helpers/common');
|
||||||
//todo import Availability type from prisma schema
|
//todo import Availability type from prisma schema
|
||||||
import { isBefore, addMinutes, isAfter, isEqual, set, getHours, getMinutes, getSeconds } from 'date-fns'; //ToDo obsolete
|
import { isBefore, addMinutes, isAfter, isEqual, set, getHours, getMinutes, getSeconds } from 'date-fns'; //ToDo obsolete
|
||||||
|
import { stat } from 'fs';
|
||||||
|
|
||||||
const { DateTime, FixedOffsetZone } = require('luxon');
|
const { DateTime, FixedOffsetZone } = require('luxon');
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ const fetchConfig = async () => {
|
|||||||
return config.default;
|
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 router = useRouter();
|
||||||
const urls = {
|
const urls = {
|
||||||
@ -67,14 +68,13 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
// Define the minimum and maximum times
|
// get cart event or set default time for Sofia timezone
|
||||||
const minTime = new Date();
|
const minTime = cartEvent?.startTime || DateTime.now().set({ hour: 8, minute: 0, second: 0, millisecond: 0, zone: 'Europe/Sofia' }).toJSDate();
|
||||||
minTime.setHours(9, 0, 0, 0); // 8:00 AM
|
const maxTime = cartEvent?.endTime || DateTime.now().set({ hour: 20, minute: 0, second: 0, millisecond: 0, zone: 'Europe/Sofia' }).toJSDate();
|
||||||
const maxTime = new Date();
|
|
||||||
maxTime.setHours(19, 30, 0, 0); // 8:00 PM
|
|
||||||
|
|
||||||
useEffect(() => {
|
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
|
// Common function to set shared properties
|
||||||
function setSharedAvailabilityProperties(availability, group, timeSlots) {
|
function setSharedAvailabilityProperties(availability, group, timeSlots) {
|
||||||
// Define a fixed offset for Sofia (+2 hours from UTC, ignoring DST)
|
let startTime = common.setTimeHHmm(new Date(availability.startTime || day), common.getTimeFormatted(group[0].startTime));
|
||||||
const fixedZone = FixedOffsetZone.instance(120); // Offset in minutes
|
let endTime = common.setTimeHHmm(new Date(availability.endTime || day), common.getTimeFormatted(group[group.length - 1].endTime));
|
||||||
|
availability.startTime = startTime;
|
||||||
// availability.startTime = group[0].startTime;
|
availability.endTime = endTime;
|
||||||
// availability.endTime = group[group.length - 1].endTime;
|
availability.name = common.getTimeFormatted(group[0].startTime) + "--" + common.getTimeFormatted(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);
|
|
||||||
|
|
||||||
availability.isWithTransportIn = group[0].isFirst && timeSlots[0].isWithTransport;
|
availability.isWithTransportIn = group[0].isFirst && timeSlots[0].isWithTransport;
|
||||||
availability.isWithTransportOut = group[group.length - 1].isLast && timeSlots[timeSlots.length - 1].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;
|
let currentTime = start;
|
||||||
|
|
||||||
//const baseDate = new Date(Date.UTC(2000, 0, 1, 0, 0, 0));
|
//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)) {
|
while (isBefore(currentTime, end)) {
|
||||||
let slotStart = normalizeTime(currentTime, baseDate);
|
let slotStart = currentTime;
|
||||||
let slotEnd = normalizeTime(addMinutes(currentTime, increment), baseDate);
|
let slotEnd = addMinutes(currentTime, increment);
|
||||||
|
|
||||||
const isChecked = items.some(item => {
|
const isChecked = items.some(item => {
|
||||||
let itemStart = item.startTime ? normalizeTime(new Date(item.startTime), baseDate) : null;
|
return item.startTime && item.endTime &&
|
||||||
let itemEnd = item.endTime ? normalizeTime(new Date(item.endTime), baseDate) : null;
|
(slotStart.getTime() < item.endTime.getTime()) &&
|
||||||
|
(slotEnd.getTime() > item.startTime.getTime());
|
||||||
return itemStart && itemEnd &&
|
|
||||||
(slotStart.getTime() < itemEnd.getTime()) &&
|
|
||||||
(slotEnd.getTime() > itemStart.getTime());
|
|
||||||
});
|
|
||||||
|
|
||||||
slots.push({
|
|
||||||
startTime: slotStart,
|
|
||||||
endTime: slotEnd,
|
|
||||||
isChecked: isChecked,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
slots.push({ startTime: slotStart, endTime: slotEnd, isChecked: isChecked, });
|
||||||
currentTime = addMinutes(currentTime, increment);
|
currentTime = addMinutes(currentTime, increment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,16 +311,6 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
|||||||
return slots;
|
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 TimeSlotCheckboxes = ({ slots, setSlots, items: [] }) => {
|
||||||
const [allDay, setAllDay] = useState(slots.every(slot => slot.isChecked));
|
const [allDay, setAllDay] = useState(slots.every(slot => slot.isChecked));
|
||||||
const handleAllDayChange = (e) => {
|
const handleAllDayChange = (e) => {
|
||||||
|
@ -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 { Calendar, momentLocalizer, dateFnsLocalizer } from 'react-big-calendar';
|
||||||
import 'react-big-calendar/lib/css/react-big-calendar.css';
|
import 'react-big-calendar/lib/css/react-big-calendar.css';
|
||||||
import AvailabilityForm from '../availability/AvailabilityForm';
|
import AvailabilityForm from '../availability/AvailabilityForm';
|
||||||
@ -18,11 +18,13 @@ import { MdToday } from 'react-icons/md';
|
|||||||
|
|
||||||
import { useSwipeable } from 'react-swipeable';
|
import { useSwipeable } from 'react-swipeable';
|
||||||
import axiosInstance from '../../src/axiosSecure';
|
import axiosInstance from '../../src/axiosSecure';
|
||||||
|
import { set } from 'date-fns';
|
||||||
|
import { get } from 'http';
|
||||||
|
|
||||||
// import { set, format, addDays } from 'date-fns';
|
// import { set, format, addDays } from 'date-fns';
|
||||||
// import { isEqual, isSameDay, getHours, getMinutes } from 'date-fns';
|
// import { isEqual, isSameDay, getHours, getMinutes } from 'date-fns';
|
||||||
import { filter } from 'jszip';
|
// import { filter } from 'jszip';
|
||||||
import e from 'express';
|
// import e from 'express';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -46,7 +48,7 @@ const messages = {
|
|||||||
// Any other labels you want to translate...
|
// Any other labels you want to translate...
|
||||||
};
|
};
|
||||||
|
|
||||||
const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
const AvCalendar = ({ publisherId, events, selectedDate, cartEvents }) => {
|
||||||
|
|
||||||
const isAdmin = ProtectedRoute.IsInRole(UserRole.ADMIN);
|
const isAdmin = ProtectedRoute.IsInRole(UserRole.ADMIN);
|
||||||
|
|
||||||
@ -65,7 +67,15 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
|||||||
return { start, end };
|
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
|
// Update internal state when `events` prop changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -113,6 +123,7 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
|||||||
//setDisplayedEvents(evts);
|
//setDisplayedEvents(evts);
|
||||||
}, [visibleRange, evts, currentView]);
|
}, [visibleRange, evts, currentView]);
|
||||||
|
|
||||||
|
// todo: review that
|
||||||
const handlers = useSwipeable({
|
const handlers = useSwipeable({
|
||||||
onSwipedLeft: () => navigate('NEXT'),
|
onSwipedLeft: () => navigate('NEXT'),
|
||||||
onSwipedRight: () => navigate('PREV'),
|
onSwipedRight: () => navigate('PREV'),
|
||||||
@ -201,18 +212,13 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
|||||||
return existingEvents;
|
return existingEvents;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define min and max times
|
|
||||||
const minHour = 8; // 8:00 AM
|
// const totalHours = maxHour - minHour;
|
||||||
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 handleSelect = ({ mode, start, end }) => {
|
const handleSelect = ({ mode, start, end }) => {
|
||||||
const startdate = typeof start === 'string' ? new Date(start) : start;
|
//we set the time to proper timezone
|
||||||
const enddate = typeof end === 'string' ? new Date(end) : end;
|
const startdate = common.setTimezone(start);
|
||||||
|
const enddate = common.setTimezone(end);
|
||||||
|
|
||||||
if (!start || !end) return;
|
if (!start || !end) return;
|
||||||
//readonly for past dates (ToDo: if not admin)
|
//readonly for past dates (ToDo: if not admin)
|
||||||
@ -224,27 +230,10 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
|||||||
end = common.setTimeHHmm(startdate, "23:59");
|
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);
|
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);
|
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);
|
console.log("handleSelect: " + existingEvents);
|
||||||
|
setCartEvent(getCartEvent(date));
|
||||||
setSelectedEvents(existingEvents);
|
setSelectedEvents(existingEvents);
|
||||||
setIsModalOpen(true);
|
setIsModalOpen(true);
|
||||||
};
|
};
|
||||||
@ -509,8 +498,8 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
|||||||
onSelectSlot={handleSelect}
|
onSelectSlot={handleSelect}
|
||||||
onSelectEvent={handleEventClick}
|
onSelectEvent={handleEventClick}
|
||||||
style={{ height: '100%', width: '100%' }}
|
style={{ height: '100%', width: '100%' }}
|
||||||
min={minTime} // Set minimum time
|
min={cartEvent?.startTime} // Set minimum time
|
||||||
max={maxTime} // Set maximum time
|
max={cartEvent?.endTime} // Set maximum time
|
||||||
messages={messages}
|
messages={messages}
|
||||||
view={currentView}
|
view={currentView}
|
||||||
views={['month', 'week', 'agenda']}
|
views={['month', 'week', 'agenda']}
|
||||||
@ -541,6 +530,7 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
|||||||
date={date}
|
date={date}
|
||||||
onDone={handleDialogClose}
|
onDone={handleDialogClose}
|
||||||
inline={true}
|
inline={true}
|
||||||
|
cartEvent={cartEvent}
|
||||||
// Pass other props as needed
|
// Pass other props as needed
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -69,8 +69,8 @@ export default function CartEventForm(props: IProps) {
|
|||||||
try {
|
try {
|
||||||
console.log("fetching cart event from component " + router.query.id);
|
console.log("fetching cart event from component " + router.query.id);
|
||||||
const { data } = await axiosInstance.get(urls.apiUrl + id);
|
const { data } = await axiosInstance.get(urls.apiUrl + id);
|
||||||
data.startTime = common.formatTimeHHmm(data.startTime)
|
data.startTime = common.getTimeFormatted(data.startTime)
|
||||||
data.endTime = common.formatTimeHHmm(data.endTime)
|
data.endTime = common.getTimeFormatted(data.endTime)
|
||||||
setEvt(data);
|
setEvt(data);
|
||||||
|
|
||||||
console.log("id:" + evt.id);
|
console.log("id:" + evt.id);
|
||||||
|
@ -11,9 +11,15 @@ function PublisherSearchBox({ id, selectedId, onChange, isFocused, filterDate, s
|
|||||||
const [searchResults, setSearchResults] = useState([]);
|
const [searchResults, setSearchResults] = useState([]);
|
||||||
const [selectedDate, setSelectedDate] = useState(filterDate);
|
const [selectedDate, setSelectedDate] = useState(filterDate);
|
||||||
|
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// fetchPublishers();
|
||||||
|
// }, []); // Empty dependency array ensures this useEffect runs only once
|
||||||
|
|
||||||
|
// Update publishers when filterDate or showList changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchPublishers();
|
fetchPublishers();
|
||||||
}, []); // Empty dependency array ensures this useEffect runs only once
|
}, [filterDate, showList]);
|
||||||
|
|
||||||
const fetchPublishers = async () => {
|
const fetchPublishers = async () => {
|
||||||
console.log("fetchPublishers called");
|
console.log("fetchPublishers called");
|
||||||
@ -60,10 +66,7 @@ function PublisherSearchBox({ id, selectedId, onChange, isFocused, filterDate, s
|
|||||||
// console.log("filterDate changed = ", filterDate);
|
// console.log("filterDate changed = ", filterDate);
|
||||||
// }, [filterDate]);
|
// }, [filterDate]);
|
||||||
|
|
||||||
// Update publishers when filterDate or showList changes
|
|
||||||
useEffect(() => {
|
|
||||||
fetchPublishers();
|
|
||||||
}, [filterDate, showList]);
|
|
||||||
|
|
||||||
// Update selectedItem when selectedId changes and also at the initial load
|
// Update selectedItem when selectedId changes and also at the initial load
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -161,7 +161,7 @@ export default async function handler(req, res) {
|
|||||||
newPubs: newPubs,
|
newPubs: newPubs,
|
||||||
placeName: assignment.shift.cartEvent.location.name,
|
placeName: assignment.shift.cartEvent.location.name,
|
||||||
dateStr: common.getDateFormated(assignment.shift.startTime),
|
dateStr: common.getDateFormated(assignment.shift.startTime),
|
||||||
time: common.formatTimeHHmm(assignment.shift.startTime),
|
time: common.getTimeFormatted(assignment.shift.startTime),
|
||||||
sentDate: common.getDateFormated(new Date())
|
sentDate: common.getDateFormated(new Date())
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ export default async function handler(req, res) {
|
|||||||
email: pubsToSend[i].email,
|
email: pubsToSend[i].email,
|
||||||
placeName: assignment.shift.cartEvent.location.name,
|
placeName: assignment.shift.cartEvent.location.name,
|
||||||
dateStr: common.getDateFormated(assignment.shift.startTime),
|
dateStr: common.getDateFormated(assignment.shift.startTime),
|
||||||
time: common.formatTimeHHmm(assignment.shift.startTime),
|
time: common.getTimeFormatted(assignment.shift.startTime),
|
||||||
sentDate: common.getDateFormated(new Date())
|
sentDate: common.getDateFormated(new Date())
|
||||||
};
|
};
|
||||||
let results = emailHelper.SendEmailHandlebars(
|
let results = emailHelper.SendEmailHandlebars(
|
||||||
|
@ -15,13 +15,14 @@ import { getServerSession } from "next-auth/next"
|
|||||||
|
|
||||||
import PublisherSearchBox from '../components/publisher/PublisherSearchBox';
|
import PublisherSearchBox from '../components/publisher/PublisherSearchBox';
|
||||||
import PublisherInlineForm from '../components/publisher/PublisherInlineForm';
|
import PublisherInlineForm from '../components/publisher/PublisherInlineForm';
|
||||||
|
import CartEventForm from "components/cartevent/CartEventForm";
|
||||||
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
initialItems: Availability[];
|
initialItems: Availability[];
|
||||||
initialUserId: string;
|
initialUserId: string;
|
||||||
}
|
}
|
||||||
export default function IndexPage({ initialItems, initialUserId }: IProps) {
|
export default function IndexPage({ initialItems, initialUserId, cartEvents }: IProps) {
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
const [userName, setUserName] = useState(session?.user?.name);
|
const [userName, setUserName] = useState(session?.user?.name);
|
||||||
const [userId, setUserId] = useState(initialUserId);
|
const [userId, setUserId] = useState(initialUserId);
|
||||||
@ -78,7 +79,7 @@ export default function IndexPage({ initialItems, initialUserId }: IProps) {
|
|||||||
<div className="text-center font-bold pb-3 xs:pb-1">
|
<div className="text-center font-bold pb-3 xs:pb-1">
|
||||||
<PublisherInlineForm publisherId={userId} />
|
<PublisherInlineForm publisherId={userId} />
|
||||||
</div>
|
</div>
|
||||||
<AvCalendar publisherId={userId} events={events} selectedDate={new Date()} />
|
<AvCalendar publisherId={userId} events={events} selectedDate={new Date()} cartEvents={cartEvents} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
@ -223,10 +224,30 @@ export const getServerSideProps = async (context) => {
|
|||||||
return updatedItem;
|
return updatedItem;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// log first availability startTime to verify timezone and UTC conversion
|
||||||
|
|
||||||
|
console.log("First availability startTime: " + items[0].startTime);
|
||||||
|
console.log("First availability startTime: " + items[0].startTime.toLocaleString());
|
||||||
|
|
||||||
|
const prisma = common.getPrismaClient();
|
||||||
|
let cartEvents = await prisma.cartEvent.findMany({
|
||||||
|
where: {
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
startTime: true,
|
||||||
|
endTime: true,
|
||||||
|
dayofweek: true,
|
||||||
|
shiftDuration: true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
cartEvents = common.convertDatesToISOStrings(cartEvents);
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
initialItems: items,
|
initialItems: items,
|
||||||
userId: session?.user.id,
|
userId: session?.user.id,
|
||||||
|
cartEvents: cartEvents,
|
||||||
// messages: (await import(`../content/i18n/${context.locale}.json`)).default
|
// messages: (await import(`../content/i18n/${context.locale}.json`)).default
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -339,14 +339,8 @@ exports.compareTimes = function (time1, time2) {
|
|||||||
const time2String = `${getHours(time2)}:${getMinutes(time2)}`;
|
const time2String = `${getHours(time2)}:${getMinutes(time2)}`;
|
||||||
return time1String.localeCompare(time2String);
|
return time1String.localeCompare(time2String);
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.normalizeTime = function (date, baseDate) {
|
exports.normalizeTime = function (date, baseDate) {
|
||||||
// return set(baseDate, {
|
|
||||||
// hours: getHours(date),
|
|
||||||
// minutes: getMinutes(date),
|
|
||||||
// seconds: getSeconds(date),
|
|
||||||
// milliseconds: 0
|
|
||||||
// });
|
|
||||||
//don't use date-fns
|
|
||||||
let newDate = new Date(baseDate);
|
let newDate = new Date(baseDate);
|
||||||
newDate.setHours(date.getHours(), date.getMinutes(), date.getSeconds(), 0);
|
newDate.setHours(date.getHours(), date.getMinutes(), date.getSeconds(), 0);
|
||||||
return newDate;
|
return newDate;
|
||||||
@ -549,54 +543,96 @@ exports.getCurrentYearMonth = () => {
|
|||||||
const month = String(currentDate.getMonth() + 1).padStart(2, '0'); // Month is 0-indexed
|
const month = String(currentDate.getMonth() + 1).padStart(2, '0'); // Month is 0-indexed
|
||||||
return `${year}-${month}`;
|
return `${year}-${month}`;
|
||||||
}
|
}
|
||||||
exports.getTimeFormatted = function (date) {
|
|
||||||
const dateTime = DateTime.fromJSDate(date, { zone: 'Europe/Sofia' });
|
|
||||||
return dateTime.toFormat('HH:mm');
|
// new date FNs
|
||||||
|
// Utility to handle date parsing consistently
|
||||||
|
const parseDate = (input) => {
|
||||||
|
return (typeof input === 'string' || input instanceof Date)
|
||||||
|
? DateTime.fromJSDate(new Date(input), { zone: 'Europe/Sofia' })
|
||||||
|
: DateTime.now({ zone: 'Europe/Sofia' });
|
||||||
|
};
|
||||||
|
exports.parseDate = parseDate;
|
||||||
|
|
||||||
|
// Set timezone to 'Europe/Sofia' without translating time
|
||||||
|
exports.setTimezone = (input) => {
|
||||||
|
let dateTime = parseDate(input);
|
||||||
|
dateTime = dateTime.setZone('Europe/Sofia', { keepLocalTime: true });
|
||||||
|
return dateTime.toJSDate();
|
||||||
};
|
};
|
||||||
|
|
||||||
// format date to 'HH:mm' time string required by the time picker
|
// Format date to a specified format, defaulting to 'HH:mm'
|
||||||
exports.formatTimeHHmm = function (input) {
|
exports.getTimeFormatted = (input, format = 'HH:mm') => {
|
||||||
// Check if the input is a string or a Date object
|
const dateTime = parseDate(input);
|
||||||
const date = (typeof input === 'string') ? new Date(input) : input;
|
return dateTime.toFormat(format);
|
||||||
|
};
|
||||||
|
|
||||||
return date.toLocaleTimeString('en-US', {
|
// Set time in 'HH:mm' format to a date and return as JS Date in Sofia timezone
|
||||||
hour12: false,
|
exports.setTimeHHmm = (input, timeString) => {
|
||||||
hour: '2-digit',
|
let dateTime = parseDate(input);
|
||||||
minute: '2-digit',
|
const [hour, minute] = timeString.split(':').map(Number);
|
||||||
timeZone: 'Europe/Sofia'
|
dateTime = dateTime.set({ hour, minute, second: 0, millisecond: 0 });
|
||||||
}).substring(0, 5);
|
return dateTime.toJSDate();
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// Parse 'HH:mm' time string to a JS Date object in Sofia timezone for today
|
||||||
//parse 'HH:mm' time string to date object
|
|
||||||
exports.parseTimeHHmm = (timeString) => {
|
exports.parseTimeHHmm = (timeString) => {
|
||||||
// If timeString is already a date, return it as is
|
const dateTime = DateTime.now({ zone: 'Europe/Sofia' });
|
||||||
if (timeString instanceof Date) {
|
const [hour, minute] = timeString.split(':').map(Number);
|
||||||
return timeString;
|
return dateTime.set({ hour, minute, second: 0, millisecond: 0 }).toJSDate();
|
||||||
}
|
|
||||||
|
|
||||||
const [hours, minutes] = timeString.split(':');
|
|
||||||
const date = new Date();
|
|
||||||
date.setHours(hours);
|
|
||||||
date.setMinutes(minutes);
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.setTimeHHmm = (date, timeStringOrHours) => {
|
|
||||||
const newDate = new Date(date);
|
|
||||||
|
|
||||||
if (typeof timeStringOrHours === 'string' && timeStringOrHours.includes(':')) {
|
|
||||||
// If hours is a string in "HH:mm" format
|
|
||||||
const [h, m] = timeStringOrHours.split(':');
|
|
||||||
newDate.setHours(parseInt(h, 10), parseInt(m, 10), 0, 0);
|
|
||||||
} else {
|
|
||||||
// If hours and minutes are provided separately
|
|
||||||
newDate.setHours(parseInt(timeStringOrHours, 10), 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newDate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ToDo: update all uses of this function to use the new one
|
||||||
|
|
||||||
|
// exports.getTimeFormatted = function (date) {
|
||||||
|
// const dateTime = DateTime.fromJSDate(date, { zone: 'Europe/Sofia' });
|
||||||
|
// return dateTime.toFormat('HH:mm');
|
||||||
|
// };
|
||||||
|
|
||||||
|
// exports.setTimeHHmm = (date, timeStringOrHours) => {
|
||||||
|
// const newDate = new Date(date);
|
||||||
|
|
||||||
|
// if (typeof timeStringOrHours === 'string' && timeStringOrHours.includes(':')) {
|
||||||
|
// // If hours is a string in "HH:mm" format
|
||||||
|
// const [h, m] = timeStringOrHours.split(':');
|
||||||
|
// newDate.setHours(parseInt(h, 10), parseInt(m, 10), 0, 0);
|
||||||
|
// } else {
|
||||||
|
// // If hours and minutes are provided separately
|
||||||
|
// newDate.setHours(parseInt(timeStringOrHours, 10), 0, 0, 0);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return newDate;
|
||||||
|
// };
|
||||||
|
// // format date to 'HH:mm' time string required by the time picker
|
||||||
|
// exports.formatTimeHHmm = function (input) {
|
||||||
|
// // Check if the input is a string or a Date object
|
||||||
|
// const date = (typeof input === 'string') ? new Date(input) : input;
|
||||||
|
|
||||||
|
// return date.toLocaleTimeString('en-US', {
|
||||||
|
// hour12: false,
|
||||||
|
// hour: '2-digit',
|
||||||
|
// minute: '2-digit',
|
||||||
|
// timeZone: 'Europe/Sofia'
|
||||||
|
// }).substring(0, 5);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// //parse 'HH:mm' time string to date object
|
||||||
|
// exports.parseTimeHHmm = (timeString) => {
|
||||||
|
// // If timeString is already a date, return it as is
|
||||||
|
// if (timeString instanceof Date) {
|
||||||
|
// return timeString;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const [hours, minutes] = timeString.split(':');
|
||||||
|
// const date = new Date();
|
||||||
|
// date.setHours(hours);
|
||||||
|
// date.setMinutes(minutes);
|
||||||
|
// return date;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.getTimeInMinutes = (dateOrTimestamp) => {
|
exports.getTimeInMinutes = (dateOrTimestamp) => {
|
||||||
const date = new Date(dateOrTimestamp);
|
const date = new Date(dateOrTimestamp);
|
||||||
logger.debug("getTimeInMinutes: date = ", date);
|
logger.debug("getTimeInMinutes: date = ", date);
|
||||||
@ -782,8 +818,13 @@ exports.convertDatesToISOStrings = function (obj) {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (obj instanceof Date) {
|
||||||
|
// return obj.toISOString();
|
||||||
|
// }
|
||||||
if (obj instanceof Date) {
|
if (obj instanceof Date) {
|
||||||
return obj.toISOString();
|
// Convert the Date object to a Luxon DateTime in UTC
|
||||||
|
const utcDate = DateTime.fromJSDate(obj, { zone: 'utc' });
|
||||||
|
return utcDate.toISO(); // Output in UTC as ISO string
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(obj)) {
|
if (Array.isArray(obj)) {
|
||||||
@ -800,7 +841,29 @@ exports.convertDatesToISOStrings = function (obj) {
|
|||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
function adjustDateForDST(date, timezone) {
|
||||||
|
// Convert the date to the specified timezone
|
||||||
|
let dateTime = DateTime.fromJSDate(date, { zone: timezone });
|
||||||
|
|
||||||
|
// Check if the original date is in DST
|
||||||
|
const isOriginalDST = dateTime.isInDST;
|
||||||
|
|
||||||
|
// Check if the current date in the same timezone is in DST
|
||||||
|
const isNowDST = DateTime.now().setZone(timezone).isInDST;
|
||||||
|
|
||||||
|
// Compare and adjust if necessary
|
||||||
|
if (isOriginalDST && !isNowDST) {
|
||||||
|
// If original date was in DST but now is not, subtract one hour
|
||||||
|
dateTime = dateTime.minus({ hours: 1 });
|
||||||
|
} else if (!isOriginalDST && isNowDST) {
|
||||||
|
// If original date was not in DST but now is, add one hour
|
||||||
|
dateTime = dateTime.plus({ hours: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the adjusted date as a JavaScript Date
|
||||||
|
return dateTime.toJSDate();
|
||||||
|
}
|
||||||
|
exports.adjustDateForDST = adjustDateForDST;
|
||||||
|
|
||||||
// exports.getInitials = function (names) {
|
// exports.getInitials = function (names) {
|
||||||
// const parts = names.split(' '); // Split the full name into parts
|
// const parts = names.split(' '); // Split the full name into parts
|
||||||
|
Reference in New Issue
Block a user