From aa8d4365d75ddc63adb21476ed8e1edd3f0d0afc Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 12 Aug 2026 20:10:56 +0000 Subject: [PATCH] Put RSVP'd events on the calendar, and move the demo catalogue to this month MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signing up for an event did nothing to your calendar: both the agenda and the hour grid only listed events you had explicitly pinned, so an RSVP left no trace anywhere. On top of that the bundled catalogue was dated October– December 2025, so every list that filters to upcoming events was empty no matter what you did. - New utils/myEvents.ts + hooks/useMyEvents: one definition of "my events" (RSVP'd going/maybe, pinned, or hosting) now feeding the calendar grid, the mobile agenda, My Events and the Home interest profile. Recurring occurrences resolve to their series, so an RSVP covers every occurrence. - Removing an event from the calendar clears the RSVP that put it there; events you host can't be removed from your own calendar. - RSVPs now persist on the device in offline/demo mode and for dev personas, so "You're going" survives a reload instead of vanishing. - Pins are filed under the week the event actually falls in, not the week you happened to be viewing, and unpinning clears the pin whatever week it is in. - Mobile grid shows a rolling 3-day window starting today and opens on the first event of the range rather than an empty midnight. - data/allEvents.json is re-dated across the current month — some events already past, some today, the rest upcoming — via the new scripts/refreshEventDates.js (npm run refresh-events), which keeps ids and campus-local hours stable so saved RSVPs and pins still line up. - Winter/holiday-specific copy rewritten to be season-neutral, eight start-of-term events added, and the two unused stale mock data files dropped. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_011nrgpkJbvZ9JCf2VA2kKvJ --- apps/client/DATABASE_SETUP.md | 19 +- apps/client/README.md | 5 +- apps/client/app/(tabs)/calendar.tsx | 103 +- apps/client/app/(tabs)/index.tsx | 22 +- apps/client/app/dev.tsx | 4 +- apps/client/app/my-events.tsx | 44 +- apps/client/components/calendar/WeekView.tsx | 22 + apps/client/components/events/AgendaList.tsx | 5 +- apps/client/contexts/EventsContext.tsx | 75 +- apps/client/data/allEvents.json | 2734 +++++++++++++----- apps/client/data/currentWeekEvents.json | 253 -- apps/client/data/mockEvents.json | 998 ------- apps/client/hooks/useMyEvents.ts | 52 + apps/client/hooks/useScheduledEvents.ts | 15 +- apps/client/lib/scheduledEventsApi.ts | 8 +- apps/client/package.json | 1 + apps/client/scripts/refreshEventDates.js | 180 ++ apps/client/tests/localRsvps.test.ts | 103 + apps/client/tests/myEvents.test.ts | 156 + apps/client/utils/devTools.ts | 4 +- apps/client/utils/localRsvps.ts | 124 + apps/client/utils/myEvents.ts | 66 + apps/client/utils/scheduledEvents.ts | 18 +- 23 files changed, 2858 insertions(+), 2153 deletions(-) delete mode 100644 apps/client/data/currentWeekEvents.json delete mode 100644 apps/client/data/mockEvents.json create mode 100644 apps/client/hooks/useMyEvents.ts create mode 100644 apps/client/scripts/refreshEventDates.js create mode 100644 apps/client/tests/localRsvps.test.ts create mode 100644 apps/client/tests/myEvents.test.ts create mode 100644 apps/client/utils/localRsvps.ts create mode 100644 apps/client/utils/myEvents.ts diff --git a/apps/client/DATABASE_SETUP.md b/apps/client/DATABASE_SETUP.md index 36bf139..fb89176 100644 --- a/apps/client/DATABASE_SETUP.md +++ b/apps/client/DATABASE_SETUP.md @@ -82,11 +82,20 @@ The app currently uses **localStorage** (web) for data persistence. Events are l ## Testing Without Database -The app works with mock data stored in: -- `data/mockEvents.json` - 40 sample events -- `data/currentWeekEvents.json` - 10 events for current week +With no Supabase credentials the app runs in offline demo mode against +`data/allEvents.json` (125 events). RSVPs and calendar pins made in that mode +are saved to the device (localStorage) so they survive a reload. -Events are automatically loaded from these files on first launch and stored in localStorage. +Demo dates go stale as months pass. Re-date the whole catalogue onto the +current month — some events already past, some today, the rest upcoming: + +```bash +pnpm --filter @universify/client exec node scripts/refreshEventDates.js +# or, from apps/client: npm run refresh-events +``` + +Event ids are preserved, so RSVPs and pins already saved on a device still +line up afterwards. ## Troubleshooting @@ -97,7 +106,7 @@ Events are automatically loaded from these files on first launch and stored in l ```javascript localStorage.removeItem('universify_events'); ``` -3. **Check event dates** - Events in `currentWeekEvents.json` are dated November 2025. Navigate to that week in the calendar to see them. +3. **Check event dates** - The calendar only shows events you RSVP'd to, pinned, or are hosting. If the demo catalogue is stale, run `node scripts/refreshEventDates.js` to move it onto the current month. ### Recommendations not showing? diff --git a/apps/client/README.md b/apps/client/README.md index 4cbb3d5..77dbef7 100644 --- a/apps/client/README.md +++ b/apps/client/README.md @@ -124,9 +124,8 @@ apps/client/ │ ├── event.ts │ ├── user.ts │ └── settings.ts -└── data/ # Mock data - ├── mockEvents.json # 40 diverse events - ├── mockUsers.json # 5 test accounts +└── data/ # Demo data (used when Supabase is unset) + ├── allEvents.json # 125 events, re-datable onto the current month └── categories.json # 12 event categories ``` diff --git a/apps/client/app/(tabs)/calendar.tsx b/apps/client/app/(tabs)/calendar.tsx index 76d5701..50c0215 100644 --- a/apps/client/app/(tabs)/calendar.tsx +++ b/apps/client/app/(tabs)/calendar.tsx @@ -22,15 +22,17 @@ import { useEventReminders } from '@/hooks/useEventReminders'; import { storage } from '@/lib/storage'; import { useAppTheme } from '@/hooks/useAppTheme'; import { AppPalette } from '@/constants/theme'; -import { AgendaList, AgendaBadge } from '@/components/events/AgendaList'; +import { AgendaList } from '@/components/events/AgendaList'; import { SegmentedControl } from '@/components/ui/SegmentedControl'; +import { useMyEvents } from '@/hooks/useMyEvents'; +import { eventsInRange } from '@/utils/myEvents'; // Universify event id -> Google Calendar event id map, persisted so // unscheduling can delete the Google copy even after a reload const GCAL_MAP_STORAGE_KEY = 'universify_gcal_event_map'; export default function CalendarScreen() { - const { events, isLoading } = useEvents(); + const { events, isLoading, updateRSVP } = useEvents(); const { currentUser } = useAuth(); const { settings, updateSettings } = useSettings(); const { isMobile, isDesktop } = useResponsive(); @@ -42,12 +44,13 @@ export default function CalendarScreen() { const calendar = useCalendar(isMobile ? 3 : settings.calendarViewDays); const weekKey = getWeekKey(calendar.currentDate); const { - scheduledEventIds, - allScheduledIds: allScheduledEventIds, isLoading: isLoadingScheduled, scheduleEvent: scheduleEventForWeek, unscheduleEvent: unscheduleEventForWeek, } = useScheduledEvents(currentUser?.id, weekKey); + // Everything the user RSVP'd to, pinned, or is hosting — an RSVP alone is + // enough to put an event on the calendar. + const { myEvents, myEventIds, relationFor } = useMyEvents(); const [expandedCardId, setExpandedCardId] = useState(null); const [customDays, setCustomDays] = useState(settings.calendarViewDays.toString()); @@ -79,7 +82,9 @@ export default function CalendarScreen() { .catch((err) => console.error('Failed to persist Google Calendar event map:', err)); }; - const viewDays = settings.calendarViewDays; + // Phones show a rolling 3-day window starting today; the Sunday-aligned week + // only makes sense with a desktop's worth of horizontal room. + const viewDays = isMobile ? 3 : settings.calendarViewDays; // Get days to display based on view mode const displayDays = useMemo(() => { @@ -117,59 +122,44 @@ export default function CalendarScreen() { }, [googleEvents, displayDays]); // Get events to display in the calendar - // Merge local scheduled events (plus their recurring occurrences within + // Merge the user's own events (plus their recurring occurrences within // the visible range) with Google events const weekEvents = useMemo(() => { - // Local events: only show if scheduled - const local = events.filter((event) => scheduledEventIds.includes(event.id)); - if (displayDays.length === 0) return [...local, ...googleViewEvents]; + if (displayDays.length === 0) return [...myEvents, ...googleViewEvents]; const viewStart = new Date(displayDays[0]); viewStart.setHours(0, 0, 0, 0); const viewEnd = new Date(displayDays[displayDays.length - 1]); viewEnd.setHours(23, 59, 59, 999); - return [...expandRecurringEvents(local, viewStart, viewEnd), ...googleViewEvents]; - }, [events, scheduledEventIds, googleViewEvents, displayDays]); + const inView = eventsInRange( + expandRecurringEvents(myEvents, viewStart, viewEnd), + viewStart, + viewEnd + ); + return [...inView, ...googleViewEvents]; + }, [myEvents, googleViewEvents, displayDays]); - // Interest profile mined from the events the user has scheduled — the + // Interest profile mined from the events the user engaged with — the // recommendation engine extracts title n-grams, categories and time-of-day // preferences from them. - const engagedEvents = useMemo( - () => events.filter((e) => allScheduledEventIds.includes(e.id)), - [events, allScheduledEventIds] - ); - const { topInterests } = useUserInterests({ events: engagedEvents }); + const { topInterests } = useUserInterests({ events: myEvents }); - // Browser notifications ~30 min before scheduled events (web, opt-in pref) + // Browser notifications ~30 min before the user's events (web, opt-in pref) useEventReminders( - engagedEvents, + myEvents, currentUser?.preferences.notificationPreferences.eventReminders ?? false ); - // Agenda view: the user's scheduled events (with recurring occurrences) - // over the next 30 days, in a date-grouped timeline + // Agenda view: the user's events (with recurring occurrences) over the next + // 60 days, in a date-grouped timeline const agendaEvents = useMemo(() => { const now = new Date(); - const horizon = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000); - const scheduled = events.filter((e) => allScheduledEventIds.includes(e.id)); - return expandRecurringEvents(scheduled, now, horizon).filter( + const horizon = new Date(now.getTime() + 60 * 24 * 60 * 60 * 1000); + return expandRecurringEvents(myEvents, now, horizon).filter( (e) => new Date(e.endTime) >= now && new Date(e.startTime) <= horizon ); - }, [events, allScheduledEventIds]); - - const agendaBadgeFor = (event: Event): AgendaBadge | null => { - const baseId = baseEventId(event.id); - if (currentUser?.createdEvents.includes(baseId)) return 'created'; - const rsvp = currentUser - ? events - .find((e) => e.id === baseId) - ?.attendees.find((a) => a.userId === currentUser.id)?.status - : null; - if (rsvp === 'going') return 'going'; - if (rsvp === 'maybe') return 'maybe'; - return 'scheduled'; - }; + }, [myEvents]); // Get all events for sidebar (sorted by date) // Only include Universify events (Google events are already on the calendar) @@ -210,8 +200,10 @@ export default function CalendarScreen() { }; const handleScheduleEvent = async (event: Event) => { - // Schedule locally (handles both localStorage and Supabase) - await scheduleEventForWeek(event.id); + // Pin under the week the event actually falls in, not the week being + // viewed, and against the series rather than a display occurrence. + const baseId = baseEventId(event.id); + await scheduleEventForWeek(baseId, getWeekKey(new Date(event.startTime))); // Sync to Google Calendar if authenticated if (isGoogleAuthenticated) { @@ -281,6 +273,7 @@ export default function CalendarScreen() { }; const handleUnscheduleEvent = async (event: Event) => { + const baseId = baseEventId(event.id); if (isGoogleAuthenticated) { const { data: { session } } = await supabase.auth.getSession(); const token = session?.provider_token || providerToken || googleSession?.provider_token; @@ -302,7 +295,14 @@ export default function CalendarScreen() { } } } - unscheduleEventForWeek(event.id); + await unscheduleEventForWeek(baseId); + + // The × on a card means "not on my calendar" — an RSVP is enough to put an + // event there, so clear that too rather than leaving the card unchanged. + const relation = relationFor(event); + if (currentUser && (relation === 'going' || relation === 'maybe')) { + await updateRSVP(baseId, currentUser.id, null); + } }; // Navigation handlers @@ -364,7 +364,7 @@ export default function CalendarScreen() { router.push('/(tabs)/find') }} @@ -386,7 +386,7 @@ export default function CalendarScreen() { ) : ( { const expandedEvent = sortedEvents.find(e => e.id === expandedCardId); if (!expandedEvent) return null; - const isScheduled = scheduledEventIds.includes(expandedEvent.id); + const isScheduled = myEventIds.has(expandedEvent.id); + const isHosting = relationFor(expandedEvent) === 'created'; return ( handleScheduleEvent(expandedEvent)} - onUnschedule={() => handleUnscheduleEvent(expandedEvent)} + // You can't remove an event you're hosting from your own calendar + onUnschedule={ + isHosting ? undefined : () => handleUnscheduleEvent(expandedEvent) + } onToggleExpand={() => setExpandedCardId(null)} /> ); @@ -515,7 +519,8 @@ export default function CalendarScreen() { showsVerticalScrollIndicator > {sortedEvents.map((event) => { - const isScheduled = scheduledEventIds.includes(event.id); + const isScheduled = myEventIds.has(event.id); + const isHosting = relationFor(event) === 'created'; const isExpanded = expandedCardId === event.id; return ( handleScheduleEvent(event)} - onUnschedule={() => handleUnscheduleEvent(event)} + onUnschedule={ + isHosting ? undefined : () => handleUnscheduleEvent(event) + } onToggleExpand={() => setExpandedCardId(isExpanded ? null : event.id)} /> ); diff --git a/apps/client/app/(tabs)/index.tsx b/apps/client/app/(tabs)/index.tsx index 6f19e7d..29ad8d8 100644 --- a/apps/client/app/(tabs)/index.tsx +++ b/apps/client/app/(tabs)/index.tsx @@ -14,7 +14,7 @@ import { FilterDrawer } from '@/components/layout/FilterDrawer'; import { Event } from '@/types/event'; import { getUpcomingEvents } from '@/utils/eventHelpers'; import { useUserInterests, rankEventsForUser } from '@/hooks/useRecommendations'; -import { useScheduledEvents, getWeekKey } from '@/hooks/useScheduledEvents'; +import { useMyEvents } from '@/hooks/useMyEvents'; function HomeScreenContent() { const { events } = useEvents(); @@ -28,22 +28,10 @@ function HomeScreenContent() { const [selectedEvent, setSelectedEvent] = useState(null); const [showFilters, setShowFilters] = useState(false); - // Events the user engaged with (scheduled, RSVP'd, created) form the - // interest profile that the recommendation engine mines. - const { allScheduledIds } = useScheduledEvents(currentUser?.id, getWeekKey(new Date())); - const engagedEvents = useMemo(() => { - const userId = currentUser?.id; - const createdIds = new Set(currentUser?.createdEvents ?? []); - const scheduledIds = new Set(allScheduledIds); - return events.filter( - (event) => - scheduledIds.has(event.id) || - createdIds.has(event.id) || - (userId != null && event.attendees.some((a) => a.userId === userId)) - ); - }, [events, currentUser, allScheduledIds]); - - const { topInterests } = useUserInterests({ events: engagedEvents }); + // Events the user engaged with (RSVP'd, pinned, hosting) form the interest + // profile that the recommendation engine mines. + const { myEvents } = useMyEvents(); + const { topInterests } = useUserInterests({ events: myEvents }); // Ranked recommendations: interest profile + explicit category preferences // + popularity, over upcoming events (respecting any active filters). diff --git a/apps/client/app/dev.tsx b/apps/client/app/dev.tsx index e468975..0d436ff 100644 --- a/apps/client/app/dev.tsx +++ b/apps/client/app/dev.tsx @@ -215,8 +215,8 @@ export default function DevScreen() { {/* Data tools */}
- Seeded events are pinned to the next 7 days (bundled mock data has - fixed dates), tagged dev-seed, and removable in one tap. + Seeded events are pinned to the next 7 days, tagged dev-seed, and + removable in one tap. createStyles(colors, fontScale), [colors, fontScale]); const { currentUser } = useAuth(); - const { events } = useEvents(); - const weekKey = useMemo(() => getWeekKey(new Date()), []); - const { allScheduledIds } = useScheduledEvents(currentUser?.id, weekKey); + // Same "my events" set the calendar and agenda read from + const { myEvents, relationFor } = useMyEvents(); const [tab, setTab] = useState('upcoming'); const [query, setQuery] = useState(''); - // Everything the user is going to, hosting, or saved to their calendar - const myEvents = useMemo(() => { - if (!currentUser) return []; - const scheduled = new Set(allScheduledIds); - const created = new Set(currentUser.createdEvents); - return events.filter((event) => { - const rsvp = event.attendees.find((a) => a.userId === currentUser.id)?.status; - return ( - rsvp === 'going' || - rsvp === 'maybe' || - scheduled.has(event.id) || - created.has(event.id) - ); - }); - }, [events, currentUser, allScheduledIds]); - const visibleEvents = useMemo(() => { const now = Date.now(); const inTab = myEvents.filter((event) => { @@ -67,19 +48,6 @@ export default function MyEventsScreen() { ); }, [myEvents, tab, query]); - const badgeFor = useCallback( - (event: Event): AgendaBadge | null => { - if (!currentUser) return null; - if (currentUser.createdEvents.includes(event.id)) return 'created'; - const rsvp = event.attendees.find((a) => a.userId === currentUser.id)?.status; - if (rsvp === 'going') return 'going'; - if (rsvp === 'maybe') return 'maybe'; - if (allScheduledIds.includes(event.id)) return 'scheduled'; - return null; - }, - [currentUser, allScheduledIds] - ); - const topBar = ( router.back()} style={styles.backButton}> @@ -162,7 +130,7 @@ export default function MyEventsScreen() { router.push(`/event/${event.id}`)} - badgeFor={badgeFor} + badgeFor={relationFor} descending={tab === 'past'} emptyTitle={ tab === 'upcoming' diff --git a/apps/client/components/calendar/WeekView.tsx b/apps/client/components/calendar/WeekView.tsx index 7835403..5661f1a 100644 --- a/apps/client/components/calendar/WeekView.tsx +++ b/apps/client/components/calendar/WeekView.tsx @@ -49,6 +49,27 @@ export const WeekView: React.FC = ({ weekDays, events, onEventPre const [finalSelection, setFinalSelection] = useState(null); const gridBodyRef = useRef(null); const gridLayoutRef = useRef<{ x: number; y: number; width: number; height: number } | null>(null); + const verticalScrollRef = useRef(null); + const scrolledForRef = useRef(''); + + // The grid runs from midnight, which is always empty — open it on the first + // event of the visible range instead (or the morning when there is none). + useEffect(() => { + const key = `${weekDays[0]?.toDateString() ?? ''}-${events.length > 0}`; + if (scrolledForRef.current === key) return; + scrolledForRef.current = key; + + const hours = events + .map((event) => new Date(event.startTime)) + .filter((date) => !isNaN(date.getTime())) + .map((date) => date.getHours()); + const earliest = hours.length > 0 ? Math.min(...hours) : 8; + const target = Math.max(0, Math.min(earliest - 1, 20)); + + requestAnimationFrame(() => { + verticalScrollRef.current?.scrollTo({ y: target * HOUR_HEIGHT, animated: false }); + }); + }, [weekDays, events]); // Clear selection when externalSelection becomes null (reset button clicked) useEffect(() => { @@ -375,6 +396,7 @@ export const WeekView: React.FC = ({ weekDays, events, onEventPre contentContainerStyle={{ flexGrow: 1 }} > (undefined); export const EventsProvider: React.FC<{ children: ReactNode }> = ({ children }) => { - const { addCreatedEvent } = useAuth(); - const [events, setEvents] = useState([]); + const { addCreatedEvent, currentUser } = useAuth(); + const [rawEvents, setRawEvents] = useState([]); + const [rsvpStore, setRsvpStore] = useState({}); const [isLoading, setIsLoading] = useState(true); + // RSVPs have nowhere to persist when there is no Supabase project, and + // dev-mode personas are not real auth.users rows — keep those on the device + // so "You're going" survives a reload. + const userId = currentUser?.id; + const usesLocalRsvps = !isSupabaseConfigured || isDevUserId(userId); + useEffect(() => { loadEvents(); + storage + .getItem(LOCAL_RSVP_STORAGE_KEY) + .then((raw) => setRsvpStore(parseRsvpStore(raw))) + .catch((error) => console.error('Failed to load saved RSVPs:', error)); }, []); + // Locally-stored RSVPs are layered over whatever the source returned, so + // every consumer of `events` sees one consistent answer. + const events = useMemo( + () => (usesLocalRsvps ? applyLocalRsvps(rawEvents, rsvpStore, userId) : rawEvents), + [rawEvents, rsvpStore, userId, usesLocalRsvps] + ); + const loadEvents = async () => { try { setIsLoading(true); const fetchedEvents = await fetchEvents(); if (fetchedEvents.length > 0) { - setEvents(fetchedEvents.filter((e) => !e.id.startsWith('gcal-'))); + setRawEvents(fetchedEvents.filter((e) => !e.id.startsWith('gcal-'))); } else { const fallbackEvents = (allEventsData as Event[]).filter((e) => !e.id.startsWith('gcal-')); - setEvents(fallbackEvents); + setRawEvents(fallbackEvents); } } catch (error) { if (!(error instanceof SupabaseNotConfiguredError)) { console.error('Failed to load events from Supabase:', error); } const fallbackEvents = (allEventsData as Event[]).filter((e) => !e.id.startsWith('gcal-')); - setEvents(fallbackEvents); + setRawEvents(fallbackEvents); } finally { setIsLoading(false); } @@ -91,20 +118,20 @@ export const EventsProvider: React.FC<{ children: ReactNode }> = ({ children }) updatedAt: now, imageUrl: eventData.imageUrl, }; - setEvents((prev) => [...prev, localEvent]); + setRawEvents((prev) => [...prev, localEvent]); addCreatedEvent(localEvent.id); return localEvent; } const newEvent = await createEventAPI(eventData, userId, organizerName); - setEvents((prev) => [...prev, newEvent]); + setRawEvents((prev) => [...prev, newEvent]); addCreatedEvent(newEvent.id); return newEvent; }; const updateEvent = async (eventId: string, updates: Partial) => { await updateEventAPI(eventId, updates); - setEvents((prev) => + setRawEvents((prev) => prev.map((event) => event.id === eventId ? { ...event, ...updates, updatedAt: new Date().toISOString() } : event ) @@ -113,13 +140,26 @@ export const EventsProvider: React.FC<{ children: ReactNode }> = ({ children }) const deleteEvent = async (eventId: string) => { await deleteEventAPI(eventId); - setEvents((prev) => prev.filter((event) => event.id !== eventId)); + setRawEvents((prev) => prev.filter((event) => event.id !== eventId)); }; const updateRSVP = async (eventId: string, userId: string, status: RSVPStatus) => { const event = events.find((e) => e.id === eventId); if (!event) return; + // Without a server to write to, the device is the record: persist the RSVP + // and let the derived `events` list pick it up. + if (!isSupabaseConfigured || isDevUserId(userId)) { + setRsvpStore((prev) => { + const next = setLocalRsvp(prev, userId, eventId, status); + storage + .setItem(LOCAL_RSVP_STORAGE_KEY, JSON.stringify(next)) + .catch((error) => console.error('Failed to save RSVP:', error)); + return next; + }); + return; + } + const filteredAttendees = event.attendees.filter((a) => a.userId !== userId); const newCounts = { ...event.rsvpCounts }; const existingAttendee = event.attendees.find((a) => a.userId === userId); @@ -140,7 +180,7 @@ export const EventsProvider: React.FC<{ children: ReactNode }> = ({ children }) } // Optimistic local update so the UI responds immediately - setEvents((prev) => + setRawEvents((prev) => prev.map((e) => e.id === eventId ? { @@ -153,24 +193,21 @@ export const EventsProvider: React.FC<{ children: ReactNode }> = ({ children }) ) ); - // Dev-mode personas keep RSVPs in local state only - if (isDevUserId(userId)) return; - try { // Write the user's own RSVP row; a DB trigger recomputes the aggregates await setRSVPAPI(eventId, userId, status); // Pull the authoritative aggregates back (handles concurrent RSVPs) const fresh = await fetchEventAPI(eventId); if (fresh) { - setEvents((prev) => prev.map((e) => (e.id === eventId ? fresh : e))); + setRawEvents((prev) => prev.map((e) => (e.id === eventId ? fresh : e))); } } catch (error) { if (error instanceof SupabaseNotConfiguredError) { - // Offline demo mode: the optimistic local state is the state + // Credentials disappeared mid-session: keep the optimistic state return; } console.error('Failed to persist RSVP, reverting:', error); - setEvents((prev) => prev.map((e) => (e.id === eventId ? event : e))); + setRawEvents((prev) => prev.map((e) => (e.id === eventId ? event : e))); } }; @@ -195,7 +232,7 @@ export const EventsProvider: React.FC<{ children: ReactNode }> = ({ children }) * another source (similar title, close start time) are dropped. */ const addExternalEvents = (newEvents: Event[]) => { - setEvents((prev) => { + setRawEvents((prev) => { const newIds = new Set(newEvents.map((e) => e.id)); // Remove old versions of these events, then append the new ones const filtered = prev.filter((e) => !newIds.has(e.id)); @@ -208,7 +245,7 @@ export const EventsProvider: React.FC<{ children: ReactNode }> = ({ children }) * Used to clear Slack-imported events (prefix "slack-"). */ const removeExternalEvents = (idPrefix: string) => { - setEvents((prev) => prev.filter((e) => !e.id.startsWith(idPrefix))); + setRawEvents((prev) => prev.filter((e) => !e.id.startsWith(idPrefix))); }; const value: EventsContextType = { diff --git a/apps/client/data/allEvents.json b/apps/client/data/allEvents.json index 50c5432..e392288 100644 --- a/apps/client/data/allEvents.json +++ b/apps/client/data/allEvents.json @@ -3,8 +3,8 @@ "id": "evt-001", "title": "Carnegie Mellon Career Fair", "description": "Annual career fair featuring top tech companies and startups. Bring your resume and dress professionally!", - "startTime": "2025-10-20T10:00:00Z", - "endTime": "2025-10-20T16:00:00Z", + "startTime": "2026-08-01T14:00:00.000Z", + "endTime": "2026-08-01T20:00:00.000Z", "location": "Wiegand Gymnasium", "categories": [ "Career", @@ -32,15 +32,15 @@ "recruiting", "tech" ], - "createdAt": "2025-09-15T10:00:00Z", - "updatedAt": "2025-10-01T10:00:00Z" + "createdAt": "2026-07-11T14:00:00.000Z", + "updatedAt": "2026-07-25T14:00:00.000Z" }, { "id": "evt-002", "title": "Scotty's Lab: Arduino Workshop", "description": "Learn the basics of Arduino programming and build your own LED circuit!", - "startTime": "2025-10-19T13:00:00Z", - "endTime": "2025-10-19T15:00:00Z", + "startTime": "2026-08-01T17:00:00.000Z", + "endTime": "2026-08-01T19:00:00.000Z", "location": "Hunt Library Maker Space", "categories": [ "Tech", @@ -68,15 +68,15 @@ "electronics", "workshop" ], - "createdAt": "2025-09-20T10:00:00Z", - "updatedAt": "2025-10-05T10:00:00Z" + "createdAt": "2026-07-11T17:00:00.000Z", + "updatedAt": "2026-07-25T17:00:00.000Z" }, { "id": "evt-003", "title": "Poker Night @ Wiegand", "description": "Casual poker game, all skill levels welcome! Bring $5 for buy-in.", - "startTime": "2025-10-18T18:30:00Z", - "endTime": "2025-10-18T22:00:00Z", + "startTime": "2026-08-01T22:30:00.000Z", + "endTime": "2026-08-02T02:00:00.000Z", "location": "Wiegand Gym Lounge", "categories": [ "Social", @@ -104,15 +104,15 @@ "games", "social" ], - "createdAt": "2025-10-15T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" + "createdAt": "2026-07-11T22:30:00.000Z", + "updatedAt": "2026-07-25T22:30:00.000Z" }, { "id": "evt-004", "title": "Free Pizza & Study Session", - "description": "Grab free pizza while studying for midterms. Quiet study space available.", - "startTime": "2025-10-21T17:00:00Z", - "endTime": "2025-10-21T21:00:00Z", + "description": "Grab free pizza while you study. Quiet study space with unlimited slices.", + "startTime": "2026-08-01T21:00:00.000Z", + "endTime": "2026-08-02T01:00:00.000Z", "location": "Gates Hillman Center 4th Floor", "categories": [ "Food", @@ -139,15 +139,15 @@ "study", "pizza" ], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-12T10:00:00Z" + "createdAt": "2026-07-11T21:00:00.000Z", + "updatedAt": "2026-07-25T21:00:00.000Z" }, { "id": "evt-005", "title": "Basketball Pickup Game", "description": "Looking for 4 more players for a casual basketball game. All levels welcome!", - "startTime": "2025-10-19T16:00:00Z", - "endTime": "2025-10-19T18:00:00Z", + "startTime": "2026-08-01T20:00:00.000Z", + "endTime": "2026-08-01T22:00:00.000Z", "location": "Highmark Center Court 2", "categories": [ "Sports", @@ -175,15 +175,15 @@ "sports", "pickup" ], - "createdAt": "2025-10-17T10:00:00Z", - "updatedAt": "2025-10-17T10:00:00Z" + "createdAt": "2026-07-11T20:00:00.000Z", + "updatedAt": "2026-07-25T20:00:00.000Z" }, { "id": "evt-006", "title": "Yoga & Mindfulness Session", "description": "Start your day with gentle yoga and meditation. Mats provided.", - "startTime": "2025-10-20T07:00:00Z", - "endTime": "2025-10-20T08:00:00Z", + "startTime": "2026-08-02T11:00:00.000Z", + "endTime": "2026-08-02T12:00:00.000Z", "location": "University Center McKenna Room", "categories": [ "Wellness", @@ -211,15 +211,15 @@ "wellness", "meditation" ], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-08T10:00:00Z" + "createdAt": "2026-07-12T11:00:00.000Z", + "updatedAt": "2026-07-26T11:00:00.000Z" }, { "id": "evt-007", "title": "Hackathon: TartanHacks 2025", "description": "24-hour hackathon with prizes, workshops, and free food! Form teams or join one there.", - "startTime": "2025-10-25T18:00:00Z", - "endTime": "2025-10-26T18:00:00Z", + "startTime": "2026-08-02T22:00:00.000Z", + "endTime": "2026-08-03T22:00:00.000Z", "location": "Gates Hillman Center", "categories": [ "Tech", @@ -247,15 +247,15 @@ "coding", "tech" ], - "createdAt": "2025-09-01T10:00:00Z", - "updatedAt": "2025-10-10T10:00:00Z" + "createdAt": "2026-07-12T22:00:00.000Z", + "updatedAt": "2026-07-26T22:00:00.000Z" }, { "id": "evt-008", "title": "Art Gallery Opening: Student Showcase", "description": "Featuring works from CMU art students. Wine and cheese reception.", - "startTime": "2025-10-22T18:00:00Z", - "endTime": "2025-10-22T21:00:00Z", + "startTime": "2026-08-02T22:00:00.000Z", + "endTime": "2026-08-03T01:00:00.000Z", "location": "Miller Gallery", "categories": [ "Arts", @@ -282,15 +282,15 @@ "gallery", "exhibition" ], - "createdAt": "2025-10-01T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" + "createdAt": "2026-07-12T22:00:00.000Z", + "updatedAt": "2026-07-26T22:00:00.000Z" }, { "id": "evt-009", "title": "Coffee Chat: Alumni in Tech", "description": "Informal networking with CMU alumni working at FAANG companies.", - "startTime": "2025-10-23T15:00:00Z", - "endTime": "2025-10-23T16:30:00Z", + "startTime": "2026-08-02T19:00:00.000Z", + "endTime": "2026-08-02T20:30:00.000Z", "location": "Rothberg's Roasters", "categories": [ "Career", @@ -318,15 +318,15 @@ "alumni", "career" ], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" + "createdAt": "2026-07-12T19:00:00.000Z", + "updatedAt": "2026-07-26T19:00:00.000Z" }, { "id": "evt-010", "title": "Lunar Gala Fashion Show", "description": "CMU's premier fashion show featuring student designers. Tickets required.", - "startTime": "2025-10-21T19:00:00Z", - "endTime": "2025-10-21T22:00:00Z", + "startTime": "2026-08-03T23:00:00.000Z", + "endTime": "2026-08-04T02:00:00.000Z", "location": "Wiegand Gymnasium", "categories": [ "Arts", @@ -354,15 +354,15 @@ "show", "design" ], - "createdAt": "2025-08-15T10:00:00Z", - "updatedAt": "2025-10-10T10:00:00Z" + "createdAt": "2026-07-13T23:00:00.000Z", + "updatedAt": "2026-07-27T23:00:00.000Z" }, { "id": "evt-011", "title": "Trivia Night @ The Underground", "description": "Test your knowledge! Teams of 4-6. Prizes for top 3 teams.", - "startTime": "2025-10-24T20:00:00Z", - "endTime": "2025-10-24T22:30:00Z", + "startTime": "2026-08-04T00:00:00.000Z", + "endTime": "2026-08-04T02:30:00.000Z", "location": "The Underground", "categories": [ "Fun", @@ -390,15 +390,15 @@ "games", "competition" ], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" + "createdAt": "2026-07-14T00:00:00.000Z", + "updatedAt": "2026-07-28T00:00:00.000Z" }, { "id": "evt-012", "title": "Machine Learning Workshop", "description": "Introduction to neural networks and deep learning with hands-on coding.", - "startTime": "2025-10-26T14:00:00Z", - "endTime": "2025-10-26T17:00:00Z", + "startTime": "2026-08-03T18:00:00.000Z", + "endTime": "2026-08-03T21:00:00.000Z", "location": "Gates Hillman 6115", "categories": [ "Tech", @@ -426,15 +426,15 @@ "ai", "workshop" ], - "createdAt": "2025-10-01T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" + "createdAt": "2026-07-13T18:00:00.000Z", + "updatedAt": "2026-07-27T18:00:00.000Z" }, { "id": "evt-013", "title": "Bubble Tea Run", "description": "Going to get bubble tea in Oakland, anyone want to join? Meeting at UC.", - "startTime": "2025-10-19T14:30:00Z", - "endTime": "2025-10-19T16:00:00Z", + "startTime": "2026-08-03T18:30:00.000Z", + "endTime": "2026-08-03T20:00:00.000Z", "location": "University Center Entrance", "categories": [ "Food", @@ -462,15 +462,15 @@ "boba", "social" ], - "createdAt": "2025-10-18T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" + "createdAt": "2026-07-13T18:30:00.000Z", + "updatedAt": "2026-07-27T18:30:00.000Z" }, { "id": "evt-014", "title": "Startup Pitch Competition", "description": "Watch student entrepreneurs pitch their startups. $10k in prizes!", - "startTime": "2025-10-27T17:00:00Z", - "endTime": "2025-10-27T20:00:00Z", + "startTime": "2026-08-04T21:00:00.000Z", + "endTime": "2026-08-05T00:00:00.000Z", "location": "Tepper Auditorium", "categories": [ "Career", @@ -498,15 +498,15 @@ "pitch", "entrepreneurship" ], - "createdAt": "2025-09-20T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" + "createdAt": "2026-07-14T21:00:00.000Z", + "updatedAt": "2026-07-28T21:00:00.000Z" }, { "id": "evt-015", "title": "Salsa Dancing Lessons", "description": "Beginner-friendly salsa lessons. No partner needed!", - "startTime": "2025-10-25T19:00:00Z", - "endTime": "2025-10-25T21:00:00Z", + "startTime": "2026-08-04T23:00:00.000Z", + "endTime": "2026-08-05T01:00:00.000Z", "location": "Rangos Ballroom", "categories": [ "Fun", @@ -534,15 +534,15 @@ "salsa", "lessons" ], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" + "createdAt": "2026-07-14T23:00:00.000Z", + "updatedAt": "2026-07-28T23:00:00.000Z" }, { "id": "evt-016", "title": "Study Abroad Info Session", "description": "Learn about study abroad opportunities for next semester.", - "startTime": "2025-10-23T12:00:00Z", - "endTime": "2025-10-23T13:00:00Z", + "startTime": "2026-08-04T16:00:00.000Z", + "endTime": "2026-08-04T17:00:00.000Z", "location": "Warner Hall 100", "categories": [ "Academic", @@ -570,15 +570,15 @@ "international", "info-session" ], - "createdAt": "2025-10-01T10:00:00Z", - "updatedAt": "2025-10-10T10:00:00Z" + "createdAt": "2026-07-14T16:00:00.000Z", + "updatedAt": "2026-07-28T16:00:00.000Z" }, { "id": "evt-017", "title": "Rock Climbing @ The Climbing Wall", "description": "Casual climbing session. Equipment provided, all levels welcome!", - "startTime": "2025-10-20T15:00:00Z", - "endTime": "2025-10-20T17:00:00Z", + "startTime": "2026-08-04T19:00:00.000Z", + "endTime": "2026-08-04T21:00:00.000Z", "location": "Cohon Center Climbing Wall", "categories": [ "Sports", @@ -606,15 +606,15 @@ "sports", "fitness" ], - "createdAt": "2025-10-17T10:00:00Z", - "updatedAt": "2025-10-17T10:00:00Z" + "createdAt": "2026-07-14T19:00:00.000Z", + "updatedAt": "2026-07-28T19:00:00.000Z" }, { "id": "evt-018", "title": "Diwali Celebration", "description": "Celebrate the festival of lights with food, music, and performances!", - "startTime": "2025-10-28T18:00:00Z", - "endTime": "2025-10-28T22:00:00Z", + "startTime": "2026-08-05T22:00:00.000Z", + "endTime": "2026-08-06T02:00:00.000Z", "location": "Rangos Ballroom", "categories": [ "Events", @@ -643,15 +643,15 @@ "cultural", "celebration" ], - "createdAt": "2025-09-15T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" + "createdAt": "2026-07-15T22:00:00.000Z", + "updatedAt": "2026-07-29T22:00:00.000Z" }, { "id": "evt-019", "title": "Resume Review Drop-In", "description": "Get your resume reviewed by career advisors. No appointment needed.", - "startTime": "2025-10-24T13:00:00Z", - "endTime": "2025-10-24T16:00:00Z", + "startTime": "2026-08-05T17:00:00.000Z", + "endTime": "2026-08-05T20:00:00.000Z", "location": "Career Center", "categories": [ "Career", @@ -678,15 +678,15 @@ "career", "advising" ], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" + "createdAt": "2026-07-15T17:00:00.000Z", + "updatedAt": "2026-07-29T17:00:00.000Z" }, { "id": "evt-020", "title": "Board Game Night", "description": "Bring your favorite board games or play ours! Snacks provided.", - "startTime": "2025-10-26T19:00:00Z", - "endTime": "2025-10-26T23:00:00Z", + "startTime": "2026-08-05T23:00:00.000Z", + "endTime": "2026-08-06T03:00:00.000Z", "location": "Morewood Gardens Lounge", "categories": [ "Fun", @@ -714,15 +714,15 @@ "board-games", "social" ], - "createdAt": "2025-10-20T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" + "createdAt": "2026-07-15T23:00:00.000Z", + "updatedAt": "2026-07-29T23:00:00.000Z" }, { "id": "evt-021", "title": "Cybersecurity CTF Competition", "description": "Capture the flag competition testing your hacking skills. Form teams of 3-4.", - "startTime": "2025-10-29T18:00:00Z", - "endTime": "2025-10-30T06:00:00Z", + "startTime": "2026-08-05T22:00:00.000Z", + "endTime": "2026-08-06T10:00:00.000Z", "location": "Gates Hillman Center", "categories": [ "Tech", @@ -750,15 +750,15 @@ "security", "hacking" ], - "createdAt": "2025-10-01T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" + "createdAt": "2026-07-15T22:00:00.000Z", + "updatedAt": "2026-07-29T22:00:00.000Z" }, { "id": "evt-022", "title": "Farmers Market on Campus", "description": "Fresh produce, baked goods, and local crafts from Pittsburgh vendors.", - "startTime": "2025-10-22T10:00:00Z", - "endTime": "2025-10-22T14:00:00Z", + "startTime": "2026-08-06T14:00:00.000Z", + "endTime": "2026-08-06T18:00:00.000Z", "location": "The Cut", "categories": [ "Food", @@ -785,15 +785,15 @@ "food", "local" ], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-12T10:00:00Z" + "createdAt": "2026-07-16T14:00:00.000Z", + "updatedAt": "2026-07-30T14:00:00.000Z" }, { "id": "evt-023", "title": "Improv Comedy Show", "description": "Student improv troupe performs. Audience participation encouraged!", - "startTime": "2025-10-25T20:00:00Z", - "endTime": "2025-10-25T21:30:00Z", + "startTime": "2026-08-07T00:00:00.000Z", + "endTime": "2026-08-07T01:30:00.000Z", "location": "Kresge Theatre", "categories": [ "Arts", @@ -821,15 +821,15 @@ "comedy", "performance" ], - "createdAt": "2025-10-08T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" + "createdAt": "2026-07-17T00:00:00.000Z", + "updatedAt": "2026-07-31T00:00:00.000Z" }, { "id": "evt-024", "title": "Meditation & Stress Relief", - "description": "Guided meditation session to help with midterm stress.", - "startTime": "2025-10-23T17:00:00Z", - "endTime": "2025-10-23T18:00:00Z", + "description": "Guided meditation session to reset between classes.", + "startTime": "2026-08-06T21:00:00.000Z", + "endTime": "2026-08-06T22:00:00.000Z", "location": "Wellness Center", "categories": [ "Wellness", @@ -857,15 +857,15 @@ "wellness", "stress-relief" ], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" + "createdAt": "2026-07-16T21:00:00.000Z", + "updatedAt": "2026-07-30T21:00:00.000Z" }, { "id": "evt-025", "title": "Late Night Breakfast", - "description": "Free pancakes, waffles, and breakfast foods during finals prep!", - "startTime": "2025-10-30T22:00:00Z", - "endTime": "2025-10-31T01:00:00Z", + "description": "Free pancakes, waffles, and breakfast foods served at midnight.", + "startTime": "2026-08-07T02:00:00.000Z", + "endTime": "2026-08-07T05:00:00.000Z", "location": "Resnik Dining Hall", "categories": [ "Food", @@ -892,15 +892,15 @@ "breakfast", "free" ], - "createdAt": "2025-10-15T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" + "createdAt": "2026-07-17T02:00:00.000Z", + "updatedAt": "2026-07-31T02:00:00.000Z" }, { "id": "evt-026", "title": "Photography Walk: Fall Colors", "description": "Explore campus and capture autumn colors. Bring your camera or phone!", - "startTime": "2025-10-21T14:00:00Z", - "endTime": "2025-10-21T16:00:00Z", + "startTime": "2026-08-07T18:00:00.000Z", + "endTime": "2026-08-07T20:00:00.000Z", "location": "Schenley Park Entrance", "categories": [ "Arts", @@ -928,15 +928,15 @@ "nature", "fall" ], - "createdAt": "2025-10-16T10:00:00Z", - "updatedAt": "2025-10-16T10:00:00Z" + "createdAt": "2026-07-17T18:00:00.000Z", + "updatedAt": "2026-07-31T18:00:00.000Z" }, { "id": "evt-027", "title": "Mock Interview Practice", "description": "Practice technical interviews with upperclassmen. Sign up for time slots.", - "startTime": "2025-10-27T10:00:00Z", - "endTime": "2025-10-27T16:00:00Z", + "startTime": "2026-08-07T14:00:00.000Z", + "endTime": "2026-08-07T20:00:00.000Z", "location": "Gates Hillman 4000", "categories": [ "Career", @@ -964,15 +964,20 @@ "career", "practice" ], - "createdAt": "2025-10-12T10:00:00Z", - "updatedAt": "2025-10-22T10:00:00Z" + "createdAt": "2026-07-17T14:00:00.000Z", + "updatedAt": "2026-07-31T14:00:00.000Z", + "recurring": { + "frequency": "weekly", + "interval": 1, + "endDate": "2026-09-30" + } }, { "id": "evt-028", "title": "Volleyball Tournament", "description": "Intramural volleyball tournament. Teams of 6, sign up by Oct 23.", - "startTime": "2025-10-28T13:00:00Z", - "endTime": "2025-10-28T18:00:00Z", + "startTime": "2026-08-07T17:00:00.000Z", + "endTime": "2026-08-07T22:00:00.000Z", "location": "Highmark Center Courts", "categories": [ "Sports", @@ -1000,15 +1005,15 @@ "tournament", "sports" ], - "createdAt": "2025-10-08T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" + "createdAt": "2026-07-17T17:00:00.000Z", + "updatedAt": "2026-07-31T17:00:00.000Z" }, { "id": "evt-029", "title": "Open Mic Night", "description": "Share your music, poetry, or comedy. Sign up at the door or just watch!", - "startTime": "2025-10-24T19:00:00Z", - "endTime": "2025-10-24T22:00:00Z", + "startTime": "2026-08-07T23:00:00.000Z", + "endTime": "2026-08-08T02:00:00.000Z", "location": "The Underground", "categories": [ "Arts", @@ -1036,15 +1041,15 @@ "music", "performance" ], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" + "createdAt": "2026-07-17T23:00:00.000Z", + "updatedAt": "2026-07-31T23:00:00.000Z" }, { "id": "evt-030", "title": "Sustainability Workshop", "description": "Learn about sustainable living and campus green initiatives.", - "startTime": "2025-10-26T11:00:00Z", - "endTime": "2025-10-26T12:30:00Z", + "startTime": "2026-08-08T15:00:00.000Z", + "endTime": "2026-08-08T16:30:00.000Z", "location": "Posner Hall 153", "categories": [ "Academic", @@ -1072,15 +1077,15 @@ "environment", "workshop" ], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" + "createdAt": "2026-07-18T15:00:00.000Z", + "updatedAt": "2026-08-01T15:00:00.000Z" }, { "id": "evt-031", "title": "Brunch & Study Group", "description": "Casual brunch meetup for 15-213 students. Bring your questions!", - "startTime": "2025-10-22T11:00:00Z", - "endTime": "2025-10-22T13:00:00Z", + "startTime": "2026-08-08T15:00:00.000Z", + "endTime": "2026-08-08T17:00:00.000Z", "location": "Entropy Cafe", "categories": [ "Academic", @@ -1108,15 +1113,20 @@ "brunch", "15-213" ], - "createdAt": "2025-10-19T10:00:00Z", - "updatedAt": "2025-10-19T10:00:00Z" + "createdAt": "2026-07-18T15:00:00.000Z", + "updatedAt": "2026-08-01T15:00:00.000Z", + "recurring": { + "frequency": "weekly", + "interval": 1, + "endDate": "2026-09-30" + } }, { "id": "evt-032", "title": "Karaoke Night", "description": "Sing your heart out! Private rooms available for groups.", - "startTime": "2025-10-27T21:00:00Z", - "endTime": "2025-10-28T00:00:00Z", + "startTime": "2026-08-09T01:00:00.000Z", + "endTime": "2026-08-09T04:00:00.000Z", "location": "The Underground", "categories": [ "Fun", @@ -1144,15 +1154,15 @@ "music", "fun" ], - "createdAt": "2025-10-12T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" + "createdAt": "2026-07-19T01:00:00.000Z", + "updatedAt": "2026-08-02T01:00:00.000Z" }, { "id": "evt-033", "title": "3D Printing Workshop", "description": "Learn to design and print 3D models. Beginners welcome!", - "startTime": "2025-10-29T15:00:00Z", - "endTime": "2025-10-29T17:00:00Z", + "startTime": "2026-08-08T19:00:00.000Z", + "endTime": "2026-08-08T21:00:00.000Z", "location": "Hunt Library Maker Space", "categories": [ "Tech", @@ -1180,15 +1190,15 @@ "maker", "workshop" ], - "createdAt": "2025-10-15T10:00:00Z", - "updatedAt": "2025-10-22T10:00:00Z" + "createdAt": "2026-07-18T19:00:00.000Z", + "updatedAt": "2026-08-01T19:00:00.000Z" }, { "id": "evt-034", "title": "Soccer Scrimmage", "description": "Pickup soccer game on the Cut. All skill levels welcome!", - "startTime": "2025-10-23T16:30:00Z", - "endTime": "2025-10-23T18:30:00Z", + "startTime": "2026-08-09T20:30:00.000Z", + "endTime": "2026-08-09T22:30:00.000Z", "location": "The Cut", "categories": [ "Sports", @@ -1216,15 +1226,15 @@ "sports", "pickup" ], - "createdAt": "2025-10-21T10:00:00Z", - "updatedAt": "2025-10-21T10:00:00Z" + "createdAt": "2026-07-19T20:30:00.000Z", + "updatedAt": "2026-08-02T20:30:00.000Z" }, { "id": "evt-035", "title": "Film Screening: Indie Night", "description": "Screening of award-winning indie films. Free popcorn!", - "startTime": "2025-10-25T19:30:00Z", - "endTime": "2025-10-25T22:00:00Z", + "startTime": "2026-08-09T23:30:00.000Z", + "endTime": "2026-08-10T02:00:00.000Z", "location": "McConomy Auditorium", "categories": [ "Arts", @@ -1252,15 +1262,15 @@ "movie", "screening" ], - "createdAt": "2025-10-08T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" + "createdAt": "2026-07-19T23:30:00.000Z", + "updatedAt": "2026-08-02T23:30:00.000Z" }, { "id": "evt-036", "title": "Data Science Meetup", "description": "Network with data science professionals and students. Pizza provided!", - "startTime": "2025-10-28T18:30:00Z", - "endTime": "2025-10-28T20:30:00Z", + "startTime": "2026-08-09T22:30:00.000Z", + "endTime": "2026-08-10T00:30:00.000Z", "location": "Tepper Quad", "categories": [ "Tech", @@ -1289,15 +1299,15 @@ "networking", "tech" ], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" + "createdAt": "2026-07-19T22:30:00.000Z", + "updatedAt": "2026-08-02T22:30:00.000Z" }, { "id": "evt-037", "title": "Acapella Concert", "description": "CMU's acapella groups perform. Free admission!", - "startTime": "2025-10-26T20:00:00Z", - "endTime": "2025-10-26T22:00:00Z", + "startTime": "2026-08-10T00:00:00.000Z", + "endTime": "2026-08-10T02:00:00.000Z", "location": "Kresge Theatre", "categories": [ "Arts", @@ -1325,15 +1335,15 @@ "music", "concert" ], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" + "createdAt": "2026-07-20T00:00:00.000Z", + "updatedAt": "2026-08-03T00:00:00.000Z" }, { "id": "evt-038", "title": "Cooking Class: Asian Cuisine", "description": "Learn to make dumplings and fried rice. Ingredients provided!", - "startTime": "2025-10-29T17:00:00Z", - "endTime": "2025-10-29T19:30:00Z", + "startTime": "2026-08-10T21:00:00.000Z", + "endTime": "2026-08-10T23:30:00.000Z", "location": "Resnik Kitchen", "categories": [ "Food", @@ -1361,15 +1371,15 @@ "food", "asian-cuisine" ], - "createdAt": "2025-10-15T10:00:00Z", - "updatedAt": "2025-10-22T10:00:00Z" + "createdAt": "2026-07-20T21:00:00.000Z", + "updatedAt": "2026-08-03T21:00:00.000Z" }, { "id": "evt-039", "title": "Mental Health Panel", "description": "Discussion on student mental health with counselors and peer support.", - "startTime": "2025-10-24T16:00:00Z", - "endTime": "2025-10-24T17:30:00Z", + "startTime": "2026-08-10T20:00:00.000Z", + "endTime": "2026-08-10T21:30:00.000Z", "location": "Cohon Center Conference Room", "categories": [ "Wellness", @@ -1397,15 +1407,15 @@ "wellness", "panel" ], - "createdAt": "2025-10-08T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" + "createdAt": "2026-07-20T20:00:00.000Z", + "updatedAt": "2026-08-03T20:00:00.000Z" }, { "id": "evt-040", "title": "Frisbee on the Cut", "description": "Casual ultimate frisbee. Just show up and play!", - "startTime": "2025-10-20T13:00:00Z", - "endTime": "2025-10-20T15:00:00Z", + "startTime": "2026-08-10T17:00:00.000Z", + "endTime": "2026-08-10T19:00:00.000Z", "location": "The Cut", "categories": [ "Sports", @@ -1434,15 +1444,297 @@ "sports", "casual" ], - "createdAt": "2025-10-18T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" + "createdAt": "2026-07-20T17:00:00.000Z", + "updatedAt": "2026-08-03T17:00:00.000Z" + }, + { + "id": "evt-041", + "title": "Activities Fair on the Cut", + "description": "Every student org on campus in one place. Free swag, sign-up sheets, and a lot of free food.", + "startTime": "2026-08-10T19:00:00.000Z", + "endTime": "2026-08-10T22:00:00.000Z", + "location": "The Cut", + "categories": [ + "Social", + "Events" + ], + "organizer": { + "id": "org-900", + "name": "Student Government", + "type": "club" + }, + "color": "#FF6B6B", + "rsvpEnabled": true, + "rsvpCounts": { + "going": 380, + "maybe": 120, + "notGoing": 2 + }, + "attendees": [], + "attendeeVisibility": "public", + "isClubEvent": true, + "isSocialEvent": true, + "capacity": 1200, + "tags": [ + "clubs", + "orgs", + "freshman" + ], + "createdAt": "2026-07-20T19:00:00.000Z", + "updatedAt": "2026-08-03T19:00:00.000Z" + }, + { + "id": "evt-042", + "title": "Move-In Crew: Volunteer Shift", + "description": "Help first-years haul boxes up the hill. Free t-shirt and lunch for volunteers.", + "startTime": "2026-08-11T13:00:00.000Z", + "endTime": "2026-08-11T17:00:00.000Z", + "location": "Morewood Gardens", + "categories": [ + "Social" + ], + "organizer": { + "id": "org-901", + "name": "Orientation Committee", + "type": "club" + }, + "color": "#4ECDC4", + "rsvpEnabled": true, + "rsvpCounts": { + "going": 46, + "maybe": 12, + "notGoing": 2 + }, + "attendees": [], + "attendeeVisibility": "public", + "isClubEvent": true, + "isSocialEvent": true, + "capacity": 80, + "tags": [ + "volunteer", + "movein" + ], + "createdAt": "2026-07-21T13:00:00.000Z", + "updatedAt": "2026-08-04T13:00:00.000Z" + }, + { + "id": "evt-043", + "title": "Welcome Back BBQ", + "description": "Burgers, veggie dogs, lawn games, and the whole campus on one field.", + "startTime": "2026-08-11T21:00:00.000Z", + "endTime": "2026-08-12T00:00:00.000Z", + "location": "Schenley Park", + "categories": [ + "Food", + "Social" + ], + "organizer": { + "id": "org-902", + "name": "Campus Life", + "type": "club" + }, + "color": "#FFA07A", + "rsvpEnabled": true, + "rsvpCounts": { + "going": 274, + "maybe": 88, + "notGoing": 2 + }, + "attendees": [], + "attendeeVisibility": "public", + "isClubEvent": true, + "isSocialEvent": true, + "capacity": 600, + "tags": [ + "bbq", + "food", + "welcome" + ], + "createdAt": "2026-07-21T21:00:00.000Z", + "updatedAt": "2026-08-04T21:00:00.000Z" + }, + { + "id": "evt-044", + "title": "First-Year Orientation: Campus Tour", + "description": "Walking tour of campus with upperclass guides. Learn the shortcuts nobody tells you about.", + "startTime": "2026-08-11T14:00:00.000Z", + "endTime": "2026-08-11T16:00:00.000Z", + "location": "Cohon University Center", + "categories": [ + "Academic", + "Events" + ], + "organizer": { + "id": "org-903", + "name": "Orientation Committee", + "type": "club" + }, + "color": "#45B7D1", + "rsvpEnabled": true, + "rsvpCounts": { + "going": 189, + "maybe": 54, + "notGoing": 2 + }, + "attendees": [], + "attendeeVisibility": "public", + "isClubEvent": true, + "isSocialEvent": false, + "capacity": 300, + "tags": [ + "orientation", + "freshman", + "tour" + ], + "createdAt": "2026-07-21T14:00:00.000Z", + "updatedAt": "2026-08-04T14:00:00.000Z" + }, + { + "id": "evt-045", + "title": "Student Org Open House", + "description": "Drop in and meet officers from 40+ clubs. Bring questions, leave with a calendar full of meetings.", + "startTime": "2026-08-11T22:00:00.000Z", + "endTime": "2026-08-12T00:00:00.000Z", + "location": "Rangos Ballroom", + "categories": [ + "Networking", + "Social" + ], + "organizer": { + "id": "org-904", + "name": "Student Government", + "type": "club" + }, + "color": "#A29BFE", + "rsvpEnabled": true, + "rsvpCounts": { + "going": 132, + "maybe": 61, + "notGoing": 2 + }, + "attendees": [], + "attendeeVisibility": "public", + "isClubEvent": true, + "isSocialEvent": true, + "capacity": 400, + "tags": [ + "clubs", + "networking" + ], + "createdAt": "2026-07-21T22:00:00.000Z", + "updatedAt": "2026-08-04T22:00:00.000Z" + }, + { + "id": "evt-046", + "title": "Late Night at the Underground", + "description": "Free bowling, pool, and pizza until 1am. No cover, just show your ID.", + "startTime": "2026-08-13T01:00:00.000Z", + "endTime": "2026-08-13T05:00:00.000Z", + "location": "The Underground", + "categories": [ + "Fun", + "Social" + ], + "organizer": { + "id": "org-905", + "name": "Campus Programming Board", + "type": "club" + }, + "color": "#FD79A8", + "rsvpEnabled": true, + "rsvpCounts": { + "going": 143, + "maybe": 47, + "notGoing": 2 + }, + "attendees": [], + "attendeeVisibility": "public", + "isClubEvent": true, + "isSocialEvent": true, + "capacity": 250, + "tags": [ + "latenight", + "games", + "free" + ], + "createdAt": "2026-07-23T01:00:00.000Z", + "updatedAt": "2026-08-06T01:00:00.000Z" + }, + { + "id": "evt-047", + "title": "Intramural Sports Signup Night", + "description": "Pick a sport, find a team, get on a roster. Soccer, volleyball, basketball, and dodgeball.", + "startTime": "2026-08-12T23:00:00.000Z", + "endTime": "2026-08-13T01:00:00.000Z", + "location": "Cohon Fitness Center", + "categories": [ + "Sports" + ], + "organizer": { + "id": "org-906", + "name": "Campus Recreation", + "type": "club" + }, + "color": "#98D8C8", + "rsvpEnabled": true, + "rsvpCounts": { + "going": 97, + "maybe": 33, + "notGoing": 2 + }, + "attendees": [], + "attendeeVisibility": "public", + "isClubEvent": true, + "isSocialEvent": false, + "capacity": 200, + "tags": [ + "sports", + "intramural" + ], + "createdAt": "2026-07-22T23:00:00.000Z", + "updatedAt": "2026-08-05T23:00:00.000Z" + }, + { + "id": "evt-048", + "title": "Career Center Kickoff: Resume Lab", + "description": "Bring a draft, leave with a resume that survives a recruiter skim. Walk-in reviews all afternoon.", + "startTime": "2026-08-12T17:00:00.000Z", + "endTime": "2026-08-12T21:00:00.000Z", + "location": "Career & Professional Development Center", + "categories": [ + "Career" + ], + "organizer": { + "id": "org-907", + "name": "Career Services", + "type": "club" + }, + "color": "#F7B801", + "rsvpEnabled": true, + "rsvpCounts": { + "going": 71, + "maybe": 24, + "notGoing": 2 + }, + "attendees": [], + "attendeeVisibility": "public", + "isClubEvent": true, + "isSocialEvent": false, + "capacity": 120, + "tags": [ + "career", + "resume", + "jobs" + ], + "createdAt": "2026-07-22T17:00:00.000Z", + "updatedAt": "2026-08-05T17:00:00.000Z" }, { "id": "evt-current-001", "title": "Morning Yoga Session", "description": "Start your day with a relaxing yoga session", - "startTime": "2025-11-17T08:00:00.000Z", - "endTime": "2025-11-17T09:00:00.000Z", + "startTime": "2026-08-12T12:00:00.000Z", + "endTime": "2026-08-12T13:00:00.000Z", "location": "UC Gym", "categories": [ "Wellness", @@ -1470,15 +1762,15 @@ "wellness", "morning" ], - "createdAt": "2025-11-10T10:00:00.000Z", - "updatedAt": "2025-11-10T10:00:00.000Z" + "createdAt": "2026-07-22T12:00:00.000Z", + "updatedAt": "2026-08-05T12:00:00.000Z" }, { "id": "evt-current-002", "title": "CS Study Group", "description": "Study session for 15-213 exam prep", - "startTime": "2025-11-17T14:00:00.000Z", - "endTime": "2025-11-17T16:00:00.000Z", + "startTime": "2026-08-13T18:00:00.000Z", + "endTime": "2026-08-13T20:00:00.000Z", "location": "Gates 4th Floor", "categories": [ "Academic", @@ -1506,15 +1798,15 @@ "cs", "exam" ], - "createdAt": "2025-11-12T10:00:00.000Z", - "updatedAt": "2025-11-12T10:00:00.000Z" + "createdAt": "2026-07-23T18:00:00.000Z", + "updatedAt": "2026-08-06T18:00:00.000Z" }, { "id": "evt-current-003", "title": "Basketball Pickup Game", "description": "Casual basketball game, all skill levels welcome!", - "startTime": "2025-11-17T18:30:00.000Z", - "endTime": "2025-11-17T20:00:00.000Z", + "startTime": "2026-08-13T22:30:00.000Z", + "endTime": "2026-08-14T00:00:00.000Z", "location": "Highmark Center", "categories": [ "Sports", @@ -1542,15 +1834,15 @@ "sports", "pickup" ], - "createdAt": "2025-11-13T10:00:00.000Z", - "updatedAt": "2025-11-13T10:00:00.000Z" + "createdAt": "2026-07-23T22:30:00.000Z", + "updatedAt": "2026-08-06T22:30:00.000Z" }, { "id": "evt-current-004", "title": "Tech Talk: AI in Healthcare", "description": "Guest speaker from Google discussing AI applications in healthcare", - "startTime": "2025-11-18T17:00:00.000Z", - "endTime": "2025-11-18T18:30:00.000Z", + "startTime": "2026-08-13T21:00:00.000Z", + "endTime": "2026-08-13T22:30:00.000Z", "location": "Gates Hillman Center", "categories": [ "Tech", @@ -1579,15 +1871,15 @@ "healthcare", "talk" ], - "createdAt": "2025-11-05T10:00:00.000Z", - "updatedAt": "2025-11-08T10:00:00.000Z" + "createdAt": "2026-07-23T21:00:00.000Z", + "updatedAt": "2026-08-06T21:00:00.000Z" }, { "id": "evt-current-005", "title": "Coffee & Code", "description": "Casual coding session at Entropy. Work on projects or just hang out!", - "startTime": "2025-11-18T10:00:00.000Z", - "endTime": "2025-11-18T12:00:00.000Z", + "startTime": "2026-08-13T14:00:00.000Z", + "endTime": "2026-08-13T16:00:00.000Z", "location": "Entropy Coffee", "categories": [ "Social", @@ -1615,15 +1907,15 @@ "coding", "social" ], - "createdAt": "2025-11-14T10:00:00.000Z", - "updatedAt": "2025-11-14T10:00:00.000Z" + "createdAt": "2026-07-23T14:00:00.000Z", + "updatedAt": "2026-08-06T14:00:00.000Z" }, { "id": "evt-current-006", "title": "Poker Night", "description": "Texas Hold'em poker night in Wiegand. $5 buy-in, winner takes all!", - "startTime": "2025-11-18T20:00:00.000Z", - "endTime": "2025-11-18T23:00:00.000Z", + "startTime": "2026-08-15T00:00:00.000Z", + "endTime": "2026-08-15T03:00:00.000Z", "location": "Wiegand Gym Lounge", "categories": [ "Social", @@ -1651,15 +1943,15 @@ "games", "night" ], - "createdAt": "2025-11-15T10:00:00.000Z", - "updatedAt": "2025-11-15T10:00:00.000Z" + "createdAt": "2026-07-25T00:00:00.000Z", + "updatedAt": "2026-08-08T00:00:00.000Z" }, { "id": "evt-current-007", "title": "Design Workshop: Figma Basics", "description": "Learn the fundamentals of Figma for UI/UX design", - "startTime": "2025-11-19T15:00:00.000Z", - "endTime": "2025-11-19T17:00:00.000Z", + "startTime": "2026-08-14T19:00:00.000Z", + "endTime": "2026-08-14T21:00:00.000Z", "location": "Hunt Library", "categories": [ "Design", @@ -1687,15 +1979,15 @@ "figma", "workshop" ], - "createdAt": "2025-11-08T10:00:00.000Z", - "updatedAt": "2025-11-10T10:00:00.000Z" + "createdAt": "2026-07-24T19:00:00.000Z", + "updatedAt": "2026-08-07T19:00:00.000Z" }, { "id": "evt-current-008", "title": "Lunch & Learn: Entrepreneurship", "description": "Free lunch and discussion about starting your own company", - "startTime": "2025-11-19T12:00:00.000Z", - "endTime": "2025-11-19T13:30:00.000Z", + "startTime": "2026-08-14T16:00:00.000Z", + "endTime": "2026-08-14T17:30:00.000Z", "location": "Tepper Quad", "categories": [ "Career", @@ -1723,15 +2015,15 @@ "lunch", "career" ], - "createdAt": "2025-11-06T10:00:00.000Z", - "updatedAt": "2025-11-09T10:00:00.000Z" + "createdAt": "2026-07-24T16:00:00.000Z", + "updatedAt": "2026-08-07T16:00:00.000Z" }, { "id": "evt-current-009", "title": "Movie Night: The Social Network", "description": "Watch The Social Network with free popcorn!", - "startTime": "2025-11-20T19:00:00.000Z", - "endTime": "2025-11-20T21:30:00.000Z", + "startTime": "2026-08-14T23:00:00.000Z", + "endTime": "2026-08-15T01:30:00.000Z", "location": "McConomy Auditorium", "categories": [ "Entertainment", @@ -1759,15 +2051,15 @@ "social", "entertainment" ], - "createdAt": "2025-11-07T10:00:00.000Z", - "updatedAt": "2025-11-11T10:00:00.000Z" + "createdAt": "2026-07-24T23:00:00.000Z", + "updatedAt": "2026-08-07T23:00:00.000Z" }, { "id": "evt-current-010", "title": "Hackathon Kickoff", "description": "24-hour hackathon starts now! Build something amazing!", - "startTime": "2025-11-21T18:00:00.000Z", - "endTime": "2025-11-22T18:00:00.000Z", + "startTime": "2026-08-15T22:00:00.000Z", + "endTime": "2026-08-16T22:00:00.000Z", "location": "Gates Hillman Center", "categories": [ "Tech", @@ -1795,17 +2087,20 @@ "coding", "competition" ], - "createdAt": "2025-10-15T10:00:00.000Z", - "updatedAt": "2025-11-01T10:00:00.000Z" + "createdAt": "2026-07-25T22:00:00.000Z", + "updatedAt": "2026-08-08T22:00:00.000Z" }, { "id": "evt-dec-001", - "title": "December Study Session", - "description": "Final exam prep session with free coffee and snacks", - "startTime": "2025-12-01T09:00:00.000Z", - "endTime": "2025-12-01T12:00:00.000Z", + "title": "Late Night Study Session", + "description": "Group study session with free coffee and snacks.", + "startTime": "2026-08-15T13:00:00.000Z", + "endTime": "2026-08-15T16:00:00.000Z", "location": "Hunt Library", - "categories": ["Academic", "Study"], + "categories": [ + "Academic", + "Study" + ], "organizer": { "id": "org-academic", "name": "Academic Support", @@ -1813,24 +2108,35 @@ }, "color": "#8B7FFF", "rsvpEnabled": true, - "rsvpCounts": { "going": 42, "maybe": 18, "notGoing": 3 }, + "rsvpCounts": { + "going": 42, + "maybe": 18, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 60, - "tags": ["study", "exams", "academic"], - "createdAt": "2025-11-25T10:00:00.000Z", - "updatedAt": "2025-11-25T10:00:00.000Z" + "tags": [ + "study", + "exams", + "academic" + ], + "createdAt": "2026-07-25T13:00:00.000Z", + "updatedAt": "2026-08-08T13:00:00.000Z" }, { "id": "evt-dec-002", - "title": "Holiday Cookie Decorating", - "description": "Decorate cookies and get into the holiday spirit!", - "startTime": "2025-12-01T15:00:00.000Z", - "endTime": "2025-12-01T17:00:00.000Z", + "title": "Cookie Decorating Night", + "description": "Decorate cookies and take a box home. No baking skills required.", + "startTime": "2026-08-15T19:00:00.000Z", + "endTime": "2026-08-15T21:00:00.000Z", "location": "UC Activities Room", - "categories": ["Social", "Food"], + "categories": [ + "Social", + "Food" + ], "organizer": { "id": "org-activities", "name": "Student Activities", @@ -1838,24 +2144,34 @@ }, "color": "#FF6BA8", "rsvpEnabled": true, - "rsvpCounts": { "going": 28, "maybe": 12, "notGoing": 2 }, + "rsvpCounts": { + "going": 28, + "maybe": 12, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 40, - "tags": ["holiday", "cookies", "social"], - "createdAt": "2025-11-20T10:00:00.000Z", - "updatedAt": "2025-11-20T10:00:00.000Z" + "tags": [ + "cookies", + "social" + ], + "createdAt": "2026-07-25T19:00:00.000Z", + "updatedAt": "2026-08-08T19:00:00.000Z" }, { "id": "evt-dec-003", - "title": "Winter Career Networking Mixer", - "description": "Network with alumni and recruiters before the holidays", - "startTime": "2025-12-02T17:00:00.000Z", - "endTime": "2025-12-02T19:30:00.000Z", + "title": "Alumni Career Networking Mixer", + "description": "Network with alumni and recruiters over appetizers.", + "startTime": "2026-08-15T21:00:00.000Z", + "endTime": "2026-08-15T23:30:00.000Z", "location": "Tepper Quad", - "categories": ["Career", "Networking"], + "categories": [ + "Career", + "Networking" + ], "organizer": { "id": "org-career", "name": "Career Services", @@ -1863,24 +2179,35 @@ }, "color": "#FF6B6B", "rsvpEnabled": true, - "rsvpCounts": { "going": 89, "maybe": 34, "notGoing": 8 }, + "rsvpCounts": { + "going": 89, + "maybe": 34, + "notGoing": 8 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 120, - "tags": ["networking", "career", "alumni"], - "createdAt": "2025-11-18T10:00:00.000Z", - "updatedAt": "2025-11-18T10:00:00.000Z" + "tags": [ + "networking", + "career", + "alumni" + ], + "createdAt": "2026-07-25T21:00:00.000Z", + "updatedAt": "2026-08-08T21:00:00.000Z" }, { "id": "evt-dec-004", "title": "Morning Meditation", "description": "Start your day with guided meditation and mindfulness", - "startTime": "2025-12-02T07:30:00.000Z", - "endTime": "2025-12-02T08:30:00.000Z", + "startTime": "2026-08-16T11:30:00.000Z", + "endTime": "2026-08-16T12:30:00.000Z", "location": "UC Wellness Center", - "categories": ["Wellness", "Social"], + "categories": [ + "Wellness", + "Social" + ], "organizer": { "id": "org-wellness", "name": "Wellness Club", @@ -1888,24 +2215,35 @@ }, "color": "#95E1D3", "rsvpEnabled": true, - "rsvpCounts": { "going": 15, "maybe": 8, "notGoing": 1 }, + "rsvpCounts": { + "going": 15, + "maybe": 8, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 25, - "tags": ["meditation", "wellness", "morning"], - "createdAt": "2025-11-22T10:00:00.000Z", - "updatedAt": "2025-11-22T10:00:00.000Z" + "tags": [ + "meditation", + "wellness", + "morning" + ], + "createdAt": "2026-07-26T11:30:00.000Z", + "updatedAt": "2026-08-09T11:30:00.000Z" }, { "id": "evt-dec-005", "title": "Python Workshop: Data Analysis", "description": "Learn pandas and numpy for data analysis projects", - "startTime": "2025-12-03T14:00:00.000Z", - "endTime": "2025-12-03T16:00:00.000Z", + "startTime": "2026-08-16T18:00:00.000Z", + "endTime": "2026-08-16T20:00:00.000Z", "location": "Gates 5th Floor Lab", - "categories": ["Tech", "Academic"], + "categories": [ + "Tech", + "Academic" + ], "organizer": { "id": "org-cs-club", "name": "Computer Science Club", @@ -1913,24 +2251,35 @@ }, "color": "#4ECDC4", "rsvpEnabled": true, - "rsvpCounts": { "going": 56, "maybe": 23, "notGoing": 4 }, + "rsvpCounts": { + "going": 56, + "maybe": 23, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 80, - "tags": ["python", "data", "workshop"], - "createdAt": "2025-11-19T10:00:00.000Z", - "updatedAt": "2025-11-19T10:00:00.000Z" + "tags": [ + "python", + "data", + "workshop" + ], + "createdAt": "2026-07-26T18:00:00.000Z", + "updatedAt": "2026-08-09T18:00:00.000Z" }, { "id": "evt-dec-006", "title": "Basketball Tournament", "description": "Intramural basketball tournament - sign up your team!", - "startTime": "2025-12-03T18:00:00.000Z", - "endTime": "2025-12-03T21:00:00.000Z", + "startTime": "2026-08-16T22:00:00.000Z", + "endTime": "2026-08-17T01:00:00.000Z", "location": "Highmark Center", - "categories": ["Sports", "Competition"], + "categories": [ + "Sports", + "Competition" + ], "organizer": { "id": "org-sports", "name": "Intramural Sports", @@ -1938,24 +2287,35 @@ }, "color": "#FF8C94", "rsvpEnabled": true, - "rsvpCounts": { "going": 32, "maybe": 15, "notGoing": 3 }, + "rsvpCounts": { + "going": 32, + "maybe": 15, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 50, - "tags": ["basketball", "tournament", "sports"], - "createdAt": "2025-11-17T10:00:00.000Z", - "updatedAt": "2025-11-17T10:00:00.000Z" + "tags": [ + "basketball", + "tournament", + "sports" + ], + "createdAt": "2026-07-26T22:00:00.000Z", + "updatedAt": "2026-08-09T22:00:00.000Z" }, { "id": "evt-dec-007", - "title": "Holiday Movie Marathon", - "description": "Watch classic holiday movies with hot chocolate and popcorn", - "startTime": "2025-12-04T19:00:00.000Z", - "endTime": "2025-12-04T23:00:00.000Z", + "title": "Movie Marathon Night", + "description": "Back-to-back classics with hot chocolate and popcorn.", + "startTime": "2026-08-16T23:00:00.000Z", + "endTime": "2026-08-17T03:00:00.000Z", "location": "McConomy Auditorium", - "categories": ["Entertainment", "Social"], + "categories": [ + "Entertainment", + "Social" + ], "organizer": { "id": "org-activities", "name": "Student Activities", @@ -1963,24 +2323,34 @@ }, "color": "#FFD93D", "rsvpEnabled": true, - "rsvpCounts": { "going": 78, "maybe": 31, "notGoing": 6 }, + "rsvpCounts": { + "going": 78, + "maybe": 31, + "notGoing": 6 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 150, - "tags": ["movies", "holiday", "social"], - "createdAt": "2025-11-21T10:00:00.000Z", - "updatedAt": "2025-11-21T10:00:00.000Z" - }, - { + "tags": [ + "movies", + "social" + ], + "createdAt": "2026-07-26T23:00:00.000Z", + "updatedAt": "2026-08-09T23:00:00.000Z" + }, + { "id": "evt-dec-008", "title": "Final Project Help Session", "description": "Get help with your final projects from TAs and peers", - "startTime": "2025-12-04T10:00:00.000Z", - "endTime": "2025-12-04T13:00:00.000Z", + "startTime": "2026-08-17T14:00:00.000Z", + "endTime": "2026-08-17T17:00:00.000Z", "location": "Gates 4th Floor", - "categories": ["Academic", "Study"], + "categories": [ + "Academic", + "Study" + ], "organizer": { "id": "user-005", "name": "TA Office Hours", @@ -1988,24 +2358,35 @@ }, "color": "#8B7FFF", "rsvpEnabled": true, - "rsvpCounts": { "going": 24, "maybe": 11, "notGoing": 2 }, + "rsvpCounts": { + "going": 24, + "maybe": 11, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": false, "isSocialEvent": false, "capacity": 35, - "tags": ["projects", "help", "academic"], - "createdAt": "2025-11-23T10:00:00.000Z", - "updatedAt": "2025-11-23T10:00:00.000Z" + "tags": [ + "projects", + "help", + "academic" + ], + "createdAt": "2026-07-27T14:00:00.000Z", + "updatedAt": "2026-08-10T14:00:00.000Z" }, { "id": "evt-dec-009", - "title": "Holiday Potluck Dinner", - "description": "Bring a dish to share! Celebrate the end of the semester together", - "startTime": "2025-12-05T18:00:00.000Z", - "endTime": "2025-12-05T21:00:00.000Z", + "title": "International Potluck Dinner", + "description": "Bring a dish to share and try food from across campus.", + "startTime": "2026-08-17T22:00:00.000Z", + "endTime": "2026-08-18T01:00:00.000Z", "location": "UC Ballroom", - "categories": ["Food", "Social"], + "categories": [ + "Food", + "Social" + ], "organizer": { "id": "org-dining", "name": "Dining Services", @@ -2013,24 +2394,34 @@ }, "color": "#FFA07A", "rsvpEnabled": true, - "rsvpCounts": { "going": 134, "maybe": 56, "notGoing": 9 }, + "rsvpCounts": { + "going": 134, + "maybe": 56, + "notGoing": 9 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 200, - "tags": ["potluck", "food", "holiday"], - "createdAt": "2025-11-16T10:00:00.000Z", - "updatedAt": "2025-11-16T10:00:00.000Z" + "tags": [ + "potluck", + "food" + ], + "createdAt": "2026-07-27T22:00:00.000Z", + "updatedAt": "2026-08-10T22:00:00.000Z" }, { "id": "evt-dec-010", - "title": "Gift Wrapping Workshop", - "description": "Learn to wrap gifts beautifully for the holidays", - "startTime": "2025-12-05T14:00:00.000Z", - "endTime": "2025-12-05T16:00:00.000Z", + "title": "Paper Craft Workshop", + "description": "Learn folding and wrapping techniques. Materials provided.", + "startTime": "2026-08-17T18:00:00.000Z", + "endTime": "2026-08-17T20:00:00.000Z", "location": "Hunt Library Study Room", - "categories": ["Social", "Fun"], + "categories": [ + "Social", + "Fun" + ], "organizer": { "id": "user-006", "name": "Sarah Johnson", @@ -2038,24 +2429,34 @@ }, "color": "#FF6BA8", "rsvpEnabled": true, - "rsvpCounts": { "going": 19, "maybe": 9, "notGoing": 1 }, + "rsvpCounts": { + "going": 19, + "maybe": 9, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": false, "isSocialEvent": true, "capacity": 30, - "tags": ["gifts", "holiday", "workshop"], - "createdAt": "2025-11-24T10:00:00.000Z", - "updatedAt": "2025-11-24T10:00:00.000Z" + "tags": [ + "gifts", + "workshop" + ], + "createdAt": "2026-07-27T18:00:00.000Z", + "updatedAt": "2026-08-10T18:00:00.000Z" }, { "id": "evt-dec-011", - "title": "Winter Break Planning Session", - "description": "Discuss travel plans, internships, and break activities", - "startTime": "2025-12-06T11:00:00.000Z", - "endTime": "2025-12-06T12:30:00.000Z", + "title": "Break & Travel Planning Session", + "description": "Compare travel plans, internships, and break activities.", + "startTime": "2026-08-17T15:00:00.000Z", + "endTime": "2026-08-17T16:30:00.000Z", "location": "Tepper Quad", - "categories": ["Social", "Networking"], + "categories": [ + "Social", + "Networking" + ], "organizer": { "id": "org-student-gov", "name": "Student Government", @@ -2063,24 +2464,35 @@ }, "color": "#4ECDC4", "rsvpEnabled": true, - "rsvpCounts": { "going": 37, "maybe": 18, "notGoing": 4 }, + "rsvpCounts": { + "going": 37, + "maybe": 18, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 50, - "tags": ["planning", "break", "social"], - "createdAt": "2025-11-26T10:00:00.000Z", - "updatedAt": "2025-11-26T10:00:00.000Z" + "tags": [ + "planning", + "break", + "social" + ], + "createdAt": "2026-07-27T15:00:00.000Z", + "updatedAt": "2026-08-10T15:00:00.000Z" }, { "id": "evt-dec-012", "title": "Late Night Study Group", - "description": "Study together for finals - snacks and coffee provided", - "startTime": "2025-12-06T20:00:00.000Z", - "endTime": "2025-12-07T01:00:00.000Z", + "description": "Study together late — snacks and coffee provided.", + "startTime": "2026-08-19T00:00:00.000Z", + "endTime": "2026-08-19T05:00:00.000Z", "location": "Hunt Library 24/7 Study Space", - "categories": ["Academic", "Study"], + "categories": [ + "Academic", + "Study" + ], "organizer": { "id": "user-007", "name": "Study Group Leaders", @@ -2088,24 +2500,34 @@ }, "color": "#8B7FFF", "rsvpEnabled": true, - "rsvpCounts": { "going": 28, "maybe": 14, "notGoing": 3 }, + "rsvpCounts": { + "going": 28, + "maybe": 14, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": false, "isSocialEvent": true, "capacity": 40, - "tags": ["study", "finals", "late-night"], - "createdAt": "2025-11-27T10:00:00.000Z", - "updatedAt": "2025-11-27T10:00:00.000Z" + "tags": [ + "study", + "late-night" + ], + "createdAt": "2026-07-29T00:00:00.000Z", + "updatedAt": "2026-08-12T00:00:00.000Z" }, { "id": "evt-dec-013", - "title": "Holiday Card Making", - "description": "Create handmade holiday cards for friends and family", - "startTime": "2025-12-07T13:00:00.000Z", - "endTime": "2025-12-07T15:30:00.000Z", + "title": "Card Making Workshop", + "description": "Create handmade cards for friends and family.", + "startTime": "2026-08-18T17:00:00.000Z", + "endTime": "2026-08-18T19:30:00.000Z", "location": "UC Arts & Crafts Room", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-arts", "name": "Arts Club", @@ -2113,24 +2535,34 @@ }, "color": "#FF6BA8", "rsvpEnabled": true, - "rsvpCounts": { "going": 22, "maybe": 10, "notGoing": 2 }, + "rsvpCounts": { + "going": 22, + "maybe": 10, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 35, - "tags": ["cards", "arts", "holiday"], - "createdAt": "2025-11-28T10:00:00.000Z", - "updatedAt": "2025-11-28T10:00:00.000Z" + "tags": [ + "cards", + "arts" + ], + "createdAt": "2026-07-28T17:00:00.000Z", + "updatedAt": "2026-08-11T17:00:00.000Z" }, { "id": "evt-dec-014", "title": "End of Semester Celebration", "description": "Celebrate finishing the semester! Food, music, and fun", - "startTime": "2025-12-07T17:00:00.000Z", - "endTime": "2025-12-07T20:00:00.000Z", + "startTime": "2026-08-18T21:00:00.000Z", + "endTime": "2026-08-19T00:00:00.000Z", "location": "Wiegand Gymnasium", - "categories": ["Social", "Fun"], + "categories": [ + "Social", + "Fun" + ], "organizer": { "id": "org-activities", "name": "Student Activities", @@ -2138,24 +2570,35 @@ }, "color": "#FFD93D", "rsvpEnabled": true, - "rsvpCounts": { "going": 156, "maybe": 67, "notGoing": 12 }, + "rsvpCounts": { + "going": 156, + "maybe": 67, + "notGoing": 12 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 300, - "tags": ["celebration", "semester", "social"], - "createdAt": "2025-11-15T10:00:00.000Z", - "updatedAt": "2025-11-15T10:00:00.000Z" + "tags": [ + "celebration", + "semester", + "social" + ], + "createdAt": "2026-07-28T21:00:00.000Z", + "updatedAt": "2026-08-11T21:00:00.000Z" }, { "id": "evt-dec-015", "title": "AI & Machine Learning Workshop", "description": "Hands-on workshop on building neural networks and ML models", - "startTime": "2025-12-01T13:00:00.000Z", - "endTime": "2025-12-01T16:00:00.000Z", + "startTime": "2026-08-18T17:00:00.000Z", + "endTime": "2026-08-18T20:00:00.000Z", "location": "Gates Hillman Center 4401", - "categories": ["Tech", "Academic"], + "categories": [ + "Tech", + "Academic" + ], "organizer": { "id": "org-ai-club", "name": "AI Club", @@ -2163,24 +2606,37 @@ }, "color": "#9B59B6", "rsvpEnabled": true, - "rsvpCounts": { "going": 89, "maybe": 34, "notGoing": 5 }, + "rsvpCounts": { + "going": 89, + "maybe": 34, + "notGoing": 5 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 100, - "tags": ["ai", "machine-learning", "coding", "tech", "workshop"], - "createdAt": "2025-11-20T10:00:00.000Z", - "updatedAt": "2025-11-20T10:00:00.000Z" + "tags": [ + "ai", + "machine-learning", + "coding", + "tech", + "workshop" + ], + "createdAt": "2026-07-28T17:00:00.000Z", + "updatedAt": "2026-08-11T17:00:00.000Z" }, { "id": "evt-dec-016", "title": "Yoga & Meditation Session", "description": "Relax and de-stress with guided yoga and meditation", - "startTime": "2025-12-01T18:00:00.000Z", - "endTime": "2025-12-01T19:30:00.000Z", + "startTime": "2026-08-19T22:00:00.000Z", + "endTime": "2026-08-19T23:30:00.000Z", "location": "UC Fitness Center", - "categories": ["Wellness", "Health"], + "categories": [ + "Wellness", + "Health" + ], "organizer": { "id": "org-wellness", "name": "Wellness Center", @@ -2188,24 +2644,37 @@ }, "color": "#2ECC71", "rsvpEnabled": true, - "rsvpCounts": { "going": 45, "maybe": 18, "notGoing": 2 }, + "rsvpCounts": { + "going": 45, + "maybe": 18, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 50, - "tags": ["yoga", "meditation", "wellness", "mindfulness", "stress-relief"], - "createdAt": "2025-11-18T10:00:00.000Z", - "updatedAt": "2025-11-18T10:00:00.000Z" + "tags": [ + "yoga", + "meditation", + "wellness", + "mindfulness", + "stress-relief" + ], + "createdAt": "2026-07-29T22:00:00.000Z", + "updatedAt": "2026-08-12T22:00:00.000Z" }, { "id": "evt-dec-017", "title": "Photography Walk", "description": "Explore campus and practice photography techniques", - "startTime": "2025-12-02T10:00:00.000Z", - "endTime": "2025-12-02T12:00:00.000Z", + "startTime": "2026-08-19T14:00:00.000Z", + "endTime": "2026-08-19T16:00:00.000Z", "location": "Meet at The Fence", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "user-008", "name": "Photography Club", @@ -2213,24 +2682,37 @@ }, "color": "#E74C3C", "rsvpEnabled": true, - "rsvpCounts": { "going": 32, "maybe": 15, "notGoing": 3 }, + "rsvpCounts": { + "going": 32, + "maybe": 15, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": false, "isSocialEvent": true, "capacity": 40, - "tags": ["photography", "arts", "outdoor", "creative", "camera"], - "createdAt": "2025-11-22T10:00:00.000Z", - "updatedAt": "2025-11-22T10:00:00.000Z" + "tags": [ + "photography", + "arts", + "outdoor", + "creative", + "camera" + ], + "createdAt": "2026-07-29T14:00:00.000Z", + "updatedAt": "2026-08-12T14:00:00.000Z" }, { "id": "evt-dec-018", "title": "Entrepreneurship Pitch Night", "description": "Students pitch startup ideas to judges and investors", - "startTime": "2025-12-02T19:00:00.000Z", - "endTime": "2025-12-02T22:00:00.000Z", + "startTime": "2026-08-19T23:00:00.000Z", + "endTime": "2026-08-20T02:00:00.000Z", "location": "Tepper School of Business", - "categories": ["Career", "Networking"], + "categories": [ + "Career", + "Networking" + ], "organizer": { "id": "org-entrepreneurship", "name": "Entrepreneurship Club", @@ -2238,24 +2720,37 @@ }, "color": "#3498DB", "rsvpEnabled": true, - "rsvpCounts": { "going": 112, "maybe": 45, "notGoing": 8 }, + "rsvpCounts": { + "going": 112, + "maybe": 45, + "notGoing": 8 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 150, - "tags": ["entrepreneurship", "startup", "pitch", "business", "networking"], - "createdAt": "2025-11-19T10:00:00.000Z", - "updatedAt": "2025-11-19T10:00:00.000Z" + "tags": [ + "entrepreneurship", + "startup", + "pitch", + "business", + "networking" + ], + "createdAt": "2026-07-29T23:00:00.000Z", + "updatedAt": "2026-08-12T23:00:00.000Z" }, { "id": "evt-dec-019", "title": "Board Game Night", "description": "Play board games, card games, and tabletop RPGs", - "startTime": "2025-12-03T19:00:00.000Z", - "endTime": "2025-12-03T23:00:00.000Z", + "startTime": "2026-08-19T23:00:00.000Z", + "endTime": "2026-08-20T03:00:00.000Z", "location": "UC Game Room", - "categories": ["Social", "Fun"], + "categories": [ + "Social", + "Fun" + ], "organizer": { "id": "org-gaming", "name": "Gaming Club", @@ -2263,24 +2758,37 @@ }, "color": "#F39C12", "rsvpEnabled": true, - "rsvpCounts": { "going": 67, "maybe": 28, "notGoing": 4 }, + "rsvpCounts": { + "going": 67, + "maybe": 28, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 80, - "tags": ["gaming", "board-games", "social", "fun", "tabletop"], - "createdAt": "2025-11-21T10:00:00.000Z", - "updatedAt": "2025-11-21T10:00:00.000Z" + "tags": [ + "gaming", + "board-games", + "social", + "fun", + "tabletop" + ], + "createdAt": "2026-07-29T23:00:00.000Z", + "updatedAt": "2026-08-12T23:00:00.000Z" }, { "id": "evt-dec-020", - "title": "Cooking Class: Holiday Treats", - "description": "Learn to bake cookies, pies, and other holiday desserts", - "startTime": "2025-12-03T14:00:00.000Z", - "endTime": "2025-12-03T17:00:00.000Z", + "title": "Cooking Class: Baking Basics", + "description": "Learn to bake cookies, pies, and other desserts from scratch.", + "startTime": "2026-08-20T18:00:00.000Z", + "endTime": "2026-08-20T21:00:00.000Z", "location": "UC Kitchen", - "categories": ["Food", "Social"], + "categories": [ + "Food", + "Social" + ], "organizer": { "id": "org-cooking", "name": "Cooking Club", @@ -2288,24 +2796,36 @@ }, "color": "#E67E22", "rsvpEnabled": true, - "rsvpCounts": { "going": 41, "maybe": 19, "notGoing": 2 }, + "rsvpCounts": { + "going": 41, + "maybe": 19, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 50, - "tags": ["cooking", "baking", "food", "holiday", "desserts"], - "createdAt": "2025-11-23T10:00:00.000Z", - "updatedAt": "2025-11-23T10:00:00.000Z" + "tags": [ + "cooking", + "baking", + "food", + "desserts" + ], + "createdAt": "2026-07-30T18:00:00.000Z", + "updatedAt": "2026-08-13T18:00:00.000Z" }, { "id": "evt-dec-021", "title": "Debate Tournament", "description": "Competitive debate on current events and policy", - "startTime": "2025-12-04T09:00:00.000Z", - "endTime": "2025-12-04T17:00:00.000Z", + "startTime": "2026-08-20T13:00:00.000Z", + "endTime": "2026-08-20T21:00:00.000Z", "location": "Baker Hall", - "categories": ["Academic", "Social"], + "categories": [ + "Academic", + "Social" + ], "organizer": { "id": "org-debate", "name": "Debate Team", @@ -2313,24 +2833,37 @@ }, "color": "#1ABC9C", "rsvpEnabled": true, - "rsvpCounts": { "going": 56, "maybe": 22, "notGoing": 6 }, + "rsvpCounts": { + "going": 56, + "maybe": 22, + "notGoing": 6 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 100, - "tags": ["debate", "academic", "competition", "public-speaking", "policy"], - "createdAt": "2025-11-17T10:00:00.000Z", - "updatedAt": "2025-11-17T10:00:00.000Z" + "tags": [ + "debate", + "academic", + "competition", + "public-speaking", + "policy" + ], + "createdAt": "2026-07-30T13:00:00.000Z", + "updatedAt": "2026-08-13T13:00:00.000Z" }, { "id": "evt-dec-022", "title": "Robotics Demo Day", "description": "See student-built robots in action and learn about robotics", - "startTime": "2025-12-04T15:00:00.000Z", - "endTime": "2025-12-04T18:00:00.000Z", + "startTime": "2026-08-20T19:00:00.000Z", + "endTime": "2026-08-20T22:00:00.000Z", "location": "Newell-Simon Hall", - "categories": ["Tech", "Academic"], + "categories": [ + "Tech", + "Academic" + ], "organizer": { "id": "org-robotics", "name": "Robotics Club", @@ -2338,24 +2871,37 @@ }, "color": "#34495E", "rsvpEnabled": true, - "rsvpCounts": { "going": 78, "maybe": 31, "notGoing": 4 }, + "rsvpCounts": { + "going": 78, + "maybe": 31, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 120, - "tags": ["robotics", "tech", "engineering", "demos", "hands-on"], - "createdAt": "2025-11-25T10:00:00.000Z", - "updatedAt": "2025-11-25T10:00:00.000Z" + "tags": [ + "robotics", + "tech", + "engineering", + "demos", + "hands-on" + ], + "createdAt": "2026-07-30T19:00:00.000Z", + "updatedAt": "2026-08-13T19:00:00.000Z" }, { "id": "evt-dec-023", "title": "Language Exchange Meetup", "description": "Practice languages with native speakers - Spanish, French, Chinese, Japanese, and more", - "startTime": "2025-12-05T16:00:00.000Z", - "endTime": "2025-12-05T18:00:00.000Z", + "startTime": "2026-08-20T20:00:00.000Z", + "endTime": "2026-08-20T22:00:00.000Z", "location": "Hunt Library Study Room 3", - "categories": ["Social", "Academic"], + "categories": [ + "Social", + "Academic" + ], "organizer": { "id": "org-languages", "name": "Language Exchange Club", @@ -2363,24 +2909,37 @@ }, "color": "#16A085", "rsvpEnabled": true, - "rsvpCounts": { "going": 54, "maybe": 24, "notGoing": 3 }, + "rsvpCounts": { + "going": 54, + "maybe": 24, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 60, - "tags": ["language", "exchange", "multilingual", "social", "learning"], - "createdAt": "2025-11-26T10:00:00.000Z", - "updatedAt": "2025-11-26T10:00:00.000Z" + "tags": [ + "language", + "exchange", + "multilingual", + "social", + "learning" + ], + "createdAt": "2026-07-30T20:00:00.000Z", + "updatedAt": "2026-08-13T20:00:00.000Z" }, { "id": "evt-dec-024", "title": "Theater Performance: One-Act Plays", "description": "Student-written and performed one-act plays", - "startTime": "2025-12-05T19:30:00.000Z", - "endTime": "2025-12-05T22:00:00.000Z", + "startTime": "2026-08-21T23:30:00.000Z", + "endTime": "2026-08-22T02:00:00.000Z", "location": "Kresge Theater", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-theater", "name": "Theater Club", @@ -2388,24 +2947,37 @@ }, "color": "#C0392B", "rsvpEnabled": true, - "rsvpCounts": { "going": 98, "maybe": 42, "notGoing": 7 }, + "rsvpCounts": { + "going": 98, + "maybe": 42, + "notGoing": 7 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 200, - "tags": ["theater", "performance", "arts", "drama", "entertainment"], - "createdAt": "2025-11-20T10:00:00.000Z", - "updatedAt": "2025-11-20T10:00:00.000Z" + "tags": [ + "theater", + "performance", + "arts", + "drama", + "entertainment" + ], + "createdAt": "2026-07-31T23:30:00.000Z", + "updatedAt": "2026-08-14T23:30:00.000Z" }, { "id": "evt-dec-025", "title": "Volunteer Day: Community Service", "description": "Help local community organizations - food bank, shelter, and more", - "startTime": "2025-12-06T08:00:00.000Z", - "endTime": "2025-12-06T14:00:00.000Z", + "startTime": "2026-08-21T12:00:00.000Z", + "endTime": "2026-08-21T18:00:00.000Z", "location": "Meet at UC Main Entrance", - "categories": ["Social", "Volunteering"], + "categories": [ + "Social", + "Volunteering" + ], "organizer": { "id": "org-volunteer", "name": "Community Service Club", @@ -2413,24 +2985,37 @@ }, "color": "#27AE60", "rsvpEnabled": true, - "rsvpCounts": { "going": 73, "maybe": 29, "notGoing": 5 }, + "rsvpCounts": { + "going": 73, + "maybe": 29, + "notGoing": 5 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 100, - "tags": ["volunteering", "community", "service", "charity", "giving-back"], - "createdAt": "2025-11-18T10:00:00.000Z", - "updatedAt": "2025-11-18T10:00:00.000Z" + "tags": [ + "volunteering", + "community", + "service", + "charity", + "giving-back" + ], + "createdAt": "2026-07-31T12:00:00.000Z", + "updatedAt": "2026-08-14T12:00:00.000Z" }, { "id": "evt-dec-026", "title": "Hackathon Kickoff", "description": "24-hour coding competition - build something awesome!", - "startTime": "2025-12-06T10:00:00.000Z", - "endTime": "2025-12-07T10:00:00.000Z", + "startTime": "2026-08-21T14:00:00.000Z", + "endTime": "2026-08-22T14:00:00.000Z", "location": "Gates Hillman Center", - "categories": ["Tech", "Academic"], + "categories": [ + "Tech", + "Academic" + ], "organizer": { "id": "org-hackathon", "name": "Hackathon Organizers", @@ -2438,24 +3023,37 @@ }, "color": "#8E44AD", "rsvpEnabled": true, - "rsvpCounts": { "going": 145, "maybe": 58, "notGoing": 12 }, + "rsvpCounts": { + "going": 145, + "maybe": 58, + "notGoing": 12 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 200, - "tags": ["hackathon", "coding", "tech", "competition", "programming"], - "createdAt": "2025-11-15T10:00:00.000Z", - "updatedAt": "2025-11-15T10:00:00.000Z" + "tags": [ + "hackathon", + "coding", + "tech", + "competition", + "programming" + ], + "createdAt": "2026-07-31T14:00:00.000Z", + "updatedAt": "2026-08-14T14:00:00.000Z" }, { "id": "evt-dec-027", "title": "Poetry Slam", "description": "Share original poetry or just listen to amazing performances", - "startTime": "2025-12-06T19:00:00.000Z", - "endTime": "2025-12-06T21:30:00.000Z", + "startTime": "2026-08-21T23:00:00.000Z", + "endTime": "2026-08-22T01:30:00.000Z", "location": "UC Coffeehouse", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-poetry", "name": "Poetry Club", @@ -2463,24 +3061,37 @@ }, "color": "#D35400", "rsvpEnabled": true, - "rsvpCounts": { "going": 38, "maybe": 16, "notGoing": 2 }, + "rsvpCounts": { + "going": 38, + "maybe": 16, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 50, - "tags": ["poetry", "arts", "performance", "creative", "spoken-word"], - "createdAt": "2025-11-24T10:00:00.000Z", - "updatedAt": "2025-11-24T10:00:00.000Z" + "tags": [ + "poetry", + "arts", + "performance", + "creative", + "spoken-word" + ], + "createdAt": "2026-07-31T23:00:00.000Z", + "updatedAt": "2026-08-14T23:00:00.000Z" }, { "id": "evt-dec-028", "title": "Sustainability Workshop", "description": "Learn about climate change, recycling, and sustainable living", - "startTime": "2025-12-07T10:00:00.000Z", - "endTime": "2025-12-07T12:00:00.000Z", + "startTime": "2026-08-22T14:00:00.000Z", + "endTime": "2026-08-22T16:00:00.000Z", "location": "Porter Hall", - "categories": ["Academic", "Social"], + "categories": [ + "Academic", + "Social" + ], "organizer": { "id": "org-sustainability", "name": "Sustainability Club", @@ -2488,24 +3099,37 @@ }, "color": "#229954", "rsvpEnabled": true, - "rsvpCounts": { "going": 62, "maybe": 25, "notGoing": 4 }, + "rsvpCounts": { + "going": 62, + "maybe": 25, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 80, - "tags": ["sustainability", "environment", "climate", "green", "eco-friendly"], - "createdAt": "2025-11-22T10:00:00.000Z", - "updatedAt": "2025-11-22T10:00:00.000Z" + "tags": [ + "sustainability", + "environment", + "climate", + "green", + "eco-friendly" + ], + "createdAt": "2026-08-01T14:00:00.000Z", + "updatedAt": "2026-08-15T14:00:00.000Z" }, { "id": "evt-dec-029", "title": "Dance Workshop: Hip-Hop", "description": "Learn hip-hop dance moves and choreography", - "startTime": "2025-12-07T15:00:00.000Z", - "endTime": "2025-12-07T17:00:00.000Z", + "startTime": "2026-08-22T19:00:00.000Z", + "endTime": "2026-08-22T21:00:00.000Z", "location": "UC Dance Studio", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-dance", "name": "Dance Club", @@ -2513,24 +3137,37 @@ }, "color": "#E91E63", "rsvpEnabled": true, - "rsvpCounts": { "going": 51, "maybe": 21, "notGoing": 3 }, + "rsvpCounts": { + "going": 51, + "maybe": 21, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 60, - "tags": ["dance", "hip-hop", "arts", "fitness", "music"], - "createdAt": "2025-11-27T10:00:00.000Z", - "updatedAt": "2025-11-27T10:00:00.000Z" + "tags": [ + "dance", + "hip-hop", + "arts", + "fitness", + "music" + ], + "createdAt": "2026-08-01T19:00:00.000Z", + "updatedAt": "2026-08-15T19:00:00.000Z" }, { "id": "evt-dec-030", "title": "Music Jam Session", "description": "Bring your instrument and jam with other musicians", - "startTime": "2025-12-01T20:00:00.000Z", - "endTime": "2025-12-01T23:00:00.000Z", + "startTime": "2026-08-23T00:00:00.000Z", + "endTime": "2026-08-23T03:00:00.000Z", "location": "UC Music Room", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-music", "name": "Music Club", @@ -2538,24 +3175,37 @@ }, "color": "#9B59B6", "rsvpEnabled": true, - "rsvpCounts": { "going": 43, "maybe": 18, "notGoing": 2 }, + "rsvpCounts": { + "going": 43, + "maybe": 18, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 50, - "tags": ["music", "jam", "instruments", "arts", "collaboration"], - "createdAt": "2025-11-19T10:00:00.000Z", - "updatedAt": "2025-11-19T10:00:00.000Z" + "tags": [ + "music", + "jam", + "instruments", + "arts", + "collaboration" + ], + "createdAt": "2026-08-02T00:00:00.000Z", + "updatedAt": "2026-08-16T00:00:00.000Z" }, { "id": "evt-dec-031", "title": "Cybersecurity Workshop", "description": "Learn about encryption, network security, and ethical hacking", - "startTime": "2025-12-02T14:00:00.000Z", - "endTime": "2025-12-02T17:00:00.000Z", + "startTime": "2026-08-22T18:00:00.000Z", + "endTime": "2026-08-22T21:00:00.000Z", "location": "Gates Hillman Center 4307", - "categories": ["Tech", "Academic"], + "categories": [ + "Tech", + "Academic" + ], "organizer": { "id": "org-cyber", "name": "Cybersecurity Club", @@ -2563,24 +3213,37 @@ }, "color": "#2C3E50", "rsvpEnabled": true, - "rsvpCounts": { "going": 71, "maybe": 28, "notGoing": 5 }, + "rsvpCounts": { + "going": 71, + "maybe": 28, + "notGoing": 5 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 90, - "tags": ["cybersecurity", "security", "tech", "hacking", "encryption"], - "createdAt": "2025-11-21T10:00:00.000Z", - "updatedAt": "2025-11-21T10:00:00.000Z" + "tags": [ + "cybersecurity", + "security", + "tech", + "hacking", + "encryption" + ], + "createdAt": "2026-08-01T18:00:00.000Z", + "updatedAt": "2026-08-15T18:00:00.000Z" }, { "id": "evt-dec-032", "title": "Fitness Bootcamp", "description": "High-intensity workout session - all fitness levels welcome", - "startTime": "2025-12-03T07:00:00.000Z", - "endTime": "2025-12-03T08:30:00.000Z", + "startTime": "2026-08-23T11:00:00.000Z", + "endTime": "2026-08-23T12:30:00.000Z", "location": "UC Fitness Center", - "categories": ["Sports", "Health"], + "categories": [ + "Sports", + "Health" + ], "organizer": { "id": "org-fitness", "name": "Fitness Club", @@ -2588,24 +3251,37 @@ }, "color": "#E74C3C", "rsvpEnabled": true, - "rsvpCounts": { "going": 59, "maybe": 23, "notGoing": 4 }, + "rsvpCounts": { + "going": 59, + "maybe": 23, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 70, - "tags": ["fitness", "workout", "exercise", "health", "bootcamp"], - "createdAt": "2025-11-23T10:00:00.000Z", - "updatedAt": "2025-11-23T10:00:00.000Z" + "tags": [ + "fitness", + "workout", + "exercise", + "health", + "bootcamp" + ], + "createdAt": "2026-08-02T11:00:00.000Z", + "updatedAt": "2026-08-16T11:00:00.000Z" }, { "id": "evt-dec-033", "title": "Travel Planning Session", "description": "Share travel tips, plan trips, and learn about study abroad programs", - "startTime": "2025-12-04T16:00:00.000Z", - "endTime": "2025-12-04T18:00:00.000Z", + "startTime": "2026-08-23T20:00:00.000Z", + "endTime": "2026-08-23T22:00:00.000Z", "location": "Hunt Library Study Room 2", - "categories": ["Social", "Networking"], + "categories": [ + "Social", + "Networking" + ], "organizer": { "id": "org-travel", "name": "Travel Club", @@ -2613,24 +3289,37 @@ }, "color": "#3498DB", "rsvpEnabled": true, - "rsvpCounts": { "going": 48, "maybe": 20, "notGoing": 3 }, + "rsvpCounts": { + "going": 48, + "maybe": 20, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 60, - "tags": ["travel", "study-abroad", "adventure", "planning", "networking"], - "createdAt": "2025-11-25T10:00:00.000Z", - "updatedAt": "2025-11-25T10:00:00.000Z" + "tags": [ + "travel", + "study-abroad", + "adventure", + "planning", + "networking" + ], + "createdAt": "2026-08-02T20:00:00.000Z", + "updatedAt": "2026-08-16T20:00:00.000Z" }, { "id": "evt-dec-034", "title": "Video Game Tournament", "description": "Competitive gaming tournament - multiple games and prizes", - "startTime": "2025-12-07T19:00:00.000Z", - "endTime": "2025-12-07T23:00:00.000Z", + "startTime": "2026-08-23T23:00:00.000Z", + "endTime": "2026-08-24T03:00:00.000Z", "location": "UC Game Room", - "categories": ["Social", "Fun"], + "categories": [ + "Social", + "Fun" + ], "organizer": { "id": "org-esports", "name": "Esports Club", @@ -2638,24 +3327,37 @@ }, "color": "#F39C12", "rsvpEnabled": true, - "rsvpCounts": { "going": 92, "maybe": 38, "notGoing": 7 }, + "rsvpCounts": { + "going": 92, + "maybe": 38, + "notGoing": 7 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 120, - "tags": ["gaming", "esports", "tournament", "competition", "video-games"], - "createdAt": "2025-11-28T10:00:00.000Z", - "updatedAt": "2025-11-28T10:00:00.000Z" + "tags": [ + "gaming", + "esports", + "tournament", + "competition", + "video-games" + ], + "createdAt": "2026-08-02T23:00:00.000Z", + "updatedAt": "2026-08-16T23:00:00.000Z" }, { "id": "evt-dec-035", "title": "Web Development Bootcamp", "description": "Learn React, Node.js, and modern web development practices", - "startTime": "2025-12-01T10:00:00.000Z", - "endTime": "2025-12-01T15:00:00.000Z", + "startTime": "2026-08-23T14:00:00.000Z", + "endTime": "2026-08-23T19:00:00.000Z", "location": "Gates Hillman Center 4405", - "categories": ["Tech", "Academic"], + "categories": [ + "Tech", + "Academic" + ], "organizer": { "id": "org-web-dev", "name": "Web Development Club", @@ -2663,24 +3365,37 @@ }, "color": "#3498DB", "rsvpEnabled": true, - "rsvpCounts": { "going": 95, "maybe": 37, "notGoing": 6 }, + "rsvpCounts": { + "going": 95, + "maybe": 37, + "notGoing": 6 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 110, - "tags": ["web-dev", "react", "nodejs", "coding", "frontend"], - "createdAt": "2025-11-29T10:00:00.000Z", - "updatedAt": "2025-11-29T10:00:00.000Z" + "tags": [ + "web-dev", + "react", + "nodejs", + "coding", + "frontend" + ], + "createdAt": "2026-08-02T14:00:00.000Z", + "updatedAt": "2026-08-16T14:00:00.000Z" }, { "id": "evt-dec-036", "title": "Karaoke Night", "description": "Sing your heart out with friends - all skill levels welcome!", - "startTime": "2025-12-01T20:00:00.000Z", - "endTime": "2025-12-02T00:00:00.000Z", + "startTime": "2026-08-25T00:00:00.000Z", + "endTime": "2026-08-25T04:00:00.000Z", "location": "UC Coffeehouse", - "categories": ["Social", "Fun"], + "categories": [ + "Social", + "Fun" + ], "organizer": { "id": "org-entertainment", "name": "Entertainment Committee", @@ -2688,24 +3403,37 @@ }, "color": "#E91E63", "rsvpEnabled": true, - "rsvpCounts": { "going": 84, "maybe": 35, "notGoing": 5 }, + "rsvpCounts": { + "going": 84, + "maybe": 35, + "notGoing": 5 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 100, - "tags": ["karaoke", "music", "singing", "social", "fun"], - "createdAt": "2025-11-30T10:00:00.000Z", - "updatedAt": "2025-11-30T10:00:00.000Z" + "tags": [ + "karaoke", + "music", + "singing", + "social", + "fun" + ], + "createdAt": "2026-08-04T00:00:00.000Z", + "updatedAt": "2026-08-18T00:00:00.000Z" }, { "id": "evt-dec-037", "title": "Data Science Workshop", "description": "Introduction to Python, pandas, and data visualization", - "startTime": "2025-12-02T13:00:00.000Z", - "endTime": "2025-12-02T16:00:00.000Z", + "startTime": "2026-08-24T17:00:00.000Z", + "endTime": "2026-08-24T20:00:00.000Z", "location": "Gates Hillman Center 4303", - "categories": ["Tech", "Academic"], + "categories": [ + "Tech", + "Academic" + ], "organizer": { "id": "org-data-science", "name": "Data Science Club", @@ -2713,24 +3441,37 @@ }, "color": "#9B59B6", "rsvpEnabled": true, - "rsvpCounts": { "going": 76, "maybe": 30, "notGoing": 4 }, + "rsvpCounts": { + "going": 76, + "maybe": 30, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 90, - "tags": ["data-science", "python", "pandas", "analytics", "statistics"], - "createdAt": "2025-11-29T10:00:00.000Z", - "updatedAt": "2025-11-29T10:00:00.000Z" + "tags": [ + "data-science", + "python", + "pandas", + "analytics", + "statistics" + ], + "createdAt": "2026-08-03T17:00:00.000Z", + "updatedAt": "2026-08-17T17:00:00.000Z" }, { "id": "evt-dec-038", "title": "Rock Climbing Session", "description": "Indoor rock climbing for all experience levels", - "startTime": "2025-12-02T18:00:00.000Z", - "endTime": "2025-12-02T20:00:00.000Z", + "startTime": "2026-08-24T22:00:00.000Z", + "endTime": "2026-08-25T00:00:00.000Z", "location": "UC Fitness Center Climbing Wall", - "categories": ["Sports", "Health"], + "categories": [ + "Sports", + "Health" + ], "organizer": { "id": "org-climbing", "name": "Rock Climbing Club", @@ -2738,24 +3479,37 @@ }, "color": "#E74C3C", "rsvpEnabled": true, - "rsvpCounts": { "going": 48, "maybe": 19, "notGoing": 3 }, + "rsvpCounts": { + "going": 48, + "maybe": 19, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 60, - "tags": ["rock-climbing", "sports", "fitness", "adventure", "outdoor"], - "createdAt": "2025-11-30T10:00:00.000Z", - "updatedAt": "2025-11-30T10:00:00.000Z" + "tags": [ + "rock-climbing", + "sports", + "fitness", + "adventure", + "outdoor" + ], + "createdAt": "2026-08-03T22:00:00.000Z", + "updatedAt": "2026-08-17T22:00:00.000Z" }, { "id": "evt-dec-039", "title": "Creative Writing Workshop", "description": "Improve your writing skills with exercises and peer feedback", - "startTime": "2025-12-03T10:00:00.000Z", - "endTime": "2025-12-03T12:30:00.000Z", + "startTime": "2026-08-24T14:00:00.000Z", + "endTime": "2026-08-24T16:30:00.000Z", "location": "Hunt Library Study Room 1", - "categories": ["Arts", "Academic"], + "categories": [ + "Arts", + "Academic" + ], "organizer": { "id": "org-writing", "name": "Creative Writing Club", @@ -2763,24 +3517,37 @@ }, "color": "#16A085", "rsvpEnabled": true, - "rsvpCounts": { "going": 35, "maybe": 14, "notGoing": 2 }, + "rsvpCounts": { + "going": 35, + "maybe": 14, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 45, - "tags": ["writing", "creative", "literature", "arts", "storytelling"], - "createdAt": "2025-11-28T10:00:00.000Z", - "updatedAt": "2025-11-28T10:00:00.000Z" + "tags": [ + "writing", + "creative", + "literature", + "arts", + "storytelling" + ], + "createdAt": "2026-08-03T14:00:00.000Z", + "updatedAt": "2026-08-17T14:00:00.000Z" }, { "id": "evt-dec-040", "title": "Basketball Pickup Games", "description": "Casual basketball games - all skill levels welcome", - "startTime": "2025-12-03T19:00:00.000Z", - "endTime": "2025-12-03T21:00:00.000Z", + "startTime": "2026-08-25T23:00:00.000Z", + "endTime": "2026-08-26T01:00:00.000Z", "location": "Wiegand Gymnasium", - "categories": ["Sports", "Social"], + "categories": [ + "Sports", + "Social" + ], "organizer": { "id": "org-basketball", "name": "Basketball Club", @@ -2788,24 +3555,37 @@ }, "color": "#F39C12", "rsvpEnabled": true, - "rsvpCounts": { "going": 52, "maybe": 22, "notGoing": 4 }, + "rsvpCounts": { + "going": 52, + "maybe": 22, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 40, - "tags": ["basketball", "sports", "fitness", "team", "competitive"], - "createdAt": "2025-11-29T10:00:00.000Z", - "updatedAt": "2025-11-29T10:00:00.000Z" + "tags": [ + "basketball", + "sports", + "fitness", + "team", + "competitive" + ], + "createdAt": "2026-08-04T23:00:00.000Z", + "updatedAt": "2026-08-18T23:00:00.000Z" }, { "id": "evt-dec-041", "title": "3D Printing Workshop", "description": "Learn to design and print 3D objects", - "startTime": "2025-12-04T11:00:00.000Z", - "endTime": "2025-12-04T14:00:00.000Z", + "startTime": "2026-08-25T15:00:00.000Z", + "endTime": "2026-08-25T18:00:00.000Z", "location": "Hunt Library Maker Space", - "categories": ["Tech", "Arts"], + "categories": [ + "Tech", + "Arts" + ], "organizer": { "id": "org-maker", "name": "Maker Club", @@ -2813,24 +3593,37 @@ }, "color": "#8E44AD", "rsvpEnabled": true, - "rsvpCounts": { "going": 41, "maybe": 17, "notGoing": 2 }, + "rsvpCounts": { + "going": 41, + "maybe": 17, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 50, - "tags": ["3d-printing", "maker", "design", "tech", "prototyping"], - "createdAt": "2025-11-30T10:00:00.000Z", - "updatedAt": "2025-11-30T10:00:00.000Z" + "tags": [ + "3d-printing", + "maker", + "design", + "tech", + "prototyping" + ], + "createdAt": "2026-08-04T15:00:00.000Z", + "updatedAt": "2026-08-18T15:00:00.000Z" }, { "id": "evt-dec-042", - "title": "Movie Night: Holiday Classics", - "description": "Watch classic holiday movies with popcorn and hot chocolate", - "startTime": "2025-12-04T19:00:00.000Z", - "endTime": "2025-12-04T22:30:00.000Z", + "title": "Movie Night: Cult Classics", + "description": "Watch cult classics with popcorn and hot chocolate.", + "startTime": "2026-08-25T23:00:00.000Z", + "endTime": "2026-08-26T02:30:00.000Z", "location": "UC Theater", - "categories": ["Social", "Fun"], + "categories": [ + "Social", + "Fun" + ], "organizer": { "id": "org-film", "name": "Film Club", @@ -2838,24 +3631,36 @@ }, "color": "#C0392B", "rsvpEnabled": true, - "rsvpCounts": { "going": 108, "maybe": 44, "notGoing": 8 }, + "rsvpCounts": { + "going": 108, + "maybe": 44, + "notGoing": 8 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 150, - "tags": ["movies", "film", "holiday", "entertainment", "social"], - "createdAt": "2025-11-28T10:00:00.000Z", - "updatedAt": "2025-11-28T10:00:00.000Z" + "tags": [ + "movies", + "film", + "entertainment", + "social" + ], + "createdAt": "2026-08-04T23:00:00.000Z", + "updatedAt": "2026-08-18T23:00:00.000Z" }, { "id": "evt-dec-043", "title": "Blockchain & Cryptocurrency Talk", "description": "Learn about blockchain technology and cryptocurrency trends", - "startTime": "2025-12-05T10:00:00.000Z", - "endTime": "2025-12-05T12:00:00.000Z", + "startTime": "2026-08-25T14:00:00.000Z", + "endTime": "2026-08-25T16:00:00.000Z", "location": "Tepper School of Business", - "categories": ["Tech", "Career"], + "categories": [ + "Tech", + "Career" + ], "organizer": { "id": "org-blockchain", "name": "Blockchain Club", @@ -2863,24 +3668,37 @@ }, "color": "#34495E", "rsvpEnabled": true, - "rsvpCounts": { "going": 68, "maybe": 27, "notGoing": 5 }, + "rsvpCounts": { + "going": 68, + "maybe": 27, + "notGoing": 5 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 85, - "tags": ["blockchain", "cryptocurrency", "crypto", "tech", "finance"], - "createdAt": "2025-11-29T10:00:00.000Z", - "updatedAt": "2025-11-29T10:00:00.000Z" + "tags": [ + "blockchain", + "cryptocurrency", + "crypto", + "tech", + "finance" + ], + "createdAt": "2026-08-04T14:00:00.000Z", + "updatedAt": "2026-08-18T14:00:00.000Z" }, { "id": "evt-dec-044", "title": "Origami Workshop", "description": "Learn the art of paper folding - create beautiful origami pieces", - "startTime": "2025-12-05T15:00:00.000Z", - "endTime": "2025-12-05T17:00:00.000Z", + "startTime": "2026-08-26T19:00:00.000Z", + "endTime": "2026-08-26T21:00:00.000Z", "location": "UC Arts & Crafts Room", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "user-009", "name": "Origami Enthusiasts", @@ -2888,24 +3706,37 @@ }, "color": "#FF6BA8", "rsvpEnabled": true, - "rsvpCounts": { "going": 29, "maybe": 12, "notGoing": 1 }, + "rsvpCounts": { + "going": 29, + "maybe": 12, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": false, "isSocialEvent": true, "capacity": 35, - "tags": ["origami", "arts", "crafts", "creative", "relaxing"], - "createdAt": "2025-11-30T10:00:00.000Z", - "updatedAt": "2025-11-30T10:00:00.000Z" + "tags": [ + "origami", + "arts", + "crafts", + "creative", + "relaxing" + ], + "createdAt": "2026-08-05T19:00:00.000Z", + "updatedAt": "2026-08-19T19:00:00.000Z" }, { "id": "evt-dec-045", "title": "Speed Networking Event", "description": "Meet professionals and students in quick networking sessions", - "startTime": "2025-12-06T13:00:00.000Z", - "endTime": "2025-12-06T15:30:00.000Z", + "startTime": "2026-08-26T17:00:00.000Z", + "endTime": "2026-08-26T19:30:00.000Z", "location": "Tepper Quad", - "categories": ["Career", "Networking"], + "categories": [ + "Career", + "Networking" + ], "organizer": { "id": "org-networking", "name": "Professional Development Club", @@ -2913,24 +3744,37 @@ }, "color": "#3498DB", "rsvpEnabled": true, - "rsvpCounts": { "going": 127, "maybe": 51, "notGoing": 9 }, + "rsvpCounts": { + "going": 127, + "maybe": 51, + "notGoing": 9 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 160, - "tags": ["networking", "career", "professional", "connections", "business"], - "createdAt": "2025-11-27T10:00:00.000Z", - "updatedAt": "2025-11-27T10:00:00.000Z" + "tags": [ + "networking", + "career", + "professional", + "connections", + "business" + ], + "createdAt": "2026-08-05T17:00:00.000Z", + "updatedAt": "2026-08-19T17:00:00.000Z" }, { "id": "evt-dec-046", "title": "Chess Tournament", "description": "Competitive chess tournament with prizes for winners", - "startTime": "2025-12-06T14:00:00.000Z", - "endTime": "2025-12-06T18:00:00.000Z", + "startTime": "2026-08-26T18:00:00.000Z", + "endTime": "2026-08-26T22:00:00.000Z", "location": "UC Game Room", - "categories": ["Social", "Fun"], + "categories": [ + "Social", + "Fun" + ], "organizer": { "id": "org-chess", "name": "Chess Club", @@ -2938,24 +3782,37 @@ }, "color": "#2C3E50", "rsvpEnabled": true, - "rsvpCounts": { "going": 56, "maybe": 23, "notGoing": 4 }, + "rsvpCounts": { + "going": 56, + "maybe": 23, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 70, - "tags": ["chess", "strategy", "competition", "games", "intellectual"], - "createdAt": "2025-11-28T10:00:00.000Z", - "updatedAt": "2025-11-28T10:00:00.000Z" + "tags": [ + "chess", + "strategy", + "competition", + "games", + "intellectual" + ], + "createdAt": "2026-08-05T18:00:00.000Z", + "updatedAt": "2026-08-19T18:00:00.000Z" }, { "id": "evt-dec-047", "title": "Podcast Recording Session", "description": "Record episodes for the student podcast - guests welcome", - "startTime": "2025-12-07T11:00:00.000Z", - "endTime": "2025-12-07T13:00:00.000Z", + "startTime": "2026-08-26T15:00:00.000Z", + "endTime": "2026-08-26T17:00:00.000Z", "location": "Hunt Library Media Lab", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-podcast", "name": "Student Podcast Team", @@ -2963,24 +3820,37 @@ }, "color": "#9B59B6", "rsvpEnabled": true, - "rsvpCounts": { "going": 24, "maybe": 10, "notGoing": 1 }, + "rsvpCounts": { + "going": 24, + "maybe": 10, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 30, - "tags": ["podcast", "media", "recording", "audio", "broadcasting"], - "createdAt": "2025-11-29T10:00:00.000Z", - "updatedAt": "2025-11-29T10:00:00.000Z" + "tags": [ + "podcast", + "media", + "recording", + "audio", + "broadcasting" + ], + "createdAt": "2026-08-05T15:00:00.000Z", + "updatedAt": "2026-08-19T15:00:00.000Z" }, { "id": "evt-dec-048", "title": "Soccer Match", "description": "Friendly soccer game - all skill levels welcome", - "startTime": "2025-12-01T16:00:00.000Z", - "endTime": "2025-12-01T18:00:00.000Z", + "startTime": "2026-08-27T20:00:00.000Z", + "endTime": "2026-08-27T22:00:00.000Z", "location": "Gesling Stadium", - "categories": ["Sports", "Social"], + "categories": [ + "Sports", + "Social" + ], "organizer": { "id": "org-soccer", "name": "Soccer Club", @@ -2988,24 +3858,37 @@ }, "color": "#27AE60", "rsvpEnabled": true, - "rsvpCounts": { "going": 63, "maybe": 25, "notGoing": 5 }, + "rsvpCounts": { + "going": 63, + "maybe": 25, + "notGoing": 5 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 44, - "tags": ["soccer", "football", "sports", "team", "outdoor"], - "createdAt": "2025-11-30T10:00:00.000Z", - "updatedAt": "2025-11-30T10:00:00.000Z" + "tags": [ + "soccer", + "football", + "sports", + "team", + "outdoor" + ], + "createdAt": "2026-08-06T20:00:00.000Z", + "updatedAt": "2026-08-20T20:00:00.000Z" }, { "id": "evt-dec-049", "title": "Mental Health Support Group", "description": "Safe space to discuss stress, anxiety, and mental wellness", - "startTime": "2025-12-02T19:00:00.000Z", - "endTime": "2025-12-02T20:30:00.000Z", + "startTime": "2026-08-27T23:00:00.000Z", + "endTime": "2026-08-28T00:30:00.000Z", "location": "UC Counseling Center", - "categories": ["Wellness", "Social"], + "categories": [ + "Wellness", + "Social" + ], "organizer": { "id": "org-mental-health", "name": "Mental Health Awareness Club", @@ -3013,24 +3896,37 @@ }, "color": "#2ECC71", "rsvpEnabled": true, - "rsvpCounts": { "going": 18, "maybe": 8, "notGoing": 1 }, + "rsvpCounts": { + "going": 18, + "maybe": 8, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 25, - "tags": ["mental-health", "wellness", "support", "self-care", "therapy"], - "createdAt": "2025-11-28T10:00:00.000Z", - "updatedAt": "2025-11-28T10:00:00.000Z" + "tags": [ + "mental-health", + "wellness", + "support", + "self-care", + "therapy" + ], + "createdAt": "2026-08-06T23:00:00.000Z", + "updatedAt": "2026-08-20T23:00:00.000Z" }, { "id": "evt-dec-050", "title": "Virtual Reality Demo", "description": "Try VR headsets and experience immersive technology", - "startTime": "2025-12-03T15:00:00.000Z", - "endTime": "2025-12-03T18:00:00.000Z", + "startTime": "2026-08-27T19:00:00.000Z", + "endTime": "2026-08-27T22:00:00.000Z", "location": "Gates Hillman Center VR Lab", - "categories": ["Tech", "Social"], + "categories": [ + "Tech", + "Social" + ], "organizer": { "id": "org-vr", "name": "VR/AR Club", @@ -3038,24 +3934,37 @@ }, "color": "#8E44AD", "rsvpEnabled": true, - "rsvpCounts": { "going": 72, "maybe": 29, "notGoing": 5 }, + "rsvpCounts": { + "going": 72, + "maybe": 29, + "notGoing": 5 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 90, - "tags": ["vr", "virtual-reality", "ar", "tech", "immersive"], - "createdAt": "2025-11-29T10:00:00.000Z", - "updatedAt": "2025-11-29T10:00:00.000Z" + "tags": [ + "vr", + "virtual-reality", + "ar", + "tech", + "immersive" + ], + "createdAt": "2026-08-06T19:00:00.000Z", + "updatedAt": "2026-08-20T19:00:00.000Z" }, { "id": "evt-dec-051", "title": "Comedy Night", "description": "Stand-up comedy performances by students", - "startTime": "2025-12-04T20:00:00.000Z", - "endTime": "2025-12-04T22:00:00.000Z", + "startTime": "2026-08-28T00:00:00.000Z", + "endTime": "2026-08-28T02:00:00.000Z", "location": "UC Coffeehouse", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-comedy", "name": "Comedy Club", @@ -3063,24 +3972,37 @@ }, "color": "#F39C12", "rsvpEnabled": true, - "rsvpCounts": { "going": 89, "maybe": 36, "notGoing": 6 }, + "rsvpCounts": { + "going": 89, + "maybe": 36, + "notGoing": 6 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 110, - "tags": ["comedy", "stand-up", "entertainment", "humor", "performance"], - "createdAt": "2025-11-30T10:00:00.000Z", - "updatedAt": "2025-11-30T10:00:00.000Z" + "tags": [ + "comedy", + "stand-up", + "entertainment", + "humor", + "performance" + ], + "createdAt": "2026-08-07T00:00:00.000Z", + "updatedAt": "2026-08-21T00:00:00.000Z" }, { "id": "evt-dec-052", "title": "Investment Club Meeting", "description": "Discuss stock market trends and investment strategies", - "startTime": "2025-12-05T18:00:00.000Z", - "endTime": "2025-12-05T20:00:00.000Z", + "startTime": "2026-08-28T22:00:00.000Z", + "endTime": "2026-08-29T00:00:00.000Z", "location": "Tepper School of Business", - "categories": ["Career", "Academic"], + "categories": [ + "Career", + "Academic" + ], "organizer": { "id": "org-investment", "name": "Investment Club", @@ -3088,24 +4010,37 @@ }, "color": "#3498DB", "rsvpEnabled": true, - "rsvpCounts": { "going": 47, "maybe": 19, "notGoing": 3 }, + "rsvpCounts": { + "going": 47, + "maybe": 19, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 60, - "tags": ["investment", "finance", "stocks", "trading", "business"], - "createdAt": "2025-11-28T10:00:00.000Z", - "updatedAt": "2025-11-28T10:00:00.000Z" + "tags": [ + "investment", + "finance", + "stocks", + "trading", + "business" + ], + "createdAt": "2026-08-07T22:00:00.000Z", + "updatedAt": "2026-08-21T22:00:00.000Z" }, { "id": "evt-dec-053", "title": "Tennis Tournament", "description": "Singles and doubles tennis tournament", - "startTime": "2025-12-06T09:00:00.000Z", - "endTime": "2025-12-06T17:00:00.000Z", + "startTime": "2026-08-28T13:00:00.000Z", + "endTime": "2026-08-28T21:00:00.000Z", "location": "Tennis Courts", - "categories": ["Sports", "Social"], + "categories": [ + "Sports", + "Social" + ], "organizer": { "id": "org-tennis", "name": "Tennis Club", @@ -3113,24 +4048,37 @@ }, "color": "#27AE60", "rsvpEnabled": true, - "rsvpCounts": { "going": 34, "maybe": 14, "notGoing": 3 }, + "rsvpCounts": { + "going": 34, + "maybe": 14, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 32, - "tags": ["tennis", "sports", "competition", "outdoor", "fitness"], - "createdAt": "2025-11-29T10:00:00.000Z", - "updatedAt": "2025-11-29T10:00:00.000Z" + "tags": [ + "tennis", + "sports", + "competition", + "outdoor", + "fitness" + ], + "createdAt": "2026-08-07T13:00:00.000Z", + "updatedAt": "2026-08-21T13:00:00.000Z" }, { "id": "evt-dec-054", "title": "Study Abroad Info Session", "description": "Learn about study abroad opportunities and application process", - "startTime": "2025-12-07T14:00:00.000Z", - "endTime": "2025-12-07T16:00:00.000Z", + "startTime": "2026-08-28T18:00:00.000Z", + "endTime": "2026-08-28T20:00:00.000Z", "location": "Baker Hall", - "categories": ["Academic", "Networking"], + "categories": [ + "Academic", + "Networking" + ], "organizer": { "id": "org-study-abroad", "name": "Study Abroad Office", @@ -3138,24 +4086,37 @@ }, "color": "#16A085", "rsvpEnabled": true, - "rsvpCounts": { "going": 81, "maybe": 33, "notGoing": 6 }, + "rsvpCounts": { + "going": 81, + "maybe": 33, + "notGoing": 6 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 100, - "tags": ["study-abroad", "travel", "education", "international", "academic"], - "createdAt": "2025-11-30T10:00:00.000Z", - "updatedAt": "2025-11-30T10:00:00.000Z" + "tags": [ + "study-abroad", + "travel", + "education", + "international", + "academic" + ], + "createdAt": "2026-08-07T18:00:00.000Z", + "updatedAt": "2026-08-21T18:00:00.000Z" }, { "id": "evt-dec-055", "title": "Afternoon Coding Workshop", "description": "Build a web app from scratch - React and Node.js", - "startTime": "2025-12-06T15:00:00.000Z", - "endTime": "2025-12-06T17:00:00.000Z", + "startTime": "2026-08-28T19:00:00.000Z", + "endTime": "2026-08-28T21:00:00.000Z", "location": "Gates Hillman Center 4401", - "categories": ["Tech", "Academic"], + "categories": [ + "Tech", + "Academic" + ], "organizer": { "id": "org-coding", "name": "Coding Club", @@ -3163,24 +4124,37 @@ }, "color": "#3498DB", "rsvpEnabled": true, - "rsvpCounts": { "going": 64, "maybe": 26, "notGoing": 4 }, + "rsvpCounts": { + "going": 64, + "maybe": 26, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 80, - "tags": ["coding", "react", "web-dev", "workshop", "tech"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "coding", + "react", + "web-dev", + "workshop", + "tech" + ], + "createdAt": "2026-08-07T19:00:00.000Z", + "updatedAt": "2026-08-21T19:00:00.000Z" }, { "id": "evt-dec-056", "title": "Coffee & Study Session", "description": "Study together with free coffee and snacks", - "startTime": "2025-12-06T15:30:00.000Z", - "endTime": "2025-12-06T17:30:00.000Z", + "startTime": "2026-08-29T19:30:00.000Z", + "endTime": "2026-08-29T21:30:00.000Z", "location": "Hunt Library Study Room 2", - "categories": ["Academic", "Social"], + "categories": [ + "Academic", + "Social" + ], "organizer": { "id": "org-study", "name": "Study Group", @@ -3188,24 +4162,36 @@ }, "color": "#8B7FFF", "rsvpEnabled": true, - "rsvpCounts": { "going": 38, "maybe": 15, "notGoing": 2 }, + "rsvpCounts": { + "going": 38, + "maybe": 15, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 50, - "tags": ["study", "coffee", "academic", "social", "finals"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "study", + "coffee", + "academic", + "social" + ], + "createdAt": "2026-08-08T19:30:00.000Z", + "updatedAt": "2026-08-22T19:30:00.000Z" }, { "id": "evt-dec-057", "title": "Guitar Lessons", "description": "Learn basic guitar chords and strumming patterns", - "startTime": "2025-12-06T16:00:00.000Z", - "endTime": "2025-12-06T18:00:00.000Z", + "startTime": "2026-08-29T20:00:00.000Z", + "endTime": "2026-08-29T22:00:00.000Z", "location": "UC Music Room", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-music-lessons", "name": "Music Instruction", @@ -3213,24 +4199,37 @@ }, "color": "#9B59B6", "rsvpEnabled": true, - "rsvpCounts": { "going": 22, "maybe": 9, "notGoing": 1 }, + "rsvpCounts": { + "going": 22, + "maybe": 9, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 30, - "tags": ["guitar", "music", "lessons", "arts", "learning"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "guitar", + "music", + "lessons", + "arts", + "learning" + ], + "createdAt": "2026-08-08T20:00:00.000Z", + "updatedAt": "2026-08-22T20:00:00.000Z" }, { "id": "evt-dec-058", "title": "Product Design Workshop", "description": "Learn UX/UI design principles and create mockups", - "startTime": "2025-12-06T16:30:00.000Z", - "endTime": "2025-12-06T18:30:00.000Z", + "startTime": "2026-08-29T20:30:00.000Z", + "endTime": "2026-08-29T22:30:00.000Z", "location": "Hunt Library Design Lab", - "categories": ["Tech", "Arts"], + "categories": [ + "Tech", + "Arts" + ], "organizer": { "id": "org-design", "name": "Design Club", @@ -3238,24 +4237,37 @@ }, "color": "#E74C3C", "rsvpEnabled": true, - "rsvpCounts": { "going": 45, "maybe": 18, "notGoing": 3 }, + "rsvpCounts": { + "going": 45, + "maybe": 18, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 55, - "tags": ["design", "ux", "ui", "product", "creative"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "design", + "ux", + "ui", + "product", + "creative" + ], + "createdAt": "2026-08-08T20:30:00.000Z", + "updatedAt": "2026-08-22T20:30:00.000Z" }, { "id": "evt-dec-059", "title": "Basketball Practice", "description": "Team practice and drills", - "startTime": "2025-12-06T17:00:00.000Z", - "endTime": "2025-12-06T19:00:00.000Z", + "startTime": "2026-08-29T21:00:00.000Z", + "endTime": "2026-08-29T23:00:00.000Z", "location": "Wiegand Gymnasium", - "categories": ["Sports", "Social"], + "categories": [ + "Sports", + "Social" + ], "organizer": { "id": "org-basketball-team", "name": "Basketball Team", @@ -3263,24 +4275,37 @@ }, "color": "#F39C12", "rsvpEnabled": true, - "rsvpCounts": { "going": 28, "maybe": 11, "notGoing": 2 }, + "rsvpCounts": { + "going": 28, + "maybe": 11, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 20, - "tags": ["basketball", "sports", "practice", "team", "fitness"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "basketball", + "sports", + "practice", + "team", + "fitness" + ], + "createdAt": "2026-08-08T21:00:00.000Z", + "updatedAt": "2026-08-22T21:00:00.000Z" }, { "id": "evt-dec-060", "title": "Book Club Discussion", "description": "Discuss this month's book selection", - "startTime": "2025-12-06T15:00:00.000Z", - "endTime": "2025-12-06T16:30:00.000Z", + "startTime": "2026-08-30T19:00:00.000Z", + "endTime": "2026-08-30T20:30:00.000Z", "location": "Hunt Library Study Room 3", - "categories": ["Social", "Academic"], + "categories": [ + "Social", + "Academic" + ], "organizer": { "id": "org-book-club", "name": "Book Club", @@ -3288,24 +4313,37 @@ }, "color": "#16A085", "rsvpEnabled": true, - "rsvpCounts": { "going": 31, "maybe": 13, "notGoing": 2 }, + "rsvpCounts": { + "going": 31, + "maybe": 13, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 40, - "tags": ["books", "reading", "literature", "discussion", "social"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "books", + "reading", + "literature", + "discussion", + "social" + ], + "createdAt": "2026-08-09T19:00:00.000Z", + "updatedAt": "2026-08-23T19:00:00.000Z" }, { "id": "evt-dec-061", "title": "Python Programming Session", "description": "Advanced Python topics and coding practice", - "startTime": "2025-12-06T16:00:00.000Z", - "endTime": "2025-12-06T18:00:00.000Z", + "startTime": "2026-08-30T20:00:00.000Z", + "endTime": "2026-08-30T22:00:00.000Z", "location": "Gates Hillman Center 4305", - "categories": ["Tech", "Academic"], + "categories": [ + "Tech", + "Academic" + ], "organizer": { "id": "org-python", "name": "Python Club", @@ -3313,24 +4351,37 @@ }, "color": "#3498DB", "rsvpEnabled": true, - "rsvpCounts": { "going": 52, "maybe": 21, "notGoing": 3 }, + "rsvpCounts": { + "going": 52, + "maybe": 21, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 65, - "tags": ["python", "programming", "coding", "tech", "academic"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "python", + "programming", + "coding", + "tech", + "academic" + ], + "createdAt": "2026-08-09T20:00:00.000Z", + "updatedAt": "2026-08-23T20:00:00.000Z" }, { "id": "evt-dec-062", "title": "Yoga & Stretching", "description": "Relaxing yoga session to unwind after classes", - "startTime": "2025-12-06T17:30:00.000Z", - "endTime": "2025-12-06T19:00:00.000Z", + "startTime": "2026-08-30T21:30:00.000Z", + "endTime": "2026-08-30T23:00:00.000Z", "location": "UC Fitness Center", - "categories": ["Wellness", "Health"], + "categories": [ + "Wellness", + "Health" + ], "organizer": { "id": "org-yoga", "name": "Yoga Club", @@ -3338,24 +4389,37 @@ }, "color": "#2ECC71", "rsvpEnabled": true, - "rsvpCounts": { "going": 41, "maybe": 17, "notGoing": 2 }, + "rsvpCounts": { + "going": 41, + "maybe": 17, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 50, - "tags": ["yoga", "wellness", "stretching", "relaxation", "health"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "yoga", + "wellness", + "stretching", + "relaxation", + "health" + ], + "createdAt": "2026-08-09T21:30:00.000Z", + "updatedAt": "2026-08-23T21:30:00.000Z" }, { "id": "evt-dec-063", "title": "Resume Review Session", "description": "Get feedback on your resume from career advisors", - "startTime": "2025-12-06T15:00:00.000Z", - "endTime": "2025-12-06T17:00:00.000Z", + "startTime": "2026-08-30T19:00:00.000Z", + "endTime": "2026-08-30T21:00:00.000Z", "location": "Tepper School of Business", - "categories": ["Career", "Networking"], + "categories": [ + "Career", + "Networking" + ], "organizer": { "id": "org-career-services", "name": "Career Services", @@ -3363,24 +4427,37 @@ }, "color": "#E67E22", "rsvpEnabled": true, - "rsvpCounts": { "going": 73, "maybe": 29, "notGoing": 5 }, + "rsvpCounts": { + "going": 73, + "maybe": 29, + "notGoing": 5 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 90, - "tags": ["resume", "career", "job-search", "professional", "advice"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "resume", + "career", + "job-search", + "professional", + "advice" + ], + "createdAt": "2026-08-09T19:00:00.000Z", + "updatedAt": "2026-08-23T19:00:00.000Z" }, { "id": "evt-dec-064", "title": "Dungeons & Dragons Session", "description": "Epic D&D campaign - all experience levels welcome", - "startTime": "2025-12-06T16:00:00.000Z", - "endTime": "2025-12-06T19:00:00.000Z", + "startTime": "2026-08-31T20:00:00.000Z", + "endTime": "2026-08-31T23:00:00.000Z", "location": "UC Game Room", - "categories": ["Social", "Fun"], + "categories": [ + "Social", + "Fun" + ], "organizer": { "id": "org-dnd", "name": "D&D Club", @@ -3388,24 +4465,37 @@ }, "color": "#8E44AD", "rsvpEnabled": true, - "rsvpCounts": { "going": 19, "maybe": 8, "notGoing": 1 }, + "rsvpCounts": { + "going": 19, + "maybe": 8, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 8, - "tags": ["dnd", "dungeons-dragons", "gaming", "rpg", "tabletop"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "dnd", + "dungeons-dragons", + "gaming", + "rpg", + "tabletop" + ], + "createdAt": "2026-08-10T20:00:00.000Z", + "updatedAt": "2026-08-24T20:00:00.000Z" }, { "id": "evt-dec-065", "title": "Machine Learning Study Group", "description": "Review ML concepts and work on projects together", - "startTime": "2025-12-06T15:30:00.000Z", - "endTime": "2025-12-06T17:30:00.000Z", + "startTime": "2026-08-31T19:30:00.000Z", + "endTime": "2026-08-31T21:30:00.000Z", "location": "Gates Hillman Center 4403", - "categories": ["Tech", "Academic"], + "categories": [ + "Tech", + "Academic" + ], "organizer": { "id": "org-ml-study", "name": "ML Study Group", @@ -3413,24 +4503,37 @@ }, "color": "#9B59B6", "rsvpEnabled": true, - "rsvpCounts": { "going": 36, "maybe": 14, "notGoing": 2 }, + "rsvpCounts": { + "going": 36, + "maybe": 14, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": false, "isSocialEvent": false, "capacity": 45, - "tags": ["machine-learning", "ml", "ai", "study", "academic"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "machine-learning", + "ml", + "ai", + "study", + "academic" + ], + "createdAt": "2026-08-10T19:30:00.000Z", + "updatedAt": "2026-08-24T19:30:00.000Z" }, { "id": "evt-dec-066", "title": "Pottery Workshop", "description": "Create ceramic pieces - materials provided", - "startTime": "2025-12-06T17:00:00.000Z", - "endTime": "2025-12-06T19:00:00.000Z", + "startTime": "2026-08-31T21:00:00.000Z", + "endTime": "2026-08-31T23:00:00.000Z", "location": "UC Arts & Crafts Room", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-pottery", "name": "Arts & Crafts Club", @@ -3438,24 +4541,37 @@ }, "color": "#E91E63", "rsvpEnabled": true, - "rsvpCounts": { "going": 27, "maybe": 11, "notGoing": 1 }, + "rsvpCounts": { + "going": 27, + "maybe": 11, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 35, - "tags": ["pottery", "ceramics", "arts", "crafts", "creative"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "pottery", + "ceramics", + "arts", + "crafts", + "creative" + ], + "createdAt": "2026-08-10T21:00:00.000Z", + "updatedAt": "2026-08-24T21:00:00.000Z" }, { "id": "evt-dec-067", "title": "Financial Planning Workshop", "description": "Learn about budgeting, investing, and financial literacy", - "startTime": "2025-12-06T16:30:00.000Z", - "endTime": "2025-12-06T18:00:00.000Z", + "startTime": "2026-08-31T20:30:00.000Z", + "endTime": "2026-08-31T22:00:00.000Z", "location": "Tepper School of Business", - "categories": ["Career", "Academic"], + "categories": [ + "Career", + "Academic" + ], "organizer": { "id": "org-finance", "name": "Finance Club", @@ -3463,24 +4579,37 @@ }, "color": "#27AE60", "rsvpEnabled": true, - "rsvpCounts": { "going": 58, "maybe": 23, "notGoing": 4 }, + "rsvpCounts": { + "going": 58, + "maybe": 23, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 70, - "tags": ["finance", "money", "investing", "budgeting", "career"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "finance", + "money", + "investing", + "budgeting", + "career" + ], + "createdAt": "2026-08-10T20:30:00.000Z", + "updatedAt": "2026-08-24T20:30:00.000Z" }, { "id": "evt-dec-068", "title": "Salsa Dancing Class", "description": "Learn salsa dance moves - no experience needed", - "startTime": "2025-12-06T18:00:00.000Z", - "endTime": "2025-12-06T19:00:00.000Z", + "startTime": "2026-09-01T22:00:00.000Z", + "endTime": "2026-09-01T23:00:00.000Z", "location": "UC Dance Studio", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-salsa", "name": "Dance Club", @@ -3488,24 +4617,37 @@ }, "color": "#C0392B", "rsvpEnabled": true, - "rsvpCounts": { "going": 33, "maybe": 13, "notGoing": 2 }, + "rsvpCounts": { + "going": 33, + "maybe": 13, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 40, - "tags": ["salsa", "dancing", "dance", "social", "fun"], - "createdAt": "2025-12-01T10:00:00.000Z", - "updatedAt": "2025-12-01T10:00:00.000Z" + "tags": [ + "salsa", + "dancing", + "dance", + "social", + "fun" + ], + "createdAt": "2026-08-11T22:00:00.000Z", + "updatedAt": "2026-08-25T22:00:00.000Z" }, { "id": "evt-dec-069", "title": "Watercolor Painting Workshop", "description": "Learn watercolor techniques and create your own masterpiece", - "startTime": "2025-12-06T14:00:00.000Z", - "endTime": "2025-12-06T16:00:00.000Z", + "startTime": "2026-09-01T18:00:00.000Z", + "endTime": "2026-09-01T20:00:00.000Z", "location": "UC Arts & Crafts Room", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-watercolor", "name": "Arts Club", @@ -3513,24 +4655,37 @@ }, "color": "#E91E63", "rsvpEnabled": true, - "rsvpCounts": { "going": 28, "maybe": 11, "notGoing": 1 }, + "rsvpCounts": { + "going": 28, + "maybe": 11, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 35, - "tags": ["watercolor", "painting", "arts", "creative", "workshop"], - "createdAt": "2025-12-02T10:00:00.000Z", - "updatedAt": "2025-12-02T10:00:00.000Z" + "tags": [ + "watercolor", + "painting", + "arts", + "creative", + "workshop" + ], + "createdAt": "2026-08-11T18:00:00.000Z", + "updatedAt": "2026-08-25T18:00:00.000Z" }, { "id": "evt-dec-070", "title": "Digital Art & Illustration Class", "description": "Learn digital art techniques using tablets and software", - "startTime": "2025-12-06T15:00:00.000Z", - "endTime": "2025-12-06T17:00:00.000Z", + "startTime": "2026-09-01T19:00:00.000Z", + "endTime": "2026-09-01T21:00:00.000Z", "location": "Hunt Library Design Lab", - "categories": ["Arts", "Tech"], + "categories": [ + "Arts", + "Tech" + ], "organizer": { "id": "org-digital-art", "name": "Digital Arts Club", @@ -3538,24 +4693,37 @@ }, "color": "#9B59B6", "rsvpEnabled": true, - "rsvpCounts": { "going": 42, "maybe": 17, "notGoing": 3 }, + "rsvpCounts": { + "going": 42, + "maybe": 17, + "notGoing": 3 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": false, "capacity": 50, - "tags": ["digital-art", "illustration", "arts", "tech", "creative"], - "createdAt": "2025-12-02T10:00:00.000Z", - "updatedAt": "2025-12-02T10:00:00.000Z" + "tags": [ + "digital-art", + "illustration", + "arts", + "tech", + "creative" + ], + "createdAt": "2026-08-11T19:00:00.000Z", + "updatedAt": "2026-08-25T19:00:00.000Z" }, { "id": "evt-dec-071", "title": "Sculpture Making Session", "description": "Create sculptures using clay and other materials", - "startTime": "2025-12-06T16:00:00.000Z", - "endTime": "2025-12-06T18:00:00.000Z", + "startTime": "2026-09-01T20:00:00.000Z", + "endTime": "2026-09-01T22:00:00.000Z", "location": "UC Arts & Crafts Room", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-sculpture", "name": "Sculpture Club", @@ -3563,24 +4731,37 @@ }, "color": "#D35400", "rsvpEnabled": true, - "rsvpCounts": { "going": 19, "maybe": 8, "notGoing": 1 }, + "rsvpCounts": { + "going": 19, + "maybe": 8, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 25, - "tags": ["sculpture", "clay", "arts", "crafts", "creative"], - "createdAt": "2025-12-02T10:00:00.000Z", - "updatedAt": "2025-12-02T10:00:00.000Z" + "tags": [ + "sculpture", + "clay", + "arts", + "crafts", + "creative" + ], + "createdAt": "2026-08-11T20:00:00.000Z", + "updatedAt": "2026-08-25T20:00:00.000Z" }, { "id": "evt-dec-072", "title": "Calligraphy Workshop", "description": "Learn beautiful handwriting and calligraphy techniques", - "startTime": "2025-12-06T17:00:00.000Z", - "endTime": "2025-12-06T19:00:00.000Z", + "startTime": "2026-09-02T21:00:00.000Z", + "endTime": "2026-09-02T23:00:00.000Z", "location": "Hunt Library Study Room 1", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-calligraphy", "name": "Calligraphy Club", @@ -3588,24 +4769,37 @@ }, "color": "#16A085", "rsvpEnabled": true, - "rsvpCounts": { "going": 31, "maybe": 13, "notGoing": 2 }, + "rsvpCounts": { + "going": 31, + "maybe": 13, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 40, - "tags": ["calligraphy", "handwriting", "arts", "creative", "meditation"], - "createdAt": "2025-12-02T10:00:00.000Z", - "updatedAt": "2025-12-02T10:00:00.000Z" + "tags": [ + "calligraphy", + "handwriting", + "arts", + "creative", + "meditation" + ], + "createdAt": "2026-08-12T21:00:00.000Z", + "updatedAt": "2026-08-26T21:00:00.000Z" }, { "id": "evt-dec-073", "title": "Art Gallery Opening", "description": "View student artwork and meet the artists", - "startTime": "2025-12-06T18:00:00.000Z", - "endTime": "2025-12-06T20:00:00.000Z", + "startTime": "2026-09-02T22:00:00.000Z", + "endTime": "2026-09-03T00:00:00.000Z", "location": "UC Gallery", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-gallery", "name": "Student Art Gallery", @@ -3613,24 +4807,37 @@ }, "color": "#C0392B", "rsvpEnabled": true, - "rsvpCounts": { "going": 67, "maybe": 27, "notGoing": 4 }, + "rsvpCounts": { + "going": 67, + "maybe": 27, + "notGoing": 4 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 100, - "tags": ["gallery", "exhibition", "arts", "social", "networking"], - "createdAt": "2025-12-02T10:00:00.000Z", - "updatedAt": "2025-12-02T10:00:00.000Z" + "tags": [ + "gallery", + "exhibition", + "arts", + "social", + "networking" + ], + "createdAt": "2026-08-12T22:00:00.000Z", + "updatedAt": "2026-08-26T22:00:00.000Z" }, { "id": "evt-dec-074", "title": "Sketching & Drawing Session", "description": "Practice drawing skills with live models and still life", - "startTime": "2025-12-06T13:00:00.000Z", - "endTime": "2025-12-06T15:00:00.000Z", + "startTime": "2026-09-02T17:00:00.000Z", + "endTime": "2026-09-02T19:00:00.000Z", "location": "UC Arts Studio", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-sketching", "name": "Drawing Club", @@ -3638,24 +4845,37 @@ }, "color": "#8E44AD", "rsvpEnabled": true, - "rsvpCounts": { "going": 35, "maybe": 14, "notGoing": 2 }, + "rsvpCounts": { + "going": 35, + "maybe": 14, + "notGoing": 2 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 45, - "tags": ["sketching", "drawing", "arts", "creative", "practice"], - "createdAt": "2025-12-02T10:00:00.000Z", - "updatedAt": "2025-12-02T10:00:00.000Z" + "tags": [ + "sketching", + "drawing", + "arts", + "creative", + "practice" + ], + "createdAt": "2026-08-12T17:00:00.000Z", + "updatedAt": "2026-08-26T17:00:00.000Z" }, { "id": "evt-dec-075", "title": "Collage Making Workshop", "description": "Create collages from magazines, photos, and mixed media", - "startTime": "2025-12-06T15:30:00.000Z", - "endTime": "2025-12-06T17:30:00.000Z", + "startTime": "2026-09-02T19:30:00.000Z", + "endTime": "2026-09-02T21:30:00.000Z", "location": "UC Arts & Crafts Room", - "categories": ["Arts", "Social"], + "categories": [ + "Arts", + "Social" + ], "organizer": { "id": "org-collage", "name": "Mixed Media Club", @@ -3663,14 +4883,24 @@ }, "color": "#FF6BA8", "rsvpEnabled": true, - "rsvpCounts": { "going": 24, "maybe": 10, "notGoing": 1 }, + "rsvpCounts": { + "going": 24, + "maybe": 10, + "notGoing": 1 + }, "attendees": [], "attendeeVisibility": "public", "isClubEvent": true, "isSocialEvent": true, "capacity": 30, - "tags": ["collage", "mixed-media", "arts", "creative", "crafts"], - "createdAt": "2025-12-02T10:00:00.000Z", - "updatedAt": "2025-12-02T10:00:00.000Z" + "tags": [ + "collage", + "mixed-media", + "arts", + "creative", + "crafts" + ], + "createdAt": "2026-08-12T19:30:00.000Z", + "updatedAt": "2026-08-26T19:30:00.000Z" } -] \ No newline at end of file +] diff --git a/apps/client/data/currentWeekEvents.json b/apps/client/data/currentWeekEvents.json deleted file mode 100644 index e1840f3..0000000 --- a/apps/client/data/currentWeekEvents.json +++ /dev/null @@ -1,253 +0,0 @@ -[ - { - "id": "evt-current-001", - "title": "Morning Yoga Session", - "description": "Start your day with a relaxing yoga session", - "startTime": "2025-11-17T08:00:00.000Z", - "endTime": "2025-11-17T09:00:00.000Z", - "location": "UC Gym", - "categories": ["Wellness", "Social"], - "organizer": { - "id": "org-wellness", - "name": "Wellness Club", - "type": "club" - }, - "color": "#95E1D3", - "rsvpEnabled": true, - "rsvpCounts": { "going": 15, "maybe": 5, "notGoing": 2 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 25, - "tags": ["yoga", "wellness", "morning"], - "createdAt": "2025-11-10T10:00:00.000Z", - "updatedAt": "2025-11-10T10:00:00.000Z" - }, - { - "id": "evt-current-002", - "title": "CS Study Group", - "description": "Study session for 15-213 exam prep", - "startTime": "2025-11-17T14:00:00.000Z", - "endTime": "2025-11-17T16:00:00.000Z", - "location": "Gates 4th Floor", - "categories": ["Academic", "Study"], - "organizer": { - "id": "user-001", - "name": "Alex Johnson", - "type": "student" - }, - "color": "#8B7FFF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 8, "maybe": 3, "notGoing": 0 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 12, - "tags": ["study", "cs", "exam"], - "createdAt": "2025-11-12T10:00:00.000Z", - "updatedAt": "2025-11-12T10:00:00.000Z" - }, - { - "id": "evt-current-003", - "title": "Basketball Pickup Game", - "description": "Casual basketball game, all skill levels welcome!", - "startTime": "2025-11-17T18:30:00.000Z", - "endTime": "2025-11-17T20:00:00.000Z", - "location": "Highmark Center", - "categories": ["Sports", "Social"], - "organizer": { - "id": "user-002", - "name": "Sarah Miller", - "type": "student" - }, - "color": "#FF6BA8", - "rsvpEnabled": true, - "rsvpCounts": { "going": 10, "maybe": 4, "notGoing": 1 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 16, - "tags": ["basketball", "sports", "pickup"], - "createdAt": "2025-11-13T10:00:00.000Z", - "updatedAt": "2025-11-13T10:00:00.000Z" - }, - { - "id": "evt-current-004", - "title": "Tech Talk: AI in Healthcare", - "description": "Guest speaker from Google discussing AI applications in healthcare", - "startTime": "2025-11-18T17:00:00.000Z", - "endTime": "2025-11-18T18:30:00.000Z", - "location": "Gates Hillman Center", - "categories": ["Tech", "Career"], - "organizer": { - "id": "org-cs-club", - "name": "Computer Science Club", - "type": "club" - }, - "color": "#4ECDC4", - "rsvpEnabled": true, - "rsvpCounts": { "going": 89, "maybe": 23, "notGoing": 5 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 150, - "tags": ["tech", "ai", "healthcare", "talk"], - "createdAt": "2025-11-05T10:00:00.000Z", - "updatedAt": "2025-11-08T10:00:00.000Z" - }, - { - "id": "evt-current-005", - "title": "Coffee & Code", - "description": "Casual coding session at Entropy. Work on projects or just hang out!", - "startTime": "2025-11-18T10:00:00.000Z", - "endTime": "2025-11-18T12:00:00.000Z", - "location": "Entropy Coffee", - "categories": ["Social", "Tech"], - "organizer": { - "id": "user-003", - "name": "Mike Chen", - "type": "student" - }, - "color": "#FFD93D", - "rsvpEnabled": true, - "rsvpCounts": { "going": 12, "maybe": 7, "notGoing": 2 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 20, - "tags": ["coffee", "coding", "social"], - "createdAt": "2025-11-14T10:00:00.000Z", - "updatedAt": "2025-11-14T10:00:00.000Z" - }, - { - "id": "evt-current-006", - "title": "Poker Night", - "description": "Texas Hold'em poker night in Wiegand. $5 buy-in, winner takes all!", - "startTime": "2025-11-18T20:00:00.000Z", - "endTime": "2025-11-18T23:00:00.000Z", - "location": "Wiegand Gym Lounge", - "categories": ["Social", "Games"], - "organizer": { - "id": "user-004", - "name": "Emma Davis", - "type": "student" - }, - "color": "#FF6B6B", - "rsvpEnabled": true, - "rsvpCounts": { "going": 8, "maybe": 5, "notGoing": 1 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 10, - "tags": ["poker", "games", "night"], - "createdAt": "2025-11-15T10:00:00.000Z", - "updatedAt": "2025-11-15T10:00:00.000Z" - }, - { - "id": "evt-current-007", - "title": "Design Workshop: Figma Basics", - "description": "Learn the fundamentals of Figma for UI/UX design", - "startTime": "2025-11-19T15:00:00.000Z", - "endTime": "2025-11-19T17:00:00.000Z", - "location": "Hunt Library", - "categories": ["Design", "Academic"], - "organizer": { - "id": "org-design", - "name": "Design Club", - "type": "club" - }, - "color": "#8B7FFF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 34, "maybe": 12, "notGoing": 3 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 50, - "tags": ["design", "figma", "workshop"], - "createdAt": "2025-11-08T10:00:00.000Z", - "updatedAt": "2025-11-10T10:00:00.000Z" - }, - { - "id": "evt-current-008", - "title": "Lunch & Learn: Entrepreneurship", - "description": "Free lunch and discussion about starting your own company", - "startTime": "2025-11-19T12:00:00.000Z", - "endTime": "2025-11-19T13:30:00.000Z", - "location": "Tepper Quad", - "categories": ["Career", "Networking"], - "organizer": { - "id": "org-entrepreneur", - "name": "Entrepreneurship Club", - "type": "club" - }, - "color": "#4ECDC4", - "rsvpEnabled": true, - "rsvpCounts": { "going": 45, "maybe": 18, "notGoing": 4 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 60, - "tags": ["entrepreneurship", "lunch", "career"], - "createdAt": "2025-11-06T10:00:00.000Z", - "updatedAt": "2025-11-09T10:00:00.000Z" - }, - { - "id": "evt-current-009", - "title": "Movie Night: The Social Network", - "description": "Watch The Social Network with free popcorn!", - "startTime": "2025-11-20T19:00:00.000Z", - "endTime": "2025-11-20T21:30:00.000Z", - "location": "McConomy Auditorium", - "categories": ["Entertainment", "Social"], - "organizer": { - "id": "org-activities", - "name": "Student Activities", - "type": "club" - }, - "color": "#FF6BA8", - "rsvpEnabled": true, - "rsvpCounts": { "going": 67, "maybe": 29, "notGoing": 8 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 100, - "tags": ["movie", "social", "entertainment"], - "createdAt": "2025-11-07T10:00:00.000Z", - "updatedAt": "2025-11-11T10:00:00.000Z" - }, - { - "id": "evt-current-010", - "title": "Hackathon Kickoff", - "description": "24-hour hackathon starts now! Build something amazing!", - "startTime": "2025-11-21T18:00:00.000Z", - "endTime": "2025-11-22T18:00:00.000Z", - "location": "Gates Hillman Center", - "categories": ["Tech", "Competition"], - "organizer": { - "id": "org-hack", - "name": "HackCMU", - "type": "club" - }, - "color": "#FFD93D", - "rsvpEnabled": true, - "rsvpCounts": { "going": 156, "maybe": 34, "notGoing": 12 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 200, - "tags": ["hackathon", "coding", "competition"], - "createdAt": "2025-10-15T10:00:00.000Z", - "updatedAt": "2025-11-01T10:00:00.000Z" - } -] - diff --git a/apps/client/data/mockEvents.json b/apps/client/data/mockEvents.json deleted file mode 100644 index 728f403..0000000 --- a/apps/client/data/mockEvents.json +++ /dev/null @@ -1,998 +0,0 @@ -[ - { - "id": "evt-001", - "title": "Carnegie Mellon Career Fair", - "description": "Annual career fair featuring top tech companies and startups. Bring your resume and dress professionally!", - "startTime": "2025-10-20T10:00:00Z", - "endTime": "2025-10-20T16:00:00Z", - "location": "Wiegand Gymnasium", - "categories": ["Career", "Networking"], - "organizer": { - "id": "org-001", - "name": "Career Services", - "type": "club" - }, - "color": "#FF6B6B", - "rsvpEnabled": true, - "rsvpCounts": { "going": 234, "maybe": 67, "notGoing": 12 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 500, - "tags": ["career", "recruiting", "tech"], - "createdAt": "2025-09-15T10:00:00Z", - "updatedAt": "2025-10-01T10:00:00Z" - }, - { - "id": "evt-002", - "title": "Scotty's Lab: Arduino Workshop", - "description": "Learn the basics of Arduino programming and build your own LED circuit!", - "startTime": "2025-10-19T13:00:00Z", - "endTime": "2025-10-19T15:00:00Z", - "location": "Hunt Library Maker Space", - "categories": ["Tech", "Academic"], - "organizer": { - "id": "org-002", - "name": "Scotty's Lab", - "type": "club" - }, - "color": "#8B7FFF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 28, "maybe": 15, "notGoing": 3 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 30, - "tags": ["arduino", "electronics", "workshop"], - "createdAt": "2025-09-20T10:00:00Z", - "updatedAt": "2025-10-05T10:00:00Z" - }, - { - "id": "evt-003", - "title": "Poker Night @ Wiegand", - "description": "Casual poker game, all skill levels welcome! Bring $5 for buy-in.", - "startTime": "2025-10-18T18:30:00Z", - "endTime": "2025-10-18T22:00:00Z", - "location": "Wiegand Gym Lounge", - "categories": ["Social", "Fun"], - "organizer": { - "id": "user-001", - "name": "Alex Chen", - "type": "individual" - }, - "color": "#FF8C94", - "rsvpEnabled": true, - "rsvpCounts": { "going": 8, "maybe": 4, "notGoing": 0 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 12, - "tags": ["poker", "games", "social"], - "createdAt": "2025-10-15T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" - }, - { - "id": "evt-004", - "title": "Free Pizza & Study Session", - "description": "Grab free pizza while studying for midterms. Quiet study space available.", - "startTime": "2025-10-21T17:00:00Z", - "endTime": "2025-10-21T21:00:00Z", - "location": "Gates Hillman Center 4th Floor", - "categories": ["Food", "Academic"], - "organizer": { - "id": "org-003", - "name": "Student Government", - "type": "club" - }, - "color": "#FFA07A", - "rsvpEnabled": true, - "rsvpCounts": { "going": 156, "maybe": 89, "notGoing": 5 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "tags": ["food", "study", "pizza"], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-12T10:00:00Z" - }, - { - "id": "evt-005", - "title": "Basketball Pickup Game", - "description": "Looking for 4 more players for a casual basketball game. All levels welcome!", - "startTime": "2025-10-19T16:00:00Z", - "endTime": "2025-10-19T18:00:00Z", - "location": "Highmark Center Court 2", - "categories": ["Sports", "Social"], - "organizer": { - "id": "user-002", - "name": "Jordan Smith", - "type": "individual" - }, - "color": "#95E1D3", - "rsvpEnabled": true, - "rsvpCounts": { "going": 6, "maybe": 3, "notGoing": 1 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 10, - "tags": ["basketball", "sports", "pickup"], - "createdAt": "2025-10-17T10:00:00Z", - "updatedAt": "2025-10-17T10:00:00Z" - }, - { - "id": "evt-006", - "title": "Yoga & Mindfulness Session", - "description": "Start your day with gentle yoga and meditation. Mats provided.", - "startTime": "2025-10-20T07:00:00Z", - "endTime": "2025-10-20T08:00:00Z", - "location": "University Center McKenna Room", - "categories": ["Wellness", "Afternoon"], - "organizer": { - "id": "org-004", - "name": "Wellness Center", - "type": "club" - }, - "color": "#A8E6CF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 18, "maybe": 7, "notGoing": 2 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 25, - "tags": ["yoga", "wellness", "meditation"], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-08T10:00:00Z" - }, - { - "id": "evt-007", - "title": "Hackathon: TartanHacks 2025", - "description": "24-hour hackathon with prizes, workshops, and free food! Form teams or join one there.", - "startTime": "2025-10-25T18:00:00Z", - "endTime": "2025-10-26T18:00:00Z", - "location": "Gates Hillman Center", - "categories": ["Tech", "Events"], - "organizer": { - "id": "org-005", - "name": "ScottyLabs", - "type": "club" - }, - "color": "#5B9BD5", - "rsvpEnabled": true, - "rsvpCounts": { "going": 312, "maybe": 145, "notGoing": 23 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 400, - "tags": ["hackathon", "coding", "tech"], - "createdAt": "2025-09-01T10:00:00Z", - "updatedAt": "2025-10-10T10:00:00Z" - }, - { - "id": "evt-008", - "title": "Art Gallery Opening: Student Showcase", - "description": "Featuring works from CMU art students. Wine and cheese reception.", - "startTime": "2025-10-22T18:00:00Z", - "endTime": "2025-10-22T21:00:00Z", - "location": "Miller Gallery", - "categories": ["Arts", "Social"], - "organizer": { - "id": "org-006", - "name": "School of Art", - "type": "club" - }, - "color": "#C7A4FF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 67, "maybe": 34, "notGoing": 8 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "tags": ["art", "gallery", "exhibition"], - "createdAt": "2025-10-01T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" - }, - { - "id": "evt-009", - "title": "Coffee Chat: Alumni in Tech", - "description": "Informal networking with CMU alumni working at FAANG companies.", - "startTime": "2025-10-23T15:00:00Z", - "endTime": "2025-10-23T16:30:00Z", - "location": "Rothberg's Roasters", - "categories": ["Career", "Networking"], - "organizer": { - "id": "org-007", - "name": "Alumni Relations", - "type": "club" - }, - "color": "#FF6BA8", - "rsvpEnabled": true, - "rsvpCounts": { "going": 45, "maybe": 23, "notGoing": 5 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 50, - "tags": ["networking", "alumni", "career"], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" - }, - { - "id": "evt-010", - "title": "Lunar Gala Fashion Show", - "description": "CMU's premier fashion show featuring student designers. Tickets required.", - "startTime": "2025-10-21T19:00:00Z", - "endTime": "2025-10-21T22:00:00Z", - "location": "Wiegand Gymnasium", - "categories": ["Arts", "Events"], - "organizer": { - "id": "org-008", - "name": "Lunar Gala", - "type": "club" - }, - "color": "#FF6BA8", - "rsvpEnabled": true, - "rsvpCounts": { "going": 489, "maybe": 156, "notGoing": 34 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 600, - "tags": ["fashion", "show", "design"], - "createdAt": "2025-08-15T10:00:00Z", - "updatedAt": "2025-10-10T10:00:00Z" - }, - { - "id": "evt-011", - "title": "Trivia Night @ The Underground", - "description": "Test your knowledge! Teams of 4-6. Prizes for top 3 teams.", - "startTime": "2025-10-24T20:00:00Z", - "endTime": "2025-10-24T22:30:00Z", - "location": "The Underground", - "categories": ["Fun", "Social"], - "organizer": { - "id": "org-009", - "name": "Student Activities", - "type": "club" - }, - "color": "#FFD93D", - "rsvpEnabled": true, - "rsvpCounts": { "going": 78, "maybe": 45, "notGoing": 12 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 120, - "tags": ["trivia", "games", "competition"], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" - }, - { - "id": "evt-012", - "title": "Machine Learning Workshop", - "description": "Introduction to neural networks and deep learning with hands-on coding.", - "startTime": "2025-10-26T14:00:00Z", - "endTime": "2025-10-26T17:00:00Z", - "location": "Gates Hillman 6115", - "categories": ["Tech", "Academic"], - "organizer": { - "id": "org-010", - "name": "AI Club", - "type": "club" - }, - "color": "#5B9BD5", - "rsvpEnabled": true, - "rsvpCounts": { "going": 92, "maybe": 38, "notGoing": 7 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 100, - "tags": ["ml", "ai", "workshop"], - "createdAt": "2025-10-01T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" - }, - { - "id": "evt-013", - "title": "Bubble Tea Run", - "description": "Going to get bubble tea in Oakland, anyone want to join? Meeting at UC.", - "startTime": "2025-10-19T14:30:00Z", - "endTime": "2025-10-19T16:00:00Z", - "location": "University Center Entrance", - "categories": ["Food", "Social"], - "organizer": { - "id": "user-003", - "name": "Sarah Kim", - "type": "individual" - }, - "color": "#FFA07A", - "rsvpEnabled": true, - "rsvpCounts": { "going": 5, "maybe": 3, "notGoing": 0 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 10, - "tags": ["food", "boba", "social"], - "createdAt": "2025-10-18T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" - }, - { - "id": "evt-014", - "title": "Startup Pitch Competition", - "description": "Watch student entrepreneurs pitch their startups. $10k in prizes!", - "startTime": "2025-10-27T17:00:00Z", - "endTime": "2025-10-27T20:00:00Z", - "location": "Tepper Auditorium", - "categories": ["Career", "Events"], - "organizer": { - "id": "org-011", - "name": "Entrepreneurship Club", - "type": "club" - }, - "color": "#FF6B6B", - "rsvpEnabled": true, - "rsvpCounts": { "going": 134, "maybe": 67, "notGoing": 15 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 200, - "tags": ["startup", "pitch", "entrepreneurship"], - "createdAt": "2025-09-20T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" - }, - { - "id": "evt-015", - "title": "Salsa Dancing Lessons", - "description": "Beginner-friendly salsa lessons. No partner needed!", - "startTime": "2025-10-25T19:00:00Z", - "endTime": "2025-10-25T21:00:00Z", - "location": "Rangos Ballroom", - "categories": ["Fun", "Social"], - "organizer": { - "id": "org-012", - "name": "Latin Dance Club", - "type": "club" - }, - "color": "#FF8C94", - "rsvpEnabled": true, - "rsvpCounts": { "going": 56, "maybe": 28, "notGoing": 4 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 80, - "tags": ["dance", "salsa", "lessons"], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" - }, - { - "id": "evt-016", - "title": "Study Abroad Info Session", - "description": "Learn about study abroad opportunities for next semester.", - "startTime": "2025-10-23T12:00:00Z", - "endTime": "2025-10-23T13:00:00Z", - "location": "Warner Hall 100", - "categories": ["Academic", "Events"], - "organizer": { - "id": "org-013", - "name": "Global Programs", - "type": "club" - }, - "color": "#8B7FFF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 43, "maybe": 29, "notGoing": 8 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 60, - "tags": ["study-abroad", "international", "info-session"], - "createdAt": "2025-10-01T10:00:00Z", - "updatedAt": "2025-10-10T10:00:00Z" - }, - { - "id": "evt-017", - "title": "Rock Climbing @ The Climbing Wall", - "description": "Casual climbing session. Equipment provided, all levels welcome!", - "startTime": "2025-10-20T15:00:00Z", - "endTime": "2025-10-20T17:00:00Z", - "location": "Cohon Center Climbing Wall", - "categories": ["Sports", "Wellness"], - "organizer": { - "id": "user-004", - "name": "Mike Torres", - "type": "individual" - }, - "color": "#95E1D3", - "rsvpEnabled": true, - "rsvpCounts": { "going": 12, "maybe": 6, "notGoing": 1 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 20, - "tags": ["climbing", "sports", "fitness"], - "createdAt": "2025-10-17T10:00:00Z", - "updatedAt": "2025-10-17T10:00:00Z" - }, - { - "id": "evt-018", - "title": "Diwali Celebration", - "description": "Celebrate the festival of lights with food, music, and performances!", - "startTime": "2025-10-28T18:00:00Z", - "endTime": "2025-10-28T22:00:00Z", - "location": "Rangos Ballroom", - "categories": ["Events", "Social", "Food"], - "organizer": { - "id": "org-014", - "name": "Indian Student Association", - "type": "club" - }, - "color": "#FFD93D", - "rsvpEnabled": true, - "rsvpCounts": { "going": 267, "maybe": 98, "notGoing": 23 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 400, - "tags": ["diwali", "cultural", "celebration"], - "createdAt": "2025-09-15T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" - }, - { - "id": "evt-019", - "title": "Resume Review Drop-In", - "description": "Get your resume reviewed by career advisors. No appointment needed.", - "startTime": "2025-10-24T13:00:00Z", - "endTime": "2025-10-24T16:00:00Z", - "location": "Career Center", - "categories": ["Career", "Academic"], - "organizer": { - "id": "org-001", - "name": "Career Services", - "type": "club" - }, - "color": "#FF6B6B", - "rsvpEnabled": false, - "rsvpCounts": { "going": 0, "maybe": 0, "notGoing": 0 }, - "attendees": [], - "attendeeVisibility": "private", - "isClubEvent": true, - "isSocialEvent": false, - "tags": ["resume", "career", "advising"], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" - }, - { - "id": "evt-020", - "title": "Board Game Night", - "description": "Bring your favorite board games or play ours! Snacks provided.", - "startTime": "2025-10-26T19:00:00Z", - "endTime": "2025-10-26T23:00:00Z", - "location": "Morewood Gardens Lounge", - "categories": ["Fun", "Social"], - "organizer": { - "id": "user-005", - "name": "Emily Zhang", - "type": "individual" - }, - "color": "#FFD93D", - "rsvpEnabled": true, - "rsvpCounts": { "going": 18, "maybe": 9, "notGoing": 2 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 30, - "tags": ["games", "board-games", "social"], - "createdAt": "2025-10-20T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" - }, - { - "id": "evt-021", - "title": "Cybersecurity CTF Competition", - "description": "Capture the flag competition testing your hacking skills. Form teams of 3-4.", - "startTime": "2025-10-29T18:00:00Z", - "endTime": "2025-10-30T06:00:00Z", - "location": "Gates Hillman Center", - "categories": ["Tech", "Events"], - "organizer": { - "id": "org-015", - "name": "Security Club", - "type": "club" - }, - "color": "#5B9BD5", - "rsvpEnabled": true, - "rsvpCounts": { "going": 76, "maybe": 34, "notGoing": 8 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 100, - "tags": ["ctf", "security", "hacking"], - "createdAt": "2025-10-01T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" - }, - { - "id": "evt-022", - "title": "Farmers Market on Campus", - "description": "Fresh produce, baked goods, and local crafts from Pittsburgh vendors.", - "startTime": "2025-10-22T10:00:00Z", - "endTime": "2025-10-22T14:00:00Z", - "location": "The Cut", - "categories": ["Food", "Events"], - "organizer": { - "id": "org-016", - "name": "Sustainability Committee", - "type": "club" - }, - "color": "#6BCF7F", - "rsvpEnabled": false, - "rsvpCounts": { "going": 0, "maybe": 0, "notGoing": 0 }, - "attendees": [], - "attendeeVisibility": "private", - "isClubEvent": true, - "isSocialEvent": false, - "tags": ["farmers-market", "food", "local"], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-12T10:00:00Z" - }, - { - "id": "evt-023", - "title": "Improv Comedy Show", - "description": "Student improv troupe performs. Audience participation encouraged!", - "startTime": "2025-10-25T20:00:00Z", - "endTime": "2025-10-25T21:30:00Z", - "location": "Kresge Theatre", - "categories": ["Arts", "Fun"], - "organizer": { - "id": "org-017", - "name": "No Parking Players", - "type": "club" - }, - "color": "#C7A4FF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 89, "maybe": 45, "notGoing": 12 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 150, - "tags": ["improv", "comedy", "performance"], - "createdAt": "2025-10-08T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" - }, - { - "id": "evt-024", - "title": "Meditation & Stress Relief", - "description": "Guided meditation session to help with midterm stress.", - "startTime": "2025-10-23T17:00:00Z", - "endTime": "2025-10-23T18:00:00Z", - "location": "Wellness Center", - "categories": ["Wellness", "Afternoon"], - "organizer": { - "id": "org-004", - "name": "Wellness Center", - "type": "club" - }, - "color": "#A8E6CF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 23, "maybe": 12, "notGoing": 3 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 30, - "tags": ["meditation", "wellness", "stress-relief"], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" - }, - { - "id": "evt-025", - "title": "Late Night Breakfast", - "description": "Free pancakes, waffles, and breakfast foods during finals prep!", - "startTime": "2025-10-30T22:00:00Z", - "endTime": "2025-10-31T01:00:00Z", - "location": "Resnik Dining Hall", - "categories": ["Food", "Events"], - "organizer": { - "id": "org-003", - "name": "Student Government", - "type": "club" - }, - "color": "#FFA07A", - "rsvpEnabled": false, - "rsvpCounts": { "going": 0, "maybe": 0, "notGoing": 0 }, - "attendees": [], - "attendeeVisibility": "private", - "isClubEvent": true, - "isSocialEvent": false, - "tags": ["food", "breakfast", "free"], - "createdAt": "2025-10-15T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" - }, - { - "id": "evt-026", - "title": "Photography Walk: Fall Colors", - "description": "Explore campus and capture autumn colors. Bring your camera or phone!", - "startTime": "2025-10-21T14:00:00Z", - "endTime": "2025-10-21T16:00:00Z", - "location": "Schenley Park Entrance", - "categories": ["Arts", "Afternoon"], - "organizer": { - "id": "user-006", - "name": "Rachel Park", - "type": "individual" - }, - "color": "#C7A4FF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 14, "maybe": 7, "notGoing": 1 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 20, - "tags": ["photography", "nature", "fall"], - "createdAt": "2025-10-16T10:00:00Z", - "updatedAt": "2025-10-16T10:00:00Z" - }, - { - "id": "evt-027", - "title": "Mock Interview Practice", - "description": "Practice technical interviews with upperclassmen. Sign up for time slots.", - "startTime": "2025-10-27T10:00:00Z", - "endTime": "2025-10-27T16:00:00Z", - "location": "Gates Hillman 4000", - "categories": ["Career", "Academic"], - "organizer": { - "id": "org-018", - "name": "CS Mentorship Program", - "type": "club" - }, - "color": "#FF6B6B", - "rsvpEnabled": true, - "rsvpCounts": { "going": 54, "maybe": 23, "notGoing": 6 }, - "attendees": [], - "attendeeVisibility": "private", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 60, - "tags": ["interview", "career", "practice"], - "createdAt": "2025-10-12T10:00:00Z", - "updatedAt": "2025-10-22T10:00:00Z" - }, - { - "id": "evt-028", - "title": "Volleyball Tournament", - "description": "Intramural volleyball tournament. Teams of 6, sign up by Oct 23.", - "startTime": "2025-10-28T13:00:00Z", - "endTime": "2025-10-28T18:00:00Z", - "location": "Highmark Center Courts", - "categories": ["Sports", "Events"], - "organizer": { - "id": "org-019", - "name": "Intramural Sports", - "type": "club" - }, - "color": "#95E1D3", - "rsvpEnabled": true, - "rsvpCounts": { "going": 48, "maybe": 18, "notGoing": 4 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 72, - "tags": ["volleyball", "tournament", "sports"], - "createdAt": "2025-10-08T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" - }, - { - "id": "evt-029", - "title": "Open Mic Night", - "description": "Share your music, poetry, or comedy. Sign up at the door or just watch!", - "startTime": "2025-10-24T19:00:00Z", - "endTime": "2025-10-24T22:00:00Z", - "location": "The Underground", - "categories": ["Arts", "Social"], - "organizer": { - "id": "org-020", - "name": "Student Activities", - "type": "club" - }, - "color": "#C7A4FF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 67, "maybe": 34, "notGoing": 9 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 100, - "tags": ["open-mic", "music", "performance"], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" - }, - { - "id": "evt-030", - "title": "Sustainability Workshop", - "description": "Learn about sustainable living and campus green initiatives.", - "startTime": "2025-10-26T11:00:00Z", - "endTime": "2025-10-26T12:30:00Z", - "location": "Posner Hall 153", - "categories": ["Academic", "Events"], - "organizer": { - "id": "org-016", - "name": "Sustainability Committee", - "type": "club" - }, - "color": "#6BCF7F", - "rsvpEnabled": true, - "rsvpCounts": { "going": 32, "maybe": 18, "notGoing": 5 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 50, - "tags": ["sustainability", "environment", "workshop"], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-15T10:00:00Z" - }, - { - "id": "evt-031", - "title": "Brunch & Study Group", - "description": "Casual brunch meetup for 15-213 students. Bring your questions!", - "startTime": "2025-10-22T11:00:00Z", - "endTime": "2025-10-22T13:00:00Z", - "location": "Entropy Cafe", - "categories": ["Academic", "Food"], - "organizer": { - "id": "user-007", - "name": "David Liu", - "type": "individual" - }, - "color": "#8B7FFF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 9, "maybe": 5, "notGoing": 1 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 15, - "tags": ["study-group", "brunch", "15-213"], - "createdAt": "2025-10-19T10:00:00Z", - "updatedAt": "2025-10-19T10:00:00Z" - }, - { - "id": "evt-032", - "title": "Karaoke Night", - "description": "Sing your heart out! Private rooms available for groups.", - "startTime": "2025-10-27T21:00:00Z", - "endTime": "2025-10-28T00:00:00Z", - "location": "The Underground", - "categories": ["Fun", "Social"], - "organizer": { - "id": "org-009", - "name": "Student Activities", - "type": "club" - }, - "color": "#FFD93D", - "rsvpEnabled": true, - "rsvpCounts": { "going": 94, "maybe": 52, "notGoing": 15 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 150, - "tags": ["karaoke", "music", "fun"], - "createdAt": "2025-10-12T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" - }, - { - "id": "evt-033", - "title": "3D Printing Workshop", - "description": "Learn to design and print 3D models. Beginners welcome!", - "startTime": "2025-10-29T15:00:00Z", - "endTime": "2025-10-29T17:00:00Z", - "location": "Hunt Library Maker Space", - "categories": ["Tech", "Academic"], - "organizer": { - "id": "org-021", - "name": "Maker Club", - "type": "club" - }, - "color": "#5B9BD5", - "rsvpEnabled": true, - "rsvpCounts": { "going": 24, "maybe": 11, "notGoing": 2 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 30, - "tags": ["3d-printing", "maker", "workshop"], - "createdAt": "2025-10-15T10:00:00Z", - "updatedAt": "2025-10-22T10:00:00Z" - }, - { - "id": "evt-034", - "title": "Soccer Scrimmage", - "description": "Pickup soccer game on the Cut. All skill levels welcome!", - "startTime": "2025-10-23T16:30:00Z", - "endTime": "2025-10-23T18:30:00Z", - "location": "The Cut", - "categories": ["Sports", "Social"], - "organizer": { - "id": "user-008", - "name": "Carlos Rodriguez", - "type": "individual" - }, - "color": "#95E1D3", - "rsvpEnabled": true, - "rsvpCounts": { "going": 16, "maybe": 8, "notGoing": 2 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 22, - "tags": ["soccer", "sports", "pickup"], - "createdAt": "2025-10-21T10:00:00Z", - "updatedAt": "2025-10-21T10:00:00Z" - }, - { - "id": "evt-035", - "title": "Film Screening: Indie Night", - "description": "Screening of award-winning indie films. Free popcorn!", - "startTime": "2025-10-25T19:30:00Z", - "endTime": "2025-10-25T22:00:00Z", - "location": "McConomy Auditorium", - "categories": ["Arts", "Events"], - "organizer": { - "id": "org-022", - "name": "Film Club", - "type": "club" - }, - "color": "#C7A4FF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 78, "maybe": 39, "notGoing": 11 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 120, - "tags": ["film", "movie", "screening"], - "createdAt": "2025-10-08T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" - }, - { - "id": "evt-036", - "title": "Data Science Meetup", - "description": "Network with data science professionals and students. Pizza provided!", - "startTime": "2025-10-28T18:30:00Z", - "endTime": "2025-10-28T20:30:00Z", - "location": "Tepper Quad", - "categories": ["Tech", "Networking", "Food"], - "organizer": { - "id": "org-023", - "name": "Data Science Club", - "type": "club" - }, - "color": "#5B9BD5", - "rsvpEnabled": true, - "rsvpCounts": { "going": 87, "maybe": 43, "notGoing": 9 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 100, - "tags": ["data-science", "networking", "tech"], - "createdAt": "2025-10-10T10:00:00Z", - "updatedAt": "2025-10-20T10:00:00Z" - }, - { - "id": "evt-037", - "title": "Acapella Concert", - "description": "CMU's acapella groups perform. Free admission!", - "startTime": "2025-10-26T20:00:00Z", - "endTime": "2025-10-26T22:00:00Z", - "location": "Kresge Theatre", - "categories": ["Arts", "Events"], - "organizer": { - "id": "org-024", - "name": "Acapella Council", - "type": "club" - }, - "color": "#C7A4FF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 156, "maybe": 78, "notGoing": 18 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 200, - "tags": ["acapella", "music", "concert"], - "createdAt": "2025-10-05T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" - }, - { - "id": "evt-038", - "title": "Cooking Class: Asian Cuisine", - "description": "Learn to make dumplings and fried rice. Ingredients provided!", - "startTime": "2025-10-29T17:00:00Z", - "endTime": "2025-10-29T19:30:00Z", - "location": "Resnik Kitchen", - "categories": ["Food", "Social"], - "organizer": { - "id": "org-025", - "name": "Cooking Club", - "type": "club" - }, - "color": "#FFA07A", - "rsvpEnabled": true, - "rsvpCounts": { "going": 18, "maybe": 8, "notGoing": 2 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 20, - "tags": ["cooking", "food", "asian-cuisine"], - "createdAt": "2025-10-15T10:00:00Z", - "updatedAt": "2025-10-22T10:00:00Z" - }, - { - "id": "evt-039", - "title": "Mental Health Panel", - "description": "Discussion on student mental health with counselors and peer support.", - "startTime": "2025-10-24T16:00:00Z", - "endTime": "2025-10-24T17:30:00Z", - "location": "Cohon Center Conference Room", - "categories": ["Wellness", "Academic"], - "organizer": { - "id": "org-026", - "name": "Mental Health Initiative", - "type": "club" - }, - "color": "#A8E6CF", - "rsvpEnabled": true, - "rsvpCounts": { "going": 45, "maybe": 23, "notGoing": 7 }, - "attendees": [], - "attendeeVisibility": "private", - "isClubEvent": true, - "isSocialEvent": false, - "capacity": 60, - "tags": ["mental-health", "wellness", "panel"], - "createdAt": "2025-10-08T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" - }, - { - "id": "evt-040", - "title": "Frisbee on the Cut", - "description": "Casual ultimate frisbee. Just show up and play!", - "startTime": "2025-10-20T13:00:00Z", - "endTime": "2025-10-20T15:00:00Z", - "location": "The Cut", - "categories": ["Sports", "Social", "Afternoon"], - "organizer": { - "id": "user-009", - "name": "Jessica Wu", - "type": "individual" - }, - "color": "#95E1D3", - "rsvpEnabled": true, - "rsvpCounts": { "going": 11, "maybe": 6, "notGoing": 1 }, - "attendees": [], - "attendeeVisibility": "public", - "isClubEvent": false, - "isSocialEvent": true, - "capacity": 20, - "tags": ["frisbee", "sports", "casual"], - "createdAt": "2025-10-18T10:00:00Z", - "updatedAt": "2025-10-18T10:00:00Z" - } -] - diff --git a/apps/client/hooks/useMyEvents.ts b/apps/client/hooks/useMyEvents.ts new file mode 100644 index 0000000..43a2e4f --- /dev/null +++ b/apps/client/hooks/useMyEvents.ts @@ -0,0 +1,52 @@ +import { useCallback, useMemo } from 'react'; +import { Event } from '@/types/event'; +import { useAuth } from '@/contexts/AuthContext'; +import { useEvents } from '@/contexts/EventsContext'; +import { useScheduledEvents, getWeekKey } from '@/hooks/useScheduledEvents'; +import { MyEventRelation, relationForEvent, selectMyEvents } from '@/utils/myEvents'; + +/** + * Everything on the user's plate: events they RSVP'd going/maybe to, pinned to + * their calendar, or are hosting. + * + * Every surface that shows "your" events reads from here, so an RSVP made on + * the event page immediately shows up on the calendar, the mobile agenda and + * My Events without each screen inventing its own rules. + */ +export function useMyEvents() { + const { currentUser } = useAuth(); + const { events, isLoading: isLoadingEvents } = useEvents(); + // Any week key works here: we only read the all-weeks set. + const thisWeek = useMemo(() => getWeekKey(new Date()), []); + const { allScheduledIds, isLoading: isLoadingScheduled, refresh } = useScheduledEvents( + currentUser?.id, + thisWeek + ); + + const ctx = useMemo( + () => ({ + userId: currentUser?.id, + createdIds: currentUser?.createdEvents ?? [], + scheduledIds: allScheduledIds, + }), + [currentUser?.id, currentUser?.createdEvents, allScheduledIds] + ); + + const myEvents = useMemo(() => selectMyEvents(events, ctx), [events, ctx]); + + const myEventIds = useMemo(() => new Set(myEvents.map((e) => e.id)), [myEvents]); + + const relationFor = useCallback( + (event: Event): MyEventRelation | null => relationForEvent(event, ctx), + [ctx] + ); + + return { + myEvents, + myEventIds, + relationFor, + scheduledIds: allScheduledIds, + isLoading: isLoadingEvents || isLoadingScheduled, + refresh, + }; +} diff --git a/apps/client/hooks/useScheduledEvents.ts b/apps/client/hooks/useScheduledEvents.ts index 5202326..07df85a 100644 --- a/apps/client/hooks/useScheduledEvents.ts +++ b/apps/client/hooks/useScheduledEvents.ts @@ -53,12 +53,15 @@ export function useScheduledEvents(rawUserId: string | undefined, weekKey: strin loadScheduled(); }, [loadScheduled]); + // Pins are stored per week. Callers should pass the week the event actually + // falls in (`forWeekKey`); otherwise an event pinned while browsing another + // week would be filed under the week being viewed and vanish from its own. const scheduleEventForWeek = useCallback( - async (eventId: string) => { + async (eventId: string, forWeekKey: string = weekKey) => { if (userId) { - await scheduleEventInSupabase(userId, eventId, weekKey); + await scheduleEventInSupabase(userId, eventId, forWeekKey); } else { - scheduleEvent(eventId, weekKey); + scheduleEvent(eventId, forWeekKey); } await loadScheduled(); }, @@ -68,13 +71,13 @@ export function useScheduledEvents(rawUserId: string | undefined, weekKey: strin const unscheduleEventForWeek = useCallback( async (eventId: string) => { if (userId) { - await unscheduleEventInSupabase(userId, eventId, weekKey); + await unscheduleEventInSupabase(userId, eventId); } else { - unscheduleEvent(eventId, weekKey); + unscheduleEvent(eventId); } await loadScheduled(); }, - [userId, weekKey, loadScheduled] + [userId, loadScheduled] ); return { diff --git a/apps/client/lib/scheduledEventsApi.ts b/apps/client/lib/scheduledEventsApi.ts index 3fdf1be..f742c6a 100644 --- a/apps/client/lib/scheduledEventsApi.ts +++ b/apps/client/lib/scheduledEventsApi.ts @@ -28,17 +28,17 @@ export async function scheduleEventInSupabase( if (error) throw error; } +// An event belongs to exactly one week, so unpinning removes it whatever week +// it was filed under. export async function unscheduleEventInSupabase( userId: string, - eventId: string, - weekKey: string + eventId: string ): Promise { const { error } = await supabase .from('user_scheduled_events') .delete() .eq('user_id', userId) - .eq('event_id', eventId) - .eq('week_key', weekKey); + .eq('event_id', eventId); if (error) throw error; } diff --git a/apps/client/package.json b/apps/client/package.json index 9b0742a..2d7cc71 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -9,6 +9,7 @@ "typecheck": "tsc --noEmit", "reset-project": "node ./scripts/reset-project.js", "seed": "npx tsx scripts/seedEvents.ts", + "refresh-events": "node scripts/refreshEventDates.js", "test:backend": "npx tsx scripts/test-backend.ts", "test:unit": "tsx --test tests/*.test.ts", "test:e2e": "playwright test", diff --git a/apps/client/scripts/refreshEventDates.js b/apps/client/scripts/refreshEventDates.js new file mode 100644 index 0000000..d7cd7ac --- /dev/null +++ b/apps/client/scripts/refreshEventDates.js @@ -0,0 +1,180 @@ +/** + * Re-date the bundled demo events onto the current month. + * + * The seed catalogue is content the app ships with — real CMU-flavoured + * titles, locations and organisers — but its dates go stale the moment the + * month turns over, and an events app whose events are all in the past looks + * broken. This rewrites `data/allEvents.json` in place, spreading every event + * across a window that starts on the 1st of the current month and runs at + * least three weeks past today, so there is always a mix of events that + * already happened, events happening today, and events still to come. + * + * Content, ids and RSVP counts are preserved — ids especially, so RSVPs and + * calendar pins saved on a device still line up after a refresh. + * + * Usage: + * node scripts/refreshEventDates.js # anchor on today + * node scripts/refreshEventDates.js --today 2026-09-03 + */ +const fs = require('fs'); +const path = require('path'); + +// Campus time. Wall-clock hours in the source data are treated as local +// Pittsburgh times so a 10:00 career fair stays a 10:00 career fair. +const TIME_ZONE = 'America/New_York'; + +const DATA_FILE = path.join(__dirname, '..', 'data', 'allEvents.json'); +const DAY_MS = 24 * 60 * 60 * 1000; +// Always keep at least this much future runway, even when run on the 30th +const MIN_FUTURE_DAYS = 21; +// Titles that read like a standing commitment become weekly series +const RECURRING_TITLE = /weekly|practice|study group|office hours|rehearsal|club meeting/i; +const MAX_RECURRING = 6; + +/** Offset of `timeZone` from UTC, in ms, at the given instant. */ +function offsetMs(date, timeZone) { + const parts = new Intl.DateTimeFormat('en-US', { + timeZone, + hour12: false, + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + }) + .formatToParts(date) + .reduce((acc, part) => ({ ...acc, [part.type]: part.value }), {}); + + const asUtc = Date.UTC( + Number(parts.year), + Number(parts.month) - 1, + Number(parts.day), + Number(parts.hour) % 24, + Number(parts.minute), + Number(parts.second) + ); + return asUtc - date.getTime(); +} + +/** The wall-clock hour and minute an instant lands on in `timeZone`. */ +function zonedHourMinute(date, timeZone) { + const parts = new Intl.DateTimeFormat('en-US', { + timeZone, + hour12: false, + hour: '2-digit', + minute: '2-digit', + }) + .formatToParts(date) + .reduce((acc, part) => ({ ...acc, [part.type]: part.value }), {}); + return { hour: Number(parts.hour) % 24, minute: Number(parts.minute) }; +} + +/** Wall-clock time in `timeZone` -> the UTC instant it refers to. */ +function zonedToUtc(year, month, day, hour, minute, timeZone) { + const naive = Date.UTC(year, month - 1, day, hour, minute); + // One correction pass is exact except inside a DST transition hour + return new Date(naive - offsetMs(new Date(naive), timeZone)); +} + +function parseArgs(argv) { + const todayIndex = argv.indexOf('--today'); + if (todayIndex === -1) return { today: new Date() }; + const value = argv[todayIndex + 1]; + const parsed = new Date(`${value}T12:00:00Z`); + if (isNaN(parsed.getTime())) { + throw new Error(`--today expects YYYY-MM-DD, got "${value}"`); + } + return { today: parsed }; +} + +function isoDate(date) { + return date.toISOString().slice(0, 10); +} + +function main() { + const { today } = parseArgs(process.argv.slice(2)); + const year = today.getUTCFullYear(); + const month = today.getUTCMonth() + 1; + const dayOfMonth = today.getUTCDate(); + const daysInMonth = new Date(Date.UTC(year, month, 0)).getUTCDate(); + + // 1st of this month .. end of month (or 3 weeks out, whichever is later) + const spanDays = Math.max(daysInMonth, dayOfMonth + MIN_FUTURE_DAYS); + + const events = JSON.parse(fs.readFileSync(DATA_FILE, 'utf8')); + if (!Array.isArray(events) || events.length === 0) { + throw new Error(`No events found in ${DATA_FILE}`); + } + + // Order by id, not by current date: ids never change, so re-running this + // script lands every event on exactly the same day rather than reshuffling + // the catalogue a little further each time. + const ordered = [...events].sort((a, b) => a.id.localeCompare(b.id)); + + const windowStart = zonedToUtc(year, month, 1, 0, 0, TIME_ZONE); + const windowEnd = new Date(windowStart.getTime() + (spanDays - 1) * DAY_MS); + + let recurringLeft = MAX_RECURRING; + const counts = { past: 0, today: 0, future: 0, recurring: 0 }; + + ordered.forEach((event, index) => { + const start = new Date(event.startTime); + const end = new Date(event.endTime); + const durationMs = Math.max(end.getTime() - start.getTime(), 30 * 60 * 1000); + + // Keep each event at the campus-local hour it already runs at, so + // re-running this script never drifts a 7pm event into a 3pm one + const { hour, minute } = zonedHourMinute(start, TIME_ZONE); + + // Even spread across the window, in catalogue order + const dayOffset = Math.floor((index * spanDays) / ordered.length); + const slotDay = new Date(windowStart.getTime() + dayOffset * DAY_MS); + const newStart = zonedToUtc( + slotDay.getUTCFullYear(), + slotDay.getUTCMonth() + 1, + slotDay.getUTCDate(), + hour, + minute, + TIME_ZONE + ); + const newEnd = new Date(newStart.getTime() + durationMs); + + event.startTime = newStart.toISOString(); + event.endTime = newEnd.toISOString(); + event.createdAt = new Date(newStart.getTime() - 21 * DAY_MS).toISOString(); + event.updatedAt = new Date(newStart.getTime() - 7 * DAY_MS).toISOString(); + + // A few standing commitments repeat weekly through the window + if ( + recurringLeft > 0 && + dayOffset < 10 && + RECURRING_TITLE.test(event.title) && + !event.recurring + ) { + event.recurring = { + frequency: 'weekly', + interval: 1, + endDate: isoDate(new Date(windowEnd.getTime() + 28 * DAY_MS)), + }; + recurringLeft -= 1; + } + if (event.recurring) counts.recurring += 1; + + const startsToday = isoDate(newStart) === isoDate(today); + if (startsToday) counts.today += 1; + else if (newEnd < today) counts.past += 1; + else counts.future += 1; + }); + + fs.writeFileSync(DATA_FILE, `${JSON.stringify(ordered, null, 2)}\n`); + + console.log( + `Re-dated ${ordered.length} events onto ${isoDate(windowStart)} .. ${isoDate(windowEnd)}` + ); + console.log( + ` ${counts.past} already happened, ${counts.today} today, ${counts.future} upcoming, ${counts.recurring} weekly series` + ); +} + +main(); diff --git a/apps/client/tests/localRsvps.test.ts b/apps/client/tests/localRsvps.test.ts new file mode 100644 index 0000000..dc028d4 --- /dev/null +++ b/apps/client/tests/localRsvps.test.ts @@ -0,0 +1,103 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { + applyLocalRsvp, + applyLocalRsvps, + getLocalRsvp, + parseRsvpStore, + setLocalRsvp, +} from '../utils/localRsvps'; +import type { Event } from '../types/event'; + +function makeEvent(overrides: Partial & { id: string }): Event { + return { + title: 'Untitled', + description: '', + startTime: '2026-08-14T19:00:00.000Z', + endTime: '2026-08-14T20:00:00.000Z', + location: '', + categories: [], + organizer: { id: 'org', name: 'Org', type: 'club' }, + color: '#FF6B6B', + rsvpEnabled: true, + rsvpCounts: { going: 0, maybe: 0, notGoing: 0 }, + attendees: [], + attendeeVisibility: 'public', + isClubEvent: true, + isSocialEvent: false, + tags: [], + createdAt: '2026-08-01T00:00:00.000Z', + updatedAt: '2026-08-01T00:00:00.000Z', + ...overrides, + }; +} + +test('parseRsvpStore tolerates missing and malformed values', () => { + assert.deepEqual(parseRsvpStore(null), {}); + assert.deepEqual(parseRsvpStore(''), {}); + assert.deepEqual(parseRsvpStore('not json'), {}); + assert.deepEqual(parseRsvpStore('[1,2,3]'), {}); + assert.deepEqual(parseRsvpStore('{"u1":{"e1":"banana"}}'), {}); + assert.deepEqual(parseRsvpStore('{"u1":{"e1":"going","e2":"nope"}}'), { + u1: { e1: 'going' }, + }); +}); + +test('setLocalRsvp stores, replaces and clears without touching other users', () => { + let store = setLocalRsvp({}, 'u1', 'e1', 'going'); + store = setLocalRsvp(store, 'u2', 'e1', 'maybe'); + assert.equal(getLocalRsvp(store, 'u1', 'e1'), 'going'); + assert.equal(getLocalRsvp(store, 'u2', 'e1'), 'maybe'); + + store = setLocalRsvp(store, 'u1', 'e1', 'maybe'); + assert.equal(getLocalRsvp(store, 'u1', 'e1'), 'maybe'); + + store = setLocalRsvp(store, 'u1', 'e1', null); + assert.equal(getLocalRsvp(store, 'u1', 'e1'), null); + assert.equal(getLocalRsvp(store, 'u2', 'e1'), 'maybe'); + assert.ok(!('u1' in store), 'empty users are dropped'); +}); + +test('applying an RSVP adds the attendee and bumps the count once', () => { + const event = makeEvent({ id: 'e1', rsvpCounts: { going: 4, maybe: 1, notGoing: 0 } }); + const going = applyLocalRsvp(event, 'u1', 'going', 'now'); + + assert.deepEqual(going.rsvpCounts, { going: 5, maybe: 1, notGoing: 0 }); + assert.deepEqual(going.attendees, [{ userId: 'u1', status: 'going', timestamp: 'now' }]); + // Re-applying the same status must not double count + assert.equal(applyLocalRsvp(going, 'u1', 'going', 'now'), going); +}); + +test('changing an RSVP moves the count from one bucket to the other', () => { + const event = makeEvent({ + id: 'e1', + rsvpCounts: { going: 5, maybe: 1, notGoing: 0 }, + attendees: [{ userId: 'u1', status: 'going', timestamp: 'then' }], + }); + const maybe = applyLocalRsvp(event, 'u1', 'maybe', 'now'); + assert.deepEqual(maybe.rsvpCounts, { going: 4, maybe: 2, notGoing: 0 }); + assert.deepEqual(maybe.attendees, [{ userId: 'u1', status: 'maybe', timestamp: 'now' }]); +}); + +test('clearing an RSVP removes the attendee and never drives a count negative', () => { + const event = makeEvent({ + id: 'e1', + rsvpCounts: { going: 0, maybe: 0, notGoing: 0 }, + attendees: [{ userId: 'u1', status: 'going', timestamp: 'then' }], + }); + const cleared = applyLocalRsvp(event, 'u1', null); + assert.deepEqual(cleared.rsvpCounts, { going: 0, maybe: 0, notGoing: 0 }); + assert.deepEqual(cleared.attendees, []); +}); + +test('applyLocalRsvps only touches the signed-in user’s saved events', () => { + const events = [makeEvent({ id: 'e1' }), makeEvent({ id: 'e2' })]; + const store = setLocalRsvp(setLocalRsvp({}, 'u1', 'e1', 'going'), 'u2', 'e2', 'going'); + + const forU1 = applyLocalRsvps(events, store, 'u1', 'now'); + assert.deepEqual(forU1[0].attendees, [{ userId: 'u1', status: 'going', timestamp: 'now' }]); + assert.deepEqual(forU1[1].attendees, []); + + // Signed out: nothing is applied + assert.equal(applyLocalRsvps(events, store, undefined), events); +}); diff --git a/apps/client/tests/myEvents.test.ts b/apps/client/tests/myEvents.test.ts new file mode 100644 index 0000000..a35e5ee --- /dev/null +++ b/apps/client/tests/myEvents.test.ts @@ -0,0 +1,156 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { relationForEvent, selectMyEvents, eventsInRange } from '../utils/myEvents'; +import type { Event } from '../types/event'; + +function makeEvent(overrides: Partial & { id: string }): Event { + return { + title: 'Untitled', + description: '', + startTime: '2026-08-14T19:00:00.000Z', + endTime: '2026-08-14T20:00:00.000Z', + location: '', + categories: [], + organizer: { id: 'org', name: 'Org', type: 'club' }, + color: '#FF6B6B', + rsvpEnabled: true, + rsvpCounts: { going: 0, maybe: 0, notGoing: 0 }, + attendees: [], + attendeeVisibility: 'public', + isClubEvent: true, + isSocialEvent: false, + tags: [], + createdAt: '2026-08-01T00:00:00.000Z', + updatedAt: '2026-08-01T00:00:00.000Z', + ...overrides, + }; +} + +test('an RSVP alone makes an event one of mine', () => { + const event = makeEvent({ + id: 'evt-1', + attendees: [{ userId: 'u1', status: 'going', timestamp: '' }], + }); + assert.equal(relationForEvent(event, { userId: 'u1' }), 'going'); + assert.deepEqual( + selectMyEvents([event], { userId: 'u1' }).map((e) => e.id), + ['evt-1'] + ); +}); + +test('maybe counts, not-going does not', () => { + const maybe = makeEvent({ + id: 'maybe', + attendees: [{ userId: 'u1', status: 'maybe', timestamp: '' }], + }); + const declined = makeEvent({ + id: 'declined', + attendees: [{ userId: 'u1', status: 'not-going', timestamp: '' }], + }); + assert.equal(relationForEvent(maybe, { userId: 'u1' }), 'maybe'); + assert.equal(relationForEvent(declined, { userId: 'u1' }), null); + assert.deepEqual( + selectMyEvents([maybe, declined], { userId: 'u1' }).map((e) => e.id), + ['maybe'] + ); +}); + +test("another user's RSVP is not mine", () => { + const event = makeEvent({ + id: 'evt-1', + attendees: [{ userId: 'someone-else', status: 'going', timestamp: '' }], + }); + assert.equal(relationForEvent(event, { userId: 'u1' }), null); +}); + +test('hosting outranks an RSVP, and an RSVP outranks a pin', () => { + const hosted = makeEvent({ + id: 'evt-1', + attendees: [{ userId: 'u1', status: 'going', timestamp: '' }], + }); + assert.equal( + relationForEvent(hosted, { userId: 'u1', createdIds: ['evt-1'], scheduledIds: ['evt-1'] }), + 'created' + ); + + const rsvped = makeEvent({ + id: 'evt-2', + attendees: [{ userId: 'u1', status: 'going', timestamp: '' }], + }); + assert.equal(relationForEvent(rsvped, { userId: 'u1', scheduledIds: ['evt-2'] }), 'going'); + + const pinned = makeEvent({ id: 'evt-3' }); + assert.equal(relationForEvent(pinned, { userId: 'u1', scheduledIds: ['evt-3'] }), 'scheduled'); +}); + +test('a recurring occurrence inherits the relationship of its series', () => { + const occurrence = makeEvent({ + id: 'evt-1::2026-08-21', + attendees: [{ userId: 'u1', status: 'going', timestamp: '' }], + }); + assert.equal(relationForEvent(occurrence, { userId: 'u1' }), 'going'); + + const pinnedOccurrence = makeEvent({ id: 'evt-9::2026-08-21' }); + assert.equal( + relationForEvent(pinnedOccurrence, { userId: 'u1', scheduledIds: ['evt-9'] }), + 'scheduled' + ); +}); + +test('signed-out users have no events of their own', () => { + const event = makeEvent({ + id: 'evt-1', + attendees: [{ userId: 'u1', status: 'going', timestamp: '' }], + }); + assert.deepEqual(selectMyEvents([event], {}), []); +}); + +test('selectMyEvents returns events in start-time order', () => { + const later = makeEvent({ + id: 'later', + startTime: '2026-08-20T19:00:00.000Z', + endTime: '2026-08-20T20:00:00.000Z', + attendees: [{ userId: 'u1', status: 'going', timestamp: '' }], + }); + const sooner = makeEvent({ + id: 'sooner', + startTime: '2026-08-13T19:00:00.000Z', + endTime: '2026-08-13T20:00:00.000Z', + attendees: [{ userId: 'u1', status: 'going', timestamp: '' }], + }); + assert.deepEqual( + selectMyEvents([later, sooner], { userId: 'u1' }).map((e) => e.id), + ['sooner', 'later'] + ); +}); + +test('eventsInRange keeps anything overlapping the window', () => { + const before = makeEvent({ + id: 'before', + startTime: '2026-08-01T10:00:00.000Z', + endTime: '2026-08-01T11:00:00.000Z', + }); + const spanning = makeEvent({ + id: 'spanning', + startTime: '2026-08-09T23:00:00.000Z', + endTime: '2026-08-10T02:00:00.000Z', + }); + const inside = makeEvent({ + id: 'inside', + startTime: '2026-08-12T10:00:00.000Z', + endTime: '2026-08-12T11:00:00.000Z', + }); + const after = makeEvent({ + id: 'after', + startTime: '2026-09-01T10:00:00.000Z', + endTime: '2026-09-01T11:00:00.000Z', + }); + + const kept = eventsInRange( + [before, spanning, inside, after], + new Date('2026-08-10T00:00:00.000Z'), + new Date('2026-08-16T23:59:59.999Z') + ).map((e) => e.id); + + assert.deepEqual(kept, ['spanning', 'inside']); +}); diff --git a/apps/client/utils/devTools.ts b/apps/client/utils/devTools.ts index 116eb35..31c3061 100644 --- a/apps/client/utils/devTools.ts +++ b/apps/client/utils/devTools.ts @@ -2,8 +2,8 @@ import { Event, EventCategory } from '@/types/event'; /** * Dev-mode helpers: generate realistic test events pinned to the CURRENT - * week (the bundled mock data has fixed dates that drift into the past), - * so the calendar and feed always have something fresh to show. + * week, so there is always something fresh to test against without waiting + * on the bundled catalogue (which is re-dated by scripts/refreshEventDates.js). */ const SAMPLE_TITLES: { title: string; categories: EventCategory[]; location: string }[] = [ diff --git a/apps/client/utils/localRsvps.ts b/apps/client/utils/localRsvps.ts new file mode 100644 index 0000000..83e1319 --- /dev/null +++ b/apps/client/utils/localRsvps.ts @@ -0,0 +1,124 @@ +import { Event, RSVPStatus } from '@/types/event'; + +/** + * RSVPs kept on the device. + * + * The app runs in offline/demo mode when no Supabase credentials are present, + * and dev-mode personas are never real auth.users rows — in both cases an RSVP + * has nowhere to go on a server. Without this it would live in React state + * only and vanish on the next reload, which reads as "I signed up and the app + * forgot". Shape: { [userId]: { [eventId]: status } }. + */ +export type LocalRsvpStore = Record>>; + +export const LOCAL_RSVP_STORAGE_KEY = 'universify_local_rsvps'; + +const COUNT_KEY = { + going: 'going', + maybe: 'maybe', + 'not-going': 'notGoing', +} as const; + +/** Parse a persisted store, tolerating absent or corrupt values. */ +export function parseRsvpStore(raw: string | null | undefined): LocalRsvpStore { + if (!raw) return {}; + try { + const parsed = JSON.parse(raw); + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return {}; + const store: LocalRsvpStore = {}; + for (const [userId, byEvent] of Object.entries(parsed as Record)) { + if (!byEvent || typeof byEvent !== 'object' || Array.isArray(byEvent)) continue; + const clean: Record> = {}; + for (const [eventId, status] of Object.entries(byEvent as Record)) { + if (status === 'going' || status === 'maybe' || status === 'not-going') { + clean[eventId] = status; + } + } + if (Object.keys(clean).length > 0) store[userId] = clean; + } + return store; + } catch { + return {}; + } +} + +/** The user's stored status for an event, if any. */ +export function getLocalRsvp( + store: LocalRsvpStore, + userId: string, + eventId: string +): RSVPStatus { + return store[userId]?.[eventId] ?? null; +} + +/** Return a new store with the user's RSVP set (or cleared when null). */ +export function setLocalRsvp( + store: LocalRsvpStore, + userId: string, + eventId: string, + status: RSVPStatus +): LocalRsvpStore { + const forUser = { ...(store[userId] ?? {}) }; + if (status) { + forUser[eventId] = status; + } else { + delete forUser[eventId]; + } + const next = { ...store }; + if (Object.keys(forUser).length > 0) { + next[userId] = forUser; + } else { + delete next[userId]; + } + return next; +} + +/** + * Apply one stored RSVP to an event, keeping the aggregate counts consistent + * with the attendee list. Returns the event untouched when nothing changes. + */ +export function applyLocalRsvp( + event: Event, + userId: string, + status: RSVPStatus, + timestamp: string = new Date().toISOString() +): Event { + const existing = event.attendees.find((a) => a.userId === userId)?.status ?? null; + if (existing === status) return event; + + const rsvpCounts = { ...event.rsvpCounts }; + if (existing) { + const key = COUNT_KEY[existing]; + rsvpCounts[key] = Math.max(0, rsvpCounts[key] - 1); + } + if (status) { + const key = COUNT_KEY[status]; + rsvpCounts[key] = rsvpCounts[key] + 1; + } + + const attendees = event.attendees.filter((a) => a.userId !== userId); + if (status) attendees.push({ userId, status, timestamp }); + + return { ...event, rsvpCounts, attendees }; +} + +/** + * Layer the user's stored RSVPs over freshly loaded events, so a reload comes + * back with the same "You're going" state the user left behind. + */ +export function applyLocalRsvps( + events: Event[], + store: LocalRsvpStore, + userId: string | null | undefined, + timestamp?: string +): Event[] { + if (!userId) return events; + const forUser = store[userId]; + if (!forUser || Object.keys(forUser).length === 0) return events; + + return events.map((event) => { + const status = forUser[event.id]; + if (!status) return event; + return applyLocalRsvp(event, userId, status, timestamp); + }); +} diff --git a/apps/client/utils/myEvents.ts b/apps/client/utils/myEvents.ts new file mode 100644 index 0000000..d371d2b --- /dev/null +++ b/apps/client/utils/myEvents.ts @@ -0,0 +1,66 @@ +import { Event } from '@/types/event'; +import { baseEventId } from '@/utils/recurringEvents'; + +/** + * Why an event belongs to a user. Ordered by how strong the relationship is: + * hosting beats an RSVP, and an RSVP beats a plain calendar pin. + */ +export type MyEventRelation = 'created' | 'going' | 'maybe' | 'scheduled'; + +export interface MyEventContext { + /** Current user id, when signed in. */ + userId?: string | null; + /** Ids of events the user created. */ + createdIds?: readonly string[]; + /** Ids of events the user pinned to their calendar (across all weeks). */ + scheduledIds?: readonly string[]; +} + +/** + * How the given event relates to the user, or null if it doesn't. + * + * Accepts recurring-occurrence copies ("::") and resolves them to + * the base event, so an occurrence inherits the RSVP made on its series. + */ +export function relationForEvent(event: Event, ctx: MyEventContext): MyEventRelation | null { + const id = baseEventId(event.id); + + if (ctx.createdIds?.includes(id)) return 'created'; + + if (ctx.userId) { + const status = event.attendees.find((a) => a.userId === ctx.userId)?.status; + if (status === 'going') return 'going'; + if (status === 'maybe') return 'maybe'; + } + + if (ctx.scheduledIds?.includes(id)) return 'scheduled'; + + // Explicit "not going" and everything else is not the user's event + return null; +} + +/** + * Every event the user has a relationship with — what they're going to, + * maybe attending, hosting, or pinned — sorted by start time. + * + * This is the single definition of "my events" behind the calendar, the + * mobile agenda and the My Events screen, so an RSVP shows up everywhere + * without each screen re-deriving its own rules. + */ +export function selectMyEvents(events: Event[], ctx: MyEventContext): Event[] { + return events + .filter((event) => relationForEvent(event, ctx) !== null) + .sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime()); +} + +/** Events from `events` that overlap [rangeStart, rangeEnd]. */ +export function eventsInRange(events: Event[], rangeStart: Date, rangeEnd: Date): Event[] { + const start = rangeStart.getTime(); + const end = rangeEnd.getTime(); + return events.filter((event) => { + const eventStart = new Date(event.startTime).getTime(); + const eventEnd = new Date(event.endTime).getTime(); + if (isNaN(eventStart) || isNaN(eventEnd)) return false; + return eventStart <= end && eventEnd >= start; + }); +} diff --git a/apps/client/utils/scheduledEvents.ts b/apps/client/utils/scheduledEvents.ts index 8e7c4d4..53d5bfb 100644 --- a/apps/client/utils/scheduledEvents.ts +++ b/apps/client/utils/scheduledEvents.ts @@ -74,13 +74,21 @@ export const scheduleEvent = (eventId: string, weekKey: string): void => { } }; -// Remove an event from a week's schedule -export const unscheduleEvent = (eventId: string, weekKey: string): void => { +// Remove an event from the schedule. +// An event belongs to exactly one week, so unpinning clears it from every +// week bucket — that also cleans up pins older versions filed under the week +// the user happened to be viewing rather than the event's own week. +export const unscheduleEvent = (eventId: string): void => { const scheduled = getScheduledEvents(); - if (scheduled[weekKey]) { - scheduled[weekKey] = scheduled[weekKey].filter(id => id !== eventId); - saveScheduledEvents(scheduled); + let changed = false; + for (const weekKey of Object.keys(scheduled)) { + const next = scheduled[weekKey].filter((id) => id !== eventId); + if (next.length !== scheduled[weekKey].length) { + scheduled[weekKey] = next; + changed = true; + } } + if (changed) saveScheduledEvents(scheduled); }; // Get all event IDs scheduled for a week