From 800a10d2d6273311f8853013134b5719c362f34e Mon Sep 17 00:00:00 2001 From: jjams Date: Mon, 26 Jan 2026 01:44:26 -0500 Subject: [PATCH 1/8] + working ui w/o airtable data --- .../src/app/(landing)/CabinRace/CabinRace.tsx | 220 ++++++ .../app/(landing)/CabinRace/CabinTypes.tsx | 13 + apps/live/src/app/(landing)/page.tsx | 4 +- .../CabinRaceComponents/CabinRaceCard.tsx | 103 +++ .../CabinRaceScoreTent.tsx | 60 ++ .../CabinRaceComponents/ProgressBar.tsx | 45 ++ .../SVG/CabinRace/CabinRaceBaseBooth.tsx | 640 +++++++++++++++++ .../Assets/SVG/CabinRace/CabinRaceBush.tsx | 30 + .../SVG/CabinRace/CabinRaceProgressBar.tsx | 0 .../SVG/CabinRace/CabinRaceRedAirBalloon.tsx | 290 ++++++++ .../SVG/CabinRace/CabinRaceSquiggle.tsx | 22 + .../Assets/SVG/CabinRace/CabinRaceTent.tsx | 651 ++++++++++++++++++ .../CabinRace/CabinRaceYellowAirBalloon.tsx | 282 ++++++++ .../CabinRaceHotAirBalloonColors.tsx | 29 + .../CabinRaceMiniHotAirBalloon.tsx | 154 +++++ packages/ui/src/Icons/MemberIcon.tsx | 5 +- 16 files changed, 2545 insertions(+), 3 deletions(-) create mode 100644 apps/live/src/app/(landing)/CabinRace/CabinRace.tsx create mode 100644 apps/live/src/app/(landing)/CabinRace/CabinTypes.tsx create mode 100644 apps/live/src/app/components/CabinRaceComponents/CabinRaceCard.tsx create mode 100644 apps/live/src/app/components/CabinRaceComponents/CabinRaceScoreTent.tsx create mode 100644 apps/live/src/app/components/CabinRaceComponents/ProgressBar.tsx create mode 100644 apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBaseBooth.tsx create mode 100644 apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBush.tsx create mode 100644 apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceProgressBar.tsx create mode 100644 apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceRedAirBalloon.tsx create mode 100644 apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceSquiggle.tsx create mode 100644 apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceTent.tsx create mode 100644 apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceYellowAirBalloon.tsx create mode 100644 apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx create mode 100644 apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceMiniHotAirBalloon.tsx diff --git a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx new file mode 100644 index 00000000..f1e43d32 --- /dev/null +++ b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx @@ -0,0 +1,220 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import RibbonTitle from "@repo/ui/RibbonTitle"; +import useDevice from "@util/hooks/useDevice.ts"; +import { CabinRaceRedAirBalloon, CabinRaceSquiggle } from "../../lib/Assets/SVG"; +import CabinRaceCard from "../../components/CabinRaceComponents/CabinRaceCard.tsx"; +import { Cabin, CabinLead } from "./CabinTypes.tsx"; +import CabinRaceScoreTent from "../../components/CabinRaceComponents/CabinRaceScoreTent.tsx"; + +const emma: CabinLead = { + name: "Emma Vonbuelow", + src: "/headshots/directors/Emma.jpg", + url: "https://www.linkedin.com/in/emma-von/", +} + +const alina: CabinLead = { + name: "Alina Gonzalez", + src: "/headshots/tech/Alina.png", + url: "www.linkedin.com/in/agonzalez26", +} +const mockCabin1: Cabin = { + name: "Magicians", + points: 150, + description: "A magician never reveals their secrets… especially not their API keys! Need some " + + "more tricks up your sleeve? Bond with fellow carnival-goers as you learn all the tricks of " + + "the technical trade and prepare to dazzle the crowd by using your new skills in your " + + "project!", + cabinLeads: [emma, alina], +}; + +const mockCabin2: Cabin = { + name: "Acrobats", + points: 100, + description: "woohoo", + cabinLeads: [emma, emma], +} +const mockCabin3: Cabin = { + name: "Illusionist", + points: 999, + description: "holy try hards!!!!", + cabinLeads: [emma, emma], +} +const mockCabin4: Cabin = { + name: "Contortionist", + points: 0, + description: "what is happening...", + cabinLeads: [emma, emma], +} +const mockCabin5: Cabin = { + name: "Jugglers", + points: 30, + description: "not bad", + cabinLeads: [emma, emma], +} +const mockCabin6: Cabin = { + name: "Stilt-Walker", + points: 564, + description: "net zero", + cabinLeads: [emma, emma], +} +const mockCabins: Cabin[] = [mockCabin1, mockCabin2, mockCabin3, mockCabin4, mockCabin5, mockCabin6]; + +{/* Airtable */} +export type AirTableRecord = { + id: string; + createdTime: string; + fields: { + Name: string; + Points: number; + }; +}; + +export type AirtableData = { + records: AirTableRecord[]; +}; + +export default function CabinRace(): JSX.Element { + const {isDesktop, isTablet, isMobile} = useDevice(); + + // const [cabinData, setCabinData] = useState(null); + // + // async function getCabinPoints() { + // const res = await fetch("/api/cabinPoints"); + // const jsonData: AirtableData = await res.json(); + // const status = res.status; + // + // if (status == 200) { + // setCabinData(jsonData); + // } + // } + // + // useEffect(() => { + // getCabinPoints(); + // }, []); + + // TODO: replace mockCabins w whatever API call returns + + const cabinsByName: Record = Object.fromEntries( + mockCabins.map((cabin) => [cabin.name, cabin]) + ); + const cabinNames: string[] = mockCabins.map(cabin => cabin.name); + const [selectedCabinName, setSelectedCabinName] = useState(null); + useEffect(() => { + if (cabinNames.length && !selectedCabinName) { + setSelectedCabinName(cabinNames[0]); + } + }, [cabinNames, selectedCabinName]); + + + return ( + <> +
+ + {/* Squiggle at top */} + + + {/* Ribbon Title */} +
+ +
+ + {/* Welcome Hackers Text*/} +
+ +

+ Welcome to the carnival, hackers!

+
+

+ Aside from hacking away and building an amazing project, you’re also here to have + fun — and what better way to do that than with friends? In preparation for the + carnival, + you’ll be grouped into a guild of performers who are interested in the same + activities + as you. +

+

+ Complete activities together with your + guild members to earn points and possibly win some cool prizes! Most importantly, + make some new friends who you can enjoy the event with! All the while, you’ll be + enjoying free food, learning new tricks + from workshops, and building your + professional skills at career events. +

+
+
+ + {/* Cabin Info Section*/} + {/* Buttons section */} +
+ {cabinNames.map((name) => { + const isSelected = selectedCabinName === name; + return ( + + ); + })} +
+ + {/* Card + balloons */} +
+ {/* Cabin card */} + {selectedCabinName && cabinsByName[selectedCabinName] && ( +
+ +
+ )} + + {/* Balloons */} + {isDesktop && ( + + )} + {isTablet && ( + + )} +
+ + +
+ + ); +}; diff --git a/apps/live/src/app/(landing)/CabinRace/CabinTypes.tsx b/apps/live/src/app/(landing)/CabinRace/CabinTypes.tsx new file mode 100644 index 00000000..d440aca4 --- /dev/null +++ b/apps/live/src/app/(landing)/CabinRace/CabinTypes.tsx @@ -0,0 +1,13 @@ +// types +export interface CabinLead { + name: string; + src: string; + url: string; +} + +export interface Cabin { + name: string; + points: number; + description: string; + cabinLeads: CabinLead[]; +} \ No newline at end of file diff --git a/apps/live/src/app/(landing)/page.tsx b/apps/live/src/app/(landing)/page.tsx index 62902776..a301bf1c 100644 --- a/apps/live/src/app/(landing)/page.tsx +++ b/apps/live/src/app/(landing)/page.tsx @@ -3,7 +3,6 @@ import Landing from "./Landing"; import EventSchedule from "./EventSchedule"; import MentorSection from "./Mentors"; import OurTeamBackground from "./OurTeamBackground"; -import Welcome from "./Welcome"; import HitTheRoad from "./HitTheRoad"; import Resources from "./Resources"; import NavBar from "../lib/Components/NavBar"; @@ -11,6 +10,7 @@ import Footer from "@repo/ui/Footer"; import ComingUp from "./ComingUp/ComingUp"; import OurTeam from "./OurTeam"; import Keynote from "./Keynote"; +import CabinRace from "./CabinRace/CabinRace.tsx"; export default function Page(): JSX.Element { return ( @@ -18,8 +18,8 @@ export default function Page(): JSX.Element { + - diff --git a/apps/live/src/app/components/CabinRaceComponents/CabinRaceCard.tsx b/apps/live/src/app/components/CabinRaceComponents/CabinRaceCard.tsx new file mode 100644 index 00000000..bd6f5113 --- /dev/null +++ b/apps/live/src/app/components/CabinRaceComponents/CabinRaceCard.tsx @@ -0,0 +1,103 @@ +import * as React from "react"; +import {Cabin} from "../../(landing)/CabinRace/CabinTypes.tsx"; +import useDevice from "@util/hooks/useDevice.ts"; +import {ProjectStarIcon} from "main/src/app/lib/Assets/SVG"; +import Icon from "@repo/ui/Icons/MemberIcon"; + +interface CabinCardProps { + cabinInfo: Cabin; +} + +const CabinCard: React.FC = ({ cabinInfo, ...props }) => { + const { isDesktop, isTablet, isMobile } = useDevice(); + const cabinLeads = cabinInfo.cabinLeads; + + // Determine SVG dimensions + const svgDims = isDesktop + ? { width: 665, height: 476 } + : isTablet + ? { width: 405, height: 387 } + : { width: 293, height: 430 }; + + return ( +
+ {/* SVG background */} + + {isDesktop && ( + + + + + )} + {isTablet && ( + + )} + {isMobile && ( + + + + + )} + + + {/* Overlay content absolutely inside SVG bounds */} +
+
+
+ +

