From 3193ae63120951cba9fb683dea2c72c542655f6c Mon Sep 17 00:00:00 2001 From: Jeydin21 Date: Thu, 30 Oct 2025 17:05:50 -0500 Subject: [PATCH 1/2] fix: Added full-day events to the Events calendar --- lib/types.d.ts | 1 + src/app/api/events/past/route.ts | 35 +++++++++++++++++++++++++++ src/app/api/events/route.ts | 37 ++++++++++++++++++++++++++++- src/components/Events/EventDays.tsx | 23 +++++++++++------- 4 files changed, 87 insertions(+), 9 deletions(-) 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) => {

Date & Time

- {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', + })} + + + )}

)} From ee8e64305a1a5433b75e4691c3e1ce73705f72ae Mon Sep 17 00:00:00 2001 From: Jeydin21 Date: Sat, 1 Nov 2025 05:16:42 -0500 Subject: [PATCH 2/2] fix: Remove time from upcoming events card --- src/components/Events/EventTime.tsx | 21 +++++++++++++------- src/components/Events/UpcomingEvents.tsx | 25 +++++++++++++++--------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/components/Events/EventTime.tsx b/src/components/Events/EventTime.tsx index 2700d4c..8adf37f 100644 --- a/src/components/Events/EventTime.tsx +++ b/src/components/Events/EventTime.tsx @@ -3,9 +3,10 @@ type Props = { dateString: string; location?: string; + isAllDay?: boolean; }; -export default function UpcomingEventCard({ dateString, location }: Props) { +export default function UpcomingEventCard({ dateString, location, isAllDay }: Props) { const date = new Date(dateString); return (
@@ -26,12 +27,18 @@ export default function UpcomingEventCard({ dateString, location }: Props) { month: 'long', day: 'numeric', })}{' '} - at{' '} - {date?.toLocaleTimeString('en-US', { - hour: 'numeric', - minute: date.getMinutes() > 0 ? 'numeric' : undefined, - timeZoneName: 'short', - })} + {isAllDay ? ( + - All Day + ) : ( + <> + at{' '} + {date?.toLocaleTimeString('en-US', { + hour: 'numeric', + minute: date.getMinutes() > 0 ? 'numeric' : undefined, + timeZoneName: 'short', + })} + + )}
diff --git a/src/components/Events/UpcomingEvents.tsx b/src/components/Events/UpcomingEvents.tsx index d621ea6..136f5ab 100644 --- a/src/components/Events/UpcomingEvents.tsx +++ b/src/components/Events/UpcomingEvents.tsx @@ -95,7 +95,7 @@ export default function UpcomingEvents() {

{event.title}

{event.start && ( - + )}
@@ -109,14 +109,21 @@ export default function UpcomingEvents() {

Date & Time

- {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', + })} + + + )}

)}