feat: split admin dashboard, improve match ops, and player closed-match UX
Admin: add match/player overview sub-nav; refine settlement flow and league match management UI; improve action button enabled/disabled styles; enhance logo upload and outright odds sync. API: expose matchPhase/bettingOpen for closed matches; league publish guards; settlement preview with auto score save; outright team auto-sync. Player: watermark for closed/settled states; keep match and bet details visible; remove default login credentials. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -13,6 +13,7 @@ const props = defineProps<{
|
||||
oddsVersion: string;
|
||||
}>;
|
||||
stakes: Record<string, number>;
|
||||
locked?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -26,6 +27,7 @@ const columns = computed(() =>
|
||||
);
|
||||
|
||||
function setStake(sel: CsSelection, raw: string) {
|
||||
if (props.locked) return;
|
||||
const n = Math.max(0, Number(raw) || 0);
|
||||
emit('update:stakes', { ...props.stakes, [sel.id]: n });
|
||||
}
|
||||
@@ -37,7 +39,7 @@ function formatOdds(odds: string) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="cs-panel">
|
||||
<div class="cs-panel" :class="{ 'cs-panel--locked': locked }">
|
||||
<div class="cols-head">
|
||||
<span>{{ t('bet.col_home') }}</span>
|
||||
<span>{{ t('bet.col_draw') }}</span>
|
||||
@@ -57,6 +59,7 @@ function formatOdds(odds: string) {
|
||||
inputmode="decimal"
|
||||
:placeholder="t('bet.stake_placeholder')"
|
||||
:value="stakes[sel.id] ?? ''"
|
||||
:disabled="locked"
|
||||
@input="setStake(sel, ($event.target as HTMLInputElement).value)"
|
||||
/>
|
||||
</div>
|
||||
@@ -70,6 +73,14 @@ function formatOdds(odds: string) {
|
||||
padding: 6px 8px 0;
|
||||
}
|
||||
|
||||
.cs-panel--locked {
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.cs-panel--locked .stake-input {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.cols-head {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
|
||||
@@ -11,6 +11,7 @@ const props = defineProps<{
|
||||
}[];
|
||||
isSelected: (id: string) => boolean;
|
||||
compact?: boolean;
|
||||
locked?: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{ pick: [id: string] }>();
|
||||
@@ -22,18 +23,24 @@ function label(sel: (typeof props.selections)[number]) {
|
||||
}
|
||||
return sel.selectionName;
|
||||
}
|
||||
|
||||
function onPick(id: string) {
|
||||
if (props.locked) return;
|
||||
emit('pick', id);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap" :class="{ compact }">
|
||||
<div class="wrap" :class="{ compact, locked }">
|
||||
<div class="panel">
|
||||
<button
|
||||
v-for="sel in selections"
|
||||
:key="sel.id"
|
||||
type="button"
|
||||
class="odds-btn"
|
||||
:class="{ selected: isSelected(sel.id) }"
|
||||
@click="emit('pick', sel.id)"
|
||||
:class="{ selected: isSelected(sel.id), 'odds-btn--locked': locked }"
|
||||
:disabled="locked"
|
||||
@click="onPick(sel.id)"
|
||||
>
|
||||
<span class="label">{{ label(sel) }}</span>
|
||||
<span class="odds">{{ sel.odds }}</span>
|
||||
@@ -48,6 +55,10 @@ function label(sel: (typeof props.selections)[number]) {
|
||||
background: #0c0c0c;
|
||||
}
|
||||
|
||||
.wrap.locked {
|
||||
opacity: 0.78;
|
||||
}
|
||||
|
||||
.panel {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
@@ -73,6 +84,17 @@ function label(sel: (typeof props.selections)[number]) {
|
||||
background: rgba(212, 175, 55, 0.1);
|
||||
}
|
||||
|
||||
.odds-btn--locked {
|
||||
background: #111;
|
||||
border-color: #333;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.odds-btn--locked .label,
|
||||
.odds-btn--locked .odds {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 9px;
|
||||
color: var(--text-muted);
|
||||
|
||||
Reference in New Issue
Block a user