"use client"; import { useMemo, useState } from "react"; import type { Match, ScreenId, Stadium, Team } from "../../types/passport"; import { formatMatchDate, getStadiumById, getTeamById, } from "../../utils/passportMetrics"; import EmptyState from "../shared/EmptyState"; import ProgressBar from "../shared/ProgressBar"; import StatusPill from "../shared/StatusPill"; interface MatchJourneyScreenProps { matches: Match[]; teams: Team[]; stadiums: Stadium[]; onToggleMatchWatched: (matchId: string) => void; onNavigate: (screen: ScreenId) => void; } export default function MatchJourneyScreen({ matches, teams, stadiums, onToggleMatchWatched, onNavigate, }: MatchJourneyScreenProps) { const [stageFilter, setStageFilter] = useState("all"); const [statusFilter, setStatusFilter] = useState<"all" | "completed" | "live" | "upcoming">("all"); const stageOptions = useMemo( () => ["all", ...Array.from(new Set(matches.map((match) => match.stage)))], [matches], ); const filteredMatches = [...matches] .filter((match) => stageFilter === "all" || match.stage === stageFilter) .filter((match) => statusFilter === "all" || match.status === statusFilter) .sort((a, b) => new Date(a.dateTime).getTime() - new Date(b.dateTime).getTime()); const watchedCount = matches.filter((match) => match.watched).length; return (

Match journey

Stamp the road to the final.

Match cards combine fixtures, watch-state, prediction windows, venue context, and collectible rewards so every fixture becomes part of the fan's passport trail.

{stageOptions.map((stage) => ( ))}
{(["all", "live", "upcoming", "completed"] as const).map((status) => ( ))}
{filteredMatches.length === 0 ? ( ) : (
{filteredMatches.map((match) => { const homeTeam = getTeamById(teams, match.homeTeamId); const awayTeam = getTeamById(teams, match.awayTeamId); const stadium = getStadiumById(stadiums, match.venueId); const scoreLabel = match.homeScore !== undefined && match.awayScore !== undefined ? `${match.homeScore}–${match.awayScore}` : "vs"; return (
{match.status} {match.predictionWindow ? ( Prediction open ) : null}
{formatMatchDate(match.dateTime, "long")}
{homeTeam?.flagEmoji} {homeTeam?.name} {homeTeam?.shortName}
{scoreLabel}
{awayTeam?.name} {awayTeam?.flagEmoji} {awayTeam?.shortName}

{stadium?.icon} {stadium?.name}, {stadium?.city}

{match.story}

{match.tags.map((tag) => ( #{tag} ))}
{match.predictionWindow ? ( ) : null}
); })}
)}
); }