import dayjs from 'dayjs'; import { spaceHeight, weekdayHeight } from '../atoms/styles'; import { ECalendarMode, ElementHTML, ISlot, ISlotEventsToSpaces, ISlotsEventsAndEventsWithSpaces, ISpace, } from '../types'; import { oneHourHeight } from './timeUtils'; export const getBodyContainerHeight = ( spaces: ISpace[], mode: ECalendarMode, horizontal?: boolean ) => horizontal ? spaces.reduce((acc, space) => acc + (space.children.length || 1), 0) * spaceHeight : mode === ECalendarMode.DAILY ? oneHourHeight * 24 + 12 : mode === ECalendarMode.WEEKLY ? weekdayHeight * 7 : 0; /** Filtering slots by partial render indexes */ export const filterSlots = ( slots: ISlotsEventsAndEventsWithSpaces, from: number, to: number ) => { if (slots.events && slots.eventsToSpaces && !Number.isNaN(to)) { let events = {}; let eventsToSpaces = {}; Object.values(slots.events).forEach((event) => { const start = dayjs.utc(event.startDate).hour(); const end = dayjs.utc(event.endDate).hour(); if (end >= from && start <= to) { events[Number(event.id)] = event; if (Array.isArray(eventsToSpaces[Number(event.spaceId)])) { eventsToSpaces[Number(event.spaceId)].push(event); } else { eventsToSpaces = { ...eventsToSpaces, [Number(event.spaceId)]: [event], }; } } }); return { events, eventsToSpaces }; } return slots; }; export const calculateModalPosition = ( box: ElementHTML, container: ElementHTML, boxW: ElementHTML, containerW: ElementHTML ) => { const result = { y: 'top: 0;', x: 'left: 50%;', }; if (container && box) { if (container.offsetHeight - box.offsetTop >= 460) { result.y = 'top: 0;'; } else if (box.offsetTop >= 460) { result.y = 'bottom: 0;'; } else { const top = box.offsetTop - (container.offsetHeight - 460) / 2; result.y = `top: -${top}px;`; } } if (containerW && boxW) { if (containerW.offsetWidth - boxW.offsetLeft >= 275) { result.x = 'left: 50%;'; } else if (boxW.offsetLeft >= 275) { result.x = 'right: 50%;'; } else { const left = boxW.offsetLeft - (containerW.offsetWidth - 275) / 2; result.x = `left: -${left}px;`; } } return result; }; /** Removing slots what started or ended not on selected (or current) date */ export const filterSlotsForDailyView = ( slots: ISlotEventsToSpaces, date?: string ) => { const today = dayjs.utc(date).format('DD/MM/YYYY'); const eventsToSpaces = {} as ISlotEventsToSpaces; Object.entries(slots).forEach(([spaceId, events]) => { eventsToSpaces[Number(spaceId)] = events.filter( (event: ISlot) => dayjs.utc(event.startDate).format('DD/MM/YYYY') === today && dayjs.utc(event.endDate).format('DD/MM/YYYY') === today ); }); return eventsToSpaces; }; /** Removing slots what started before selected (or current) date */ export const filterSlotsForOldSlots = ( slots: ISlotEventsToSpaces, date?: string ) => { const today = dayjs.utc(date); const eventsToSpaces = {} as ISlotEventsToSpaces; Object.entries(slots).forEach(([spaceId, events]) => { eventsToSpaces[Number(spaceId)] = events.filter( (event: ISlot) => dayjs.utc(event.startDate).diff(today, 'millisecond') >= 0 ); }); return eventsToSpaces; }; export const calculateNewDate = (date: string, minutesDifference: number) => minutesDifference > 0 ? dayjs.utc(date).add(minutesDifference, 'minute').toISOString() : dayjs .utc(date) .subtract(Math.abs(minutesDifference), 'minute') .toISOString(); /** Smoothing time of DnD or resize by step */ export const getMinutesDifferenceByStep = ( date: string, minutes: number, step = 5, sum?: boolean ) => { let startMinutes = dayjs.utc(date).minute(); while (startMinutes > step) startMinutes -= step; while ((minutes + startMinutes) % step !== 0) { if (startMinutes % step > step / 2) { minutes += 1; } else { minutes -= 1; } } if (sum) return minutes + startMinutes; return minutes; }; /* @param pos: the y-position to scroll to (in pixels) @param time: the exact amount of time the scrolling will take (in milliseconds) */ export function scrollToVertical( container: HTMLDivElement, destination: number, time = 500 ) { const from = container.scrollTop; let start = 0; window.requestAnimationFrame(function step(currentTime) { start = !start ? currentTime : start; let progress = currentTime - start; if (from < destination) { container.scrollTo( container.scrollLeft, ((destination - from) * progress) / time + from ); } else { container.scrollTo( container.scrollLeft, from - ((from - destination) * progress) / time ); } if (progress < time) { window.requestAnimationFrame(step); } else { container.scrollTo(container.scrollLeft, destination); } }); } export function scrollToHorizontal( container: HTMLDivElement, destination: number, time = 500 ) { const from = container.scrollLeft; let start = 0; window.requestAnimationFrame(function step(currentTime) { start = !start ? currentTime : start; let progress = currentTime - start; if (from < destination) { container.scrollTo( ((destination - from) * progress) / time + from, container.scrollTop ); } else { container.scrollTo( from - ((from - destination) * progress) / time, container.scrollTop ); } if (progress < time) { window.requestAnimationFrame(step); } else { container.scrollTo(destination, container.scrollTop); } }); }