diff --git a/public/sp26/computer_backgrounds/sponsors_seventh_page_computer3.png b/public/sp26/computer_backgrounds/sponsors_seventh_page_computer3.png new file mode 100644 index 00000000..69e69cb4 Binary files /dev/null and b/public/sp26/computer_backgrounds/sponsors_seventh_page_computer3.png differ diff --git a/src/app/(protected)/profile/page.tsx b/src/app/(protected)/profile/page.tsx index 1a8ff954..c6129586 100644 --- a/src/app/(protected)/profile/page.tsx +++ b/src/app/(protected)/profile/page.tsx @@ -63,6 +63,16 @@ enum Role { FINANCE = 5, } +// Mapping from application status to its respective color +const applicationStatusColorMap = new Map([ + ['pending', 'text-purple-400'], + ['accepted', 'text-blue-400'], + ['rejected', 'text-red-600'], + ['waitlisted', 'text-orange-300'], + ['confirmed', 'text-green-600'], + ['declined', 'text-stone-500'] +]); + // Utility to get user role from token function getUserRole(token: string | undefined): number { if (!token) return Role.NONE; @@ -366,6 +376,13 @@ export default function Profile() {

)} + {(!isOrganizer && userData?.registration) && ( +
+

+ Application Status: {userData.registration.applicationStatus.toUpperCase()} +

+
+ )} diff --git a/src/app/(protected)/register/page.tsx b/src/app/(protected)/register/page.tsx index 78d80da9..0c9b016b 100644 --- a/src/app/(protected)/register/page.tsx +++ b/src/app/(protected)/register/page.tsx @@ -291,7 +291,7 @@ export default function RegistrationPage() { major: userInfo.major || "", phone: userInfo.phone || "", country: userInfo.country || "", - race: "", + race: userInfo.race || "", hasDietaryRestrictions: !!( userInfo.dietaryRestriction || userInfo.allergies ), diff --git a/src/components/FAQ.tsx b/src/components/FAQ.tsx index aa891ab3..009137fd 100644 --- a/src/components/FAQ.tsx +++ b/src/components/FAQ.tsx @@ -170,9 +170,40 @@ const AccordionItem: React.FC = ({ ); }; +function playRobotSound() { + try { + const ctx = new (window.AudioContext || (window as any).webkitAudioContext)(); + const playBeep = (frequency: number, startTime: number, duration: number) => { + const osc = ctx.createOscillator(); + const gain = ctx.createGain(); + osc.connect(gain); + gain.connect(ctx.destination); + osc.type = "square"; + osc.frequency.setValueAtTime(frequency, startTime); + osc.frequency.setValueAtTime(frequency * 0.5, startTime + duration * 0.6); + gain.gain.setValueAtTime(0.12, startTime); + gain.gain.exponentialRampToValueAtTime(0.01, startTime + duration); + osc.start(startTime); + osc.stop(startTime + duration); + }; + playBeep(440, 0, 0.08); + playBeep(330, 0.12, 0.1); + playBeep(550, 0.26, 0.12); + } catch { + // ignore if audio not supported or blocked + } +} + const FAQ: React.FC = () => { const [openItems, setOpenItems] = useState>(new Set()); const [fishClicked, setFishClicked] = useState(false); + const [robotDance, setRobotDance] = useState(false); + + const handleRobotClick = () => { + playRobotSound(); + setRobotDance(true); + setTimeout(() => setRobotDance(false), 800); + }; const toggleItem = (index: number) => { setOpenItems((prev) => { @@ -228,25 +259,43 @@ const FAQ: React.FC = () => { {/* Left side - Image on desktop, hidden on mobile */}
FAQ Illustration
diff --git a/src/components/Sponsors/index.tsx b/src/components/Sponsors/index.tsx index 655eda7a..39280fb9 100644 --- a/src/components/Sponsors/index.tsx +++ b/src/components/Sponsors/index.tsx @@ -169,13 +169,16 @@ const SponsorTier: React.FC = ({ const Sponsors: React.FC = () => { const { data: sponsors, isLoading, error } = useAllSponsors(); - // Group sponsors by tier level + // Group sponsors by tier level, filtering out partners const sponsorsByTier = useMemo(() => { if (!sponsors) return {}; const grouped: Record = {}; sponsors.forEach((sponsor) => { + // Skip partners - they'll be displayed separately + if (sponsor.sponsorType === "partner") return; + const level = sponsor.level.toLowerCase(); if (!grouped[level]) { grouped[level] = []; @@ -191,6 +194,14 @@ const Sponsors: React.FC = () => { return grouped; }, [sponsors]); + // Get partners separately + const partners = useMemo(() => { + if (!sponsors) return []; + return sponsors + .filter((sponsor) => sponsor.sponsorType === "partner") + .sort((a, b) => a.order - b.order); + }, [sponsors]); + if (isLoading) { return (
{ return (
{ transition={{ duration: 0.8, delay: 0.5 }} > - {/* Glowing Decorative Images - f25/1.png */} { > {/* Header */} -
+
{
{/* Main Content */} -
+
{/* Sponsor Pyramid */}
{Object.entries(TIER_CONFIG).map(([tierKey, config], index) => { @@ -351,6 +359,79 @@ const Sponsors: React.FC = () => { })}
+ {/* Event Partners Section */} + {partners.length > 0 && ( + + + Event Partners + +
+ {partners.map((partner, index) => { + const tierConfig = TIER_CONFIG.partner; + const handleClick = () => { + if (partner.link) { + window.open(partner.link, "_blank", "noopener,noreferrer"); + } + }; + return ( + +
+
+ {partner.name} +
+
+
+ ); + })} +
+
+ )} + {/* Call to Action */}