- Tabela `profiles` + coluna `profile_id` em todas as entidades (categories, transactions, recurring_expenses, accounts, player_profile, xp_events, player_quests, player_achievements, player_cosmetics) - Dados existentes migrados para profile_id = 1 (Manoel) - CLI `./api create-user --name <n> --password <p>` cria perfil com seed de categorias e player_profile; faz upsert de senha se já existir - Auth substituída: cookie+APP_PASSWORD → JWT Bearer 24h (HS256) - Middleware RequireAuth injeta profile_id no context de todas as rotas - Todos os repositórios filtram por profile_id do context - Endpoints: POST /api/auth/login, GET /api/auth/me, POST /api/auth/change-password, POST /api/logout - Frontend: auth store usa localStorage (fc_token/fc_profile), api.ts envia Authorization header, LoginView usa campo name - SettingsView reescrita com troca de senha e logout - docker-compose.yml: remove APP_USERNAME/APP_PASSWORD, adiciona JWT_SECRET Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
165 lines
5.9 KiB
Markdown
165 lines
5.9 KiB
Markdown
# Financeiro Carvalho · Handoff (Arcade Neon)
|
||
|
||
Pacote de design pronto pra ser entregue ao Claude Code / Cursor / Aider implementar.
|
||
Direção visual escolhida: **Arcade Neon**.
|
||
|
||
## O que tem aqui
|
||
|
||
```
|
||
neon-handoff/
|
||
├── STYLE_GUIDE.md ← leia primeiro
|
||
├── preview.html ← referência visual interativa (abra num servidor local)
|
||
├── tokens.css ← variáveis CSS + reset + classes utilitárias
|
||
├── components/ ← Vue 3 SFCs de referência
|
||
│ ├── NeonPanel.vue
|
||
│ ├── XPBar.vue
|
||
│ ├── HUDStat.vue
|
||
│ └── CharacterSprite.vue
|
||
├── sprites/
|
||
│ ├── sprite-data.json ← grade raw 17×24 + lista de cosméticos
|
||
│ ├── icons.json ← heart, coin, star, anchor (8×8 cada)
|
||
│ ├── manoel-default.png (e 4x)
|
||
│ ├── manoel-lv01.png (e 4x) · cabelo castanho, camisa azul, calça caqui
|
||
│ ├── manoel-lv03-bone-verolme.png · boné azul
|
||
│ ├── manoel-lv05-wingspan.png · camisa verde
|
||
│ ├── manoel-lv07-chapeu-sol.png · look "equipado" atual
|
||
│ ├── manoel-lv10-anti-vento.png · casaco roxo
|
||
│ ├── manoel-lv15-capitao.png · trajado de capitão (vermelho/preto)
|
||
│ └── manoel-sheet-4x.png · todos lado a lado pra referência
|
||
└── README.md ← este arquivo
|
||
```
|
||
|
||
## Como integrar no apps/web
|
||
|
||
1. Copie `tokens.css` para `src/styles/tokens.css`. Importe **uma vez** em `src/main.ts`:
|
||
|
||
```ts
|
||
import './styles/tokens.css'
|
||
```
|
||
|
||
2. Copie `components/*.vue` para `src/components/`. Eles já consomem `var(--fc-*)`.
|
||
|
||
3. Copie `sprites/sprite-data.json` e `sprites/icons.json` pra `src/assets/`.
|
||
Garanta que `tsconfig.json` tenha `"resolveJsonModule": true` (Vite default já tem).
|
||
|
||
4. Embrulhe o `<router-view>` em `<div class="fc-app">` — é isso que aplica o fundo + scanlines + grid.
|
||
|
||
```vue
|
||
<!-- App.vue -->
|
||
<template>
|
||
<div class="fc-app">
|
||
<AppHud />
|
||
<RouterView />
|
||
</div>
|
||
</template>
|
||
```
|
||
|
||
5. As 8 rotas do PRD (`/`, `/transacoes`, `/importar`, `/categorias`, `/recorrencias`,
|
||
`/contas`, `/personagem`, `/configuracoes`) usam o mesmo header HUD. Veja
|
||
`STYLE_GUIDE.md` §3.6 pro shape do componente.
|
||
|
||
## Sprites · uso
|
||
|
||
### Renderizar dinâmico (recomendado)
|
||
|
||
`<CharacterSprite>` lê `sprite-data.json` e aceita `theme` como prop. Cosméticos
|
||
equipados são merged no store (Pinia) e passados como `theme`.
|
||
|
||
```vue
|
||
<CharacterSprite :scale="6" :theme="gameStore.equippedTheme" :celebrate="gameStore.justLeveledUp" />
|
||
```
|
||
|
||
Exemplo de store getter:
|
||
|
||
```ts
|
||
// stores/game.ts
|
||
const equippedTheme = computed(() => {
|
||
return cosmetics.value
|
||
.filter(c => c.equipped)
|
||
.reduce((acc, c) => ({ ...acc, ...c.colors }), {} as Record<string, string>)
|
||
})
|
||
```
|
||
|
||
### Usar PNG estático
|
||
|
||
Útil pra previews em página de loja (`/personagem` → seção "cosméticos"):
|
||
|
||
```html
|
||
<img src="@/assets/sprites/manoel-lv03-bone-verolme-4x.png" alt="Boné Verolme" />
|
||
```
|
||
|
||
Sempre `image-rendering: pixelated;` no CSS pra não suavizar.
|
||
|
||
### Regenerar PNGs
|
||
|
||
`sprites/sprite-data.json` é a fonte da verdade. Se você ajustar uma cor de
|
||
cosmético lá, regenere os PNGs com um script Node:
|
||
|
||
```js
|
||
// scripts/build-sprites.mjs
|
||
import { createCanvas } from '@napi-rs/canvas' // ou node-canvas
|
||
import fs from 'node:fs/promises'
|
||
|
||
const data = JSON.parse(await fs.readFile('src/assets/sprite-data.json', 'utf8'))
|
||
// ... mesmo render do PixelSprite acima, salva PNG por cosmético
|
||
```
|
||
|
||
Ou peça pro Claude Code regenerar — o algoritmo é trivial (loop pela grade,
|
||
fillRect por célula com a cor do slot).
|
||
|
||
## Princípios para o Claude implementar
|
||
|
||
Por ordem de importância:
|
||
|
||
1. **HUD persistente em todas as rotas.** Não use sidebar — o app é um HUD de jogo.
|
||
2. **Nunca use hex direto.** Sempre `var(--fc-*)`. Se faltar token, adicione-o ao
|
||
`tokens.css` e documente no `STYLE_GUIDE.md` §1.1.
|
||
3. **Press Start 2P pra label e número. JetBrains Mono pra dado. Inter pra prosa.**
|
||
Press Start 2P sempre em maiúscula.
|
||
4. **Glow é raro.** Só nos números heroicos (47%) e no painel principal de cada
|
||
rota. Se cada card brilha, nada brilha.
|
||
5. **Verde/vermelho são binários** — meta sim / meta não. Não use vermelho pra valor
|
||
negativo (transação) — só pra alerta.
|
||
6. **Cada animação tem propósito.** Ver §6 do guia.
|
||
7. **Mobile vira bottom-nav.** Não tente espremer a HUD horizontal num iPhone.
|
||
|
||
## Telas a implementar
|
||
|
||
Conforme `STYLE_GUIDE.md` + screens visíveis em `preview.html` (Arcade · 01):
|
||
|
||
- [ ] `/` Dashboard (hero poupado, categorias, histórico, transações, recorrências, quests, patrimônio, widget personagem)
|
||
- [ ] `/transacoes` lista + CRUD
|
||
- [ ] `/importar` upload OFX/CSV + preview de deduplicação
|
||
- [ ] `/categorias` CRUD com pixel-icon picker
|
||
- [ ] `/recorrencias` lista mensal com status (paid / due / missing)
|
||
- [ ] `/contas` cards de conta + patrimônio total
|
||
- [ ] `/personagem` painel RPG completo
|
||
- [ ] `/configuracoes` formulário simples (perfil, meta %, prefs visuais)
|
||
|
||
Para qualquer tela nova: comece copiando a estrutura do dashboard,
|
||
substitua o conteúdo dos painéis, mantenha a HUD.
|
||
|
||
## Componentes adicionais que faltam
|
||
|
||
Esses não estão neste pacote — implemente seguindo os tokens já definidos:
|
||
|
||
- `AppHud.vue` (cabeçalho persistente)
|
||
- `BottomNav.vue` (mobile)
|
||
- `TransactionRow.vue`
|
||
- `QuestCard.vue`
|
||
- `CategoryBar.vue`
|
||
- `AchievementCell.vue`
|
||
- `LevelUpModal.vue` (overlay celebratório no level up)
|
||
- `MonthSwitcher.vue` (‹ MAIO · 2026 ›)
|
||
|
||
## Tom de voz
|
||
|
||
Português brasileiro, direto, com vocabulário de jogo. Não é app corporativo.
|
||
Ver `STYLE_GUIDE.md` §8.
|
||
|
||
---
|
||
|
||
Qualquer dúvida sobre **intenção visual** (não implementação), volte ao
|
||
`STYLE_GUIDE.md` ou ao `preview.html`. A página de design original do projeto
|
||
(canvas com 4 direções) também segue acessível pra comparação.
|