NG.CASH é uma empresa de tecnologia que fornece um app financeiro para a geração Z.
O teste técnico para o cargo de desenvolvedor frontend júnior consistia em:
Construir aplicação web fullstack dockeirizada para usuários NG.CASH fazerem transações entre si, com prazo sugerido de 7 dias para execução.
Foram fornecidas regras de negócio, schemas para o Banco de Dados e as características mínimas para o frontend. Você encontra uma cópia dos requisitos aqui.
É necessário ter docker
e docker-compose
instalados.
- Clone o repositório para sua máquina local;
- Abra a pasta raíz do projeto no terminal;
- Execute:
docker-compose -f compose-dev.yml up --build
- Acesse localhost:5173 para acessar o frontend de desenvolvimento com proxy
- Acesse localhost:3000 para acessar apenas o backend com a última build do frontend
- Para parar os containers, aperte ctrl+c no terminal do docker-compose
- Na pasta raíz, execute:
docker-compose -f compose-dev.yml down
para remover os containers
OBS: Alterações feitas no código na máquina local são percebidas automaticamente nos containers.
O primeiro commit de setup do projeto (64de54e) foi feito em 15/nov./2022.
Consta no Readme da entrega parcial, feita em 04/dez./2022 (787a3cb):
- Não conhecia Docker;
- Não sabia como funcionava o processo de autenticação com JWT;
- Pouquíssimo conhecimento em backend (nunca implementei server com db);
- Para executar o frontend, optei por usar um Mock Service Worker para interceptar e lidar com os requests enquanto não tenho o backend;
Devido a essas limitações, optei por enviar um frontend funcional, porém mockado e continuar aprendendo para ter em portfólio um projeto fullstack.
Para isso, entre 04/dez. e 10/jan. aprendi:
- Node + Express + Auth JWT (até 3a32b29)
- Banco de Dados + SQLite + Nestjs (Confira aqui; Influência começa em d196996)
- Padrões de Repository, Módulos, Inversão de Dependências, Camadas da Aplicação (db/repo/app/http)
- Uso de Mappers entre camadas
- Obs: Não usei Nest nem SQLite aqui, mas me apropriei de conceitos de DDD, OOP e SOLID para o projeto.
- Docker CLI + Docker-Compose (d1caa3d)
- Prisma ORM (Inicial: 03cceeb)
Confira a história completa de commits: commits/main.
- TypeScript
- React
- Vite
- TailwindCSS
- Outros: react-modal, react-icons, axios
- TypeScript
- Nodejs
- Express
- Outros: jsonwebtoken, bcrypt
- Prisma
- Postgresql
- Docker-compose
- Git
Frontend
- Frontend 100% responsivo
- Práticas de acessibilidade no React
- Padronização de tema no Tailwind
- Validação de entradas (register/login/transferência)
- Modais de Erro conforme retorno da API
- Uma tabela automática linda para as transações financeiras <3 (ver prints abaixo)
Backend
- Camadas desacopladas com inversão de dependência
- Validação de entradas do usuário e checagens redundantes
- Validação de JWT via middleware custom
- Hashing de senhas
- Postgres via imagem docker
- Repositório Prisma / ORM com migrations
ATTENTION: API WORKS WITH INTEGERS, aka: 1001 == $ 10.01
@@ Public
Create new account and user.
Request Body
// application/json
{
"username": string,
"password": string
}
Response Body
// application/json
{
"message": "account created!",
"user": {
"id": string,
"username": string,
"account": {
"id": string,
"balance": number,
"transaction_ids": string[]
},
"accessToken": string
}
}
@@ Public
Login to existing account.
Request Body
{
"username": string,
"password": string
}
Response Body
// application/json
{
"id": string,
"username": string,
"account": {
"id": string,
"balance": number
"transaction_ids": string[]
},
"accessToken": string
}
@@ Private ("Authorization": "Bearer ...")
Gets account balance.
Response Body
// application/json
{
"account": {
"id": string,
"balance": number
}
}
@@ Private ("Authorization": "Bearer ...")
Request Body
// application/json
{
"from": string,
"to": string,
"amount": number
}
Important: "from" is ACCOUNT_ID, "to" is USERNAME Example:
// application/json { "from": "59a33a94-d4e7-4fdf-a2c3-95cc7e32d960", "to": "user1234", "amount": 1000 }
Response Body
{
"message": "Success!",
"transaction": {
"from": string,
"to": string,
"amount": number,
"created_at": DateTime,
"transaction_id": string
}
}
@@ Private ("Authorization": "Bearer ...")
Gets transaction history as an array.
Response Body
// application/json
[
{
"from": string,
"to": string,
"amount": number,
"created_at": DateTime,
"transaction_id": string
},
// example:
{
"from": "teste_123",
"to": "user1234",
"amount": 15000,
"created_at": "2023-01-10T12:41:04.028Z",
"transaction_id": "6f7c72be-f868-47b2-8d54-b3abd196a5e9"
},
]
@@ DEBUG Public This route only exists for debugging purposes. Gets all users in Database.
@@ DEBUG Public This route only exists for debugging purposes. Gets all transactions in Database.