feat: profile page character display, persistent auth, cleanup
- Large animated sprite on BotProfilePage with tier-aware rendering - Dynamic status titles (UNSTOPPABLE, ON FIRE, FRESH MEAT, etc.) - Nostr auth persisted to localStorage — survives navigation and HMR - Remove grotesque close-up overlays (eyeballs, tongues, teeth, drool) - Remove crowd cheering signs (too small to look good) - Add archetype to bot stats API response - SpritePreview now accepts tier prop Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
e49735002c
commit
4a35e1e0b5
@@ -2,6 +2,7 @@
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { useRoute, useRouter, RouterLink } from 'vue-router'
|
||||
import { useNostr } from '../composables/useNostr'
|
||||
import SpritePreview from '../components/SpritePreview.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -12,6 +13,7 @@ interface BotStats {
|
||||
id: string
|
||||
name: string
|
||||
avatarSeed: string
|
||||
archetype: string
|
||||
profilePicUrl: string | null
|
||||
eloRating: number
|
||||
wins: number
|
||||
@@ -36,6 +38,19 @@ interface BotStats {
|
||||
}[]
|
||||
}
|
||||
|
||||
function getStatusTitle(s: BotStats): string {
|
||||
if (s.totalFights === 0) return 'FRESH MEAT'
|
||||
if (s.winStreak >= 10) return 'UNSTOPPABLE'
|
||||
if (s.winStreak >= 5) return 'ON FIRE'
|
||||
if (s.winStreak >= 3) return 'HOT STREAK'
|
||||
if (s.winRate >= 80 && s.totalFights >= 10) return 'DOMINANT'
|
||||
if (s.winRate >= 60) return 'RISING'
|
||||
if (s.winRate >= 40) return 'SCRAPPY'
|
||||
if (s.winRate < 20 && s.totalFights >= 5) return 'PUNCHING BAG'
|
||||
if (s.losses > s.wins && s.totalFights >= 5) return 'UNDERDOG'
|
||||
return 'CONTENDER'
|
||||
}
|
||||
|
||||
interface QueueEntry {
|
||||
botId: string
|
||||
botName: string
|
||||
@@ -127,23 +142,30 @@ const tierClass = (t: number) => `tier-${t}`
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<!-- Header -->
|
||||
<!-- Header with large character -->
|
||||
<div class="text-center mb-5">
|
||||
<img
|
||||
v-if="stats.profilePicUrl"
|
||||
:src="stats.profilePicUrl"
|
||||
alt=""
|
||||
class="w-16 h-16 rounded-full mx-auto mb-2 border-2"
|
||||
:style="{ borderColor: stats.tierColor }"
|
||||
/>
|
||||
<p class="font-display text-xs font-bold tracking-[0.2em] mb-1"
|
||||
:style="{ color: stats.tierColor }">
|
||||
{{ stats.tierName }}
|
||||
</p>
|
||||
<div class="relative inline-block mb-3">
|
||||
<SpritePreview
|
||||
:seed="stats.avatarSeed || stats.name"
|
||||
:archetype="stats.archetype"
|
||||
:tier="stats.tier"
|
||||
:size="160"
|
||||
class="mx-auto drop-shadow-[0_0_20px_var(--glow)]"
|
||||
:style="{ '--glow': stats.tierColor + '80' } as any"
|
||||
/>
|
||||
<div class="absolute -bottom-1 left-1/2 -translate-x-1/2 px-3 py-0.5 border text-[9px] font-display font-black tracking-widest whitespace-nowrap"
|
||||
:style="{ borderColor: stats.tierColor, color: stats.tierColor, backgroundColor: 'rgba(0,0,0,0.8)' }">
|
||||
{{ stats.tierName }}
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="font-display font-black text-3xl sm:text-4xl tracking-wider gradient-text">
|
||||
{{ stats.name }}
|
||||
</h2>
|
||||
<p class="font-mono text-text-muted text-[10px] mt-1">
|
||||
<p class="font-display text-sm font-bold tracking-widest mt-1"
|
||||
:style="{ color: stats.tierColor }">
|
||||
{{ getStatusTitle(stats) }}
|
||||
</p>
|
||||
<p class="font-mono text-text-muted text-[10px] mt-0.5">
|
||||
#{{ stats.rank }} of {{ stats.totalBots }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user