feat: watch another fight, rename nav — FIGHT! + WATCH, fix stale SW assets

- Add "WATCH ANOTHER FIGHT" button on post-fight overlay (loads random fight)
- Rename "JOIN A BOUT" → "FIGHT!" in nav, join page, register page
- Rename "ARENA" → "WATCH" in nav
- Server: return 404 for missing asset files instead of index.html (fixes "Unexpected token '<'")
- PWA: cleanupOutdatedCaches, skipWaiting, clientsClaim for instant SW updates
- Serve PWA files (sw.js, workbox, icons) with correct cache headers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-07 23:15:39 +00:00
co-authored by Claude Opus 4.6
parent 7d5f4a6b8d
commit 84625bc4d2
4 changed files with 38 additions and 4 deletions
+2 -2
View File
@@ -8,8 +8,8 @@ const { bot, isLoggedIn } = useNostr()
const isMenuOpen = ref(false) const isMenuOpen = ref(false)
const links = [ const links = [
{ to: '/join', label: 'JOIN A BOUT' }, { to: '/join', label: 'FIGHT!' },
{ to: '/arena', label: 'ARENA' }, { to: '/arena', label: 'WATCH' },
{ to: '/leaderboard', label: 'RANKINGS' }, { to: '/leaderboard', label: 'RANKINGS' },
] ]
</script> </script>
+34
View File
@@ -636,6 +636,29 @@ function onReplayDone() {
} }
} }
const isLoadingNext = ref(false)
async function watchAnotherFight() {
if (isLoadingNext.value) return
isLoadingNext.value = true
try {
const res = await fetch('/api/fights')
if (res.ok) {
const fights = await res.json()
const finished = fights.filter((f: any) => f.status === 'finished' && f.id !== fightId.value)
if (finished.length > 0) {
const pick = finished[Math.floor(Math.random() * finished.length)]
router.push(`/arena/${pick.id}`)
return
}
}
router.push('/arena')
} catch {
router.push('/arena')
} finally {
isLoadingNext.value = false
}
}
function startAutoBattle() { function startAutoBattle() {
if (!myBotId.value || isHumanFight.value) return if (!myBotId.value || isHumanFight.value) return
autoBattle.value = true autoBattle.value = true
@@ -934,6 +957,17 @@ function stopAutoBattle() {
</button> </button>
</template> </template>
<button
:disabled="isLoadingNext"
class="w-full py-3 bg-neon-purple/10 border-2 border-neon-purple/50 text-neon-purple
font-display font-black text-sm tracking-widest rounded-lg
hover:bg-neon-purple/20 hover:border-neon-purple transition-all
disabled:opacity-50 disabled:cursor-wait flex items-center justify-center gap-2"
@click="watchAnotherFight"
>
<span v-if="isLoadingNext" class="w-4 h-4 border-2 border-neon-purple/30 border-t-neon-purple rounded-full animate-spin" />
{{ isLoadingNext ? 'LOADING...' : 'WATCH ANOTHER FIGHT' }}
</button>
<button <button
class="w-full py-2 border border-white/10 text-text-muted class="w-full py-2 border border-white/10 text-text-muted
font-display text-xs tracking-widest rounded-lg font-display text-xs tracking-widest rounded-lg
+1 -1
View File
@@ -255,7 +255,7 @@ function handleSignOut() {
<template v-if="step === 'login'"> <template v-if="step === 'login'">
<div class="text-center mb-8"> <div class="text-center mb-8">
<h2 class="font-display font-black text-4xl tracking-wider text-neon-pink glow-pink mb-3"> <h2 class="font-display font-black text-4xl tracking-wider text-neon-pink glow-pink mb-3">
JOIN A BOUT FIGHT!
</h2> </h2>
<p class="font-mono text-text-muted text-xs"> <p class="font-mono text-text-muted text-xs">
Sign in with Nostr to fight. Sign in with Nostr to fight.
+1 -1
View File
@@ -149,7 +149,7 @@ function goFight() {
hover:bg-neon-cyan/20 transition-all" hover:bg-neon-cyan/20 transition-all"
@click="goFight" @click="goFight"
> >
JOIN A BOUT FIGHT!
</button> </button>
</div> </div>
</div> </div>