From 0c4290cfd958b8100331e52ea2d38f6774fd227c Mon Sep 17 00:00:00 2001 From: Aaren Pan Date: Wed, 8 Oct 2025 19:10:01 -0400 Subject: [PATCH 1/3] Implemented Pre-Hackathon Events subsection under Schedule --- src/components/Schedule/index.tsx | 291 +++++++++++++++++++++--------- 1 file changed, 208 insertions(+), 83 deletions(-) diff --git a/src/components/Schedule/index.tsx b/src/components/Schedule/index.tsx index b5ad3aeb..38732f46 100644 --- a/src/components/Schedule/index.tsx +++ b/src/components/Schedule/index.tsx @@ -544,6 +544,80 @@ const assignColumns = ( }; }; +// PreHackathonList: Renders a scrollable list of pre-hackathon events +interface PreHackathonEvent { + id: string; + name: string; + type: EventType; + location: string; + startTime: Date; + endTime: Date; + duration: number; +} + +const PreHackathonList: React.FC<{ + events: PreHackathonEvent[]; + onEventClick: (event: PreHackathonEvent) => void; + isMobile: boolean; +}> = ({ events, onEventClick, isMobile }) => { + return ( +
+
+

Pre-Hackathon Events

+
+
+ {events.length === 0 ? ( +

No pre-hackathon events at this time.

+ ) : ( + + )} +
+ ); +}; + const Schedule: React.FC = () => { const { data: events, isLoading, error } = useAllEvents(); const { data: twoHourFlag } = useFlagState("TwoHourIncrement"); @@ -680,6 +754,7 @@ const Schedule: React.FC = () => { return { Saturday: { events: [], totalColumns: 1 }, Sunday: { events: [], totalColumns: 1 }, + PreHackathon: [], }; // Filter events by selected categories @@ -690,25 +765,46 @@ const Schedule: React.FC = () => { const eventsByDay: { Saturday: Omit[]; Sunday: Omit[]; + PreHackathon: PreHackathonEvent[]; } = { Saturday: [], Sunday: [], + PreHackathon: [], }; + // Helper to determine if a date is on the weekend + const isWeekend = (date: Date) => { + const d = date.getDay(); + return d === 6 || d === 0; + }; + + // Saturday = 6, Sunday = 0 filteredEvents.forEach((event) => { const startTime = new Date(event.startTime); const endTime = new Date(event.endTime); - const startDayOfWeek = startTime.getDay(); // 0 = Sunday, 6 = Saturday + const startDayOfWeek = startTime.getDay(); const endDayOfWeek = endTime.getDay(); - // Only process Saturday (6) and Sunday (0) events - if ( - startDayOfWeek !== 0 && - startDayOfWeek !== 6 && - endDayOfWeek !== 0 && - endDayOfWeek !== 6 - ) + // Adds event to PreHackathon if begins before hackathon weekend + const isPreHackathon = + (startDayOfWeek !== 6 && startDayOfWeek !== 0) && + (endDayOfWeek !== 6 && endDayOfWeek !== 0); + + // Checks if event ends, or starts and ends, before Saturday + if (isPreHackathon) { + const duration = + (endTime.getTime() - startTime.getTime()) / (1000 * 60); // minutes + eventsByDay.PreHackathon.push({ + id: event.id, + name: event.name, + type: event.type, + location: event.location.name, + startTime, + endTime, + duration, + }); return; + } // Check if event crosses midnight (spans multiple days) const crossesMidnight = startTime.getDate() !== endTime.getDate(); @@ -802,6 +898,7 @@ const Schedule: React.FC = () => { return { Saturday: saturdayResult, Sunday: sundayResult, + PreHackathon: eventsByDay.PreHackathon, }; }, [events, selectedCategories]); @@ -1004,85 +1101,113 @@ const Schedule: React.FC = () => { {/* Calendar Grid */} - - {/* Day Tabs - Integrated Header */} -
-
- {(["Saturday", "Sunday"] as const).map((day) => ( - setActiveDay(day)} - className={`flex-1 py-4 px-6 font-bold transition-all duration-300 ${ - activeDay === day - ? "bg-[#215172] text-white" - : "bg-[#1a3f5c] text-white/70 hover:text-white hover:bg-[#215172]/80" - }`} - style={{ fontFamily: "Monomaniac One, monospace" }} - whileHover={{ scale: 1.02 }} - whileTap={{ scale: 0.98 }} - initial={{ opacity: 0, y: -20 }} - animate={{ opacity: 1, y: 0 }} - transition={{ duration: 0.5 }} - > -
- {day} -
-
{ + // Open modal with minimal event info + setSelectedEvent({ + id: event.id, + name: event.name, + type: event.type, + location: event.location, + startTime: event.startTime, + endTime: event.endTime, + day: "Saturday", // Not used for modal + duration: event.duration, + startMinutes: event.startTime.getHours() * 60 + event.startTime.getMinutes(), + endMinutes: event.endTime.getHours() * 60 + event.endTime.getMinutes(), + column: 0, + }); + setIsModalOpen(true); + }} + isMobile={isMobile} + /> + + {/* Day Tabs */} +
+
+ {(["Saturday", "Sunday"] as const).map((day) => ( + setActiveDay(day)} + className={`flex-1 py-4 px-6 font-bold transition-all duration-300 ${ + activeDay === day + ? "bg-[#215172] text-white" + : "bg-[#1a3f5c] text-white/70 hover:text-white hover:bg-[#215172]/80" + }`} + style={{ fontFamily: "Monomaniac One, monospace" }} + whileHover={{ scale: 1.02 }} + whileTap={{ scale: 0.98 }} + initial={{ opacity: 0, y: -20 }} + animate={{ opacity: 1, y: 0 }} + transition={{ duration: 0.5 }} > - {day === "Saturday" - ? `${processedEvents.Saturday.events.length} event${processedEvents.Saturday.events.length !== 1 ? "s" : ""}` - : `${processedEvents.Sunday.events.length} event${processedEvents.Sunday.events.length !== 1 ? "s" : ""}`} -
- - ))} +
+ {day} +
+
+ {day === "Saturday" + ? `${processedEvents.Saturday.events.length} event${processedEvents.Saturday.events.length !== 1 ? "s" : ""}` + : `${processedEvents.Sunday.events.length} event${processedEvents.Sunday.events.length !== 1 ? "s" : ""}`} +
+ + ))} +
-
-
- - - - - -
- +
+ + + + + +
+ +
{/* Download .ics Button */}
From 413ae6c6d46900b7669da3f291ee63b955f78d8d Mon Sep 17 00:00:00 2001 From: Kanishk Sachdev Date: Thu, 9 Oct 2025 04:34:19 -0400 Subject: [PATCH 2/3] Disable helpdesk --- src/app/(protected)/profile/page.tsx | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/app/(protected)/profile/page.tsx b/src/app/(protected)/profile/page.tsx index 376eb5bb..034e096d 100644 --- a/src/app/(protected)/profile/page.tsx +++ b/src/app/(protected)/profile/page.tsx @@ -9,6 +9,7 @@ import { useCreateAppleWalletPass, } from "@/lib/api/wallet/hook"; import { useAllTeams } from "@/lib/api/team"; +import { useFlagState } from "@/lib/api/flag/hook"; import Image from "next/image"; import QRCode from "react-qr-code"; import { Button } from "@/components/ui/button"; @@ -55,6 +56,9 @@ export default function Profile() { const [showQRCode, setShowQRCode] = useState(false); + // Feature flag check for HelpDesk + const { data: helpDeskFlag } = useFlagState("HelpDesk"); + const toggleQRCode = () => setShowQRCode((prev) => !prev); useEffect(() => { @@ -447,15 +451,17 @@ export default function Profile() { Manage Extra Credit - + {helpDeskFlag?.isEnabled && ( + + )} From 3872795b68f74e9aa74d144923e68426c8576c1a Mon Sep 17 00:00:00 2001 From: Kanishk Sachdev Date: Thu, 9 Oct 2025 04:53:49 -0400 Subject: [PATCH 3/3] Make events toggleable and match theme --- src/components/Schedule/index.tsx | 161 +++++++++++++++++++----------- 1 file changed, 100 insertions(+), 61 deletions(-) diff --git a/src/components/Schedule/index.tsx b/src/components/Schedule/index.tsx index 38732f46..ef3ac81b 100644 --- a/src/components/Schedule/index.tsx +++ b/src/components/Schedule/index.tsx @@ -562,56 +562,56 @@ const PreHackathonList: React.FC<{ }> = ({ events, onEventClick, isMobile }) => { return (
-
-

Pre-Hackathon Events

-
+
+

Pre-Hackathon Events

+
{events.length === 0 ? ( -

No pre-hackathon events at this time.

+

No pre-hackathon events at this time.

) : (
    {events .sort((a, b) => a.startTime.getTime() - b.startTime.getTime()) - .map((event) => ( -
  • onEventClick(event)} - > -
    {event.name}
    -
    - {event.startTime.toLocaleDateString("en-US", { - weekday: "short", - month: "short", - day: "numeric", - })} - {" · "} - {event.startTime.toLocaleTimeString("en-US", { - hour: "numeric", - minute: "2-digit", - hour12: true, - })} - {" - "} - {event.endTime.toLocaleTimeString("en-US", { - hour: "numeric", - minute: "2-digit", - hour12: true, - })} -
    -
    {event.location}
    -
  • - ))} + .map((event) => { + const colors = eventTypeColors[event.type]; + return ( +
  • onEventClick(event)} + > +
    {event.name}
    +
    + {event.startTime.toLocaleDateString("en-US", { + weekday: "short", + month: "short", + day: "numeric", + })} +
    +
    + {event.startTime.toLocaleTimeString("en-US", { + hour: "numeric", + minute: "2-digit", + hour12: true, + })} + {" - "} + {event.endTime.toLocaleTimeString("en-US", { + hour: "numeric", + minute: "2-digit", + hour12: true, + })} +
    +
    {event.location}
    +
  • + ); + })}
)}
@@ -667,6 +667,9 @@ const Schedule: React.FC = () => { // State for active day tab const [activeDay, setActiveDay] = useState<"Saturday" | "Sunday">("Saturday"); + // State for toggling pre-hackathon events visibility + const [showPreEvents, setShowPreEvents] = useState(true); + // Handle event click const handleEventClick = (event: ProcessedEvent) => { setSelectedEvent(event); @@ -902,6 +905,13 @@ const Schedule: React.FC = () => { }; }, [events, selectedCategories]); + // Check if there are any upcoming pre-hackathon events + const hasUpcomingPreEvents = useMemo(() => { + if (processedEvents.PreHackathon.length === 0) return false; + const now = new Date(); + return processedEvents.PreHackathon.some(event => event.endTime > now); + }, [processedEvents.PreHackathon]); + // Calculate time range to show const timeRange = useMemo(() => { if (!events || events.length === 0) return { start: 8, end: 22 }; // default 8 AM to 10 PM @@ -1098,41 +1108,70 @@ const Schedule: React.FC = () => { : `Showing ${selectedCategories.size} of ${Object.keys(EventType).length} categories`}
+ + {/* Toggle for Pre-Hackathon Events */} + {hasUpcomingPreEvents && ( +
+ setShowPreEvents(!showPreEvents)} + className={`px-6 py-3 rounded-xl font-bold text-sm border-3 transition-all duration-300 ${ + showPreEvents + ? "bg-[#215172] border-[#215172] text-white" + : "bg-white/80 border-[#215172] text-[#215172] hover:bg-white" + }`} + style={{ fontFamily: "Monomaniac One, monospace" }} + whileHover={{ scale: 1.05 }} + whileTap={{ scale: 0.95 }} + > + {showPreEvents ? "Hide" : "Show"} Pre-Hackathon Events + +
+ )} {/* Calendar Grid */}
{/* PreHackathonList: Displayed left of calendar on desktop, above on mobile */} - { - // Open modal with minimal event info - setSelectedEvent({ - id: event.id, - name: event.name, - type: event.type, - location: event.location, - startTime: event.startTime, - endTime: event.endTime, - day: "Saturday", // Not used for modal - duration: event.duration, - startMinutes: event.startTime.getHours() * 60 + event.startTime.getMinutes(), - endMinutes: event.endTime.getHours() * 60 + event.endTime.getMinutes(), - column: 0, - }); - setIsModalOpen(true); - }} - isMobile={isMobile} - /> + {showPreEvents && hasUpcomingPreEvents && ( + + { + // Open modal with minimal event info + setSelectedEvent({ + id: event.id, + name: event.name, + type: event.type, + location: event.location, + startTime: event.startTime, + endTime: event.endTime, + day: "Saturday", // Not used for modal + duration: event.duration, + startMinutes: event.startTime.getHours() * 60 + event.startTime.getMinutes(), + endMinutes: event.endTime.getHours() * 60 + event.endTime.getMinutes(), + column: 0, + }); + setIsModalOpen(true); + }} + isMobile={isMobile} + /> + + )} {/* Day Tabs */}