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