Skip to content

Hackathon Participation Registration & Status-Based Banner States #404

@Benjtalkshow

Description

@Benjtalkshow

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

  • Set registrationOpen: false — confirm all "Join" UI is permanently disabled regardless of policy type or timestamps, in both the banner and the modal
  • Test BEFORE_START policy — confirm the registration button is active before the start date and automatically disables once the start date passes
  • Test BEFORE_SUBMISSION_DEADLINE policy — confirm registration remains open after hackathon start and closes exactly at the submission deadline
  • Test CUSTOM policy — confirm registration closes precisely at the registrationDeadline timestamp with no fallback to other dates
  • Verify button text updates correctly across all states ("Early Register", "Register", "Late Register", "Register Interest", disabled)
  • Confirm the canRegister memo in HackathonBanner.tsx evaluates registrationOpen first before any policy logic
  • Leave the page open across a registration boundary — confirm the button and banner update reactively via useHackathonStatus() without a page refresh
  • Confirm the banner and button are always in agreement — no scenario where the banner indicates registration is open while the button is disabled, or vice versa
  • Test all time comparisons with timestamps near DST boundaries — confirm no off-by-one errors at registration window edges
  • Verify the disabled registration button remains visible with a descriptive label — it must not simply disappear
  • Provide video evidence

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions