├── .gitignore ├── API_README.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | -------------------------------------------------------------------------------- /API_README.md: -------------------------------------------------------------------------------- 1 | # Serviço de API de Transações 2 | 3 | Uma API REST baseada em TypeScript para gerenciar transações financeiras com suporte para tipos de pagamento PIX e TED. 4 | 5 | A API estará disponível em `https://fe-challenge-trace-api-production.up.railway.App`. 6 | 7 | ## Endpoints da API 8 | 9 | ### Health Check 10 | 11 | ``` 12 | GET /health 13 | ``` 14 | 15 | **Resposta:** 16 | 17 | ```json 18 | { 19 | "status": "ok", 20 | "timestamp": "2024-12-09T10:00:00.000Z" 21 | } 22 | ``` 23 | 24 | ### Listar Transações 25 | 26 | ``` 27 | GET /api/transactions 28 | ``` 29 | 30 | **Parâmetros de Query:** 31 | 32 | | Parâmetro | Tipo | Obrigatório | Padrão | Descrição | 33 | | ----------- | ------ | ----------- | ------ | ---------------------------------------------------- | 34 | | `page` | number | Não | 1 | Número da página atual | 35 | | `limit` | number | Não | 20 | Itens por página (máx: 100) | 36 | | `search` | string | Não | - | Buscar por descrição ou ID da transação | 37 | | `status` | string | Não | - | Filtrar por status: `COMPLETED`, `PENDING`, `FAILED` | 38 | | `currency` | string | Não | - | Filtrar por moeda: `BRL`, `USD`, `EUR` | 39 | | `startDate` | string | Não | - | Filtrar a partir da data (formato ISO 8601) | 40 | | `endDate` | string | Não | - | Filtrar até a data (formato ISO 8601) | 41 | 42 | **Exemplo de Requisição:** 43 | 44 | ```bash 45 | curl "http://localhost:8080/api/transactions?page=1&limit=10&status=COMPLETED¤cy=BRL" 46 | ``` 47 | 48 | **Resposta:** 49 | 50 | ```json 51 | { 52 | "data": [ 53 | { 54 | "id": "tx-1", 55 | "description": "Pagamento fornecedor", 56 | "type": "PIX", 57 | "amount": 150000, 58 | "currency": "BRL", 59 | "status": "COMPLETED", 60 | "createdAt": "2024-12-08T10:30:00.000Z", 61 | "cpfCnpj": "12345678901", 62 | "pixKey": "fornecedor@email.com", 63 | "keyType": "EMAIL" 64 | } 65 | ], 66 | "meta": { 67 | "total": 15, 68 | "page": 1, 69 | "limit": 10, 70 | "totalPages": 2, 71 | "previousCursor": null, 72 | "nextCursor": 2 73 | } 74 | } 75 | ``` 76 | 77 | **Cursores de Paginação:** 78 | 79 | - `previousCursor`: Número da página anterior (`null` se estiver na primeira página) 80 | - `nextCursor`: Número da próxima página (`null` se estiver na última página) 81 | 82 | ### Criar Transação 83 | 84 | ``` 85 | POST /api/transactions 86 | ``` 87 | 88 | **Corpo da Requisição:** 89 | 90 | #### Transação PIX 91 | 92 | ```json 93 | { 94 | "type": "PIX", 95 | "amount": 150000, 96 | "cpfCnpj": "12345678901", 97 | "pixKey": "example@email.com", 98 | "keyType": "EMAIL", 99 | "description": "Descrição opcional" 100 | } 101 | ``` 102 | 103 | **Campos obrigatórios:** 104 | 105 | - `type` - Deve ser `"PIX"` 106 | - `amount` - Inteiro em centavos (ex: 150000 = R$ 1.500,00) 107 | - `cpfCnpj` - CPF (11 dígitos) ou CNPJ (14 dígitos) 108 | - `pixKey` - Valor da chave PIX 109 | - `keyType` - Um de: `EMAIL`, `PHONE`, `CPF`, `CNPJ`, `RANDOM` 110 | 111 | **Campos opcionais:** 112 | 113 | - `description` - Descrição da transação 114 | 115 | #### Transação TED 116 | 117 | ```json 118 | { 119 | "type": "TED", 120 | "amount": 250000, 121 | "cpfCnpj": "12345678000190", 122 | "bank": "001", 123 | "account": "12345-6", 124 | "agency": "0001", 125 | "accountType": "CORRENTE", 126 | "description": "Descrição opcional" 127 | } 128 | ``` 129 | 130 | **Campos obrigatórios:** 131 | 132 | - `type` - Deve ser `"TED"` 133 | - `amount` - Inteiro em centavos 134 | - `cpfCnpj` - CPF (11 dígitos) ou CNPJ (14 dígitos) 135 | - `bank` - Código do banco 136 | - `account` - Número da conta 137 | - `agency` - Número da agência 138 | - `accountType` - Um de: `CORRENTE`, `POUPANCA` 139 | 140 | **Campos opcionais:** 141 | 142 | - `description` - Descrição da transação 143 | 144 | **Resposta de Sucesso (201 Created):** 145 | 146 | ```json 147 | { 148 | "id": "tx-16", 149 | "type": "PIX", 150 | "amount": 150000, 151 | "currency": "BRL", 152 | "status": "PENDING", 153 | "createdAt": "2024-12-09T10:00:00.000Z", 154 | "cpfCnpj": "12345678901", 155 | "pixKey": "example@email.com", 156 | "keyType": "EMAIL", 157 | "description": "Descrição opcional" 158 | } 159 | ``` 160 | 161 | **Resposta de Erro (400 Bad Request):** 162 | 163 | ```json 164 | { 165 | "status": 400, 166 | "message": "Validation error", 167 | "errors": [ 168 | { 169 | "field": "amount", 170 | "message": "Number must be greater than 0" 171 | } 172 | ] 173 | } 174 | ``` 175 | 176 | ## Regras de Validação 177 | 178 | ### CPF/CNPJ 179 | 180 | - CPF: Exatamente 11 dígitos 181 | - CNPJ: Exatamente 14 dígitos 182 | - Validação apenas de formato (sem verificação de dígitos verificadores) 183 | 184 | ### Valor 185 | 186 | - Deve ser um inteiro positivo 187 | - Armazenado em centavos (ex: 100 = R$ 1,00) 188 | 189 | ### Tipo de Transação 190 | 191 | A API valida campos obrigatórios com base no tipo de transação: 192 | 193 | **PIX:** Requer `pixKey` e `keyType` 194 | **TED:** Requer `bank`, `account`, `agency` e `accountType` 195 | 196 | ## Valores de Enum 197 | 198 | A API usa os seguintes valores de enum para vários campos. Use esses valores exatos ao criar transações ou filtrar: 199 | 200 | ### Tipo de Transação 201 | 202 | | Valor | Descrição | 203 | | ----- | ------------------------- | 204 | | `PIX` | Tipo de pagamento PIX | 205 | | `TED` | Tipo de transferência TED | 206 | 207 | ### Status da Transação 208 | 209 | | Valor | Descrição | 210 | | ----------- | ------------------------------- | 211 | | `COMPLETED` | Transação concluída com sucesso | 212 | | `PENDING` | Transação pendente | 213 | | `FAILED` | Transação falhou | 214 | 215 | **Uso:** Filtrar transações por status no parâmetro de query `?status=COMPLETED` 216 | 217 | ### Moeda 218 | 219 | | Valor | Descrição | 220 | | ----- | --------------- | 221 | | `BRL` | Real Brasileiro | 222 | | `USD` | Dólar Americano | 223 | | `EUR` | Euro | 224 | 225 | **Uso:** Filtrar transações por moeda no parâmetro de query `?currency=BRL` 226 | 227 | ### Tipo de Chave PIX 228 | 229 | Usado ao criar transações PIX (campo `keyType`): 230 | 231 | | Valor | Descrição | Exemplo | 232 | | -------- | ---------------------- | -------------------------------------- | 233 | | `EMAIL` | Endereço de e-mail | `user@example.com` | 234 | | `PHONE` | Número de telefone | `+5511987654321` | 235 | | `CPF` | Número do CPF | `12345678901` | 236 | | `CNPJ` | Número do CNPJ | `12345678000190` | 237 | | `RANDOM` | Chave aleatória (UUID) | `a1b2c3d4-e5f6-7890-abcd-ef1234567890` | 238 | 239 | ### Tipo de Conta 240 | 241 | Usado ao criar transações TED (campo `accountType`): 242 | 243 | | Valor | Descrição | 244 | | ---------- | -------------- | 245 | | `CORRENTE` | Conta corrente | 246 | | `POUPANCA` | Conta poupança | 247 | 248 | ### Dados de Mock 249 | 250 | A API inclui 15 transações pré-populadas com vários tipos, status e moedas para fins de teste. 251 | 252 | ## Códigos de Status de Resposta 253 | 254 | - `200 OK` - Requisição GET bem-sucedida 255 | - `201 Created` - Requisição POST bem-sucedida 256 | - `400 Bad Request` - Erro de validação 257 | - `500 Internal Server Error` - Erro do servidor 258 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🚀 Front-end Challenge — Transaction Management 2 | 3 | Desafio para avaliar engenheiros(as) front-end sênior na Trace Finance. 4 | 5 | ## 📋 Sobre este Desafio 6 | 7 | Este desafio tem como objetivo avaliar suas habilidades em construir uma aplicação front-end moderna, escalável e testável, utilizando as principais tecnologias e padrões que adotamos na Trace Finance. 8 | 9 | Figma do teste: https://www.figma.com/design/YXzBTEwElRuxRVssHg465f/Teste-t%C3%A9cnico?node-id=0-1&m=dev&t=0krnC3qtatApObzH-1 10 | 11 | ### 🔀 Como iniciar: 12 | 13 | 1. **Projeto novo**: Crie um projeto Next.js do zero (recomendado) 14 | 2. **Starter template**: Você pode usar qualquer template/boilerplate que preferir 15 | 16 | --- 17 | 18 | ## 📝 Contexto 19 | 20 | Você deve construir uma aplicação de **gerenciamento de transações** com: 21 | 22 | - ✅ **Formulário multi-step** para criar transações (2 etapas com sidebar) 23 | - ✅ **Listagem paginada** com filtros, pesquisa e paginação 24 | 25 | A aplicação deve ser responsiva, testável e seguir as melhores práticas de desenvolvimento front-end. 26 | 27 | ### 📦 O que forneceremos: 28 | 29 | - ✅ Base URL da API com endpoints funcionais 30 | - ✅ Documentação dos endpoints 31 | - ✅ Exemplos de payloads 32 | 33 | ### 📊 Resumo Visual do Fluxo: 34 | 35 | ``` 36 | Listagem de Transações 37 | ├─→ Filtros (Status, Currency, Data) 38 | ├─→ Pesquisa 39 | ├─→ Paginação 40 | └─→ Botão "Nova Transação" 41 | ↓ 42 | Formulário Multi-Step 43 | ├─→ Step 1: Info Básicas (Descrição, Tipo, Valor, CPF/CNPJ) 44 | └─→ Step 2: Detalhes (campos condicionais por tipo) 45 | ↓ 46 | Submissão → API → Redirect para Listagem 47 | ``` 48 | 49 | --- 50 | 51 | ## 🛠 Tecnologias (obrigatórias) 52 | 53 | ### Core Stack 54 | 55 | - **Framework**: Next.js 14+ (App Router ou Pages Router) 56 | - **Linguagem**: TypeScript 57 | - **Gerenciamento de Estado**: Zustand, Redux Toolkit ou Context API + hooks 58 | - **Formulários**: React Hook Form + Yup/Zod (validação) 59 | - **HTTP Client**: Axios, Fetch API, React query (diferencial) ou biblioteca de sua escolha 60 | - **Estilização**: Styled Components, Tailwind CSS, Stitches, PandaCSS, etc. 61 | 62 | ### Testing 63 | 64 | - **Testes Unitários/Integração**: Jest + Testing Library 65 | 66 | ### Código e Qualidade 67 | 68 | - **Linting**: ESLint com regras TypeScript 69 | - **Formatação**: Prettier 70 | - **Commits**: Conventional Commits (recomendado) 71 | 72 | --- 73 | 74 | ## 🎯 Funcionalidades Obrigatórias 75 | 76 | ### 1. Listagem de Transações (Página Principal) 77 | 78 | #### Interface 79 | 80 | **Tabela com colunas:** 81 | 82 | - ID 83 | - Tipo (PIX/TED) 84 | - Valor (formatado em BRL) 85 | - Status (badge colorido) 86 | - Data/Hora 87 | 88 | **Funcionalidades obrigatórias:** 89 | 90 | 1. **Paginação** 91 | 92 | - Controles: Infinite Scroll 93 | - Exibir "Mostrando X-Y de Z resultados" 94 | 95 | 2. **Filtros:** 96 | 97 | - **Status** (Tab): Todos, Completed, Pending, Failed 98 | - **Tipo** (select/dropdown): PIX, TED 99 | - **Data** (date range picker): Período, de -> até, mês de inicio, mês de fim 100 | - Botão "Aplicar Filtros" 101 | - Botão "Limpar Filtros" 102 | - Mostrar filtros ativos com componente de Badge 103 | 104 | 3. **Estados:** 105 | 106 | - Loading (skeleton table) 107 | - Empty state (sem resultados) 108 | - Error state (falha na API) 109 | 110 | 5. **Botão "Nova Transação"** 111 | - Redireciona para o formulário multi-step 112 | 113 | --- 114 | 115 | ### 2. Formulário Multi-Step (Criar Transação) 116 | 117 | Formulário com **2 etapas** e **sidebar lateral** indicando o step atual. 118 | 119 | #### Layout do Formulário 120 | 121 | **Desktop:** 122 | 123 | ``` 124 | ┌─────────────────┬──────────────────────────────┐ 125 | │ Sidebar │ Área Principal │ 126 | │ │ │ 127 | │ ● Step 1 │ [Campos do Step Ativo] │ 128 | │ Informações │ │ 129 | │ │ │ 130 | │ ○ Step 2 │ │ 131 | │ Detalhes │ │ 132 | │ │ │ 133 | │ │[Voltar] [Próximo/Confirmar] │ 134 | └─────────────────┴──────────────────────────────┘ 135 | ``` 136 | 137 | **Mobile:** 138 | 139 | - Sidebar pode ficar horizontal no topo ou como stepper 140 | - Campos empilhados verticalmente 141 | 142 | **Navegação:** 143 | 144 | - Botão "Voltar": Retorna ao step anterior (ou página de listagem se no Step 1) 145 | - Botão "Próximo" (Step 1): Avança para Step 2 146 | - Botão "Confirmar" (Step 2): Submete o formulário 147 | 148 | #### Step 1 - Informações Básicas 149 | 150 | **Campos:** 151 | 152 | 1. **Descrição** (input texto, **opcional**) 153 | 2. **Tipo de Transação** (select, **obrigatório**) 154 | - Opções: `PIX`, `TED` 155 | 3. **Valor** (input texto, **obrigatório**, máscara de moeda BRL) BE trabalha em centavos 156 | 4. **CPF/CNPJ** (input texto com máscara, **obrigatório**) 157 | 158 | **Comportamento:** 159 | 160 | - Botão "Próximo" habilitado apenas com campos obrigatórios válidos 161 | - Validação em tempo real (mostrar erros abaixo dos campos) 162 | - Não permitir avançar com campos inválidos 163 | 164 | #### Step 2 - Detalhes da Transação 165 | 166 | **Campos condicionais baseados no "Tipo de Transação" do Step 1:** 167 | 168 | **Se PIX:** 169 | 170 | - Chave PIX (input texto, obrigatório) 171 | - Tipo de Chave (select: CPF, Email, Telefone, Aleatória) 172 | 173 | **Se TED:** 174 | 175 | - Banco (select com lista de bancos) 176 | - Agência (input texto, obrigatório) 177 | - Conta (input texto, obrigatório) 178 | - Tipo de Conta (select: Corrente, Poupança) 179 | 180 | **Comportamento:** 181 | 182 | - **"Voltar"**: Retorna ao Step 1 com todos os dados preservados 183 | - **"Confirmar"**: Envia os dados para a API (endpoint fornecido) 184 | - Modal de confirmação (diferencial) 185 | - Após sucesso: Redireciona para listagem 186 | - Após erro: Exibe mensagem de erro 187 | - **Ao retornar para o formulário após confirmação**: Campos limpos (reset completo) 188 | 189 | **Validações:** 190 | 191 | - Todos os campos condicionais devem ter validação apropriada 192 | - Exibir mensagens de erro abaixo dos campos 193 | 194 | --- 195 | 196 | ## 🌐 API (Fornecida) 197 | 198 | ### Endpoints que forneceremos: 199 | 200 | Api base url: `https://fe-challenge-trace-api-production.up.railway.App` 201 | Api prefix: `/api` 202 | 203 | Endpoints: `/transaction` (GET, POST) 204 | 205 | Todas as informações da api podem ser encontradas em [API_README.md](API_README.md) 206 | 207 | #### `GET /api/transactions` 208 | 209 | **Query Params:** 210 | 211 | - `page` (number): Página atual 212 | - `limit` (number): Items por página 213 | - `search` (string): Busca por descrição/ID 214 | - `status` (string): COMPLETED | PENDING | FAILED 215 | - `currency` (string): BRL | USD | EUR 216 | - `startDate` (string): Data início (ISO 8601) 217 | - `endDate` (string): Data fim (ISO 8601) 218 | 219 | Mostrar filtro ativo em formato de Badge 220 | 221 | --- 222 | 223 | ## 🎨 UI/UX Requirements 224 | 225 | ### Design System 226 | 227 | - Usar theme 228 | - Tokens para cores, fontes, etc. 229 | - Dark mode (diferencial) 230 | - Criar componentes customizados básicos 231 | 232 | ### Componentes Necessários 233 | 234 | - `Button` (primary, secondary) 235 | - `Input` / `InputMask` (para CPF/CNPJ, moeda) 236 | - `Select` / `Dropdown` 237 | - `DatePicker` (para filtro de data) 238 | - `Badge` (para status) 239 | - `Table` 240 | - `Skeleton` (loading states) 241 | - `EmptyState` 242 | - `Sidebar` (para o multi-step form) 243 | 244 | ### Responsividade 245 | 246 | - **Mobile** (< 768px): Stack vertical, sidebar do form pode ser horizontal no topo 247 | - **Desktop** (≥ 768px): Layout padrão com sidebar lateral 248 | - Tabela responsiva (scroll horizontal em mobile ou cards) 249 | 250 | ## 🏗 Arquitetura e Boas Práticas 251 | 252 | ### Padrões de Código 253 | 254 | - ✅ **DRY**: Não repetir código 255 | - ✅ **Single Responsibility**: Componentes com responsabilidade única 256 | - ✅ **Custom Hooks**: Extrair lógica reutilizável 257 | - ✅ **Type Safety**: Tipar tudo (evitar `any`) 258 | - ✅ **Validações**: Usar schemas (Yup/Zod) 259 | - ✅ **Error Handling**: Tratamento apropriado de erros 260 | 261 | ## 🧪 Testes (Jest + Testing Library) 262 | 263 | ## 📝 Pré-requisitos 264 | 265 | - ✅ Repositório privado no GitHub 266 | - ✅ TypeScript configurado 267 | - ✅ Next.js 14+ 268 | - ✅ Todas as 3 funcionalidades implementadas: 269 | - Formulário multi-step completo 270 | - Listagem com filtros, pesquisa e paginação 271 | - ✅ Testes unitários 272 | - ✅ Formulários com validação 273 | - ✅ Gerenciamento de estado 274 | - ✅ Loading, error e empty states 275 | - ✅ Responsivo (mobile e desktop) 276 | - ✅ README com: 277 | - Instruções de instalação 278 | - Como rodar o projeto 279 | - Como rodar os testes 280 | - Variáveis de ambiente necessárias 281 | - ✅ Lint sem erros 282 | - ✅ Testes passando (`yarn test` ou `npm test`) 283 | 284 | --- 285 | 286 | ## 🌟 Diferenciais (Seria Legal Ter) 287 | 288 | ### Código e Arquitetura 289 | 290 | - 🎯 Arquitetura modular bem organizada (feature-based) 291 | - 🎯 Custom hooks bem abstraídos e reutilizáveis 292 | - 🎯 Error Boundary implementado 293 | - 🎯 Abstrações de serviços HTTP (camada de API bem estruturada) 294 | - 🎯 Path aliases configurados no TypeScript 295 | - 🎯 Documentação de componentes (Storybook ou similar) 296 | 297 | ### UX/UI 298 | 299 | - ✨ Dark mode 300 | - ✨ Botão para alteração de lingua 301 | - ✨ Animações e transições suaves 302 | - ✨ Toast notifications (feedback de ações) 303 | - ✨ Confirmação antes de submeter formulário 304 | - ✨ Skeleton screens customizados 305 | 306 | ### Testing e Qualidade 307 | 308 | - 🧪 Cobertura de testes 309 | - 🔧 Husky + lint-staged 310 | - 🔧 Commitlint 311 | 312 | ### Extras 313 | 314 | - 🌐 Internacionalização (PT/EN) - i18n 315 | - 🚀 Deploy em produção (Vercel, Netlify, etc.) 316 | 317 | --- 318 | 319 | ## 📤 Submissão 320 | 321 | 1. ✅ Crie um fork do repositório 322 | 2. ✅ Dê permissão de leitura para o usuário que indicarmos no repositório privado 323 | 3. ✅ No README, inclua: 324 | - Instruções de instalação 325 | - Como rodar o projeto 326 | - Como rodar os testes 327 | - Principais decisões técnicas 328 | - Tempo aproximado de desenvolvimento 329 | - Melhorias futuras (se tiver) 330 | 331 | --- 332 | 333 | ## ⏱️ Prazo 334 | 335 | **2-3 dias** a partir do recebimento do desafio e da Base URL da API. 336 | 337 | Se precisar de mais tempo, entre em contato conosco. 338 | 339 | --- 340 | 341 | ## ❓ Dúvidas 342 | 343 | Envie e-mail para `frontend@trace.finance` com o assunto **"Dúvida - Desafio Front-end"**. 344 | 345 | --- 346 | 347 | **Boa sorte! 🚀** 348 | --------------------------------------------------------------------------------