Skip to content

Refactor Winners Tab to Match Organizer Design #399

@Benjtalkshow

Description

@Benjtalkshow

Refactor Winners Tab to Match Organizer Design (app/hackathons/[slug])

Objective

Upgrade the participant-facing "Winners" tab to use the premium design already established in the organizer's PublishWinnersWizard, and ensure all project and participant links are fully functional with correct deep-linking parameters. The current implementation renders a basic card grid that lacks the visual hierarchy, deep linking, and premium "Podium" aesthetics that the organizer-side already delivers. This refactor closes that gap — the participant-facing winners experience should be indistinguishable in quality from what organizers see when publishing results.


Context & Current Implementation

Route

  • app/(landing)/hackathons/[slug]/page.tsx

Primary Component

  • components/hackathons/winners/WinnersTab.tsx

How It Currently Works

  • The page uses the useHackathonData() hook to fetch the winners dataset
  • WinnersTab is conditionally rendered when winners.length > 0 and the winnersTab feature is enabled in currentHackathon.enabledTabs
  • The current implementation renders a basic grid of winner cards that lack:
    • Clickable deep links for projects and participant profiles
    • The premium "Podium" visual hierarchy for top 3 ranks
    • USDC financial branding next to prize amounts
    • The Ribbon rank display and high-quality avatar treatments from the organizer design

UI & Design Replication

Design Source

  • Mirror the design found in components/organization/hackathons/rewards/WinnerCard.tsx exactly — this is the canonical reference and the participant-facing card must reach the same level of visual quality

Card Aesthetics

  • Use the Ribbon component for rank display on each winner tile — the ribbon should be prominently placed and visually distinct per rank position
  • Use high-quality Avatar circles for winner profile images, with appropriate fallback initials if no avatar is available
  • Include a stylized project preview card at the bottom of each winner tile, showing the project image or thumbnail alongside the project name
  • Prize amounts must display the USDC logo inline next to the value to ensure clear, unambiguous financial branding

Card Hierarchy & Podium Layout

  • Replicate the WinnersGrid layout from components/organization/hackathons/rewards/WinnersGrid.tsx as the structural foundation
  • Where applicable (i.e., when the top 3 ranked winners are present), implement the "Podium" effect — visually elevating 1st place above 2nd and 3rd, with proportional sizing or vertical offset that communicates rank at a glance
  • Cards beyond the top 3 should render in a standard grid below the podium section, maintaining the same card design without the podium elevation treatment
  • The overall layout must be responsive — the podium and grid should reflow gracefully at tablet and mobile breakpoints without breaking the visual hierarchy

Deep Linking & Logic

Project Link

  • Refactor the project name and project image/thumbnail on each winner card to be clickable links
  • Path: /projects/${projectId}?type=submission
  • The ?type=submission query parameter is required — it must always be appended to ensure the project page renders in the correct submission view context. Do not omit this parameter under any circumstance.

Participant Link

  • Refactor the participant name and avatar on each winner card to be clickable links
  • Path: /profile/${username} — linking to the participant's public profile page

Fallback Rendering

  • Both links must degrade gracefully when metadata is missing:
    • If projectId is null or undefined, render the project name and image as non-clickable text/image rather than a broken link
    • If username is null or undefined, render the participant name and avatar as non-clickable elements
    • If avatar image fails to load, fall back to styled initials using the existing Avatar component fallback pattern
  • Missing metadata must never cause a rendering error or blank card — the tile should always display whatever information is available

Technical Details

Hooks & Data Path

  • All winner data is provided by the useHackathonData() hook in the parent HackathonPage — no additional API calls should be introduced
  • Map the winners array (typed as Array<HackathonWinner>) from the hook's context output to the new WinnerCard component props
  • The mapping should be explicit and type-safe — strictly no any types

Components to Modify

  • Overhaul components/hackathons/winners/WinnersTab.tsx — this is the primary deliverable
  • Reference the logic and structure from components/organization/hackathons/rewards/PublishWinnersWizard.tsx for implementation guidance
  • Reference components/organization/hackathons/rewards/WinnerCard.tsx for the card design spec
  • Reference components/organization/hackathons/rewards/WinnersGrid.tsx for the grid and podium layout

⚠️ Caution

This is a production environment — not a sandbox.

  • Code must be performant, accessible, and clean
  • No dummy data — all winner data must come exclusively from the useHackathonData() hook; no hardcoded or mock values
  • 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

  • Confirm WinnersTab is only rendered when winners.length > 0 and winnersTab is present in currentHackathon.enabledTabs
  • Verify the Podium layout correctly elevates 1st place above 2nd and 3rd when top 3 winners are present
  • Confirm the Ribbon component displays the correct rank on each card
  • Verify the USDC logo appears inline next to all prize amounts
  • Test project deep links — clicking a project name or image navigates to /projects/${projectId}?type=submission with the query parameter correctly appended
  • Test participant profile links — clicking a participant name or avatar navigates to /profile/${username}
  • Verify fallback rendering — cards with missing projectId, username, or avatar image render gracefully without broken links, blank tiles, or console errors
  • Confirm no additional API calls are made — all data flows exclusively from useHackathonData()
  • Confirm no TypeScript any types are present in the winner data mapping layer
  • Test the layout at multiple breakpoints — confirm the podium and card grid reflow correctly at tablet and mobile sizes
  • Verify the card design visually matches components/organization/hackathons/rewards/WinnerCard.tsx at full fidelity
  • Provide video evidence

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions