Fortune-PlayLogic/app/print-odds/page.tsx
2026-03-01 14:24:51 +03:00

386 lines
16 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"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>
)
}