Technical Challenge (Online Order System)
Este repositório contém a avaliação prática para o Estágio DEV (Internship). É uma aplicação fullstack construída com um backend Node.js/Express e um frontend React/Vite.
Este é um monorepo contendo duas aplicações separadas:
/backend: A API REST Node.js (Express)./frontend: A aplicação cliente React (Vite).
Por favor, veja as instruções abaixo para rodar cada parte.
- Backend: Node.js, Express, Sequelize, SQLite 164]
- Frontend: React (Vite), React Router, Framer Motion
- Gerenciamento de Estado: React Context API (para o Carrinho)
- Estilização: Tailwind CSS
- Notificações:
react-hot-toast
Você precisará de dois terminais separados para rodar este projeto.
O servidor backend é responsável por servir os dados do banco de dados SQLite.
-
Navegue até o backend:
cd backend -
Instale as dependências:
npm install
-
Rode o Seeder do Banco de Dados (Uma Vez): Isso irá criar o arquivo
db.sqlite3em/backend/database/e populá-lo com os dados iniciais dos produtos.node src/seeders/seed.js
-
Rode o Servidor (Modo Dev): Isso inicia o servidor em
http://localhost:3001usandonodemon.npm run dev
Para verificar se o backend está funcionando, abra seu navegador (ou um cliente de API) e vá para:
http://localhost:3001/api/products
Você deve ver um JSON array dos produtos (hambúrgueres, batatas, etc.).
A aplicação frontend é o que o usuário vê. Ela consome a API do backend.
-
Abra um novo terminal.
-
Navegue até o frontend:
cd frontend -
Instale as dependências:
npm install
-
Rode o Cliente (Modo Dev): Isso inicia o app React em
http://localhost:5173.npm run dev
Abra seu navegador e vá para http://localhost:5173. Você deve ver a página principal do e-commerce com os produtos carregados.
Esta seção aborda as principais decisões de arquitetura e premissas assumidas.
-
Arquitetura de Componentes (DRY):
- Premissa: Um código limpo e fácil de manter é crucial.
- Decisão: Em vez de repetir JSX e lógica em várias páginas (como
CheckoutPageeSuccessPage), optei por uma refatoração pesada. Criei uma biblioteca de componentes "burros" reutilizáveis (ex:Button,FormInput) e componentes "inteligentes" (ex:OrderSummary, que busca seu próprio estado doCartContext). Isso torna as páginas (CheckoutPage) apenas "contêineres" que organizam os componentes.
-
Gerenciamento de Estado (Context API):
- Premissa: O estado do carrinho é global e precisa ser acessado por múltiplos componentes (Header,
ProductCard,CheckoutPage,OrderSummary). - Decisão: O
CartContextatua como a "única fonte da verdade" para o carrinho, gerenciando toda a lógica de API (CRUD) e estado de carregamento. Estados locais (como filtros daHomePage) são mantidos nos próprios componentes, evitando complexidade desnecessária no estado global.
- Premissa: O estado do carrinho é global e precisa ser acessado por múltiplos componentes (Header,
-
Experiência do Usuário (Feedback):
- Premissa: O usuário nunca deve ficar em dúvida se uma ação funcionou.
- Decisão: Cada ação assíncrona (Adicionar ao Carrinho, Finalizar Pedido) dispara um feedback triplo: 1) Um toast de "loading", 2) Um estado de
disabledno botão, e 3) Um toast final de "success" ou "error" amigável.
Sim, uma ferramenta de IA (Gemini) foi utilizada neste desafio, conforme permitido.
- Como foi utilizada: A IA foi usada como uma parceira de programação (pair-programming) focada em refatoração e qualidade de código.
- Exemplos de Prompts:
- "Eu tenho este código repetido nas minhas páginas
CheckoutPageeSuccessPage. Qual é a melhor forma de extraí-lo para um componenteButtonreutilizável?" - "Meu filtro de busca está chamando a API a cada tecla. Qual é o bug no meu
debouncecomuseState?" (O que nos levou a usaruseRef). - "Gere a documentação Markdown para estas rotas do Express."
- "Eu tenho este código repetido nas minhas páginas
A IA não escreveu a lógica central do desafio, mas atuou como uma consultora sênior para identificar "code smells", sugerir padrões de design (como a extração de componentes) e acelerar tarefas repetitivas (como escrever documentação e testes).
Clique para expandir a documentação da API
Controlado por productController.js.
Prefixo da Rota: /api/products
GET /api/products/- Descrição: Busca a lista de produtos.
- Controlador:
productController.list - Query Params (Opcionais):
page(Number): O número da página. Default: 1.search(String): Termo de busca para o nome do produto.category(String): Filtra por uma categoria exata.maxPrice(Number): Retorna produtos com preço menor ou igual a este.
Controlado por cartController.js.
Prefixo da Rota: /api/cart
-
GET /api/cart/- Descrição: Busca o conteúdo atual do carrinho.
- Controlador:
cartController.getCart
-
POST /api/cart/- Descrição: Adiciona um item ao carrinho.
- Controlador:
cartController.addItem - Body (JSON):
{ "productId": 123, "quantity": 1 }
-
DELETE /api/cart/:id- Descrição: Remove um item específico (baseado no
id) do carrinho. - Controlador:
cartController.removeItem
- Descrição: Remove um item específico (baseado no
-
PUT /api/cart/:id- Descrição: Atualiza a quantidade de um item específico (baseado no
id) no carrinho. - Controlador:
cartController.updateItemQuantity - Body (JSON):
{ "quantity": 2 }
- Descrição: Atualiza a quantidade de um item específico (baseado no
Controlado por orderController.js.
Prefixo da Rota: /api/orders
POST /api/orders/- Descrição: Simula um checkout (finaliza um pedido).
- Controlador:
orderController.checkout - Notas: Este endpoint recebe o carrinho (implicitamente, pela sessão/usuário) e retorna uma mensagem de sucesso.