386 lines
16 KiB
TypeScript
386 lines
16 KiB
TypeScript
"use client"
|
||
|
||
import { useState, useMemo } from "react"
|
||
import { cn } from "@/lib/utils"
|
||
|
||
type NationId = string
|
||
type TournamentId = string
|
||
type MarketId = string
|
||
|
||
const SPORTS_WITH_NATIONS: { sport: string; sportId: string; nations: { id: NationId; name: string; flag: string }[] }[] = [
|
||
{
|
||
sport: "Football",
|
||
sportId: "football",
|
||
nations: [
|
||
{ id: "intl-clubs", name: "International Clubs", flag: "🌍" },
|
||
{ id: "england", name: "England", flag: "🏴" },
|
||
{ id: "spain", name: "Spain", flag: "🇪🇸" },
|
||
{ id: "germany", name: "Germany", flag: "🇩🇪" },
|
||
{ id: "italy", name: "Italy", flag: "🇮🇹" },
|
||
{ id: "international", name: "International", flag: "🌐" },
|
||
{ id: "france", name: "France", flag: "🇫🇷" },
|
||
{ id: "portugal", name: "Portugal", flag: "🇵🇹" },
|
||
{ id: "england-amateur", name: "England Amateur", flag: "🏴" },
|
||
{ id: "netherlands", name: "Netherlands", flag: "🇳🇱" },
|
||
{ id: "scotland", name: "Scotland", flag: "🏴" },
|
||
{ id: "belgium", name: "Belgium", flag: "🇧🇪" },
|
||
{ id: "turkiye", name: "Turkiye", flag: "🇹🇷" },
|
||
],
|
||
},
|
||
]
|
||
|
||
const TOURNAMENTS_BY_NATION: Record<NationId, { id: TournamentId; name: string; flag: string }[]> = {
|
||
"intl-clubs": [
|
||
{ id: "uefa-cl", name: "UEFA Champions League", flag: "🏆" },
|
||
{ id: "uefa-el", name: "UEFA Europa League", flag: "🏆" },
|
||
{ id: "uefa-ecl", name: "UEFA Europa Conference League", flag: "🏆" },
|
||
{ id: "copa-libertadores", name: "Copa Libertadores", flag: "🏆" },
|
||
{ id: "copa-sudamericana", name: "Copa Sudamericana", flag: "🏆" },
|
||
],
|
||
england: [
|
||
{ id: "premier-league", name: "Premier League", flag: "🏴" },
|
||
{ id: "championship", name: "Championship", flag: "🏴" },
|
||
{ id: "league-one", name: "League One", flag: "🏴" },
|
||
{ id: "league-two", name: "League Two", flag: "🏴" },
|
||
{ id: "fa-cup", name: "FA Cup", flag: "🏴" },
|
||
{ id: "efl-cup", name: "EFL Cup", flag: "🏴" },
|
||
{ id: "national-league", name: "National League", flag: "🏴" },
|
||
],
|
||
spain: [
|
||
{ id: "laliga", name: "LaLiga", flag: "🇪🇸" },
|
||
{ id: "laliga2", name: "LaLiga 2", flag: "🇪🇸" },
|
||
{ id: "copa-del-rey", name: "Copa del Rey", flag: "🇪🇸" },
|
||
],
|
||
germany: [
|
||
{ id: "bundesliga", name: "Bundesliga", flag: "🇩🇪" },
|
||
{ id: "bundesliga2", name: "2. Bundesliga", flag: "🇩🇪" },
|
||
{ id: "dfb-pokal", name: "DFB-Pokal", flag: "🇩🇪" },
|
||
],
|
||
italy: [
|
||
{ id: "serie-a", name: "Serie A", flag: "🇮🇹" },
|
||
{ id: "serie-b", name: "Serie B", flag: "🇮🇹" },
|
||
{ id: "coppa-italia", name: "Coppa Italia", flag: "🇮🇹" },
|
||
],
|
||
international: [
|
||
{ id: "world-cup", name: "FIFA World Cup", flag: "🌐" },
|
||
{ id: "euro", name: "UEFA European Championship", flag: "🌐" },
|
||
],
|
||
france: [
|
||
{ id: "ligue1", name: "Ligue 1", flag: "🇫🇷" },
|
||
{ id: "ligue2", name: "Ligue 2", flag: "🇫🇷" },
|
||
],
|
||
portugal: [
|
||
{ id: "liga-portugal", name: "Liga Portugal", flag: "🇵🇹" },
|
||
],
|
||
"england-amateur": [],
|
||
netherlands: [
|
||
{ id: "eredivisie", name: "Eredivisie", flag: "🇳🇱" },
|
||
{ id: "eerste-divisie", name: "Eerste Divisie", flag: "🇳🇱" },
|
||
],
|
||
scotland: [{ id: "scotland-prem", name: "Scottish Premiership", flag: "🏴" }],
|
||
belgium: [{ id: "pro-league", name: "Pro League", flag: "🇧🇪" }],
|
||
turkiye: [{ id: "super-lig", name: "Süper Lig", flag: "🇹🇷" }],
|
||
}
|
||
|
||
const ALL_MARKETS: { id: MarketId; code: string; name: string }[] = [
|
||
{ id: "164", code: "164", name: "1x2" },
|
||
{ id: "166", code: "166", name: "Double Chance" },
|
||
{ id: "168", code: "168", name: "Draw No Bet" },
|
||
{ id: "170", code: "170", name: "Handicap 1:0" },
|
||
{ id: "172", code: "172", name: "Asian Handicap 0.5" },
|
||
{ id: "174", code: "174", name: "Total 0.5" },
|
||
{ id: "176", code: "176", name: "Total 1.5" },
|
||
{ id: "178", code: "178", name: "Total 2.5" },
|
||
{ id: "180", code: "180", name: "Total 3.5" },
|
||
{ id: "181", code: "181", name: "Total 4.5" },
|
||
{ id: "184", code: "184", name: "Home Team Over/Under" },
|
||
{ id: "186", code: "186", name: "Home Team Over/Under" },
|
||
{ id: "188", code: "188", name: "Away Team Over/Under" },
|
||
{ id: "189", code: "189", name: "Away Team Over/Under" },
|
||
{ id: "191", code: "191", name: "Home Team Goals" },
|
||
{ id: "193", code: "193", name: "Away Team Goals" },
|
||
{ id: "194", code: "194", name: "1st Half - 1X2" },
|
||
{ id: "196", code: "196", name: "1st Half - Draw No Bet" },
|
||
]
|
||
|
||
const MAIN_MARKET_IDS: MarketId[] = ["164", "166", "168", "178", "194"]
|
||
|
||
export default function PrintOddsPage() {
|
||
const [sportChecked, setSportChecked] = useState(true)
|
||
const [selectedNations, setSelectedNations] = useState<Set<NationId>>(new Set())
|
||
const [selectedTournaments, setSelectedTournaments] = useState<Set<TournamentId>>(new Set())
|
||
const [selectedMarkets, setSelectedMarkets] = useState<Set<MarketId>>(new Set())
|
||
const [sorting, setSorting] = useState("Events")
|
||
const [printSorting, setPrintSorting] = useState("Horizontal")
|
||
const [dateHelper, setDateHelper] = useState("Today")
|
||
const [startDate, setStartDate] = useState("02/28/2026")
|
||
const [endDate, setEndDate] = useState("02/28/2026")
|
||
const [logo, setLogo] = useState("Without logo")
|
||
|
||
const availableTournaments = useMemo(() => {
|
||
if (!sportChecked || selectedNations.size === 0) return []
|
||
const list: { id: TournamentId; name: string; flag: string }[] = []
|
||
selectedNations.forEach((nationId) => {
|
||
const tournaments = TOURNAMENTS_BY_NATION[nationId as NationId]
|
||
if (tournaments) list.push(...tournaments)
|
||
})
|
||
return list
|
||
}, [sportChecked, selectedNations])
|
||
|
||
const toggleNation = (id: NationId) => {
|
||
setSelectedNations((prev) => {
|
||
const next = new Set(prev)
|
||
if (next.has(id)) next.delete(id)
|
||
else next.add(id)
|
||
return next
|
||
})
|
||
}
|
||
|
||
const toggleTournament = (id: TournamentId) => {
|
||
setSelectedTournaments((prev) => {
|
||
const next = new Set(prev)
|
||
if (next.has(id)) next.delete(id)
|
||
else next.add(id)
|
||
return next
|
||
})
|
||
}
|
||
|
||
const toggleMarket = (id: MarketId) => {
|
||
setSelectedMarkets((prev) => {
|
||
const next = new Set(prev)
|
||
if (next.has(id)) next.delete(id)
|
||
else next.add(id)
|
||
return next
|
||
})
|
||
}
|
||
|
||
const pickMainMarkets = () => {
|
||
setSelectedMarkets((prev) => {
|
||
const next = new Set(prev)
|
||
MAIN_MARKET_IDS.forEach((id) => next.add(id))
|
||
return next
|
||
})
|
||
}
|
||
|
||
const makePdf = () => {
|
||
const printWindow = window.open("", "_blank")
|
||
if (!printWindow) {
|
||
window.print()
|
||
return
|
||
}
|
||
printWindow.document.write(`
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head><title>Print Odds</title>
|
||
<style>
|
||
body { font-family: sans-serif; padding: 20px; color: #111; }
|
||
h1 { font-size: 18px; margin-bottom: 16px; }
|
||
table { border-collapse: collapse; width: 100%; }
|
||
th, td { border: 1px solid #ddd; padding: 8px 12px; text-align: left; }
|
||
th { background: #f5f5f5; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>Print Odds – ${dateHelper}</h1>
|
||
<p><strong>Date range:</strong> ${startDate} – ${endDate}</p>
|
||
<p><strong>Nations:</strong> ${Array.from(selectedNations).join(", ")}</p>
|
||
<p><strong>Tournaments:</strong> ${Array.from(selectedTournaments).join(", ")}</p>
|
||
<p><strong>Markets:</strong> ${Array.from(selectedMarkets).map((id) => ALL_MARKETS.find((m) => m.id === id)?.name ?? id).join(", ")}</p>
|
||
<p><em>Odds sheet would be generated based on selected options.</em></p>
|
||
</body>
|
||
</html>
|
||
`)
|
||
printWindow.document.close()
|
||
printWindow.focus()
|
||
printWindow.print()
|
||
printWindow.close()
|
||
}
|
||
|
||
const sport = SPORTS_WITH_NATIONS[0]
|
||
|
||
return (
|
||
<div className="min-h-screen bg-brand-bg text-white flex flex-col">
|
||
<div className="bg-brand-surface border-b border-white/10 px-4 py-2 flex flex-wrap items-center gap-4">
|
||
<select
|
||
value={sorting}
|
||
onChange={(e) => setSorting(e.target.value)}
|
||
className="bg-brand-surface-light border border-white/20 text-white text-[11px] px-2 py-1.5 rounded-none"
|
||
>
|
||
<option value="Events">Events</option>
|
||
<option value="Leagues">Leagues</option>
|
||
</select>
|
||
<select
|
||
value={printSorting}
|
||
onChange={(e) => setPrintSorting(e.target.value)}
|
||
className="bg-brand-surface-light border border-white/20 text-white text-[11px] px-2 py-1.5 rounded-none"
|
||
>
|
||
<option value="Horizontal">Horizontal</option>
|
||
<option value="Vertical">Vertical</option>
|
||
</select>
|
||
<select
|
||
value={dateHelper}
|
||
onChange={(e) => setDateHelper(e.target.value)}
|
||
className="bg-brand-surface-light border border-white/20 text-white text-[11px] px-2 py-1.5 rounded-none"
|
||
>
|
||
<option value="Today">Today</option>
|
||
<option value="Tomorrow">Tomorrow</option>
|
||
<option value="Week">Week</option>
|
||
</select>
|
||
<input
|
||
type="text"
|
||
value={startDate}
|
||
onChange={(e) => setStartDate(e.target.value)}
|
||
className="bg-brand-surface-light border border-white/20 text-white text-[11px] w-28 px-2 py-1.5 rounded-none"
|
||
/>
|
||
<input
|
||
type="text"
|
||
value={endDate}
|
||
onChange={(e) => setEndDate(e.target.value)}
|
||
className="bg-brand-surface-light border border-white/20 text-white text-[11px] w-28 px-2 py-1.5 rounded-none"
|
||
/>
|
||
<select
|
||
value={logo}
|
||
onChange={(e) => setLogo(e.target.value)}
|
||
className="bg-brand-surface-light border border-white/20 text-white text-[11px] px-2 py-1.5 rounded-none"
|
||
>
|
||
<option value="Without logo">Without logo</option>
|
||
<option value="With logo">With logo</option>
|
||
</select>
|
||
<div className="flex-1" />
|
||
<button
|
||
type="button"
|
||
onClick={pickMainMarkets}
|
||
className="bg-brand-primary text-black px-4 py-2 text-[11px] font-bold uppercase rounded-none hover:bg-brand-primary-hover"
|
||
>
|
||
Pick Main Markets +
|
||
</button>
|
||
<button
|
||
type="button"
|
||
onClick={makePdf}
|
||
className="bg-brand-primary text-black px-4 py-2 text-[11px] font-bold uppercase rounded-none hover:bg-brand-primary-hover flex items-center gap-1"
|
||
>
|
||
Make PDF
|
||
<svg viewBox="0 0 24 24" className="size-4 fill-current"><path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0016 9.5 6.5 6.5 0 109.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></svg>
|
||
</button>
|
||
</div>
|
||
|
||
<div id="print-odds-content" className="flex-1 grid grid-cols-1 md:grid-cols-3 gap-0 p-4 min-h-0">
|
||
{/* 1 Choose Nation */}
|
||
<div className="border border-white/10 rounded-l bg-brand-surface-light overflow-hidden flex flex-col">
|
||
<div className="px-3 py-2 bg-brand-surface border-b border-white/10 text-[11px] font-black uppercase">
|
||
1 Choose Nation
|
||
</div>
|
||
<div className="flex-1 overflow-y-auto p-2 space-y-1">
|
||
<label className="flex items-center gap-2 py-1.5 px-2 hover:bg-white/5 cursor-pointer">
|
||
<input
|
||
type="checkbox"
|
||
checked={sportChecked}
|
||
onChange={(e) => setSportChecked(e.target.checked)}
|
||
className="rounded border-white/40 text-brand-primary"
|
||
/>
|
||
<span className="text-[11px] font-bold">{sport.sport}</span>
|
||
</label>
|
||
{sport.nations.map((nation) => (
|
||
<label
|
||
key={nation.id}
|
||
className={cn(
|
||
"flex items-center gap-2 py-1.5 px-2 hover:bg-white/5 cursor-pointer rounded",
|
||
selectedNations.has(nation.id) && "bg-white/10"
|
||
)}
|
||
>
|
||
<input
|
||
type="checkbox"
|
||
checked={selectedNations.has(nation.id)}
|
||
onChange={() => toggleNation(nation.id)}
|
||
className="rounded border-white/40 text-brand-primary"
|
||
/>
|
||
<span className="text-[10px] mr-1">{nation.flag}</span>
|
||
<span className="text-[11px]">{nation.name}</span>
|
||
</label>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 2 Choose Tournaments */}
|
||
<div className="border border-white/10 border-x-0 md:border-x bg-brand-surface-light overflow-hidden flex flex-col">
|
||
<div className="px-3 py-2 bg-brand-surface border-b border-white/10 text-[11px] font-black uppercase">
|
||
2 Choose Tournaments
|
||
</div>
|
||
<div className="flex-1 overflow-y-auto p-2 space-y-1">
|
||
{availableTournaments.length === 0 ? (
|
||
<p className="text-white/50 text-[11px] py-4 px-2">Select nations first</p>
|
||
) : (
|
||
<>
|
||
<label className="flex items-center gap-2 py-1.5 px-2 hover:bg-white/5 cursor-pointer">
|
||
<input
|
||
type="checkbox"
|
||
checked={selectedTournaments.size === availableTournaments.length}
|
||
onChange={(e) => {
|
||
if (e.target.checked) {
|
||
setSelectedTournaments(new Set(availableTournaments.map((t) => t.id)))
|
||
} else {
|
||
setSelectedTournaments(new Set())
|
||
}
|
||
}}
|
||
className="rounded border-white/40 text-brand-primary"
|
||
/>
|
||
<span className="text-[11px] font-bold">All</span>
|
||
</label>
|
||
{availableTournaments.map((t) => (
|
||
<label
|
||
key={t.id}
|
||
className={cn(
|
||
"flex items-center gap-2 py-1.5 px-2 hover:bg-white/5 cursor-pointer rounded",
|
||
selectedTournaments.has(t.id) && "bg-white/10"
|
||
)}
|
||
>
|
||
<input
|
||
type="checkbox"
|
||
checked={selectedTournaments.has(t.id)}
|
||
onChange={() => toggleTournament(t.id)}
|
||
className="rounded border-white/40 text-brand-primary"
|
||
/>
|
||
<span className="text-[10px] mr-1">{t.flag}</span>
|
||
<span className="text-[11px]">{t.name}</span>
|
||
</label>
|
||
))}
|
||
</>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 3 Choose Markets - shown only after nations and tournaments are chosen */}
|
||
<div className="border border-white/10 rounded-r bg-brand-surface-light overflow-hidden flex flex-col">
|
||
<div className="px-3 py-2 bg-brand-surface border-b border-white/10 text-[11px] font-black uppercase">
|
||
3 Choose Markets
|
||
</div>
|
||
<div className="flex-1 overflow-y-auto p-2 space-y-1">
|
||
{selectedNations.size === 0 || selectedTournaments.size === 0 ? (
|
||
<p className="text-white/50 text-[11px] py-4 px-2">Select nations and tournaments first</p>
|
||
) : (
|
||
ALL_MARKETS.map((m) => (
|
||
<label
|
||
key={m.id}
|
||
className={cn(
|
||
"flex items-center gap-2 py-1.5 px-2 hover:bg-white/5 cursor-pointer rounded",
|
||
selectedMarkets.has(m.id) && "bg-white/10"
|
||
)}
|
||
>
|
||
<input
|
||
type="checkbox"
|
||
checked={selectedMarkets.has(m.id)}
|
||
onChange={() => toggleMarket(m.id)}
|
||
className="rounded border-white/40 text-brand-primary"
|
||
/>
|
||
<span className="text-[10px] text-white/60 w-6">{m.code}</span>
|
||
<span className="text-[11px]">{m.name}</span>
|
||
</label>
|
||
))
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|