From 48749905075eb902bcb3271463d394fc8a9d1e6f Mon Sep 17 00:00:00 2001 From: Vi Date: Thu, 27 Aug 2026 15:40:59 -0700 Subject: [PATCH 01/11] Modify calendar components to support view mode selection (day, week, month, year) and refactor calendar header --- src/Pages/Events/Calendar/CalendarHeader.js | 60 ++++++++----------- src/Pages/Events/Calendar/CalendarView.js | 27 ++++----- .../Events/Calendar/calendarConstants.js | 8 ++- src/Pages/Events/EventIcons.js | 8 +++ src/Pages/Events/Events.js | 20 ++++++- 5 files changed, 69 insertions(+), 54 deletions(-) diff --git a/src/Pages/Events/Calendar/CalendarHeader.js b/src/Pages/Events/Calendar/CalendarHeader.js index e76a7f7df..0c1a18bcd 100644 --- a/src/Pages/Events/Calendar/CalendarHeader.js +++ b/src/Pages/Events/Calendar/CalendarHeader.js @@ -1,17 +1,17 @@ import { Link } from 'react-router-dom'; -import { ChevronLeft, ChevronRight, PlusIcon } from '../EventIcons'; -import { MONTHS, YEAR_RANGE } from './calendarConstants'; +import { ChevronDown, ChevronLeft, ChevronRight, PlusIcon } from '../EventIcons'; +import { VIEW_MODES } from './calendarConstants'; export function CalendarHeader({ - month, - year, - monthEventCount, + view, + onViewChange, + title, + eventCount, + countLabel, canCreateEvent, - onMonthChange, - onYearChange, onTodayClick, - onPreviousMonth, - onNextMonth, + onPrevious, + onNext, }) { return (
@@ -19,32 +19,20 @@ export function CalendarHeader({
-
- -
- +
+ +
-
+
{canCreateEvent && ( )} + + {title} + + +
+ + {selectedEvents.length > 0 ? ( +
+ {selectedEvents.map((event) => ( + + ))} +
+ ) : ( +

No events scheduled for this date.

+ )} +
+
+ )} + +
+ {MONTHS.map((monthName, monthIndex) => { + const monthDates = miniMonthMatrix(year, monthIndex); + + return ( +
{ + monthRefs.current[monthIndex] = node; + }} + className="min-w-0 rounded-lg border border-slate-700/50 bg-slate-900/20 p-2" + > + + +
+ {DAYS.map((day) => ( + {day} + ))} +
+ +
+ {monthDates.map((date, index) => { + if (!date) { + return +
+ ); + })} +
+ + ); +} diff --git a/src/Pages/Events/Events.js b/src/Pages/Events/Events.js index 6e3f88baa..7d13625dd 100644 --- a/src/Pages/Events/Events.js +++ b/src/Pages/Events/Events.js @@ -8,6 +8,41 @@ import { VIEW_MODES } from './Calendar/calendarConstants'; import { calendarSearchParams, visibleRange } from './Calendar/calendarUtils'; const EVENTS_CALENDAR_CURSOR_KEY = 'scevents-calendar-cursor'; +// Temporary Year-view preview events. Remove this block when preview is no longer needed. +const YEAR_VIEW_PREVIEW_EVENTS = [ + { + id: 'year-preview-2026-08-12', + name: 'Preview: Design review', + date: '2026-08-12', + time: '10:00', + status: 'published', + visibility: 'public', + }, + { + id: 'year-preview-2026-09-01', + name: 'Preview: Project kickoff', + date: '2026-09-01', + time: '14:00', + status: 'published', + visibility: 'public', + }, + { + id: 'year-preview-2026-09-03', + name: 'Preview: Member workshop', + date: '2026-09-03', + time: '18:00', + status: 'published', + visibility: 'public', + }, + { + id: 'year-preview-2026-12-15', + name: 'Preview: End-of-year social', + date: '2026-12-15', + time: '17:30', + status: 'published', + visibility: 'public', + }, +]; function canUserSeeEvent(event, user) { const userId = user?._id != null ? String(user._id) : ''; @@ -111,15 +146,25 @@ export default function EventsPage() { return new Date(today.getFullYear(), today.getMonth(), today.getDate()); }); + function handleYearMonthSelect(month) { + setCursor(new Date(cursor.getFullYear(), month, 1)); + setView('month'); + } + const isAdminView = user?.accessLevel >= membershipState.OFFICER; const visibleEvents = events.filter((event) => canUserSeeEvent(event, user)); + const showYearPreview = view === 'year' + && new URLSearchParams(location.search).get('calendarPreview') === 'year'; + const calendarEvents = showYearPreview + ? [...visibleEvents, ...YEAR_VIEW_PREVIEW_EVENTS] + : visibleEvents; const pageContainerClass = isAdminView ? 'relative h-dvh overflow-hidden bg-gradient-to-r from-gray-800 to-gray-600 text-white' : 'relative h-[calc(100dvh-4rem)] overflow-hidden bg-gradient-to-r from-gray-800 to-gray-600 text-white'; const calendarContainerClass = isAdminView ? 'relative h-full w-full overflow-hidden px-3 py-4 sm:px-4 sm:py-5 lg:px-5' : 'relative mx-auto h-full max-w-[120rem] overflow-y-auto px-4 py-6 sm:px-6 sm:py-8 lg:px-10'; - const fetchView = view === 'day' || view === 'week' ? view : 'month'; + const fetchView = view === 'day' || view === 'week' || view === 'year' ? view : 'month'; useEffect(() => { const params = calendarSearchParams(location.search, cursor, view); @@ -187,7 +232,7 @@ export default function EventsPage() { {!isLoading && !hasError && ( )} From f25991dbfa050dd1b08845682889916b0af9e980 Mon Sep 17 00:00:00 2001 From: Vi Date: Tue, 1 Sep 2026 11:33:54 -0700 Subject: [PATCH 07/11] Remove temporary year-view preview events and update event handling in calendar --- src/Pages/Events/Events.js | 42 +------------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/src/Pages/Events/Events.js b/src/Pages/Events/Events.js index 7d13625dd..493d4b14c 100644 --- a/src/Pages/Events/Events.js +++ b/src/Pages/Events/Events.js @@ -8,41 +8,6 @@ import { VIEW_MODES } from './Calendar/calendarConstants'; import { calendarSearchParams, visibleRange } from './Calendar/calendarUtils'; const EVENTS_CALENDAR_CURSOR_KEY = 'scevents-calendar-cursor'; -// Temporary Year-view preview events. Remove this block when preview is no longer needed. -const YEAR_VIEW_PREVIEW_EVENTS = [ - { - id: 'year-preview-2026-08-12', - name: 'Preview: Design review', - date: '2026-08-12', - time: '10:00', - status: 'published', - visibility: 'public', - }, - { - id: 'year-preview-2026-09-01', - name: 'Preview: Project kickoff', - date: '2026-09-01', - time: '14:00', - status: 'published', - visibility: 'public', - }, - { - id: 'year-preview-2026-09-03', - name: 'Preview: Member workshop', - date: '2026-09-03', - time: '18:00', - status: 'published', - visibility: 'public', - }, - { - id: 'year-preview-2026-12-15', - name: 'Preview: End-of-year social', - date: '2026-12-15', - time: '17:30', - status: 'published', - visibility: 'public', - }, -]; function canUserSeeEvent(event, user) { const userId = user?._id != null ? String(user._id) : ''; @@ -153,11 +118,6 @@ export default function EventsPage() { const isAdminView = user?.accessLevel >= membershipState.OFFICER; const visibleEvents = events.filter((event) => canUserSeeEvent(event, user)); - const showYearPreview = view === 'year' - && new URLSearchParams(location.search).get('calendarPreview') === 'year'; - const calendarEvents = showYearPreview - ? [...visibleEvents, ...YEAR_VIEW_PREVIEW_EVENTS] - : visibleEvents; const pageContainerClass = isAdminView ? 'relative h-dvh overflow-hidden bg-gradient-to-r from-gray-800 to-gray-600 text-white' : 'relative h-[calc(100dvh-4rem)] overflow-hidden bg-gradient-to-r from-gray-800 to-gray-600 text-white'; @@ -232,7 +192,7 @@ export default function EventsPage() { {!isLoading && !hasError && ( Date: Tue, 1 Sep 2026 16:53:03 -0700 Subject: [PATCH 08/11] Add aria-label for Year view Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/Pages/Events/Calendar/YearView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Pages/Events/Calendar/YearView.js b/src/Pages/Events/Calendar/YearView.js index 864fd1f18..2c28df850 100644 --- a/src/Pages/Events/Calendar/YearView.js +++ b/src/Pages/Events/Calendar/YearView.js @@ -130,7 +130,7 @@ export function YearView({ ? 'bg-slate-700/70 text-slate-50' : 'text-slate-200 hover:bg-slate-700/60', ].join(' ')} - aria-label={`${monthName} ${date.getDate()}`} + aria-label={`${monthName} ${date.getDate()}, ${year}`} > Date: Tue, 1 Sep 2026 16:53:59 -0700 Subject: [PATCH 09/11] Add fallback for event.id for Year view Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/Pages/Events/Calendar/YearView.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Pages/Events/Calendar/YearView.js b/src/Pages/Events/Calendar/YearView.js index 2c28df850..86b6756f4 100644 --- a/src/Pages/Events/Calendar/YearView.js +++ b/src/Pages/Events/Calendar/YearView.js @@ -60,10 +60,9 @@ export function YearView({ {selectedEvents.length > 0 ? ( -
- {selectedEvents.map((event) => ( + {selectedEvents.map((event, index) => ( Date: Tue, 1 Sep 2026 16:59:15 -0700 Subject: [PATCH 10/11] Add mssing container for selected events in Year view --- src/Pages/Events/Calendar/YearView.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Pages/Events/Calendar/YearView.js b/src/Pages/Events/Calendar/YearView.js index 86b6756f4..8fe6a756b 100644 --- a/src/Pages/Events/Calendar/YearView.js +++ b/src/Pages/Events/Calendar/YearView.js @@ -60,6 +60,7 @@ export function YearView({
{selectedEvents.length > 0 ? ( +
{selectedEvents.map((event, index) => ( Date: Tue, 1 Sep 2026 17:06:23 -0700 Subject: [PATCH 11/11] Add more descriptive aria label for event date Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/Pages/Events/Calendar/YearView.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Pages/Events/Calendar/YearView.js b/src/Pages/Events/Calendar/YearView.js index 8fe6a756b..8746d4bf3 100644 --- a/src/Pages/Events/Calendar/YearView.js +++ b/src/Pages/Events/Calendar/YearView.js @@ -130,7 +130,8 @@ export function YearView({ ? 'bg-slate-700/70 text-slate-50' : 'text-slate-200 hover:bg-slate-700/60', ].join(' ')} - aria-label={`${monthName} ${date.getDate()}, ${year}`} + aria-label={`${monthName} ${date.getDate()}, ${year}, ${eventsByDate[dateKey]?.length || 0} event${eventsByDate[dateKey]?.length === 1 ? '' : 's'}`} + aria-pressed={isSelected} >