"use client" import { useState, useEffect } from "react" import Link from "next/link" import { useSearchParams } from "next/navigation" import { useBetslipStore } from "@/lib/store/betslip-store" import { mockEvents, popularLeagues, type Event } from "@/lib/mock-data" import { useBettingStore } from "@/lib/store/betting-store" import type { AppEvent } from "@/lib/store/betting-types" import { SPORT_SLUG_TO_ID, getMarketsForTab, type ApiOdds, type MarketTabKey } from "@/lib/store/betting-api" import { cn } from "@/lib/utils" import { ChevronDown, BarChart2, TrendingUp, Plus, Loader2 } from "lucide-react" function OddsButton({ odds, onClick, isSelected }: { odds: number onClick: () => void isSelected: boolean }) { return ( ) } function EventRow({ event }: { event: Event | AppEvent }) { const { bets, addBet } = useBetslipStore() return (
{/* Small Icons & ID Column */}
{event.id || "01682"}
{/* Time & Team Column */}
11:00 PM
{event.homeTeam} - {event.awayTeam}
{/* Market Columns Grid (10 Markets) */}
{event.markets.slice(0, 10).map((market) => { const betId = `${event.id}-${market.id}` const isSelected = bets.some((b) => b.id === betId) return ( addBet({ id: betId, event: `${event.homeTeam} - ${event.awayTeam}`, league: `${event.sport} - ${event.country} - ${event.league}`, market: "1X2", selection: market.label, odds: market.odds, })} /> ) })}
{/* More Markets Button -> match detail page */}
) } const MARKET_HEADERS = ["1", "X", "2", "Over (2.5)", "Under (2.5)", "1X", "12", "X2", "Yes", "No"] const ROW1_TABS: { key: MarketTabKey; label: string }[] = [ { key: "main", label: "Main" }, { key: "goals", label: "Goals" }, { key: "handicap", label: "Handicap" }, { key: "half_time", label: "Half Time / Full Time" }, { key: "correct_score", label: "Correct Score" }, ] const ROW2_TABS: { key: MarketTabKey; label: string }[] = [ { key: "1st_half", label: "1st Half" }, { key: "2nd_half", label: "2nd Half" }, { key: "combo", label: "Combo" }, { key: "chance_mix", label: "Chance Mix" }, { key: "home", label: "Home" }, ] export function EventsList({ filter = "All", sport: sportProp = "all", search = "" }: { filter?: string sport?: string search?: string }) { const searchParams = useSearchParams() const leagueQuery = searchParams.get("league") const sportQuery = searchParams.get("sport") ?? sportProp const [selectedLeague, setSelectedLeague] = useState(leagueQuery) const [activeTab, setActiveTab] = useState("main") const { bets, addBet } = useBetslipStore() const sportId = sportQuery === "all" ? null : (SPORT_SLUG_TO_ID[sportQuery] ?? null) const leagueId = selectedLeague && !Number.isNaN(Number(selectedLeague)) ? selectedLeague : null const { events: apiEvents, loading, error, hasMore, loadMore, setFilters } = useBettingStore() useEffect(() => { setSelectedLeague(leagueQuery) }, [leagueQuery]) useEffect(() => { setFilters(sportId, leagueId) }, [sportId, leagueId, setFilters]) const handleClose = () => { const url = new URL(window.location.href) url.searchParams.delete("league") window.history.pushState({}, "", url) setSelectedLeague(null) } const useApi = !(error && apiEvents.length === 0) const events = useApi ? (filter === "Live" ? apiEvents.filter((e) => e.isLive) : apiEvents) : selectedLeague ? mockEvents.filter((e) => e.league.toLowerCase() === selectedLeague.toLowerCase()) : mockEvents.filter((e) => { if (filter === "Live" && !e.isLive) return false if (sportProp !== "all" && e.sport.toLowerCase() !== sportProp.toLowerCase()) return false return true }) const showLoadMore = useApi && hasMore && events.length > 0 // Common Header Rendering const renderTableHeaders = () => ( <> {/* Table Header Categories */}
Main
Goals
Handicap
Half Time / Full Time
Correct Score
{/* Sub Headers */}
1st Half
2nd Half
Combo
Chance Mix
Home
) const getHeadersForTab = (tab: MarketTabKey) => { const first = events[0] const rawOdds: ApiOdds[] = first && "rawOdds" in first && Array.isArray((first as AppEvent).rawOdds) ? (first as AppEvent).rawOdds! : [] return getMarketsForTab(rawOdds, tab).headers } const renderColumnHeaders = (tab: MarketTabKey, eventList: (Event | AppEvent)[]) => { let headers = eventList.length ? getHeadersForTab(tab) : getMarketsForTab([], tab).headers if (!headers.length) headers = getMarketsForTab([], "main").headers const n = Math.max(headers.length, 1) return (
ID
Time
Event
{headers.map((h, i) => ( {h} ))}
) } const renderEventItem = (event: Event | AppEvent, tab: MarketTabKey) => { const hasRawOdds = event && "rawOdds" in event && Array.isArray((event as AppEvent).rawOdds) const rawOdds = hasRawOdds ? (event as AppEvent).rawOdds! : [] const { cells } = getMarketsForTab(rawOdds, tab) const useMainMarkets = !hasRawOdds && event.markets?.length && (tab === "main" || tab === "combo" || tab === "chance_mix" || tab === "home") const displayCells = useMainMarkets ? event.markets.slice(0, 10).map((m, i) => ({ id: m.id, label: MARKET_HEADERS[i] ?? m.label, odds: m.odds })) : cells const n = Math.max(displayCells.length, 1) return (
{event.id}
{event.time} PM
{event.homeTeam} - {event.awayTeam}
{displayCells.map((cell) => { const betId = `${event.id}-${cell.id}` const isSelected = bets.some((b) => b.id === betId) const hasOdds = cell.odds > 0 return ( ) })}
) } if (loading && events.length === 0) { return (

Loading events and odds…

{/*

Resolving odds for each event

*/}
) } if (error && apiEvents.length === 0 && events.length === 0) { return (

{error}

Check NEXT_PUBLIC_BETTING_API_BASE_URL and tenant.

) } if (selectedLeague) { // Group by date for league view const groupedEvents = events.reduce((acc, event) => { if (!acc[event.date]) acc[event.date] = [] acc[event.date].push(event) return acc }, {} as Record) return (
{/* League Header / Breadcrumbs */}
••• Football | {selectedLeague === "LaLiga" ? "Spain - LaLiga" : selectedLeague}
{/* Market category tabs row 1: Main, Goals, Handicap, Half Time / Full Time, Correct Score */}
{ROW1_TABS.map(({ key, label }) => ( ))}
{/* Row 2: 1st Half, 2nd Half, Combo, Chance Mix, Home */}
{ROW2_TABS.map(({ key, label }) => ( ))}
{/* Column Headers (dynamic by tab) */} {renderColumnHeaders(activeTab, events)} {/* Grouped Events */}
{Object.entries(groupedEvents).map(([date, dateEvents]) => (
{date}
{dateEvents.map((event) => renderEventItem(event, activeTab))}
))}
{showLoadMore && (
)}
) } // Home View (No League Selected) const homeEventsByLeague = events.reduce((acc, event) => { if (!acc[event.league]) acc[event.league] = [] acc[event.league].push(event) return acc }, {} as Record) return (
{error && (
Showing sample data. API: {error}
)}
{Object.entries(homeEventsByLeague).map(([leagueName, leagueEvents]) => (
{/* League Box Header */}
{popularLeagues.find(l => l.name === leagueName)?.icon || popularLeagues.find(l => l.id.toLowerCase() === leagueName.toLowerCase())?.icon || "⚽"} {leagueName === "LaLiga" ? "Spain - LaLiga" : leagueName === "Premier League" ? "England - Premier League" : leagueName === "Bundesliga" ? "Germany - Bundesliga" : leagueName === "Ligue 1" ? "France - Ligue 1" : leagueName}
{/* Column Headers for each league box */}
Stats ID Time Event
{MARKET_HEADERS.map(h => {h})}
{/* Matches in this league */}
{leagueEvents.map((event) => renderEventItem(event, "main"))}
))}
{showLoadMore && (
)}
) }