Pular para conteúdo

Frontend

React · TypeScript · Vite · Tailwind v4 · shadcn/ui · Redux Toolkit · i18next · Vitest.

Molde: src/features/authentication/ — a primeira feature ligada ao backend. Ele tem uma tela só; para fluxo com várias telas, o exemplo é src/features/responses/ (o questionário).

respondentes não é molde

O README do front ainda aponta features/respondentes/ como exemplo. Ela é resíduo do scaffold: o respondentesApi.ts chama uma rota que não existe mais no back (responde 404), e o slice usa a máquina de status antiga. Copie dela, no máximo, a navegação entre as telas de demográficos — nunca a integração.

Anatomia de uma feature ✅

src/features/<feature>/
├── <Feature>View.tsx       a tela
├── <feature>Slice.ts       estado (Redux Toolkit) e thunks
├── <feature>Api.ts         as chamadas HTTP
└── *.test.ts(x)            ao lado do que testam

A pasta tem o mesmo nome do domínio do backend: o back tem responses, o front tem responses. Página que não espelha domínio (boas-vindas, sobre) é exceção aceita: não chama o backend.

As camadas

Camada Arquivo Faz Não pode
Integração <feature>Api.ts montar path, query e corpo sobre o apiClient conhecer Redux ou React; try/catch
Estado <feature>Slice.ts guardar o que veio do servidor, o status e o erro já como mensagem fazer fetch, formatar texto de tela
UI <Feature>View.tsx e componentes desenhar e capturar interação fazer fetch, agregar dado
Compartilhado src/lib/, src/hooks/, src/components/ o que mais de uma feature usa conhecer uma feature específica

Sinais de que a camada furou

Sinal O que está errado
View importando @/lib/apiClient a tela falando HTTP — passe pelo <feature>Api.ts
fetch( ou axios fora do apiClient HTTP fora do lugar
<feature>Api.ts importando @reduxjs/toolkit integração sabendo de estado
.reduce( na View para montar um indicador agregação no front: é do backend
src/components/ importando de src/features/ compartilhado dependendo de específico

O que vai — e o que não vai — para o Redux

Estado Onde mora
Dado que veio do servidor slice da feature
Status da requisição slice
Erro da requisição slice, já como mensagem pronta — a View não interpreta ApiError
Campos de formulário react-hook-form (Formulários)
Aberto/fechado, aba ativa useState no componente
Valor derivado (total, filtrado, ordenado) seletor, nunca um campo a mais no state

A máquina de status ✅

status: 'idle' | 'loading' | 'ready' | 'error'

Uma só, igual em toda feature, decidida pelo time em 2026-09-29. A View cobre os quatro casos — inclusive ready com lista vazia, que é uma mensagem de vazio, não ausência de estado. Feature que só desenha o caso feliz volta na review.

Dois slices antigos ainda não seguem: o authenticationSlice usa authenticated no lugar de ready, e o respondentesSlice usa a versão em português. Feature nova segue a máquina acima.

Onde mora o compartilhado

O quê Onde
Cliente HTTP (base /api/v1, cabeçalho, erro como ApiError) src/lib/apiClient.ts — use, não reimplemente
Sessão guardada no navegador src/lib/session.ts
Schemas zod src/lib/validadores.ts
cn() para juntar classes src/lib/utils.ts
Hook reutilizável src/hooks/
Tipos do backend src/types/api.ts (Contrato)
Primitivos de UI (shadcn) src/components/ui/
Layout, modais e componentes de mais de uma feature src/components/
Store, rotas, hooks tipados do Redux src/app/
Textos (pt-BR, en) src/i18n/locales/

Regra dos dois usos: o primeiro uso mora na feature; o segundo sobe para lib/, hooks/ ou components/.

Proxy da API

O Vite faz proxy de /api para http://localhost:8000. Nunca escreva URL absoluta de backend no código: em produção o caminho é outro, e o apiClient já resolve.

Ainda em consolidação 🟡

  • Nome da pasta de feature: convivem authentication, responses (inglês), respondentes (português) e boas-vindas, aguarde-confirmacao (kebab-case).
  • Chaves de i18n: hoje todas em português (autenticacao, formulario), e o ADR-0005, ainda proposto, pede inglês.

Ver Em consolidação. Passo a passo: Criar uma feature no front.