generated from include-davis/Next.js-App-Router-Starter
-
Notifications
You must be signed in to change notification settings - Fork 2
392 hacking hero #424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
392 hacking hero #424
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
043892d
init files
haylietan e2da1cb
Added mobile
haylietan cb899fa
Updated Counter
haylietan dac26f2
linting
haylietan 1ce691f
vh
haylietan 1a90d46
Merge branch 'main' into 392-hacking-hero
haylietan d6b182b
Updated font
haylietan 450c204
Added stars
haylietan 67998a9
linting
haylietan 3ed20b8
build errors
haylietan 4f404e6
move and rename files; remove useEffect
michelleyeoh 06bbec2
fixed border and center mobile
michelleyeoh 1dcd842
fix min height
michelleyeoh 82f7bfc
Merge branch 'main' into 392-hacking-hero
michelleyeoh a9c229f
revert layout
michelleyeoh 335a1c3
Merge branch '392-hacking-hero' of https://github.com/HackDavis/hackd…
michelleyeoh e485e27
removed unused timetracker
michelleyeoh 578da36
reverted urlsearchparams
michelleyeoh 68cbf24
removed priority
michelleyeoh 731ea9f
added rollout props
michelleyeoh 2834154
final cleanup
michelleyeoh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
275 changes: 275 additions & 0 deletions
275
app/(pages)/(hackers)/_components/HomeHacking/HeroHacking.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,275 @@ | ||
| 'use client'; | ||
|
|
||
| import Image from 'next/image'; | ||
| import { GoArrowRight } from 'react-icons/go'; | ||
|
|
||
| import ClientTimeProtectedDisplay from '@pages/_components/TimeProtectedDisplay/ClientTimeProtectedDisplay'; | ||
| import Countdown from './_components/Countdown'; | ||
|
|
||
| interface HeroHackingProps { | ||
| rolloutTime?: number; | ||
| loading?: boolean; | ||
| } | ||
|
|
||
| const ONE_DAY_MS = 24 * 60 * 60 * 1000; | ||
|
|
||
| export default function HeroHacking({ | ||
| rolloutTime, | ||
| loading, | ||
| }: HeroHackingProps) { | ||
| const countdownTarget = rolloutTime ? rolloutTime + ONE_DAY_MS : undefined; | ||
|
|
||
| return ( | ||
| <div className="w-full h-screen p-4 md:p-10"> | ||
| <div className="relative w-full min-h-[86vh] overflow-hidden"> | ||
| {/* content wrapper */} | ||
| <div className="relative z-10 w-full"> | ||
| {/* Main grid area */} | ||
| <div className="mx-auto h-[90vh] min-h-0 flex flex-col justify-center gap-3 md:grid md:grid-rows-[minmax(1,1fr)] md:gap-5"> | ||
| {/* Countdown bar */} | ||
| <div | ||
| className="relative flex flex-col justify-center rounded-[20px] md:rounded-[32px] bg-white/25 backdrop-blur-xl px-6 md:px-10 py-8 md:py-10 overflow-hidden" | ||
| style={{ | ||
| background: | ||
| 'linear-gradient(172deg, #46D8E9 43.03%, #76DEEB 63.28%, #FCFCD1 112.36%)', | ||
| }} | ||
| > | ||
| {/* background */} | ||
| <Image | ||
| src="/Hero/Clouds.svg" | ||
| alt="Background" | ||
| fill | ||
| className="object-cover pointer-events-none select-none -z-10" | ||
| /> | ||
|
|
||
| <div className="flex items-start justify-between gap-2"> | ||
| {/* Right: countdown (big) */} | ||
| <div className="flex-1 flex justify-center"> | ||
| <div className="text-white"> | ||
| <ClientTimeProtectedDisplay | ||
| featureId="hacking-starts" | ||
| fallback={<Countdown />} | ||
| > | ||
| {countdownTarget !== undefined && ( | ||
| <Countdown countdownTarget={countdownTarget} /> | ||
| )} | ||
| </ClientTimeProtectedDisplay> | ||
|
|
||
| {loading && ( | ||
| <div className="mt-2 text-white/90 text-sm text-right"> | ||
| loading… | ||
| </div> | ||
| )} | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| {/* Everything below countdown must fit remaining height */} | ||
| <div className="relative min-h-0"> | ||
| {/* Decorative stars */} | ||
| <Image | ||
| src="/hackers/hero/StarLeft.svg" | ||
| alt="" | ||
| width={120} | ||
| height={120} | ||
| className=" | ||
| pointer-events-none select-none | ||
| absolute z-20 | ||
| -left-2 top-[35%] md:top-[50%] | ||
| w-[56px] sm:w-[70px] md:w-[84px] lg:w-[96px] | ||
| rotate-[-8deg] | ||
| " | ||
| /> | ||
|
|
||
| <Image | ||
| src="/hackers/hero/StarRight.svg" | ||
| alt="" | ||
| width={120} | ||
| height={120} | ||
| className=" | ||
| pointer-events-none select-none | ||
| absolute z-20 | ||
| -right-2 top-[10%] | ||
| w-[56px] sm:w-[70px] md:w-[84px] lg:w-[96px] | ||
| rotate-[10deg] | ||
| " | ||
| /> | ||
| {/* ===================== MOBILE (2x2 animals) ===================== */} | ||
| <div className="md:hidden h-full flex flex-col justify-center"> | ||
| {/* 2x2 animals */} | ||
| <div className="grid grid-cols-2 gap-2"> | ||
| {/* Cow */} | ||
| <div className="relative rounded-[20px] bg-[#93F5F3] overflow-hidden flex items-end justify-center"> | ||
| <Image | ||
| src="/hackers/hero/PeepingCow.svg" | ||
| alt="Peeking cow" | ||
| width={520} | ||
| height={320} | ||
| className="w-[85%] h-auto pointer-events-none select-none" | ||
| /> | ||
| </div> | ||
|
|
||
| {/* Duck */} | ||
| <div className="relative rounded-[20px] bg-[#FFF3B6] overflow-hidden flex items-end justify-center"> | ||
| <Image | ||
| src="/hackers/hero/PeepingDuck.svg" | ||
| alt="Peeking duck" | ||
| width={520} | ||
| height={320} | ||
| className="w-[100%] h-auto pointer-events-none select-none" | ||
| /> | ||
| </div> | ||
|
|
||
| {/* Frog */} | ||
| <div className="relative rounded-[20px] bg-[#E9FBBA] overflow-hidden flex items-end justify-center"> | ||
| <Image | ||
| src="/hackers/hero/PeepingFrog.svg" | ||
| alt="Peeking frog" | ||
| width={520} | ||
| height={320} | ||
| className="w-[65%] h-auto pointer-events-none select-none" | ||
| /> | ||
| </div> | ||
|
|
||
| {/* Bunny */} | ||
| <div className="relative rounded-[20px] bg-[#FFD2D2] overflow-hidden flex items-end justify-center"> | ||
| <Image | ||
| src="/hackers/hero/PeepingBunny.svg" | ||
| alt="Peeking bunny" | ||
| width={520} | ||
| height={320} | ||
| className="w-[85%] h-auto pointer-events-none select-none" | ||
| /> | ||
| </div> | ||
| </div> | ||
|
|
||
| {/* Submit pill under grid on mobile */} | ||
| <a | ||
| href="https://hackdavis-2026.devpost.com/" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="mt-2 group relative rounded-[1000px] bg-white/25 backdrop-blur-xl min-h-[110px] flex items-center justify-center overflow-hidden" | ||
| style={{ | ||
| background: | ||
| 'linear-gradient(172deg, #46D8E9 43.03%, #76DEEB 63.28%, #FCFCD1 112.36%)', | ||
| }} | ||
| > | ||
| {/* background */} | ||
| <Image | ||
| src="/Hero/Clouds.svg" | ||
| alt="Background" | ||
| fill | ||
| className="object-cover pointer-events-none select-none -z-10 overflow-hidden" | ||
| /> | ||
| <div className="absolute inset-0 opacity-70 pointer-events-none bg-gradient-to-r from-white/0 via-white/10 to-white/0" /> | ||
| <div className="relative flex items-center gap-2"> | ||
| <span className="text-white text-4xl md:text-5xl font-extrabold tracking-wide drop-shadow-[0_6px_14px_rgba(0,0,0,0.18)]"> | ||
| SUBMIT! | ||
| </span> | ||
| <GoArrowRight className="text-white text-4xl md:text-5xl drop-shadow-[0_6px_14px_rgba(0,0,0,0.18)] transition-transform duration-300 group-hover:translate-x-1" /> | ||
| </div> | ||
| </a> | ||
| </div> | ||
|
|
||
| {/* ===================== DESKTOP (dynamically fits remaining height) ===================== */} | ||
| <div className="hidden md:grid min-h-0 h-full grid-rows-[minmax(0,1fr)_minmax(0,1fr)] gap-5"> | ||
| {/* Row 1: 3 tiles */} | ||
| <div className="min-h-0 grid grid-cols-[50fr_30fr_20fr] gap-5"> | ||
| {/* Cow */} | ||
| <div className="min-h-0 relative rounded-[28px] bg-[#93F5F3] backdrop-blur-xl overflow-hidden flex items-end justify-center"> | ||
| <Image | ||
| src="/hackers/hero/PeepingCow.svg" | ||
| alt="Peeking cow" | ||
| width={520} | ||
| height={320} | ||
| className="w-[55%] max-h-full h-auto pointer-events-none select-none" | ||
| /> | ||
| </div> | ||
|
|
||
| {/* Duck */} | ||
| <div className="min-h-0 relative rounded-[28px] bg-[#FFF3B6] overflow-hidden flex items-end justify-center"> | ||
| <Image | ||
| src="/hackers/hero/PeepingDuck.svg" | ||
| alt="Peeking duck" | ||
| width={520} | ||
| height={320} | ||
| className="w-[100%] max-h-full h-auto pointer-events-none select-none" | ||
| /> | ||
| </div> | ||
|
|
||
| {/* Frog */} | ||
| <div className="min-h-0 relative rounded-[28px] bg-[#E9FBBA] backdrop-blur-xl overflow-hidden flex items-end justify-center"> | ||
| <Image | ||
| src="/hackers/hero/PeepingFrog.svg" | ||
| alt="Peeking frog" | ||
| width={520} | ||
| height={320} | ||
| className="w-[90%] max-h-full h-auto pointer-events-none select-none" | ||
| /> | ||
| </div> | ||
| </div> | ||
|
|
||
| {/* Row 2: bunny + submit pill */} | ||
| <div className="min-h-0 grid grid-cols-[1fr_2fr] gap-5 items-stretch"> | ||
| {/* Bunny */} | ||
| <div className="min-h-0 relative rounded-[28px] bg-[#FFD2D2] backdrop-blur-xl overflow-hidden flex items-end justify-center"> | ||
| <Image | ||
| src="/hackers/hero/PeepingBunny.svg" | ||
| alt="Peeking bunny" | ||
| width={520} | ||
| height={320} | ||
| className="w-[85%] max-h-full h-auto pointer-events-none select-none" | ||
| /> | ||
| </div> | ||
|
|
||
| {/* Submit pill */} | ||
| <a | ||
| href="https://hackdavis-2026.devpost.com/" | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="group relative rounded-full bg-white/25 backdrop-blur-xl flex items-center justify-center overflow-hidden" | ||
| style={{ | ||
| background: | ||
| 'linear-gradient(172deg, #46D8E9 43.03%, #76DEEB 63.28%, #FCFCD1 112.36%)', | ||
| }} | ||
| > | ||
| {/* background */} | ||
| <Image | ||
| src="/Hero/Clouds.svg" | ||
| alt="Background" | ||
| fill | ||
| className="object-cover pointer-events-none select-none -z-10" | ||
| /> | ||
|
|
||
| <div className="absolute inset-0 opacity-70 pointer-events-none bg-gradient-to-r from-white/0 via-white/10 to-white/0" /> | ||
|
|
||
| <div className="relative flex items-center gap-6"> | ||
| <span | ||
| className="text-white font-medium tracking-[4.601px]" | ||
| style={{ | ||
| fontSize: 'clamp(28px, 6vw, 90px)', | ||
| textShadow: '0 0 31.729px rgba(255, 255, 255, 0.30)', | ||
| }} | ||
| > | ||
| SUBMIT | ||
| </span> | ||
|
|
||
| <GoArrowRight | ||
| className="text-white transition-transform duration-300 group-hover:translate-x-3" | ||
| style={{ | ||
| fontSize: 'clamp(40px, 5vw, 120px)', | ||
| textShadow: '0 0 31.729px rgba(255, 255, 255, 0.30)', | ||
| }} | ||
| /> | ||
| </div> | ||
| </a> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| {/* end main grid area */} | ||
| </div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
89 changes: 89 additions & 0 deletions
89
app/(pages)/(hackers)/_components/HomeHacking/_components/Countdown.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| 'use client'; | ||
|
|
||
| import { useState, useEffect } from 'react'; | ||
|
|
||
| interface CountdownProps { | ||
| countdownTarget?: number; | ||
| } | ||
|
|
||
| const HACKING_ENDS_TIME = new Date('2026-05-10T11:00:00-07:00').getTime(); // May 10, 2026 at 11:00 AM PDT | ||
|
|
||
| export default function Countdown({ | ||
| countdownTarget = HACKING_ENDS_TIME, | ||
| }: CountdownProps) { | ||
michelleyeoh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const [timeLeft, setTimeLeft] = useState({ | ||
| hours: 24, | ||
| minutes: 0, | ||
| seconds: 0, | ||
| }); | ||
|
|
||
| useEffect(() => { | ||
| const calculateTimeLeft = () => { | ||
| const now = Date.now(); | ||
| const difference = countdownTarget - now; | ||
|
|
||
| if (difference <= 0) { | ||
| return { hours: 0, minutes: 0, seconds: 0 }; | ||
| } | ||
|
|
||
| if (difference > 24 * 60 * 60 * 1000) { | ||
| return { hours: 24, minutes: 0, seconds: 0 }; | ||
| } | ||
|
|
||
| return { | ||
| hours: Math.floor(difference / (1000 * 60 * 60)), | ||
| minutes: Math.floor((difference / (1000 * 60)) % 60), | ||
| seconds: Math.floor((difference / 1000) % 60), | ||
| }; | ||
| }; | ||
|
|
||
| setTimeLeft(calculateTimeLeft()); | ||
|
|
||
| const timer = setInterval(() => { | ||
| setTimeLeft(calculateTimeLeft()); | ||
| }, 1000); | ||
|
|
||
| return () => clearInterval(timer); | ||
| }, [countdownTarget]); | ||
|
|
||
| const timerStyle = { | ||
| color: '#FFF', | ||
| fontFamily: 'DM Mono', | ||
| fontSize: 'clamp(36px, 12vw, 230.034px)', | ||
michelleyeoh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| fontStyle: 'normal', | ||
| fontWeight: 500, | ||
| lineHeight: 'normal', | ||
| letterSpacing: '4.601px', | ||
| textShadow: '0 0 31.729px rgba(255, 255, 255, 0.30)', | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="flex flex-col items-end text-white"> | ||
| {/* BIG TIMER */} | ||
| <div className="flex items-end gap-3 md:gap-6" style={timerStyle}> | ||
| <span className="leading-none"> | ||
| {timeLeft.hours.toString().padStart(2, '0')} | ||
| </span> | ||
|
|
||
| <span className="leading-none">:</span> | ||
|
|
||
| <span className="leading-none"> | ||
| {timeLeft.minutes.toString().padStart(2, '0')} | ||
| </span> | ||
|
|
||
| <span className="leading-none">:</span> | ||
|
|
||
| <span className="leading-none"> | ||
| {timeLeft.seconds.toString().padStart(2, '0')} | ||
| </span> | ||
| </div> | ||
|
|
||
| {/* LABEL ROW */} | ||
| {/* <div className="flex gap-8 md:gap-14 mt-3 text-xs md:text-sm font-semibold tracking-widest opacity-90"> | ||
| <span>HOURS</span> | ||
| <span>MINUTES</span> | ||
| <span>SECONDS</span> | ||
| </div> */} | ||
| </div> | ||
| ); | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.