2026-03-06 16:27:54 +00:00
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { ref, onMounted } from 'vue'
|
|
|
|
|
import { RouterLink } from 'vue-router'
|
|
|
|
|
|
|
|
|
|
interface Bot {
|
|
|
|
|
id: string
|
|
|
|
|
name: string
|
|
|
|
|
eloRating: number
|
|
|
|
|
tier: number
|
|
|
|
|
wins: number
|
|
|
|
|
losses: number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bots = ref<Bot[]>([])
|
|
|
|
|
const isLoading = ref(true)
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
try {
|
|
|
|
|
const res = await fetch('/api/bots')
|
|
|
|
|
if (res.ok) {
|
|
|
|
|
const data = await res.json()
|
|
|
|
|
bots.value = data.sort((a: Bot, b: Bot) => b.eloRating - a.eloRating)
|
|
|
|
|
}
|
2026-03-07 23:49:45 +00:00
|
|
|
} catch (err) {
|
|
|
|
|
console.warn('[Schedule] load bots failed:', err)
|
|
|
|
|
}
|
2026-03-06 16:27:54 +00:00
|
|
|
isLoading.value = false
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const tierClass = (t: number) => `tier-${t}`
|
|
|
|
|
const tierName = (t: number) => ['UNRANKED', 'ROOKIE', 'RISING', 'CONTENDER', 'CHAMPION', 'LEGEND'][t] || '???'
|
|
|
|
|
|
|
|
|
|
// Generate potential matchups from top bots
|
|
|
|
|
const matchups = ref<{ botA: Bot; botB: Bot; hype: string }[]>([])
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if (bots.value.length >= 2) {
|
|
|
|
|
const top = bots.value.slice(0, 6)
|
|
|
|
|
const hypes = [
|
|
|
|
|
'MAIN EVENT',
|
|
|
|
|
'CO-MAIN EVENT',
|
|
|
|
|
'TITLE ELIMINATOR',
|
|
|
|
|
'GRUDGE MATCH',
|
|
|
|
|
'UNDERCARD',
|
|
|
|
|
'DEBUT',
|
|
|
|
|
]
|
|
|
|
|
for (let i = 0; i < Math.min(3, Math.floor(top.length / 2)); i++) {
|
|
|
|
|
matchups.value.push({
|
|
|
|
|
botA: top[i * 2],
|
|
|
|
|
botB: top[i * 2 + 1],
|
|
|
|
|
hype: hypes[i],
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, 500)
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div class="h-[calc(100vh-4rem)] flex flex-col px-6 py-6 overflow-hidden">
|
|
|
|
|
<div class="max-w-4xl mx-auto w-full flex flex-col flex-1 min-h-0">
|
|
|
|
|
|
|
|
|
|
<!-- Header -->
|
|
|
|
|
<div class="mb-6 text-center">
|
|
|
|
|
<p class="font-display text-[10px] font-bold text-neon-purple tracking-[0.2em] mb-2 glow-purple">
|
|
|
|
|
UPCOMING
|
|
|
|
|
</p>
|
|
|
|
|
<h2 class="font-display font-black text-3xl sm:text-5xl tracking-wider">
|
|
|
|
|
<span class="gradient-text">FIGHT CARD</span>
|
|
|
|
|
</h2>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Matchups -->
|
|
|
|
|
<div class="flex-1 min-h-0 overflow-y-auto space-y-4">
|
|
|
|
|
<div
|
|
|
|
|
v-for="(matchup, i) in matchups"
|
|
|
|
|
:key="i"
|
|
|
|
|
class="border border-border rounded-lg bg-surface-raised/50 p-5
|
|
|
|
|
hover:border-neon-pink/30 transition-all"
|
|
|
|
|
:class="i === 0 ? 'neon-border-pink' : ''"
|
|
|
|
|
>
|
|
|
|
|
<p class="text-center font-display text-[10px] font-bold tracking-[0.2em] mb-4"
|
|
|
|
|
:class="i === 0 ? 'text-neon-yellow' : i === 1 ? 'text-neon-pink' : 'text-text-muted'">
|
|
|
|
|
{{ matchup.hype }}
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<div class="flex items-center justify-between">
|
|
|
|
|
<div class="flex-1 text-right pr-6">
|
|
|
|
|
<RouterLink :to="`/bot/${matchup.botA.name}`"
|
|
|
|
|
class="font-display font-black text-xl sm:text-2xl tracking-wider text-text-primary
|
|
|
|
|
hover:text-neon-cyan transition-colors">
|
|
|
|
|
{{ matchup.botA.name }}
|
|
|
|
|
</RouterLink>
|
|
|
|
|
<p class="font-mono text-xs mt-1">
|
|
|
|
|
<span :class="tierClass(matchup.botA.tier)">{{ tierName(matchup.botA.tier) }}</span>
|
|
|
|
|
<span class="text-text-muted"> · {{ Math.round(matchup.botA.eloRating) }}</span>
|
|
|
|
|
<span class="text-text-muted"> · {{ matchup.botA.wins }}W-{{ matchup.botA.losses }}L</span>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="flex-shrink-0">
|
|
|
|
|
<span class="font-display font-black text-2xl text-neon-purple glow-purple">VS</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="flex-1 pl-6">
|
|
|
|
|
<RouterLink :to="`/bot/${matchup.botB.name}`"
|
|
|
|
|
class="font-display font-black text-xl sm:text-2xl tracking-wider text-text-primary
|
|
|
|
|
hover:text-neon-cyan transition-colors">
|
|
|
|
|
{{ matchup.botB.name }}
|
|
|
|
|
</RouterLink>
|
|
|
|
|
<p class="font-mono text-xs mt-1">
|
|
|
|
|
<span :class="tierClass(matchup.botB.tier)">{{ tierName(matchup.botB.tier) }}</span>
|
|
|
|
|
<span class="text-text-muted"> · {{ Math.round(matchup.botB.eloRating) }}</span>
|
|
|
|
|
<span class="text-text-muted"> · {{ matchup.botB.wins }}W-{{ matchup.botB.losses }}L</span>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div v-if="matchups.length === 0 && !isLoading" class="flex-1 flex items-center justify-center">
|
|
|
|
|
<p class="font-display text-text-muted text-sm">
|
|
|
|
|
Card loading... check back soon.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|