i forgor
This commit is contained in:
171
beaky-frontend/src/lib/BetsTable.svelte
Normal file
171
beaky-frontend/src/lib/BetsTable.svelte
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<script>
|
||||||
|
let { bets } = $props()
|
||||||
|
|
||||||
|
function formatBetType(t) {
|
||||||
|
return {
|
||||||
|
win_draw_lose: '1X2 Result',
|
||||||
|
win_draw_lose_double: '1X2 Double',
|
||||||
|
win_lose: 'Win/Lose',
|
||||||
|
both_team_scored: 'Both Teams Score',
|
||||||
|
goal_amount: 'Over/Under Goals',
|
||||||
|
goal_handicap: 'Goal Handicap',
|
||||||
|
half_time_result: 'HT Result',
|
||||||
|
half_time_double: 'HT Double',
|
||||||
|
half_time_full_time: 'HT/FT',
|
||||||
|
corner_amount: 'Over/Under Corners',
|
||||||
|
team_corner_amount: 'Team Corners',
|
||||||
|
more_offsides: 'More Offsides',
|
||||||
|
advance: 'Advance',
|
||||||
|
unknown: 'Unknown',
|
||||||
|
}[t] ?? t
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatBetDetail(bet) {
|
||||||
|
const result = (code) => ({ '1': 'Home win', '2': 'Away win', '0': 'Draw', 'X': 'Draw' }[code] ?? code)
|
||||||
|
const double = (code) => ({ '01': 'Home or Draw', '02': 'Home or Away', '12': 'Draw or Away' }[code] ?? code)
|
||||||
|
const team = (code) => code === '1' ? bet.team1Name : bet.team2Name
|
||||||
|
const sign = (n) => (n >= 0 ? '+' : '') + n
|
||||||
|
|
||||||
|
switch (bet.ticketType) {
|
||||||
|
case 'win_draw_lose': return result(bet.betType)
|
||||||
|
case 'win_draw_lose_double': return double(bet.betType)
|
||||||
|
case 'win_lose': return result(bet.betType)
|
||||||
|
case 'both_team_scored': return 'Both teams to score'
|
||||||
|
case 'goal_amount': return (bet.over ? 'Over ' : 'Under ') + bet.line + ' goals'
|
||||||
|
case 'goal_handicap': return team(bet.team_bet) + ' ' + sign(bet.handicap_amount)
|
||||||
|
case 'half_time_result': return 'HT: ' + result(bet.betType)
|
||||||
|
case 'half_time_double': return 'HT: ' + double(bet.betType)
|
||||||
|
case 'half_time_full_time': return 'HT: ' + result(bet.ht_bet) + ' / FT: ' + result(bet.ft_bet)
|
||||||
|
case 'corner_amount': return (bet.over ? 'Over ' : 'Under ') + bet.line + ' corners'
|
||||||
|
case 'team_corner_amount': return team(bet.team_bet) + ' ' + (bet.over ? 'over ' : 'under ') + bet.line
|
||||||
|
case 'more_offsides': return team(bet.team_bet) + ' more offsides'
|
||||||
|
case 'advance': return 'Advance'
|
||||||
|
default: return bet.raw_text || 'Unknown'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="table-wrap">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Match</th>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>League</th>
|
||||||
|
<th>Bet Type</th>
|
||||||
|
<th>Pick</th>
|
||||||
|
<th>Outcome</th>
|
||||||
|
<th>Confidence</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each bets as resolved, i}
|
||||||
|
{@const bet = resolved.bet}
|
||||||
|
{@const outcome = (resolved.outcome ?? 'unknown').toLowerCase()}
|
||||||
|
{@const conf = Math.round((resolved.confidence ?? 0) * 100)}
|
||||||
|
{@const date = bet.date ? new Date(bet.date) : null}
|
||||||
|
<tr class:alt={i % 2 !== 0}>
|
||||||
|
<td class="match">
|
||||||
|
{bet.team1Name} <span class="vs">vs</span> {bet.team2Name}
|
||||||
|
</td>
|
||||||
|
<td class="secondary">
|
||||||
|
{date ? date.toLocaleDateString('cs-CZ', { day: 'numeric', month: 'short', year: 'numeric' }) : '—'}
|
||||||
|
</td>
|
||||||
|
<td class="secondary">{bet.league ?? '—'}</td>
|
||||||
|
<td>{formatBetType(bet.ticketType)}</td>
|
||||||
|
<td>{formatBetDetail(bet)}</td>
|
||||||
|
<td>
|
||||||
|
<span class="badge outcome-{outcome}">{outcome}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="conf">
|
||||||
|
<div class="conf-track">
|
||||||
|
<div class="conf-fill" style="width:{conf}%"></div>
|
||||||
|
</div>
|
||||||
|
<span class="conf-label">{conf}%</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.table-wrap {
|
||||||
|
overflow-x: auto;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead tr {
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
background: var(--bg-header);
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
text-align: left;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr {
|
||||||
|
border-bottom: 1px solid var(--border-subtle);
|
||||||
|
background: var(--bg-surface);
|
||||||
|
transition: background 0.1s;
|
||||||
|
}
|
||||||
|
tbody tr.alt { background: var(--bg-surface-alt); }
|
||||||
|
tbody tr:last-child { border-bottom: none; }
|
||||||
|
tbody tr:hover { background: var(--bg-hover); }
|
||||||
|
|
||||||
|
td {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.match { font-weight: 500; }
|
||||||
|
.vs { color: var(--text-muted); }
|
||||||
|
.secondary { color: var(--text-secondary); white-space: nowrap; }
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.125rem 0.5rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.outcome-win { background: var(--outcome-win-bg); color: var(--outcome-win-text); }
|
||||||
|
.outcome-lose { background: var(--outcome-lose-bg); color: var(--outcome-lose-text); }
|
||||||
|
.outcome-void { background: var(--outcome-void-bg); color: var(--outcome-void-text); }
|
||||||
|
.outcome-unknown { background: var(--outcome-unknown-bg); color: var(--outcome-unknown-text); }
|
||||||
|
|
||||||
|
.conf {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
.conf-track {
|
||||||
|
width: 4rem;
|
||||||
|
height: 6px;
|
||||||
|
background: var(--conf-track);
|
||||||
|
border-radius: 9999px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.conf-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: #3b82f6;
|
||||||
|
border-radius: 9999px;
|
||||||
|
}
|
||||||
|
.conf-label {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
5
beaky-frontend/src/lib/Counter.svelte
Normal file
5
beaky-frontend/src/lib/Counter.svelte
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<script>
|
||||||
|
let count = $state(0)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button class="counter" onclick={() => count++}>Count is {count}</button>
|
||||||
Reference in New Issue
Block a user