diff --git a/islands/calendar/MainCalendar.tsx b/islands/calendar/MainCalendar.tsx index 9c79997..fc65416 100644 --- a/islands/calendar/MainCalendar.tsx +++ b/islands/calendar/MainCalendar.tsx @@ -30,13 +30,11 @@ export default function MainCalendar({ initialCalendars, initialCalendarEvents, const dateFormat = new Intl.DateTimeFormat('en-GB', { year: 'numeric', month: 'long' }); const hourFormat = new Intl.DateTimeFormat('en-GB', { hour12: false, hour: '2-digit', minute: '2-digit' }); - const eventDateFormat = new Intl.DateTimeFormat('en-GB', { - year: 'numeric', - month: 'long', + const dayFormat = new Intl.DateTimeFormat('en-GB', { + weekday: 'long', day: 'numeric', - hour12: false, - hour: '2-digit', - minute: '2-digit', + month: 'long', + year: 'numeric', }); const allDayEventDateFormat = new Intl.DateTimeFormat('en-GB', { year: 'numeric', month: 'long', day: 'numeric' }); const today = new Date().toISOString().substring(0, 10); @@ -331,7 +329,26 @@ export default function MainCalendar({ initialCalendars, initialCalendarEvents, const visibleCalendarEvents = calendarEvents.value; // TODO: Send in / consider user timezone - const weeks = getWeeksForMonth(new Date(startDate)); + const weeks = view === 'month' ? getWeeksForMonth(new Date(startDate)) : []; + const hours: { date: Date; isCurrentHour: boolean }[] = view === 'day' + ? Array.from({ length: 24 }).map((_, index) => { + const hourNumber = index; + + const date = new Date(startDate); + date.setHours(hourNumber); + + const shortIsoDate = date.toISOString().substring(0, 10); + + const isCurrentHour = shortIsoDate === today && new Date().getHours() === hourNumber; + + return { + date, + isCurrentHour, + }; + }) + : []; + + // TODO: days with hours return ( <> @@ -515,8 +532,101 @@ export default function MainCalendar({ initialCalendars, initialCalendarEvents,
{view === 'day' ? ( -
- TODO: Build day view +
+
+
+ {dayFormat.format(new Date(startDate))} +
+
+
+
+ {hours.map((hour, hourIndex) => { + const shortIsoDate = hour.date.toISOString().substring(0, 10); + + const startHourDate = new Date(shortIsoDate); + startHourDate.setHours(hour.date.getHours()); + const endHourDate = new Date(shortIsoDate); + endHourDate.setHours(hour.date.getHours()); + endHourDate.setMinutes(59); + endHourDate.setSeconds(59); + endHourDate.setMilliseconds(999); + + const isLastHour = hourIndex === 23; + + const hourEvents = calendarEvents.value.filter((calendarEvent) => { + const eventStartDate = new Date(calendarEvent.start_date); + const eventEndDate = new Date(calendarEvent.end_date); + eventEndDate.setSeconds(eventEndDate.getSeconds() - 1); // Take one second back so events don't bleed into the next hour + + // Event starts and ends on this hour + if (eventStartDate >= startHourDate && eventEndDate <= endHourDate) { + return true; + } + + // Event starts before and ends after this hour + if (eventStartDate <= startHourDate && eventEndDate >= endHourDate) { + return true; + } + + // Event starts on and ends after this hour + if ( + eventStartDate >= startHourDate && eventStartDate <= endHourDate && eventEndDate >= endHourDate + ) { + return true; + } + + // Event starts before and ends on this hour + if ( + eventStartDate <= startHourDate && eventEndDate >= startHourDate && eventEndDate <= endHourDate + ) { + return true; + } + + return false; + }); + + return ( +
+ + {hourEvents.length > 0 + ? ( +
    + {hourEvents.map((hourEvent) => ( +
  1. + calendar.id === hourEvent.calendar_id) + ?.color || 'bg-gray-700' + }`} + onClick={() => openEvent.value = hourEvent} + > + +

    + {hourEvent.title} +

    +
    +
  2. + ))} +
+ ) + : null} +
+ ); + })} +
+
) : null} @@ -529,126 +639,142 @@ export default function MainCalendar({ initialCalendars, initialCalendarEvents, : null} {view === 'month' ? ( -
-
-
-
- M - on -
-
- T - ue -
-
- W - ed -
-
- T - hu -
-
- F - ri -
-
- S - at -
-
- S - un -
-
-
-
- {weeks.map((week, weekIndex) => - week.map((day, dayIndex) => { - const shortIsoDate = day.date.toISOString().substring(0, 10); +
+
+
+ Mon +
+
+ Tue +
+
+ Wed +
+
+ Thu +
+
+ Fri +
+
+ Sat +
+
+ Sun +
+
+
+
+ {weeks.map((week, weekIndex) => + week.map((day, dayIndex) => { + const shortIsoDate = day.date.toISOString().substring(0, 10); - const startDayDate = new Date(shortIsoDate); - const endDayDate = new Date(shortIsoDate); - endDayDate.setHours(23); - endDayDate.setMinutes(59); - endDayDate.setSeconds(59); - endDayDate.setMilliseconds(999); + const startDayDate = new Date(shortIsoDate); + const endDayDate = new Date(shortIsoDate); + endDayDate.setHours(23); + endDayDate.setMinutes(59); + endDayDate.setSeconds(59); + endDayDate.setMilliseconds(999); - const isBottomLeftDay = weekIndex === weeks.length - 1 && dayIndex === 0; - const isBottomRightDay = weekIndex === weeks.length - 1 && dayIndex === week.length - 1; + const isBottomLeftDay = weekIndex === weeks.length - 1 && dayIndex === 0; + const isBottomRightDay = weekIndex === weeks.length - 1 && dayIndex === week.length - 1; - const isToday = today === shortIsoDate; + const isToday = today === shortIsoDate; - // TODO: Consider events that span multiple days - const dayEvents = calendarEvents.value.filter((calendarEvent) => - new Date(calendarEvent.start_date) >= startDayDate && - new Date(calendarEvent.end_date) <= endDayDate - ); + const dayEvents = calendarEvents.value.filter((calendarEvent) => { + const eventStartDate = new Date(calendarEvent.start_date); + const eventEndDate = new Date(calendarEvent.end_date); - return ( -
= startDayDate && eventEndDate <= endDayDate) { + return true; + } + + // Event starts before and ends after this day + if (eventStartDate <= startDayDate && eventEndDate >= endDayDate) { + return true; + } + + // Event starts on and ends after this day + if ( + eventStartDate >= startDayDate && eventStartDate <= endDayDate && eventEndDate >= endDayDate + ) { + return true; + } + + // Event starts before and ends on this day + if ( + eventStartDate <= startDayDate && eventEndDate >= startDayDate && eventEndDate <= endDayDate + ) { + return true; + } + + return false; + }); + + return ( +
+
- ); - }) - )} -
+ ) + : null} + + ) + : null} +
+ ); + }) + )}