+ {cabinInfo.name} +

+
+ +

+ {cabinInfo.points} points +

+

+ {cabinInfo.description} +

+
+

Cabin Leaders

+
+ {cabinLeads.map((lead) => ( + + ))} +
+
+
+ ); +}; + +export default CabinCard; diff --git a/apps/live/src/app/components/CabinRaceComponents/CabinRaceScoreTent.tsx b/apps/live/src/app/components/CabinRaceComponents/CabinRaceScoreTent.tsx new file mode 100644 index 00000000..236b4326 --- /dev/null +++ b/apps/live/src/app/components/CabinRaceComponents/CabinRaceScoreTent.tsx @@ -0,0 +1,60 @@ +import {Cabin} from "../../(landing)/CabinRace/CabinTypes.tsx"; +import * as React from "react"; +import {CabinRaceTent, CabinRaceYellowAirBalloon} from "../../lib/Assets/SVG"; +import {ProjectStarIcon} from "main/src/app/lib/Assets/SVG"; +import ProgressBar from "./ProgressBar.tsx"; +import { + CabinRaceHotAirBalloonTheme +} from "../../lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx"; +import useDevice from "@util/hooks/useDevice.ts"; +import CabinRaceBush from "../../lib/Assets/SVG/CabinRace/CabinRaceBush.tsx"; + +type CabinSummary = Pick; + +const BALLOON_THEMES: CabinRaceHotAirBalloonTheme[] = ["blue", "green", "yellow", "purple", "white", "red"]; + +interface CabinRaceScoreTentProps { + cabinInfo: CabinSummary[]; +} + +const CabinRaceScoreTent: React.FC = ({ cabinInfo }) => { + const maxPoints = 1000; + const {isMobile, isTablet, isDesktop} = useDevice(); + + return ( +
+ + {!isMobile && ( + + )} + +
+ {cabinInfo.map((cabin, index) => ( +
+ +
+

{cabin.name}

+

{cabin.points}

+
+ +
+ ))} +
+
+ ); +}; + +export default CabinRaceScoreTent; \ No newline at end of file diff --git a/apps/live/src/app/components/CabinRaceComponents/ProgressBar.tsx b/apps/live/src/app/components/CabinRaceComponents/ProgressBar.tsx new file mode 100644 index 00000000..586c049e --- /dev/null +++ b/apps/live/src/app/components/CabinRaceComponents/ProgressBar.tsx @@ -0,0 +1,45 @@ +import React from "react"; +import {CabinRaceMiniHotAirBalloon} from "../../lib/Assets/SVG"; +import { + CabinRaceHotAirBalloonTheme +} from "../../lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx"; +import useDevice from "@util/hooks/useDevice.ts"; + +interface ProgressBarProps { + current: number; + max: number; + color: CabinRaceHotAirBalloonTheme; +} + +const ProgressBar: React.FC = ({ current, max, color }) => { + const percent = Math.min((current / max) * 100, 100); + const {isMobile} = useDevice(); + return ( +
+ {/* Bar background */} +
+ {/* Fill */} +
+
+ + {/* Balloon */} + + +
+ ); +}; + +export default ProgressBar; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBaseBooth.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBaseBooth.tsx new file mode 100644 index 00000000..c61516e2 --- /dev/null +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBaseBooth.tsx @@ -0,0 +1,640 @@ +import * as React from "react"; +import {SVGProps} from "react"; +const CabinRaceBaseBooth = (props: SVGProps) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); +export default CabinRaceBaseBooth; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBush.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBush.tsx new file mode 100644 index 00000000..74e1106c --- /dev/null +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBush.tsx @@ -0,0 +1,30 @@ +import * as React from "react"; +import {SVGProps} from "react"; +const CabinRaceBush = (props: SVGProps) => ( + + + + + + +); +export default CabinRaceBush; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceProgressBar.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceProgressBar.tsx new file mode 100644 index 00000000..e69de29b diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceRedAirBalloon.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceRedAirBalloon.tsx new file mode 100644 index 00000000..dbace0d8 --- /dev/null +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceRedAirBalloon.tsx @@ -0,0 +1,290 @@ +import * as React from "react"; +import {SVGProps} from "react"; +const CabinRaceRedAirBalloon = (props: SVGProps) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); +export default CabinRaceRedAirBalloon; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceSquiggle.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceSquiggle.tsx new file mode 100644 index 00000000..d39abd36 --- /dev/null +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceSquiggle.tsx @@ -0,0 +1,22 @@ +import * as React from "react"; +import {SVGProps} from "react"; +const SVGComponent = (props: SVGProps) => ( + + + + +); +export default SVGComponent; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceTent.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceTent.tsx new file mode 100644 index 00000000..23688a2f --- /dev/null +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceTent.tsx @@ -0,0 +1,651 @@ +import * as React from "react"; +import {SVGProps} from "react"; +const CabinRaceTent = (props: SVGProps) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); +export default CabinRaceTent; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceYellowAirBalloon.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceYellowAirBalloon.tsx new file mode 100644 index 00000000..af7c1c47 --- /dev/null +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceYellowAirBalloon.tsx @@ -0,0 +1,282 @@ +import * as React from "react"; +import {SVGProps} from "react"; +const CabinRaceYellowAirBalloon = (props: SVGProps) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); +export default CabinRaceYellowAirBalloon; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx new file mode 100644 index 00000000..c131600d --- /dev/null +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx @@ -0,0 +1,29 @@ +export const CABIN_RACE_BALLOON_COLORS = { + blue: { + primaryColor: "#2563eb", + secondaryColor: "#93c5fd", + }, + green: { + primaryColor: "#16a34a", + secondaryColor: "#86efac", + }, + yellow: { + primaryColor: "#e74c3c", + secondaryColor: "#e74c3c", + }, + purple: { + primaryColor: "#e74c3c", + secondaryColor: "#e74c3c", + }, + white: { + primaryColor: "#e74c3c", + secondaryColor: "#e74c3c", + }, + red: { + primaryColor: "#e74c3c", + secondaryColor: "#e74c3c", + }, +} as const; + +export type CabinRaceHotAirBalloonTheme = + keyof typeof CABIN_RACE_BALLOON_COLORS; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceMiniHotAirBalloon.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceMiniHotAirBalloon.tsx new file mode 100644 index 00000000..edb294cc --- /dev/null +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceMiniHotAirBalloon.tsx @@ -0,0 +1,154 @@ +import * as React from "react"; +import { SVGProps } from "react"; +import { + CABIN_RACE_BALLOON_COLORS, + CabinRaceHotAirBalloonTheme, +} from "./CabinRaceHotAirBalloonColors"; +import useDevice from "@util/hooks/useDevice.ts"; + +type SVGComponentProps = SVGProps & { + theme?: CabinRaceHotAirBalloonTheme; +}; + +const SVGComponent = ({ + theme = "blue", + ...props + }: SVGComponentProps) => { + const { primaryColor, secondaryColor } = + CABIN_RACE_BALLOON_COLORS[theme]; + const {isMobile} = useDevice(); + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default SVGComponent; \ No newline at end of file diff --git a/packages/ui/src/Icons/MemberIcon.tsx b/packages/ui/src/Icons/MemberIcon.tsx index d673f889..148a1ac8 100644 --- a/packages/ui/src/Icons/MemberIcon.tsx +++ b/packages/ui/src/Icons/MemberIcon.tsx @@ -11,6 +11,7 @@ type IconProps = { url?: string; isLive: boolean; isActive: boolean; + size?: number; }; const Icon: React.FC = ({ @@ -19,10 +20,12 @@ const Icon: React.FC = ({ url, isLive = false, isActive = false, + size = 160, }) => { return (
-
+
{name} Date: Mon, 26 Jan 2026 01:46:07 -0500 Subject: [PATCH 2/8] + working ui w/o airtable data --- .../src/app/(landing)/CabinRace/CabinRace.tsx | 262 ++-- .../app/(landing)/CabinRace/CabinTypes.tsx | 2 +- apps/live/src/app/(landing)/page.tsx | 2 - .../CabinRaceComponents/CabinRaceCard.tsx | 128 +- .../CabinRaceScoreTent.tsx | 102 +- .../CabinRaceComponents/ProgressBar.tsx | 55 +- .../SVG/CabinRace/CabinRaceBaseBooth.tsx | 1174 ++++++++-------- .../Assets/SVG/CabinRace/CabinRaceBush.tsx | 52 +- .../SVG/CabinRace/CabinRaceRedAirBalloon.tsx | 474 +++---- .../SVG/CabinRace/CabinRaceSquiggle.tsx | 36 +- .../Assets/SVG/CabinRace/CabinRaceTent.tsx | 1196 ++++++++--------- .../CabinRace/CabinRaceYellowAirBalloon.tsx | 460 +++---- .../CabinRaceHotAirBalloonColors.tsx | 2 +- .../CabinRaceMiniHotAirBalloon.tsx | 176 ++- apps/live/src/app/lib/Assets/SVG/index.ts | 7 + packages/ui/src/Icons/MemberIcon.tsx | 6 +- 16 files changed, 2102 insertions(+), 2032 deletions(-) diff --git a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx index f1e43d32..63a7f6ca 100644 --- a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx +++ b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx @@ -3,7 +3,10 @@ import React, { useEffect, useState } from "react"; import RibbonTitle from "@repo/ui/RibbonTitle"; import useDevice from "@util/hooks/useDevice.ts"; -import { CabinRaceRedAirBalloon, CabinRaceSquiggle } from "../../lib/Assets/SVG"; +import { + CabinRaceRedAirBalloon, + CabinRaceSquiggle, +} from "../../lib/Assets/SVG"; import CabinRaceCard from "../../components/CabinRaceComponents/CabinRaceCard.tsx"; import { Cabin, CabinLead } from "./CabinTypes.tsx"; import CabinRaceScoreTent from "../../components/CabinRaceComponents/CabinRaceScoreTent.tsx"; @@ -12,20 +15,21 @@ const emma: CabinLead = { name: "Emma Vonbuelow", src: "/headshots/directors/Emma.jpg", url: "https://www.linkedin.com/in/emma-von/", -} +}; const alina: CabinLead = { - name: "Alina Gonzalez", - src: "/headshots/tech/Alina.png", - url: "www.linkedin.com/in/agonzalez26", -} + name: "Alina Gonzalez", + src: "/headshots/tech/Alina.png", + url: "www.linkedin.com/in/agonzalez26", +}; const mockCabin1: Cabin = { name: "Magicians", points: 150, - description: "A magician never reveals their secrets… especially not their API keys! Need some " + - "more tricks up your sleeve? Bond with fellow carnival-goers as you learn all the tricks of " + - "the technical trade and prepare to dazzle the crowd by using your new skills in your " + - "project!", + description: + "A magician never reveals their secrets… especially not their API keys! Need some " + + "more tricks up your sleeve? Bond with fellow carnival-goers as you learn all the tricks of " + + "the technical trade and prepare to dazzle the crowd by using your new skills in your " + + "project!", cabinLeads: [emma, alina], }; @@ -34,34 +38,43 @@ const mockCabin2: Cabin = { points: 100, description: "woohoo", cabinLeads: [emma, emma], -} +}; const mockCabin3: Cabin = { name: "Illusionist", points: 999, description: "holy try hards!!!!", cabinLeads: [emma, emma], -} +}; const mockCabin4: Cabin = { name: "Contortionist", points: 0, description: "what is happening...", cabinLeads: [emma, emma], -} +}; const mockCabin5: Cabin = { name: "Jugglers", points: 30, description: "not bad", cabinLeads: [emma, emma], -} +}; const mockCabin6: Cabin = { name: "Stilt-Walker", points: 564, description: "net zero", cabinLeads: [emma, emma], +}; +const mockCabins: Cabin[] = [ + mockCabin1, + mockCabin2, + mockCabin3, + mockCabin4, + mockCabin5, + mockCabin6, +]; + +{ + /* Airtable */ } -const mockCabins: Cabin[] = [mockCabin1, mockCabin2, mockCabin3, mockCabin4, mockCabin5, mockCabin6]; - -{/* Airtable */} export type AirTableRecord = { id: string; createdTime: string; @@ -76,7 +89,7 @@ export type AirtableData = { }; export default function CabinRace(): JSX.Element { - const {isDesktop, isTablet, isMobile} = useDevice(); + const { isDesktop, isTablet, isMobile } = useDevice(); // const [cabinData, setCabinData] = useState(null); // @@ -97,124 +110,145 @@ export default function CabinRace(): JSX.Element { // TODO: replace mockCabins w whatever API call returns const cabinsByName: Record = Object.fromEntries( - mockCabins.map((cabin) => [cabin.name, cabin]) + mockCabins.map((cabin) => [cabin.name, cabin]), + ); + const cabinNames: string[] = mockCabins.map((cabin) => cabin.name); + const [selectedCabinName, setSelectedCabinName] = useState( + null, ); - const cabinNames: string[] = mockCabins.map(cabin => cabin.name); - const [selectedCabinName, setSelectedCabinName] = useState(null); useEffect(() => { if (cabinNames.length && !selectedCabinName) { setSelectedCabinName(cabinNames[0]); } }, [cabinNames, selectedCabinName]); - return ( - <> -
- - {/* Squiggle at top */} - - - {/* Ribbon Title */} -
- -
+ <> +
+ {/* Squiggle at top */} + + + {/* Ribbon Title */} +
+ +
- {/* Welcome Hackers Text*/} -
- -

+

+ Welcome to the carnival, hackers! +

+
+

- Welcome to the carnival, hackers!

-
-

- Aside from hacking away and building an amazing project, you’re also here to have - fun — and what better way to do that than with friends? In preparation for the - carnival, - you’ll be grouped into a guild of performers who are interested in the same - activities - as you. -

-

- Complete activities together with your - guild members to earn points and possibly win some cool prizes! Most importantly, - make some new friends who you can enjoy the event with! All the while, you’ll be - enjoying free food, learning new tricks - from workshops, and building your - professional skills at career events. -

-
+ Aside from hacking away and building an amazing project, you’re + also here to have fun — and what better way to do that than with + friends? In preparation for the carnival, you’ll be grouped into a + guild of performers who are interested in the same activities as + you. +

+

+ + Complete activities together + {" "} + with your guild members to earn points and possibly win some cool + prizes! Most importantly, make some new friends who you can enjoy + the event with! All the while, you’ll be enjoying{" "} + free food, learning new + tricks from workshops, + and building your professional skills at{" "} + career events. +

+
- {/* Cabin Info Section*/} - {/* Buttons section */} -
- {cabinNames.map((name) => { - const isSelected = selectedCabinName === name; - return ( - - ); - })} -
- - {/* Card + balloons */} -
- {/* Cabin card */} - {selectedCabinName && cabinsByName[selectedCabinName] && ( -
- -
- )} - - {/* Balloons */} - {isDesktop && ( - - )} - {isTablet && ( - - )} -
+ > + {name} + + ); + })} +
- + {/* Card + balloons */} +
+ {/* Cabin card */} + {selectedCabinName && cabinsByName[selectedCabinName] && ( +
+ +
+ )} + + {/* Balloons */} + {isDesktop && ( + + )} + {isTablet && ( + + )}
- + + +
+ ); -}; +} diff --git a/apps/live/src/app/(landing)/CabinRace/CabinTypes.tsx b/apps/live/src/app/(landing)/CabinRace/CabinTypes.tsx index d440aca4..80af2f13 100644 --- a/apps/live/src/app/(landing)/CabinRace/CabinTypes.tsx +++ b/apps/live/src/app/(landing)/CabinRace/CabinTypes.tsx @@ -10,4 +10,4 @@ export interface Cabin { points: number; description: string; cabinLeads: CabinLead[]; -} \ No newline at end of file +} diff --git a/apps/live/src/app/(landing)/page.tsx b/apps/live/src/app/(landing)/page.tsx index a301bf1c..a839cb3a 100644 --- a/apps/live/src/app/(landing)/page.tsx +++ b/apps/live/src/app/(landing)/page.tsx @@ -10,7 +10,6 @@ import Footer from "@repo/ui/Footer"; import ComingUp from "./ComingUp/ComingUp"; import OurTeam from "./OurTeam"; import Keynote from "./Keynote"; -import CabinRace from "./CabinRace/CabinRace.tsx"; export default function Page(): JSX.Element { return ( @@ -18,7 +17,6 @@ export default function Page(): JSX.Element { - diff --git a/apps/live/src/app/components/CabinRaceComponents/CabinRaceCard.tsx b/apps/live/src/app/components/CabinRaceComponents/CabinRaceCard.tsx index bd6f5113..03acfbdd 100644 --- a/apps/live/src/app/components/CabinRaceComponents/CabinRaceCard.tsx +++ b/apps/live/src/app/components/CabinRaceComponents/CabinRaceCard.tsx @@ -1,7 +1,7 @@ import * as React from "react"; -import {Cabin} from "../../(landing)/CabinRace/CabinTypes.tsx"; +import { Cabin } from "../../(landing)/CabinRace/CabinTypes.tsx"; import useDevice from "@util/hooks/useDevice.ts"; -import {ProjectStarIcon} from "main/src/app/lib/Assets/SVG"; +import { ProjectStarIcon } from "main/src/app/lib/Assets/SVG"; import Icon from "@repo/ui/Icons/MemberIcon"; interface CabinCardProps { @@ -14,58 +14,60 @@ const CabinCard: React.FC = ({ cabinInfo, ...props }) => { // Determine SVG dimensions const svgDims = isDesktop - ? { width: 665, height: 476 } - : isTablet - ? { width: 405, height: 387 } - : { width: 293, height: 430 }; + ? { width: 665, height: 476 } + : isTablet + ? { width: 405, height: 387 } + : { width: 293, height: 430 }; return ( -
- {/* SVG background */} - - {isDesktop && ( - - - - - )} - {isTablet && ( - - )} - {isMobile && ( - - - - - )} - +
+ {/* SVG background */} + + {isDesktop && ( + + + + + )} + {isTablet && ( + + )} + {isMobile && ( + + + + + )} + - {/* Overlay content absolutely inside SVG bounds */} -
+ {/* Overlay content absolutely inside SVG bounds */} +
- +

{cabinInfo.name}

@@ -78,21 +80,25 @@ const CabinCard: React.FC = ({ cabinInfo, ...props }) => { {cabinInfo.description}

-

Cabin Leaders

+

+ {" "} + Cabin Leaders +

+ gap-4 flex flex-row" + > {cabinLeads.map((lead) => ( - + ))}
diff --git a/apps/live/src/app/components/CabinRaceComponents/CabinRaceScoreTent.tsx b/apps/live/src/app/components/CabinRaceComponents/CabinRaceScoreTent.tsx index 236b4326..deaf7dbd 100644 --- a/apps/live/src/app/components/CabinRaceComponents/CabinRaceScoreTent.tsx +++ b/apps/live/src/app/components/CabinRaceComponents/CabinRaceScoreTent.tsx @@ -1,60 +1,84 @@ -import {Cabin} from "../../(landing)/CabinRace/CabinTypes.tsx"; +import { Cabin } from "../../(landing)/CabinRace/CabinTypes.tsx"; import * as React from "react"; -import {CabinRaceTent, CabinRaceYellowAirBalloon} from "../../lib/Assets/SVG"; -import {ProjectStarIcon} from "main/src/app/lib/Assets/SVG"; +import { CabinRaceTent, CabinRaceYellowAirBalloon } from "../../lib/Assets/SVG"; +import { ProjectStarIcon } from "main/src/app/lib/Assets/SVG"; import ProgressBar from "./ProgressBar.tsx"; -import { - CabinRaceHotAirBalloonTheme -} from "../../lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx"; +import { CabinRaceHotAirBalloonTheme } from "../../lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx"; import useDevice from "@util/hooks/useDevice.ts"; import CabinRaceBush from "../../lib/Assets/SVG/CabinRace/CabinRaceBush.tsx"; type CabinSummary = Pick; -const BALLOON_THEMES: CabinRaceHotAirBalloonTheme[] = ["blue", "green", "yellow", "purple", "white", "red"]; +const BALLOON_THEMES: CabinRaceHotAirBalloonTheme[] = [ + "blue", + "green", + "yellow", + "purple", + "white", + "red", +]; interface CabinRaceScoreTentProps { cabinInfo: CabinSummary[]; } -const CabinRaceScoreTent: React.FC = ({ cabinInfo }) => { +const CabinRaceScoreTent: React.FC = ({ + cabinInfo, +}) => { const maxPoints = 1000; - const {isMobile, isTablet, isDesktop} = useDevice(); + const { isMobile, isTablet, isDesktop } = useDevice(); return ( -
- + + {!isMobile && ( + - {!isMobile && ( - - )} - -
- {cabinInfo.map((cabin, index) => ( -
- -
-

{cabin.name}

-

{cabin.points}

-
- + )} + +
+ {cabinInfo.map((cabin, index) => ( +
+ +
+

+ {cabin.name} +

+

+ {cabin.points} +

- ))} -
+ +
+ ))}
+
); }; -export default CabinRaceScoreTent; \ No newline at end of file +export default CabinRaceScoreTent; diff --git a/apps/live/src/app/components/CabinRaceComponents/ProgressBar.tsx b/apps/live/src/app/components/CabinRaceComponents/ProgressBar.tsx index 586c049e..46a60683 100644 --- a/apps/live/src/app/components/CabinRaceComponents/ProgressBar.tsx +++ b/apps/live/src/app/components/CabinRaceComponents/ProgressBar.tsx @@ -1,8 +1,6 @@ import React from "react"; -import {CabinRaceMiniHotAirBalloon} from "../../lib/Assets/SVG"; -import { - CabinRaceHotAirBalloonTheme -} from "../../lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx"; +import { CabinRaceMiniHotAirBalloon } from "../../lib/Assets/SVG"; +import { CabinRaceHotAirBalloonTheme } from "../../lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx"; import useDevice from "@util/hooks/useDevice.ts"; interface ProgressBarProps { @@ -13,32 +11,35 @@ interface ProgressBarProps { const ProgressBar: React.FC = ({ current, max, color }) => { const percent = Math.min((current / max) * 100, 100); - const {isMobile} = useDevice(); + const { isMobile } = useDevice(); return ( -
- {/* Bar background */} -
- {/* Fill */} -
-
- - {/* Balloon */} - + {/* Bar background */} +
+ {/* Fill */} +
-
+ + {/* Balloon */} + +
); }; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBaseBooth.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBaseBooth.tsx index c61516e2..77cdee70 100644 --- a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBaseBooth.tsx +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBaseBooth.tsx @@ -1,640 +1,640 @@ import * as React from "react"; -import {SVGProps} from "react"; +import { SVGProps } from "react"; const CabinRaceBaseBooth = (props: SVGProps) => ( - + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + ); export default CabinRaceBaseBooth; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBush.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBush.tsx index 74e1106c..6b787c06 100644 --- a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBush.tsx +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceBush.tsx @@ -1,30 +1,30 @@ import * as React from "react"; -import {SVGProps} from "react"; +import { SVGProps } from "react"; const CabinRaceBush = (props: SVGProps) => ( - - - - - - + + + + + + ); export default CabinRaceBush; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceRedAirBalloon.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceRedAirBalloon.tsx index dbace0d8..8e108d43 100644 --- a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceRedAirBalloon.tsx +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceRedAirBalloon.tsx @@ -1,290 +1,290 @@ import * as React from "react"; -import {SVGProps} from "react"; +import { SVGProps } from "react"; const CabinRaceRedAirBalloon = (props: SVGProps) => ( - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + + + ); export default CabinRaceRedAirBalloon; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceSquiggle.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceSquiggle.tsx index d39abd36..088c21f9 100644 --- a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceSquiggle.tsx +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceSquiggle.tsx @@ -1,22 +1,22 @@ import * as React from "react"; -import {SVGProps} from "react"; +import { SVGProps } from "react"; const SVGComponent = (props: SVGProps) => ( - - - - + + + + ); export default SVGComponent; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceTent.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceTent.tsx index 23688a2f..fa5588fa 100644 --- a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceTent.tsx +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceTent.tsx @@ -1,651 +1,651 @@ import * as React from "react"; -import {SVGProps} from "react"; +import { SVGProps } from "react"; const CabinRaceTent = (props: SVGProps) => ( - + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + ); export default CabinRaceTent; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceYellowAirBalloon.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceYellowAirBalloon.tsx index af7c1c47..8671be19 100644 --- a/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceYellowAirBalloon.tsx +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/CabinRaceYellowAirBalloon.tsx @@ -1,282 +1,282 @@ import * as React from "react"; -import {SVGProps} from "react"; +import { SVGProps } from "react"; const CabinRaceYellowAirBalloon = (props: SVGProps) => ( - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + + + ); export default CabinRaceYellowAirBalloon; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx index c131600d..3d8a8b93 100644 --- a/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceHotAirBalloonColors.tsx @@ -26,4 +26,4 @@ export const CABIN_RACE_BALLOON_COLORS = { } as const; export type CabinRaceHotAirBalloonTheme = - keyof typeof CABIN_RACE_BALLOON_COLORS; + keyof typeof CABIN_RACE_BALLOON_COLORS; diff --git a/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceMiniHotAirBalloon.tsx b/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceMiniHotAirBalloon.tsx index edb294cc..cf4cde7e 100644 --- a/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceMiniHotAirBalloon.tsx +++ b/apps/live/src/app/lib/Assets/SVG/CabinRace/MiniHotAirBalloons/CabinRaceMiniHotAirBalloon.tsx @@ -10,145 +10,143 @@ type SVGComponentProps = SVGProps & { theme?: CabinRaceHotAirBalloonTheme; }; -const SVGComponent = ({ - theme = "blue", - ...props - }: SVGComponentProps) => { - const { primaryColor, secondaryColor } = - CABIN_RACE_BALLOON_COLORS[theme]; - const {isMobile} = useDevice(); +const SVGComponent = ({ theme = "blue", ...props }: SVGComponentProps) => { + const { primaryColor, secondaryColor } = CABIN_RACE_BALLOON_COLORS[theme]; + const { isMobile } = useDevice(); return ( - + ); }; -export default SVGComponent; \ No newline at end of file +export default SVGComponent; diff --git a/apps/live/src/app/lib/Assets/SVG/index.ts b/apps/live/src/app/lib/Assets/SVG/index.ts index e6266c2d..8a4f11e8 100644 --- a/apps/live/src/app/lib/Assets/SVG/index.ts +++ b/apps/live/src/app/lib/Assets/SVG/index.ts @@ -2,3 +2,10 @@ export { default as InfoCardCottonCandy } from "./InfoCard/InfoCardCottonCandy.t export { default as InfoCardHotDogBag } from "./InfoCard/InfoCardHotDogBag.tsx"; export { default as InfoCardPopcorn } from "./InfoCard/InfoCardPopcorn.tsx"; export { default as InfoCardIceCream } from "./InfoCard/InfoCardIceCream.tsx"; + +export { default as CabinRaceBaseBooth } from "./CabinRace/CabinRaceBaseBooth.tsx"; +export { default as CabinRaceRedAirBalloon } from "./CabinRace/CabinRaceRedAirBalloon.tsx"; +export { default as CabinRaceSquiggle } from "./CabinRace/CabinRaceSquiggle.tsx"; +export { default as CabinRaceYellowAirBalloon } from "./CabinRace/CabinRaceYellowAirBalloon.tsx"; +export { default as CabinRaceMiniHotAirBalloon } from "./CabinRace/MiniHotAirBalloons/CabinRaceMiniHotAirBalloon.tsx"; +export { default as CabinRaceTent } from "./CabinRace/CabinRaceTent.tsx"; diff --git a/packages/ui/src/Icons/MemberIcon.tsx b/packages/ui/src/Icons/MemberIcon.tsx index 148a1ac8..f4e5681e 100644 --- a/packages/ui/src/Icons/MemberIcon.tsx +++ b/packages/ui/src/Icons/MemberIcon.tsx @@ -24,8 +24,10 @@ const Icon: React.FC = ({ }) => { return (
-
+
{name} Date: Mon, 26 Jan 2026 02:12:01 -0500 Subject: [PATCH 3/8] + w airtable data --- .../src/app/(landing)/CabinRace/CabinRace.tsx | 123 ++++++------------ apps/live/src/app/(landing)/Keynote.tsx | 6 +- apps/live/src/app/api/cabinPoints/route.ts | 2 +- .../src/app/lib/Components/FilterButton.tsx | 15 +-- .../SponsorUsTestimonialsBackground.tsx | 2 +- .../components/SponsorUsTestimonialCart.tsx | 2 +- .../components/SponsorUsTestimonialWheel.tsx | 5 +- .../components/SponsorUsTestimonials.tsx | 4 +- apps/main/src/app/sponsors/page.tsx | 7 +- 9 files changed, 58 insertions(+), 108 deletions(-) diff --git a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx index 63a7f6ca..51632860 100644 --- a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx +++ b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useEffect, useState } from "react"; +import React, {useEffect, useMemo, useState} from "react"; import RibbonTitle from "@repo/ui/RibbonTitle"; import useDevice from "@util/hooks/useDevice.ts"; import { @@ -8,73 +8,10 @@ import { CabinRaceSquiggle, } from "../../lib/Assets/SVG"; import CabinRaceCard from "../../components/CabinRaceComponents/CabinRaceCard.tsx"; -import { Cabin, CabinLead } from "./CabinTypes.tsx"; +import { Cabin } from "./CabinTypes.tsx"; import CabinRaceScoreTent from "../../components/CabinRaceComponents/CabinRaceScoreTent.tsx"; -const emma: CabinLead = { - name: "Emma Vonbuelow", - src: "/headshots/directors/Emma.jpg", - url: "https://www.linkedin.com/in/emma-von/", -}; - -const alina: CabinLead = { - name: "Alina Gonzalez", - src: "/headshots/tech/Alina.png", - url: "www.linkedin.com/in/agonzalez26", -}; -const mockCabin1: Cabin = { - name: "Magicians", - points: 150, - description: - "A magician never reveals their secrets… especially not their API keys! Need some " + - "more tricks up your sleeve? Bond with fellow carnival-goers as you learn all the tricks of " + - "the technical trade and prepare to dazzle the crowd by using your new skills in your " + - "project!", - cabinLeads: [emma, alina], -}; - -const mockCabin2: Cabin = { - name: "Acrobats", - points: 100, - description: "woohoo", - cabinLeads: [emma, emma], -}; -const mockCabin3: Cabin = { - name: "Illusionist", - points: 999, - description: "holy try hards!!!!", - cabinLeads: [emma, emma], -}; -const mockCabin4: Cabin = { - name: "Contortionist", - points: 0, - description: "what is happening...", - cabinLeads: [emma, emma], -}; -const mockCabin5: Cabin = { - name: "Jugglers", - points: 30, - description: "not bad", - cabinLeads: [emma, emma], -}; -const mockCabin6: Cabin = { - name: "Stilt-Walker", - points: 564, - description: "net zero", - cabinLeads: [emma, emma], -}; -const mockCabins: Cabin[] = [ - mockCabin1, - mockCabin2, - mockCabin3, - mockCabin4, - mockCabin5, - mockCabin6, -]; - -{ - /* Airtable */ -} +{ /* Airtable */ } export type AirTableRecord = { id: string; createdTime: string; @@ -91,28 +28,42 @@ export type AirtableData = { export default function CabinRace(): JSX.Element { const { isDesktop, isTablet, isMobile } = useDevice(); - // const [cabinData, setCabinData] = useState(null); - // - // async function getCabinPoints() { - // const res = await fetch("/api/cabinPoints"); - // const jsonData: AirtableData = await res.json(); - // const status = res.status; - // - // if (status == 200) { - // setCabinData(jsonData); - // } - // } - // - // useEffect(() => { - // getCabinPoints(); - // }, []); - - // TODO: replace mockCabins w whatever API call returns + const [cabinData, setCabinData] = useState(null); + + async function getCabinPoints() { + const res = await fetch("/api/cabinPoints"); + const jsonData: AirtableData = await res.json(); + const status = res.status; + + if (status == 200) { + setCabinData(jsonData); + } + } + + useEffect(() => { + const fetchCabins = async () => { + await getCabinPoints(); + }; + + void fetchCabins(); + }, []); + + // TODO: should add cabin lead info and descriptions to airtable + const fetchedCabins = useMemo(() => { + if (!cabinData) return []; + return cabinData.records.map(record => ({ + name: record.fields.Name, + points: record.fields.Points, + description: "", + cabinLeads: [], + })); + }, [cabinData]); + const cabinsByName: Record = Object.fromEntries( - mockCabins.map((cabin) => [cabin.name, cabin]), + fetchedCabins.map((cabin) => [cabin.name, cabin]), ); - const cabinNames: string[] = mockCabins.map((cabin) => cabin.name); + const cabinNames: string[] = fetchedCabins.map((cabin) => cabin.name); const [selectedCabinName, setSelectedCabinName] = useState( null, ); @@ -247,7 +198,7 @@ export default function CabinRace(): JSX.Element { )}
- +
); diff --git a/apps/live/src/app/(landing)/Keynote.tsx b/apps/live/src/app/(landing)/Keynote.tsx index e383945d..0f7a15ea 100644 --- a/apps/live/src/app/(landing)/Keynote.tsx +++ b/apps/live/src/app/(landing)/Keynote.tsx @@ -3,9 +3,5 @@ import React from "react"; export default function Keynote(): React.ReactNode { - - return ( -
-
- ); + return
; } diff --git a/apps/live/src/app/api/cabinPoints/route.ts b/apps/live/src/app/api/cabinPoints/route.ts index 782da255..2f5ee97b 100644 --- a/apps/live/src/app/api/cabinPoints/route.ts +++ b/apps/live/src/app/api/cabinPoints/route.ts @@ -25,7 +25,7 @@ export async function GET(req: NextRequest) { } catch (err) { return NextResponse.json( { error: `Request to get airtable data failed ${err}` }, - { status: 500 } + { status: 500 }, ); } } diff --git a/apps/live/src/app/lib/Components/FilterButton.tsx b/apps/live/src/app/lib/Components/FilterButton.tsx index 02af5346..9c406b35 100644 --- a/apps/live/src/app/lib/Components/FilterButton.tsx +++ b/apps/live/src/app/lib/Components/FilterButton.tsx @@ -13,7 +13,7 @@ interface ButtonProps { const bgColorMap: Record = { canopyGreenLight: "bg-canopyGreenLight", - canopyGreen:"bg-canopyGreen", + canopyGreen: "bg-canopyGreen", mossGreen: "bg-mossGreen", mossGreenDark: "bg-mossGreenDark", firecrackerRedLight: "bg-firecrackerRedLight", @@ -28,7 +28,7 @@ const textColorMap: Record = { const borderColorMap: Record = { canopyGreenLight: "border-canopyGreenLight", - canopyGreen:"bg-canopyGreen", + canopyGreen: "bg-canopyGreen", mossGreen: "border-mossGreen", mossGreenDark: "border-mossGreenDark", firecrackerRed: "border-firecrackerRed", @@ -52,7 +52,7 @@ const hoverTextColorMap: Record = { const hoverBorderColorMap: Record = { white: "hover:border-white", canopyGreenLight: "hover:border-canopyGreenLight", - canopyGreen:"bg-canopyGreen", + canopyGreen: "bg-canopyGreen", mossGreen: "hover:border-mossGreen", mossGreenDark: "hover:border-mossGreenDark", firecrackerRed: "hover:border-firecrackerRed", @@ -83,7 +83,7 @@ const FilterButton: React.FC = ({ ? hoverBorderColorMap[hoverBorderColor] : "hover:border-white"; - const baseStyle = `font-NeulisNeue-Bold flex items-center justify-center gap-1 rounded-lg w-auto h-auto py-1 whitespace-nowrap border border-solid transition-transform duration-200 ease-in-out hover:scale-105 hover:border-[1.5px] active:brightness-90 + const baseStyle = `font-NeulisNeue-Bold flex items-center justify-center gap-1 rounded-lg w-auto h-auto py-1 whitespace-nowrap border border-solid transition-transform duration-200 ease-in-out hover:scale-105 hover:border-[1.5px] active:brightness-90 ${bgClass} ${textClass} ${borderClass} @@ -92,13 +92,12 @@ const FilterButton: React.FC = ({ ${hoverBorderClass} ${text ? "px-4" : "px-2"} `; - + return ( - ); }; -export default FilterButton; \ No newline at end of file +export default FilterButton; diff --git a/apps/main/src/app/lib/Assets/SVG/SponsorUsPageAssets/SponsorUsTestimonialsBackground.tsx b/apps/main/src/app/lib/Assets/SVG/SponsorUsPageAssets/SponsorUsTestimonialsBackground.tsx index 03d0f47f..bcb2c3b3 100644 --- a/apps/main/src/app/lib/Assets/SVG/SponsorUsPageAssets/SponsorUsTestimonialsBackground.tsx +++ b/apps/main/src/app/lib/Assets/SVG/SponsorUsPageAssets/SponsorUsTestimonialsBackground.tsx @@ -825,4 +825,4 @@ const SponsorUsTestimonialsBackground = (props: SVGProps) => ( ); -export default SponsorUsTestimonialsBackground; \ No newline at end of file +export default SponsorUsTestimonialsBackground; diff --git a/apps/main/src/app/sponsor-us/components/SponsorUsTestimonialCart.tsx b/apps/main/src/app/sponsor-us/components/SponsorUsTestimonialCart.tsx index 7e5bc7b1..9d969d1b 100644 --- a/apps/main/src/app/sponsor-us/components/SponsorUsTestimonialCart.tsx +++ b/apps/main/src/app/sponsor-us/components/SponsorUsTestimonialCart.tsx @@ -48,4 +48,4 @@ export default function SponsorUsTestimonialCart({
); -} \ No newline at end of file +} diff --git a/apps/main/src/app/sponsor-us/components/SponsorUsTestimonialWheel.tsx b/apps/main/src/app/sponsor-us/components/SponsorUsTestimonialWheel.tsx index a2198783..b03bf9cb 100644 --- a/apps/main/src/app/sponsor-us/components/SponsorUsTestimonialWheel.tsx +++ b/apps/main/src/app/sponsor-us/components/SponsorUsTestimonialWheel.tsx @@ -9,9 +9,8 @@ export type FerrisWheelProps = { export default function SponsorUsTestimonialsWheel({ classname, - transformStyle + transformStyle, }: FerrisWheelProps): React.ReactNode { - return (
@@ -23,4 +22,4 @@ export default function SponsorUsTestimonialsWheel({
); -} \ No newline at end of file +} diff --git a/apps/main/src/app/sponsor-us/components/SponsorUsTestimonials.tsx b/apps/main/src/app/sponsor-us/components/SponsorUsTestimonials.tsx index daec664d..e60f5ca9 100644 --- a/apps/main/src/app/sponsor-us/components/SponsorUsTestimonials.tsx +++ b/apps/main/src/app/sponsor-us/components/SponsorUsTestimonials.tsx @@ -142,7 +142,7 @@ export default function SponsorUsTestimonials() { {/* Ferris Wheel */} @@ -150,4 +150,4 @@ export default function SponsorUsTestimonials() {
); -} \ No newline at end of file +} diff --git a/apps/main/src/app/sponsors/page.tsx b/apps/main/src/app/sponsors/page.tsx index a16c240b..4e186310 100644 --- a/apps/main/src/app/sponsors/page.tsx +++ b/apps/main/src/app/sponsors/page.tsx @@ -30,7 +30,12 @@ function makeSponsorRow( > {ticketSizes.map((width, i) => logos?.[i] === PureButton ? ( - + Date: Mon, 26 Jan 2026 02:16:20 -0500 Subject: [PATCH 4/8] + w airtable data --- apps/live/src/app/(landing)/CabinRace/CabinRace.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx index 51632860..174526ab 100644 --- a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx +++ b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx @@ -1,6 +1,6 @@ "use client"; -import React, {useEffect, useMemo, useState} from "react"; +import React, { useEffect, useMemo, useState } from "react"; import RibbonTitle from "@repo/ui/RibbonTitle"; import useDevice from "@util/hooks/useDevice.ts"; import { @@ -11,7 +11,7 @@ import CabinRaceCard from "../../components/CabinRaceComponents/CabinRaceCard.ts import { Cabin } from "./CabinTypes.tsx"; import CabinRaceScoreTent from "../../components/CabinRaceComponents/CabinRaceScoreTent.tsx"; -{ /* Airtable */ } +{/* Airtable */} export type AirTableRecord = { id: string; createdTime: string; @@ -31,7 +31,7 @@ export default function CabinRace(): JSX.Element { const [cabinData, setCabinData] = useState(null); async function getCabinPoints() { - const res = await fetch("/api/cabinPoints"); + const res = await fetch("../api/cabinPoints"); const jsonData: AirtableData = await res.json(); const status = res.status; @@ -51,7 +51,7 @@ export default function CabinRace(): JSX.Element { // TODO: should add cabin lead info and descriptions to airtable const fetchedCabins = useMemo(() => { if (!cabinData) return []; - return cabinData.records.map(record => ({ + return cabinData.records.map((record) => ({ name: record.fields.Name, points: record.fields.Points, description: "", @@ -59,9 +59,8 @@ export default function CabinRace(): JSX.Element { })); }, [cabinData]); - const cabinsByName: Record = Object.fromEntries( - fetchedCabins.map((cabin) => [cabin.name, cabin]), + fetchedCabins.map((cabin) => [cabin.name, cabin]), ); const cabinNames: string[] = fetchedCabins.map((cabin) => cabin.name); const [selectedCabinName, setSelectedCabinName] = useState( From f3b82547b83bd618bc7a7e38aba04a09d1081a05 Mon Sep 17 00:00:00 2001 From: jjams Date: Mon, 26 Jan 2026 02:20:54 -0500 Subject: [PATCH 5/8] + accidentally deleted welcome section so reverting --- apps/live/src/app/(landing)/page.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/live/src/app/(landing)/page.tsx b/apps/live/src/app/(landing)/page.tsx index a839cb3a..62902776 100644 --- a/apps/live/src/app/(landing)/page.tsx +++ b/apps/live/src/app/(landing)/page.tsx @@ -3,6 +3,7 @@ import Landing from "./Landing"; import EventSchedule from "./EventSchedule"; import MentorSection from "./Mentors"; import OurTeamBackground from "./OurTeamBackground"; +import Welcome from "./Welcome"; import HitTheRoad from "./HitTheRoad"; import Resources from "./Resources"; import NavBar from "../lib/Components/NavBar"; @@ -18,6 +19,7 @@ export default function Page(): JSX.Element { + From ff43c83089fbd4414e8f223e86965a28ccfb4913 Mon Sep 17 00:00:00 2001 From: jjams Date: Sun, 8 Feb 2026 12:11:08 -0500 Subject: [PATCH 6/8] artable changes --- apps/live/src/app/(landing)/CabinRace/CabinRace.tsx | 10 +++++----- apps/live/src/app/(landing)/page.tsx | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx index 174526ab..13fb7a16 100644 --- a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx +++ b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx @@ -18,12 +18,13 @@ export type AirTableRecord = { fields: { Name: string; Points: number; - }; + Description?: string; + CabinLeads?: string[]; + }; }; +export type AirtableData = { records: AirTableRecord[]; }; + -export type AirtableData = { - records: AirTableRecord[]; -}; export default function CabinRace(): JSX.Element { const { isDesktop, isTablet, isMobile } = useDevice(); @@ -48,7 +49,6 @@ export default function CabinRace(): JSX.Element { void fetchCabins(); }, []); - // TODO: should add cabin lead info and descriptions to airtable const fetchedCabins = useMemo(() => { if (!cabinData) return []; return cabinData.records.map((record) => ({ diff --git a/apps/live/src/app/(landing)/page.tsx b/apps/live/src/app/(landing)/page.tsx index 62902776..ad29707d 100644 --- a/apps/live/src/app/(landing)/page.tsx +++ b/apps/live/src/app/(landing)/page.tsx @@ -11,6 +11,7 @@ import Footer from "@repo/ui/Footer"; import ComingUp from "./ComingUp/ComingUp"; import OurTeam from "./OurTeam"; import Keynote from "./Keynote"; +import CabinRace from "./CabinRace/CabinRace.tsx"; export default function Page(): JSX.Element { return ( @@ -21,6 +22,7 @@ export default function Page(): JSX.Element { + From 4afa60e91aac3903418aafdeb9c6d18a77637459 Mon Sep 17 00:00:00 2001 From: jjams Date: Sun, 8 Feb 2026 12:46:55 -0500 Subject: [PATCH 7/8] artable changes --- .../src/app/(landing)/CabinRace/CabinRace.tsx | 80 ++++++++++++++++--- 1 file changed, 67 insertions(+), 13 deletions(-) diff --git a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx index 13fb7a16..a9a0d4ae 100644 --- a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx +++ b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx @@ -8,11 +8,13 @@ import { CabinRaceSquiggle, } from "../../lib/Assets/SVG"; import CabinRaceCard from "../../components/CabinRaceComponents/CabinRaceCard.tsx"; -import { Cabin } from "./CabinTypes.tsx"; +import {Cabin, CabinLead} from "./CabinTypes.tsx"; import CabinRaceScoreTent from "../../components/CabinRaceComponents/CabinRaceScoreTent.tsx"; -{/* Airtable */} -export type AirTableRecord = { +{ + /* Airtable */ +} +export type CabinInfoRecord = { id: string; createdTime: string; fields: { @@ -20,20 +22,35 @@ export type AirTableRecord = { Points: number; Description?: string; CabinLeads?: string[]; - }; + }; +}; + +export type CabinInfo = { + records: CabinInfoRecord[]; }; -export type AirtableData = { records: AirTableRecord[]; }; +export type CabinLeadRecord = { + id: string; + createdTime: string; + fields: { + Name: string; + src: string; + url: string; + }; +}; +export type CabinLeadInfo = { + records: CabinLeadRecord[]; +}; export default function CabinRace(): JSX.Element { const { isDesktop, isTablet, isMobile } = useDevice(); - const [cabinData, setCabinData] = useState(null); + const [cabinData, setCabinData] = useState(null); async function getCabinPoints() { - const res = await fetch("../api/cabinPoints"); - const jsonData: AirtableData = await res.json(); + const res = await fetch("/api/cabinPoints"); + const jsonData: CabinInfo = await res.json(); const status = res.status; if (status == 200) { @@ -49,15 +66,52 @@ export default function CabinRace(): JSX.Element { void fetchCabins(); }, []); - const fetchedCabins = useMemo(() => { + const [cabinLeads, setCabinLeads] = useState([]); + + useEffect(() => { + if (!cabinData) return; + + const leadIds = cabinData.records.flatMap( + record => record.fields.CabinLeads ?? [], + ); + + if (!leadIds.length) return; + + const fetchLeads = async () => { + const res = await fetch( + `/api/cabinLeads?ids=${leadIds.join(",")}`, + ); + const data: CabinLeadInfo = await res.json(); + setCabinLeads(data.records); + }; + + void fetchLeads(); + }, [cabinData]); + + const fetchedCabins = useMemo(() => { if (!cabinData) return []; - return cabinData.records.map((record) => ({ + + const leadsById: Record = Object.fromEntries( + cabinLeads.map(lead => [ + lead.id, + { + name: lead.fields.Name, + src: lead.fields.src, + url: lead.fields.url, + }, + ]), + ); + + return cabinData.records.map(record => ({ name: record.fields.Name, points: record.fields.Points, - description: "", - cabinLeads: [], + description: record.fields.Description ?? "", + cabinLeads: (record.fields.CabinLeads ?? []) + .map(id => leadsById[id]) + .filter((lead): lead is CabinLead => Boolean(lead)), })); - }, [cabinData]); + }, [cabinData, cabinLeads]); + const cabinsByName: Record = Object.fromEntries( fetchedCabins.map((cabin) => [cabin.name, cabin]), From 377854846449c2c9ce54c393646dfe1f457a0e28 Mon Sep 17 00:00:00 2001 From: jjams Date: Sun, 8 Feb 2026 13:11:01 -0500 Subject: [PATCH 8/8] artable changes --- .../src/app/(landing)/CabinRace/CabinRace.tsx | 31 ++++++------- apps/live/src/app/api/cabinLeads/route.ts | 45 +++++++++++++++++++ 2 files changed, 59 insertions(+), 17 deletions(-) create mode 100644 apps/live/src/app/api/cabinLeads/route.ts diff --git a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx index a9a0d4ae..b762467b 100644 --- a/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx +++ b/apps/live/src/app/(landing)/CabinRace/CabinRace.tsx @@ -8,7 +8,7 @@ import { CabinRaceSquiggle, } from "../../lib/Assets/SVG"; import CabinRaceCard from "../../components/CabinRaceComponents/CabinRaceCard.tsx"; -import {Cabin, CabinLead} from "./CabinTypes.tsx"; +import { Cabin, CabinLead } from "./CabinTypes.tsx"; import CabinRaceScoreTent from "../../components/CabinRaceComponents/CabinRaceScoreTent.tsx"; { @@ -72,15 +72,13 @@ export default function CabinRace(): JSX.Element { if (!cabinData) return; const leadIds = cabinData.records.flatMap( - record => record.fields.CabinLeads ?? [], + (record) => record.fields.CabinLeads ?? [], ); if (!leadIds.length) return; const fetchLeads = async () => { - const res = await fetch( - `/api/cabinLeads?ids=${leadIds.join(",")}`, - ); + const res = await fetch(`/api/cabinLeads?ids=${leadIds.join(",")}`); const data: CabinLeadInfo = await res.json(); setCabinLeads(data.records); }; @@ -92,27 +90,26 @@ export default function CabinRace(): JSX.Element { if (!cabinData) return []; const leadsById: Record = Object.fromEntries( - cabinLeads.map(lead => [ - lead.id, - { - name: lead.fields.Name, - src: lead.fields.src, - url: lead.fields.url, - }, - ]), + cabinLeads.map((lead) => [ + lead.id, + { + name: lead.fields.Name, + src: lead.fields.src, + url: lead.fields.url, + }, + ]), ); - return cabinData.records.map(record => ({ + return cabinData.records.map((record) => ({ name: record.fields.Name, points: record.fields.Points, description: record.fields.Description ?? "", cabinLeads: (record.fields.CabinLeads ?? []) - .map(id => leadsById[id]) - .filter((lead): lead is CabinLead => Boolean(lead)), + .map((id) => leadsById[id]) + .filter((lead): lead is CabinLead => Boolean(lead)), })); }, [cabinData, cabinLeads]); - const cabinsByName: Record = Object.fromEntries( fetchedCabins.map((cabin) => [cabin.name, cabin]), ); diff --git a/apps/live/src/app/api/cabinLeads/route.ts b/apps/live/src/app/api/cabinLeads/route.ts new file mode 100644 index 00000000..fe8febcd --- /dev/null +++ b/apps/live/src/app/api/cabinLeads/route.ts @@ -0,0 +1,45 @@ +import { NextRequest, NextResponse } from "next/server"; + +const BASE_URL = "https://api.airtable.com/v0"; +const TABLE_NAME = "CabinLead"; + +export async function GET(req: NextRequest) { + const { searchParams } = new URL(req.url); + const ids = searchParams.get("ids"); + + if (!ids) { + return NextResponse.json({ records: [] }); + } + + const CABIN_BASE_ID = process.env.CABIN_BASE_ID; + + const filterFormula = `OR(${ids + .split(",") + .map((id) => `RECORD_ID()='${id}'`) + .join(",")})`; + + const airtableUrl = `${BASE_URL}/${CABIN_BASE_ID}/${TABLE_NAME}?filterByFormula=${encodeURIComponent( + filterFormula, + )}`; + + try { + const response = await fetch(airtableUrl, { + headers: { + Authorization: `Bearer ${process.env.AIRTABLE_TOKEN_ID}`, + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + throw new Error("API request failed"); + } + + const data = await response.json(); + return NextResponse.json(data); + } catch (err) { + return NextResponse.json( + { error: `Request to get cabin leads failed ${err}` }, + { status: 500 }, + ); + } +}