diff --git a/.prettierignore b/.prettierignore index 90a8c2f..262c724 100644 --- a/.prettierignore +++ b/.prettierignore @@ -63,4 +63,10 @@ tmp .env.*.local # Playground -.playground \ No newline at end of file +.playground + +# Changelog +CHANGELOG.md + +# GitHub +.github diff --git a/.windsurf/rules/architecture.md b/.windsurf/rules/architecture.md new file mode 100644 index 0000000..a82af48 --- /dev/null +++ b/.windsurf/rules/architecture.md @@ -0,0 +1,97 @@ +--- +description: Regras de arquitetura do projeto IBAV +--- + +# IBAV - Architecture Rules + +## Nuxt + +- O projeto utiliza Nuxt 4. Sempre verifique `nuxt.config.ts` antes de modificar configurações. +- A data de compatibilidade está em `nuxt.config.ts`. Não altere sem necessidade. +- Não adicione módulos automaticamente. Verifique `package.json` e `nuxt.config.ts` existentes. + +## Vue + +- Vue 3 Composition API é o padrão do projeto. +- ` + diff --git a/docs/docs.md b/docs/docs.md index 63a0103..1e40c8d 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -75,12 +75,12 @@ Sistema calcula: # Campos de Entrada -| Campo | Tipo | -|--------|------| -| Valor FIPE | Número | -| Ano | Número | +| Campo | Tipo | +| ------------- | ------ | +| Valor FIPE | Número | +| Ano | Número | | Quilometragem | Número | -| Conservação | Select | +| Conservação | Select | --- @@ -169,12 +169,12 @@ Acréscimo de: ## 3. Conservação -| Estado | Ajuste | -|---------|--------:| -| Excelente | +3% | -| Bom | 0% | -| Regular | -3% | -| Ruim | -8% | +| Estado | Ajuste | +| --------- | -----: | +| Excelente | +3% | +| Bom | 0% | +| Regular | -3% | +| Ruim | -8% | --- @@ -312,24 +312,24 @@ a cada 10.000 km acima da média ## Conservação -| Estado | Pontos | -|---------|--------:| -| Excelente | +30 | -| Bom | 0 | -| Regular | -30 | -| Ruim | -80 | +| Estado | Pontos | +| --------- | -----: | +| Excelente | +30 | +| Bom | 0 | +| Regular | -30 | +| Ruim | -80 | --- # Classificação -| Pontos | Classificação | -|---------|---------------| -| 900–1000 | Excelente | -| 800–899 | Muito Bom | -| 700–799 | Bom | -| 600–699 | Regular | -| abaixo de 600 | Atenção | +| Pontos | Classificação | +| ------------- | ------------- | +| 900–1000 | Excelente | +| 800–899 | Muito Bom | +| 700–799 | Bom | +| 600–699 | Regular | +| abaixo de 600 | Atenção | --- @@ -420,4 +420,4 @@ O objetivo do IBAV é oferecer uma estimativa transparente do Valor Justo do Ve # Licença -A metodologia do IBAV deverá ser pública, documentada e versionada para garantir transparência, auditabilidade e evolução contínua. \ No newline at end of file +A metodologia do IBAV deverá ser pública, documentada e versionada para garantir transparência, auditabilidade e evolução contínua. diff --git a/docs/specs/README.md b/docs/specs/README.md new file mode 100644 index 0000000..da30e91 --- /dev/null +++ b/docs/specs/README.md @@ -0,0 +1,27 @@ +# Specifications + +This directory contains technical specifications for changes to the IBAV project. + +Specs are created by the Windsurf `/create-spec` workflow and reviewed before implementation. + +## Naming convention + +- `docs/specs/.md` - the spec +- `docs/specs/-tasks.md` - the task list derived from the spec + +## Status + +- Draft - spec created, not yet approved +- Approved - spec reviewed and ready for implementation +- Completed - all tasks executed and validated + +## Process + +1. `/analyze-product` - understand the project +2. `/plan-product` - high-level planning +3. `/create-spec ` - detailed spec +4. Review and approve +5. `/create-tasks ` - task list +6. Review and approve +7. `/execute-task N` - one task at a time +8. Validate and continue only after explicit approval diff --git a/docs/specs/ibav-mvp-tasks.md b/docs/specs/ibav-mvp-tasks.md new file mode 100644 index 0000000..1a631c4 --- /dev/null +++ b/docs/specs/ibav-mvp-tasks.md @@ -0,0 +1,202 @@ +# Tasks — IBAV MVP + +## Task 1 — ✅ Definir tipos e interfaces do domínio + +### Goal + +Criar os tipos centrais usados em toda a aplicação: entradas do veículo e resultado da avaliação. + +### Files + +- `shared/types/valuation.ts` + +### Implementation + +- Declarar `VehicleInputs` com `fipeValue`, `year`, `mileage`, `condition`. +- Declarar `ValuationResult` com todos os campos de saída. +- Exportar os tipos. + +### Tests + +- Nenhum teste unitário necessário; validação por compilação TypeScript. + +### Validation + +- `pnpm nuxt prepare` ou `npx tsc --noEmit`. + +### Acceptance Criteria + +- [ ] `shared/types/valuation.ts` criado e compilável. +- [ ] Tipos refletem o contrato descrito na especificação. + +--- + +## Task 2 — ✅ Implementar utilitários base (idade, quilometragem, conservação) + +### Goal + +Criar as funções puras de cálculo de idade, desvalorização, ajuste por km e conservação. + +### Files + +- `shared/utils/vehicle.ts` +- `shared/utils/depreciation.ts` +- `shared/utils/mileage.ts` +- `shared/utils/condition.ts` + +### Implementation + +- `vehicle.ts`: `calculateAge(year)` retorna `anoAtual - year`. +- `depreciation.ts`: `calculateAgeDiscount(age)` retorna `age * 0.02`. +- `mileage.ts`: `calculateMileageAdjustment(age, mileage)` compara com `age * 15000` e aplica `±` percentuais. +- `condition.ts`: `calculateConditionAdjustment(condition)` mapeia os quatro estados para percentuais. + +### Tests + +- `test/utils/vehicle.test.ts` +- `test/utils/depreciation.test.ts` +- `test/utils/mileage.test.ts` +- `test/utils/condition.test.ts` + +### Validation + +- `pnpm test` + +### Acceptance Criteria + +- [ ] Cada utilitário cobre os cenários de limite (idade 0, km 0, km muito alta). +- [ ] Percentuais estão corretos conforme `docs/docs.md`. + +--- + +## Task 3 — ✅ Implementar VJV e IVB + +### Goal + +Compor os utilitários base para calcular o Valor Justo do Veículo e o Índice IVB. + +### Files + +- `shared/utils/vjv.ts` +- `shared/utils/ivb.ts` + +### Implementation + +- `vjv.ts`: `calculateVjv(inputs)` — aplica a fórmula usando FIPE como base, desconto idade, ajuste km e conservação. +- `ivb.ts`: `calculateIvb(inputs)` — calcula pontuação e retorna `label` (Excelente, Muito Bom, Bom, Regular, Atenção). + +### Tests + +- `test/utils/vjv.test.ts` — verificar exemplo FIPE 80.000, 2022, 90.000 km, Excelente → R$ 74.800. +- `test/utils/ivb.test.ts` — verificar mesmo exemplo → 842 pontos e classificação "Muito Bom". + +### Validation + +- `pnpm test` + +### Acceptance Criteria + +- [ ] Exemplo do `docs/docs.md` passa com arredondamento de centavos esperado. +- [ ] Todos os estados de conservação e faixas de km são testados. + +--- + +## Task 4 — ✅ Criar página com formulário e exibição de resultados + +### Goal + +Construir a interface do usuário com Nuxt UI, formulário e painel de resultado. + +### Files + +- `app/pages/index.vue` (ou `app.vue` se preferir single-page) +- `app/components/` se necessário (ex: `VehicleForm.vue`, `ResultPanel.vue`) + +### Implementation + +- Formulário com 4 campos usando Nuxt UI. +- Estados reativos com `ref`/`reactive`. +- Chamada a `calculateVjv` e `calculateIvb` a cada alteração. +- Renderização de FIPE, VJV, IVB e classificação. +- Formatação em `pt-BR` sem i18n. + +### Tests + +- `test/app.test.ts` — renderiza e interage com campos. + +### Validation + +- `pnpm dev` e `pnpm test` + +### Acceptance Criteria + +- [ ] Formulário renderiza os quatro campos. +- [ ] Alterar os campos atualiza o resultado em tempo real. +- [ ] Resultado exibe VJV, IVB e classificação. + +--- + +## Task 5 — ✅ Sincronizar formulário com query params para compartilhamento + +### Goal + +Permitir que o usuário copie e compartilhe uma URL que carregue o mesmo cálculo. + +### Files + +- `app/pages/index.vue` + +### Implementation + +- Sincronizar `useRoute().query` → estado no `onMounted`. +- Atualizar `useRouter()` query ao mudar campos. +- Converter tipos (number) de forma segura. + +### Tests + +- `test/app.test.ts` ou teste específico para query params. + +### Validation + +- `pnpm test` e teste manual de navegação. + +### Acceptance Criteria + +- [ ] URL reflete os valores preenchidos. +- [ ] Acessar URL com query params preenche o formulário. +- [ ] Não há hydration mismatch. + +--- + +## Task 6 — ✅ Integração final e verificação + +### Goal + +Garantir que todo o MVP passa em lint, testes e build. + +### Files + +- Todos afetados pelas tasks anteriores. + +### Implementation + +- Verificar e ajustar imports, formatação e tipos. +- Remover arquivos placeholder não utilizados (`hello.ts`, testes genéricos). + +### Tests + +- `pnpm test` + +### Validation + +- `pnpm lint` +- `pnpm format:check` +- `pnpm test` +- `pnpm build` + +### Acceptance Criteria + +- [ ] `pnpm lint` passa. +- [ ] `pnpm test` passa. +- [ ] `pnpm build` gera sem erros. +- [ ] Aplicação funciona em `pnpm dev`. diff --git a/docs/specs/ibav-mvp.md b/docs/specs/ibav-mvp.md new file mode 100644 index 0000000..d31f6bd --- /dev/null +++ b/docs/specs/ibav-mvp.md @@ -0,0 +1,266 @@ +# IBAV MVP — Calculadora de Valor Justo e Índice IVB + +## Problem + +A Tabela FIPE apresenta uma média nacional de preços e não reflete as condições individuais de um veículo (idade, quilometragem, conservação). Não existe uma ferramenta pública, auditável e offline que ajuste a referência FIPE com base nesses fatores de forma transparente. + +## Goal + +Implementar o **MVP do IBAV**, um cálculo reprodutível de: + +- **VJV (Valor Justo do Veículo)** +- **IVB (Índice de Valor Brasileiro)** + +A ferramenta deve funcionar **100% no frontend**, sem APIs externas, e apresentar os resultados de forma clara ao usuário. + +## Scope + +- Formulário de entrada (FIPE, ano, km, conservação) +- Cálculo da idade do veículo +- Cálculo do VJV com base na metodologia do `docs/docs.md` +- Cálculo do IVB (0-1000 pontos) e classificação +- Página/área de resultado (Valor FIPE, VJV, IVB, classificação) +- Compartilhamento básico dos resultados +- Testes unitários das funções de cálculo + +## Non-goals + +- Consulta automática à Tabela FIPE +- Backend real/persistência de dados +- Histórico de cálculos +- Comparação entre veículos +- Integração com bancos, leilões, seguro ou sinistros +- Autenticação +- Internacionalização (i18n) — o MVP será exclusivamente em português do Brasil + +## Current Architecture + +``` +app/ + app.vue # entry básico, apenas NuxtWelcome +server/ + api/hello.ts # endpoint placeholder +shared/ + utils/capitalize.ts # único utilitário existente +test/ + app.test.ts # testes do app.vue básico + utils.test.ts # testes genéricos placeholder +``` + +Stack: + +- Nuxt 4.5.1 + Vue 3.5.40 +- Nuxt UI 4.10.0 +- TypeScript 6.0 +- Vitest 4.1 + jsdom +- ESLint flat config + Prettier + +Não existe ainda nenhuma lógica de domínio implementada. + +## Proposed Solution + +1. Criar módulos de cálculo em `shared/utils/`: + - `vehicle.ts` — cálculo da idade + - `depreciation.ts` — desvalorização por idade + - `mileage.ts` — ajuste por quilometragem + - `condition.ts` — ajuste por conservação + - `vjv.ts` — cálculo do Valor Justo + - `ivb.ts` — cálculo do IVB e classificação +2. Criar uma página `app/pages/index.vue` com o formulário e o resultado. +3. Utilizar Nuxt UI para inputs (`UInput`, `USelect`) e exibição (`UCard`). +4. Persistir os inputs em query params para permitir compartilhamento por URL. +5. Testar todas as funções matemáticas com os exemplos contidos em `docs/docs.md`. + +## Functional Requirements + +- **FR1** O usuário deve informar: valor FIPE (R$), ano do veículo, quilometragem atual e estado de conservação. +- **FR2** A idade deve ser calculada automaticamente (`anoAtual - anoVeiculo`). +- **FR3** O desconto por idade deve ser `idade × 2%`. +- **FR4** O ajuste por quilometragem deve seguir a média de 15.000 km/ano: + - acima da média: `-0,5%` a cada 10.000 km + - abaixo da média: `+0,3%` a cada 10.000 km +- **FR5** O ajuste por conservação deve ser: + - Excelente: `+3%` + - Bom: `0%` + - Regular: `-3%` + - Ruim: `-8%` +- **FR6** O VJV deve ser calculado como: + `VJV = FIPE + ajusteConservação - descontoIdade ± ajusteQuilometragem` +- **FR7** O IVB deve ser calculado como pontuação de 0 a 1000: + - base: 1000 + - idade: `-15` pontos/ano + - quilometragem acima: `-10` a cada 10.000 km + - conservação: `+30/0/-30/-80` +- **FR8** O resultado deve exibir classificação IVB (Excelente, Muito Bom, Bom, Regular, Atenção). +- **FR9** O compartilhamento deve permitir copiar a URL com os parâmetros preenchidos. +- **FR10** O cálculo deve ocorrer em tempo real à medida que o usuário altera os campos. + +## Technical Requirements + +- **TR1** Todos os cálculos devem ser TypeScript puro em `shared/utils/`. +- **TR2** Nenhuma chamada de API ou backend será usada para o cálculo. +- **TR3** A moeda deve ser formatada em `pt-BR` (R$). +- **TR4** Formulário e resultados devem usar componentes Nuxt UI. +- **TR5** A página deve ser SSR-safe (sem hydration mismatch). +- **TR6** Query params devem sincronizar o estado do formulário via `useRoute().query` e `useRouter()`. +- **TR7** Cobertura de testes unitários acima de 80% para os utilitários matemáticos. +- **TR8** Em todos os arquivos `.vue` (SFC), o bloco `