Hackathon Participation Registration & Status-Based Banner States
Objective
Ensure the Hackathon Banner and Registration Modal strictly enforce the registrationDeadlinePolicy when a user attempts to join a hackathon event. All registration UI must accurately reflect the current participation window at all times — no "Join" affordance should ever be accessible outside of a valid registration period.
Important Context: This issue concerns Hackathon Participation Registration — the act of a user joining a specific hackathon event — and is entirely separate from general Boundless app account signup.
Registration Policy Enforcement
Supported Policy Types
The registration system must support all three values of registrationDeadlinePolicy:
| Policy |
Behavior |
BEFORE_START |
Registration is open until the hackathon officially starts. Once the start date passes, registration closes automatically. |
BEFORE_SUBMISSION_DEADLINE |
Registration remains open until the submission deadline is reached. Users can join even after the hackathon has started. |
CUSTOM |
Registration closes at the explicit registrationDeadline timestamp. This field must be respected exactly — no approximations or fallbacks to other dates. |
registrationOpen Flag
- If the API returns
registrationOpen: false, all "Join" UI must be permanently disabled — regardless of what the registrationDeadlinePolicy or any other timestamp suggests
- This flag is the authoritative override and must be evaluated before any policy-based logic runs
- A disabled registration state should be clearly communicated to the user — not silently hidden — so they understand why the option is unavailable
Button Text States
The registration button text must dynamically reflect the current context to set accurate user expectations:
| Context |
Button Text |
| Hackathon has not started yet |
"Early Register" |
| Hackathon is live, registration still open |
"Register" |
| Registration window is closing soon |
"Late Register" |
| Registration period not yet open |
"Register Interest" |
registrationOpen is false or deadline passed |
Button disabled with appropriate label |
- Button text must update reactively as time progresses — if a user has the page open across a registration boundary, the button state should update without requiring a page refresh
Technical Implementation
Primary Files
components/hackathons/hackathonBanner.tsx
components/hackathons/overview/RegisterHackathonModal.tsx
Hooks
useRegisterHackathon()
- Update this hook to consume and surface the
registrationOpen status returned from the API
- The hook should expose
registrationOpen as part of its return value so consuming components can gate their UI without re-fetching or duplicating logic
- Ensure the hook handles the
registrationOpen: false state as a first-class condition, not an edge case
useHackathonStatus()
- Use this hook for all reactive timeline calculations — deriving whether the current moment falls within the registration window, before the start, after the submission deadline, etc.
- All time-based evaluations must flow through this hook to ensure consistency across components and to avoid duplicated
Date.now() comparisons scattered across the codebase
- The hook must remain reactive — components consuming it should automatically reflect state changes as time progresses, without requiring a manual refresh
Logic Enforcement
Banner — canRegister Memo
- Refactor the
canRegister computed value in HackathonBanner.tsx to strictly respect the registrationDeadlinePolicy
- The memo must evaluate all three policy types (
BEFORE_START, BEFORE_SUBMISSION_DEADLINE, CUSTOM) using the timestamps provided by useHackathonStatus()
- The
registrationOpen flag must be checked first within the memo — if false, canRegister must resolve to false immediately without evaluating any further policy logic
- The memo's dependencies must be correctly declared to ensure it recalculates whenever relevant timestamps or the
registrationOpen flag change
Button — renderRegistrationButton
- Update the
renderRegistrationButton function to handle registrationOpen: false as a hard override — when this flag is false, the button must render in a permanently disabled state regardless of any other condition
- The function must map the current registration context to the correct button text from the states table above
- Disabled button states must remain visible and descriptive — the user must always understand why they cannot register, not simply encounter a missing button
Banner States
- The Hackathon Banner must reflect the current registration state at all times, acting as the primary visual indicator of the hackathon's lifecycle position
- Banner states must be driven by the same
canRegister memo and useHackathonStatus() logic — the banner and the registration button must always be in agreement; they must never contradict each other
- When
registrationOpen is false, the banner must surface a clear, on-brand message communicating that registration is closed
- When the policy is
CUSTOM, the banner should surface the registrationDeadline timestamp as a human-readable deadline or countdown so users understand the urgency
⚠️ Caution
This is a production environment — not a sandbox.
- Code must be performant, accessible, and clean
- No dummy data — all enforcement logic must operate on real
registrationDeadlinePolicy, registrationOpen, and deadline timestamp values from the API
- AI-generated code will be scrutinized; poorly structured or "hallucinated" code will result in immediate issue closure
- Follow the existing design system: shadcn/ui, Tailwind, Framer Motion
Testing & Verification
Automated Tests
npm run lint # Ensure code quality
npm run build # Verify no breaking changes in routing or types
Manual Verification
Hackathon Participation Registration & Status-Based Banner States
Objective
Ensure the Hackathon Banner and Registration Modal strictly enforce the
registrationDeadlinePolicywhen a user attempts to join a hackathon event. All registration UI must accurately reflect the current participation window at all times — no "Join" affordance should ever be accessible outside of a valid registration period.Registration Policy Enforcement
Supported Policy Types
The registration system must support all three values of
registrationDeadlinePolicy:BEFORE_STARTBEFORE_SUBMISSION_DEADLINECUSTOMregistrationDeadlinetimestamp. This field must be respected exactly — no approximations or fallbacks to other dates.registrationOpenFlagregistrationOpen: false, all "Join" UI must be permanently disabled — regardless of what theregistrationDeadlinePolicyor any other timestamp suggestsButton Text States
The registration button text must dynamically reflect the current context to set accurate user expectations:
"Early Register""Register""Late Register""Register Interest"registrationOpenisfalseor deadline passedTechnical Implementation
Primary Files
components/hackathons/hackathonBanner.tsxcomponents/hackathons/overview/RegisterHackathonModal.tsxHooks
useRegisterHackathon()registrationOpenstatus returned from the APIregistrationOpenas part of its return value so consuming components can gate their UI without re-fetching or duplicating logicregistrationOpen: falsestate as a first-class condition, not an edge caseuseHackathonStatus()Date.now()comparisons scattered across the codebaseLogic Enforcement
Banner —
canRegisterMemocanRegistercomputed value inHackathonBanner.tsxto strictly respect theregistrationDeadlinePolicyBEFORE_START,BEFORE_SUBMISSION_DEADLINE,CUSTOM) using the timestamps provided byuseHackathonStatus()registrationOpenflag must be checked first within the memo — iffalse,canRegistermust resolve tofalseimmediately without evaluating any further policy logicregistrationOpenflag changeButton —
renderRegistrationButtonrenderRegistrationButtonfunction to handleregistrationOpen: falseas a hard override — when this flag is false, the button must render in a permanently disabled state regardless of any other conditionBanner States
canRegistermemo anduseHackathonStatus()logic — the banner and the registration button must always be in agreement; they must never contradict each otherregistrationOpenisfalse, the banner must surface a clear, on-brand message communicating that registration is closedCUSTOM, the banner should surface theregistrationDeadlinetimestamp as a human-readable deadline or countdown so users understand the urgencyregistrationDeadlinePolicy,registrationOpen, and deadline timestamp values from the APITesting & Verification
Automated Tests
Manual Verification
registrationOpen: false— confirm all "Join" UI is permanently disabled regardless of policy type or timestamps, in both the banner and the modalBEFORE_STARTpolicy — confirm the registration button is active before the start date and automatically disables once the start date passesBEFORE_SUBMISSION_DEADLINEpolicy — confirm registration remains open after hackathon start and closes exactly at the submission deadlineCUSTOMpolicy — confirm registration closes precisely at theregistrationDeadlinetimestamp with no fallback to other dates"Early Register","Register","Late Register","Register Interest", disabled)canRegistermemo inHackathonBanner.tsxevaluatesregistrationOpenfirst before any policy logicuseHackathonStatus()without a page refresh