feat(#29): Arcade Neon design system — visual overhaul completo
Implementa o sistema visual Arcade Neon do neon-handoff/ em todo o app: - tokens.css: tokens --fc-*, utilities (fc-pixel/mono/body/glow), form inputs/buttons globais - AppHud.vue: HUD persistente com LV/XP/META + nav chips por rota - BottomNav.vue: nav mobile com 5 rotas - NeonPanel.vue, CharacterSprite.vue, XPBar.vue, HUDStat.vue: componentes base - MonthSwitcher.vue, LevelUpModal.vue - HomeView, CharacterView, TransactionsView, ImportView, CategoriesView, AccountsView, SettingsView: reescritos com Arcade Neon - sprites PNG (lv01–lv15) + sprite-data.json: cosméticos com temas de cor - game.ts: equippedTheme getter para merge de cores do cosmético equipado - 008_cosmetics.sql: seeds alinhados com sprite-data.json Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<header class="fc-hud">
|
||||
<div class="fc-hud__logo">
|
||||
<span class="fc-hud__logo-mark" />
|
||||
<div>
|
||||
<div class="fc-pixel" style="font-size:10px;color:var(--fc-accent-2)">CARVALHO</div>
|
||||
<div class="fc-pixel" style="font-size:7px;color:var(--fc-text-dim)">FIN.SYS v2.0</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fc-hud__sep" />
|
||||
|
||||
<div class="fc-hud__stats">
|
||||
<HUDStat label="LV" :value="profile?.level ?? 1" color="var(--fc-gold)" />
|
||||
<HUDStat label="XP" :value="profile?.xp ?? 0" :sub="`/${profile?.xp_to_next ?? 100}`" color="var(--fc-accent-2)" />
|
||||
<HUDStat label="META" :value="metaPct" sub="/40%" color="metaColor" />
|
||||
</div>
|
||||
|
||||
<nav class="fc-hud__nav">
|
||||
<RouterLink
|
||||
v-for="item in navItems"
|
||||
:key="item.to"
|
||||
:to="item.to"
|
||||
class="fc-hud__nav-item fc-pixel"
|
||||
>{{ item.label }}</RouterLink>
|
||||
</nav>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useGameStore } from '@/stores/game'
|
||||
import { useDashboardStore } from '@/stores/dashboard'
|
||||
import HUDStat from './HUDStat.vue'
|
||||
|
||||
const gameStore = useGameStore()
|
||||
const dashStore = useDashboardStore()
|
||||
|
||||
const profile = computed(() => gameStore.summary?.profile)
|
||||
const metaPct = computed(() => dashStore.data ? `${dashStore.data.savings_pct.toFixed(0)}%` : '--')
|
||||
const metaColor = computed(() => {
|
||||
if (!dashStore.data) return 'var(--fc-text-dim)'
|
||||
return dashStore.data.savings_pct >= 40 ? 'var(--fc-green)' : 'var(--fc-red)'
|
||||
})
|
||||
|
||||
const navItems = [
|
||||
{ to: '/', label: 'HOME' },
|
||||
{ to: '/transacoes', label: 'TX' },
|
||||
{ to: '/importar', label: 'IMPORT' },
|
||||
{ to: '/contas', label: 'CONTAS' },
|
||||
{ to: '/personagem', label: 'PERS.' },
|
||||
{ to: '/configuracoes', label: 'CFG' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fc-hud {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--fc-space-4);
|
||||
padding: 10px 20px;
|
||||
border-bottom: 2px solid var(--fc-panel-edge);
|
||||
background: linear-gradient(180deg, var(--fc-bg-panel), var(--fc-bg));
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.fc-hud__logo {
|
||||
display: flex; align-items: center; gap: 10px; flex-shrink: 0;
|
||||
}
|
||||
.fc-hud__logo-mark {
|
||||
display: inline-block; width: 26px; height: 26px;
|
||||
background: var(--fc-accent);
|
||||
box-shadow: 0 0 10px var(--fc-accent);
|
||||
position: relative; flex-shrink: 0;
|
||||
}
|
||||
.fc-hud__logo-mark::before {
|
||||
content: ''; position: absolute; inset: 5px; background: var(--fc-bg);
|
||||
}
|
||||
.fc-hud__logo-mark::after {
|
||||
content: ''; position: absolute; top: 8px; left: 8px; width: 10px; height: 10px;
|
||||
background: var(--fc-accent-2);
|
||||
}
|
||||
.fc-hud__sep {
|
||||
width: 2px; height: 32px; background: var(--fc-panel-edge); flex-shrink: 0;
|
||||
}
|
||||
.fc-hud__stats {
|
||||
display: flex; gap: var(--fc-space-4); align-items: center; flex-shrink: 0;
|
||||
}
|
||||
.fc-hud__nav {
|
||||
display: flex; gap: var(--fc-space-2); align-items: center; flex-wrap: wrap;
|
||||
margin-left: auto;
|
||||
}
|
||||
.fc-hud__nav-item {
|
||||
font-size: 8px;
|
||||
padding: 5px 8px;
|
||||
border: 1px solid var(--fc-panel-edge);
|
||||
border-radius: var(--fc-radius-sm);
|
||||
color: var(--fc-text-dim);
|
||||
text-decoration: none;
|
||||
transition: all .12s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.fc-hud__nav-item:hover,
|
||||
.fc-hud__nav-item.router-link-active {
|
||||
border-color: var(--fc-accent-3);
|
||||
color: var(--fc-text);
|
||||
background: rgba(168,85,247,.15);
|
||||
box-shadow: 0 0 8px rgba(168,85,247,.3);
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.fc-hud__nav { display: none; }
|
||||
.fc-hud__sep { display: none; }
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user