Files
botfights/frontend/src/pages/RegisterPage.vue
T
DorianandClaude Opus 4.6 335c148866 feat: botfights v1 — full fighting game with Kaplay engine
- Vue 3 + Vite + Tailwind 4 frontend with synthwave aesthetic
- Hono backend on port 9100 with SQLite/Drizzle
- Procedural pixel-art sprite generator (48x48, 8 animation states)
- Kaplay fight scene with punch/kick/special/knockback/KO animations
- 12 mock bots across 6 tiers with Elo rating system
- 9 challenge types, 10 fight arenas with modifiers
- Fight replay with staggered battle log and ~1 min timing
- Sprite preview page at /sprites

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 16:27:54 +00:00

140 lines
4.5 KiB
Vue

<script setup lang="ts">
import { ref, reactive } from 'vue'
const form = reactive({
name: '',
webhookUrl: '',
avatarSeed: '',
})
const isSubmitting = ref(false)
const result = ref<{ success: boolean; message: string } | null>(null)
async function handleSubmit() {
if (!form.name || !form.webhookUrl) return
isSubmitting.value = true
result.value = null
try {
const res = await fetch('/api/bots', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: form.name,
webhook_url: form.webhookUrl,
avatar_seed: form.avatarSeed || form.name,
}),
})
const data = await res.json()
if (res.ok) {
result.value = {
success: true,
message: `"${data.name}" is in the ring. Ring Card secret: ${data.secret}`,
}
form.name = ''
form.webhookUrl = ''
form.avatarSeed = ''
} else {
result.value = { success: false, message: data.error || 'Registration failed.' }
}
} catch {
result.value = { success: false, message: 'Network error. Is the server running?' }
} finally {
isSubmitting.value = false
}
}
</script>
<template>
<div class="h-[calc(100vh-4rem)] flex flex-col items-center justify-center px-6 overflow-hidden">
<div class="max-w-md w-full slide-up">
<div class="text-center mb-8">
<h2 class="font-display font-black text-3xl tracking-wider gradient-text mb-2">
ENTER THE RING
</h2>
<p class="font-mono text-text-muted text-xs">
Register your bot. Get a Ring Card. Start fighting.
</p>
</div>
<form class="space-y-5" @submit.prevent="handleSubmit">
<div>
<label class="block text-text-secondary text-[10px] font-display font-bold uppercase tracking-[0.15em] mb-2">
Bot Name
</label>
<input
v-model="form.name"
type="text"
required
maxlength="32"
placeholder="skull_crusher_9000"
class="w-full bg-surface border-2 border-border px-4 py-3 text-sm font-mono
text-text-primary placeholder-text-muted
focus:outline-none focus:border-neon-cyan/50 transition-colors"
/>
</div>
<div>
<label class="block text-text-secondary text-[10px] font-display font-bold uppercase tracking-[0.15em] mb-2">
Webhook URL
</label>
<input
v-model="form.webhookUrl"
type="url"
required
placeholder="https://your-bot.example.com/fight"
class="w-full bg-surface border-2 border-border px-4 py-3 text-sm font-mono
text-text-primary placeholder-text-muted
focus:outline-none focus:border-neon-cyan/50 transition-colors"
/>
<p class="text-text-muted text-[10px] font-mono mt-1.5">
We POST fight challenges here. HTTPS required.
</p>
</div>
<div>
<label class="block text-text-secondary text-[10px] font-display font-bold uppercase tracking-[0.15em] mb-2">
Avatar Seed <span class="text-text-muted">(optional)</span>
</label>
<input
v-model="form.avatarSeed"
type="text"
maxlength="64"
placeholder="defaults to bot name"
class="w-full bg-surface border-2 border-border px-4 py-3 text-sm font-mono
text-text-primary placeholder-text-muted
focus:outline-none focus:border-neon-cyan/50 transition-colors"
/>
</div>
<button
type="submit"
:disabled="isSubmitting"
class="w-full py-3 bg-neon-pink/10 border-2 border-neon-pink/50 text-neon-pink
font-display font-bold text-sm tracking-wider
hover:bg-neon-pink/20 hover:border-neon-pink transition-all neon-border-pink
disabled:opacity-50 disabled:cursor-not-allowed"
>
{{ isSubmitting ? 'REGISTERING...' : 'REGISTER FIGHTER' }}
</button>
</form>
<div
v-if="result"
class="mt-6 p-4 border-2 font-mono text-xs leading-relaxed"
:class="result.success
? 'bg-neon-cyan/5 border-neon-cyan/30 text-neon-cyan'
: 'bg-ko/5 border-ko/30 text-ko'"
>
{{ result.message }}
<p v-if="result.success" class="mt-2 text-text-muted">
Save this secret. It will NOT be shown again.
</p>
</div>
</div>
</div>
</template>