feat: add next event indicator to Show Page Calendar tab (#4348)

* feat: add next event indicator to Show Page Calendar tab

Closes #4289

* feat: improve calendar animation

* refactor: add some utils and fix sorting edge case with full day

* refactor: rename CalendarCurrentEventIndicator to CalendarCurrentEventCursor

* fix: fix tests

* Fix lint

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Thaïs
2024-03-12 10:27:51 -03:00
committed by GitHub
parent 0d8e700239
commit ab4ab1dfba
17 changed files with 668 additions and 110 deletions

View File

@ -0,0 +1,75 @@
import { useMemo, useState } from 'react';
import { getYear, isThisMonth, startOfDay, startOfMonth } from 'date-fns';
import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent';
import { findUpcomingCalendarEvent } from '@/activities/calendar/utils/findUpcomingCalendarEvent';
import { groupArrayItemsBy } from '~/utils/array/groupArrayItemsBy';
import { isDefined } from '~/utils/isDefined';
import { sortDesc } from '~/utils/sort';
export const useCalendarEvents = (calendarEvents: CalendarEvent[]) => {
const calendarEventsByDayTime = groupArrayItemsBy(
calendarEvents,
({ startsAt }) => startOfDay(startsAt).getTime(),
);
const sortedDayTimes = Object.keys(calendarEventsByDayTime)
.map(Number)
.sort(sortDesc);
const daysByMonthTime = groupArrayItemsBy(sortedDayTimes, (dayTime) =>
startOfMonth(dayTime).getTime(),
);
const sortedMonthTimes = Object.keys(daysByMonthTime)
.map(Number)
.sort(sortDesc);
const monthTimesByYear = groupArrayItemsBy(sortedMonthTimes, getYear);
const getPreviousCalendarEvent = (calendarEvent: CalendarEvent) => {
const calendarEventIndex = calendarEvents.indexOf(calendarEvent);
return calendarEventIndex < calendarEvents.length - 1
? calendarEvents[calendarEventIndex + 1]
: undefined;
};
const getNextCalendarEvent = (calendarEvent: CalendarEvent) => {
const calendarEventIndex = calendarEvents.indexOf(calendarEvent);
return calendarEventIndex > 0
? calendarEvents[calendarEventIndex - 1]
: undefined;
};
const initialUpcomingCalendarEvent = useMemo(
() => findUpcomingCalendarEvent(calendarEvents),
[calendarEvents],
);
const lastEventInCalendar = calendarEvents[0];
const [currentCalendarEvent, setCurrentCalendarEvent] = useState(
(initialUpcomingCalendarEvent &&
(isThisMonth(initialUpcomingCalendarEvent.startsAt)
? initialUpcomingCalendarEvent
: getPreviousCalendarEvent(initialUpcomingCalendarEvent))) ||
lastEventInCalendar,
);
const updateCurrentCalendarEvent = () => {
const nextCurrentCalendarEvent = getNextCalendarEvent(currentCalendarEvent);
if (isDefined(nextCurrentCalendarEvent)) {
setCurrentCalendarEvent(nextCurrentCalendarEvent);
}
};
return {
calendarEventsByDayTime,
currentCalendarEvent,
daysByMonthTime,
getNextCalendarEvent,
monthTimes: sortedMonthTimes,
monthTimesByYear,
updateCurrentCalendarEvent,
};
};