diff --git a/lib/types.d.ts b/lib/types.d.ts index 21e4e5a..3e3f6ce 100644 --- a/lib/types.d.ts +++ b/lib/types.d.ts @@ -44,6 +44,7 @@ export type Event = { start?: Date; location?: string; description?: string; + isAllDay?: boolean; }; export type WorkShopLink = { type: 'github' | 'video'; link: string }; diff --git a/src/app/api/events/past/route.ts b/src/app/api/events/past/route.ts index ba3600b..13b4498 100644 --- a/src/app/api/events/past/route.ts +++ b/src/app/api/events/past/route.ts @@ -21,6 +21,11 @@ type CalendarEvent = { description?: string; start?: { dateTime?: string; + date?: string; + }; + end?: { + dateTime?: string; + date?: string; }; } @@ -110,9 +115,39 @@ function parseItems(list: CalendarEvent[]): Event[] { toAdd.location = item.location; } + // Handle both timed events (dateTime) and full-day events (date) if (item.start?.dateTime) { toAdd.start = new Date(item.start.dateTime); + toAdd.isAllDay = false; res.push(toAdd); + } else if (item.start?.date) { + // For full-day events, create date at noon local time to avoid timezone shifts + const [startYear, startMonth, startDay] = item.start.date.split('-').map(Number); + const startDate = new Date(startYear, startMonth - 1, startDay, 12, 0, 0); + + // Check if it's a multi-day event + if (item.end?.date) { + const [endYear, endMonth, endDay] = item.end.date.split('-').map(Number); + const endDate = new Date(endYear, endMonth - 1, endDay, 12, 0, 0); + + // Create an event for each day in the range + const currentDate = new Date(startDate); + while (currentDate < endDate) { + const eventCopy: Event = { + ...toAdd, + id: `${item.id}-${currentDate.getFullYear()}-${currentDate.getMonth()}-${currentDate.getDate()}`, + start: new Date(currentDate), + isAllDay: true, + }; + res.push(eventCopy); + currentDate.setDate(currentDate.getDate() + 1); + } + } else { + // Single-day event + toAdd.start = startDate; + toAdd.isAllDay = true; + res.push(toAdd); + } } } catch (err) { console.warn(`Failed to parse event: ${item.id}`, err); diff --git a/src/app/api/events/route.ts b/src/app/api/events/route.ts index 789a97d..77f64a4 100644 --- a/src/app/api/events/route.ts +++ b/src/app/api/events/route.ts @@ -22,6 +22,11 @@ type CalendarEvent = { location?: string; start?: { dateTime?: string; + date?: string; + }; + end?: { + dateTime?: string; + date?: string; }; }; @@ -37,7 +42,7 @@ export async function GET(request: Request) { const yearParam = url.searchParams.get('year'); const monthParam = url.searchParams.get('month'); - let apiUrl = `${endpoint}?key=${process.env.CALENDAR_API_KEY}`; + let apiUrl = `${endpoint}?key=${process.env.CALENDAR_API_KEY}&singleEvents=true&orderBy=startTime`; if (yearParam && monthParam) { const year = parseInt(yearParam, 10); @@ -134,9 +139,39 @@ function parseItems(list: CalendarEvent[]): Event[] { toAdd.location = item.location; } + // Handle both timed events (dateTime) and full-day events (date) if (item.start?.dateTime) { toAdd.start = new Date(item.start.dateTime); + toAdd.isAllDay = false; res.push(toAdd); + } else if (item.start?.date) { + // For full-day events, create date at noon local time to avoid timezone shifts + const [startYear, startMonth, startDay] = item.start.date.split('-').map(Number); + const startDate = new Date(startYear, startMonth - 1, startDay, 12, 0, 0); + + // Check if it's a multi-day event + if (item.end?.date) { + const [endYear, endMonth, endDay] = item.end.date.split('-').map(Number); + const endDate = new Date(endYear, endMonth - 1, endDay, 12, 0, 0); + + // Create an event for each day in the range + const currentDate = new Date(startDate); + while (currentDate < endDate) { + const eventCopy: Event = { + ...toAdd, + id: `${item.id}-${currentDate.getFullYear()}-${currentDate.getMonth()}-${currentDate.getDate()}`, + start: new Date(currentDate), + isAllDay: true, + }; + res.push(eventCopy); + currentDate.setDate(currentDate.getDate() + 1); + } + } else { + // Single-day event + toAdd.start = startDate; + toAdd.isAllDay = true; + res.push(toAdd); + } } } catch (err) { console.warn(`Failed to parse event: ${item.id}`, err); diff --git a/src/components/Events/EventDays.tsx b/src/components/Events/EventDays.tsx index f34757c..0d4d40b 100644 --- a/src/components/Events/EventDays.tsx +++ b/src/components/Events/EventDays.tsx @@ -71,14 +71,21 @@ const EventComponent = ({ event, day, month }: Props) => {
- {formatDate(localStartDate)}{" "}at{" "} - - {localStartDate.toLocaleTimeString('en-US', { - hour: 'numeric', - minute: '2-digit', - timeZoneName: 'short', - })} - + {formatDate(localStartDate)} + {event.isAllDay ? ( + - All Day + ) : ( + <> + {" "}at{" "} + + {localStartDate.toLocaleTimeString('en-US', { + hour: 'numeric', + minute: '2-digit', + timeZoneName: 'short', + })} + + > + )}
- {formatDate(event.start)}{" "}at{" "} - - {event.start.toLocaleTimeString('en-US', { - hour: 'numeric', - minute: '2-digit', - timeZoneName: 'short', - })} - + {formatDate(event.start)}{' '} + {event.isAllDay ? ( + - All Day + ) : ( + <> + at{' '} + + {event.start.toLocaleTimeString('en-US', { + hour: 'numeric', + minute: '2-digit', + timeZoneName: 'short', + })} + + > + )}