O Sistema de reembolso é o segundo desafio da formação React 2025.
Neste projeto, o objetivo é construir um aplicativo de solicitações de reembolso para ambientes corporativos.
A aplicação contempla criação, listagem e remoção de reembolsos. Além disso, também contempla o upload de recibo relacionado ao reembolso, busca pelo nome do autor da solicitação, paginação e página de detalhes do pedido.
Esse desafio reforça conceitos fundamentais do React e aprofunda em novos tópicos que serão usados em qualquer aplicação.
Materiais para você usar como base para o desenvolvimento
Estrutura, regras e requisitos do projeto
Construir um aplicativo de sistema de reembolso funcional, aplicando os seguintes pontos:
Para desenvolver esse projeto, recomendamos utilizar as principais ferramentas que utilizamos durante o desenvolvimento do projeto Álbum de fotos dessa formação.
Além disso, você deve consumir a API que preparamos para esse projeto, assim você pode se concentrar em desenvolver apenas a parte web frontend. Nas 2 próximas seções, abordaremos com mais detalhes sobre a estrutura e como utilizá-la.
Para que você consiga utilizar a API, é preciso baixar o código no repositório, seja clonando utilizando o comando git clone git@github.com:rocketseat-education/refund-api.git ou clicando na opção Download ZIP.
Após o download, você deve acessar a pasta do seu projeto e instalar as dependências com o comando npm i. Para executar o projeto, é preciso preparar o banco de dados primeiro. Para isso, execute o comando npm run db:prepare, isso criará o banco de dados SQLite. Por fim, para executar a aplicação basta executar o comando npm run dev.
Com isso, a sua API estará pronta para ser consumida no endereço http://localhost:3333.
A API desse desafio foi estruturada seguindo a opinião do framework Adonis. Porém, você não é obrigado a entender o framework/node para entender as rotas, pois documentaremos elas mais abaixo. Para interagir com o banco e API, sugerimos duas ferramentas para te auxiliar:
db.sqlite3 gerado na pasta tmp após a execução do comando npm run db:prepare.Base URL: http://localhost:3333
/receipts — Cria um reciboFaz upload de um comprovante/nota fiscal.
Headers: Content-Type: multipart/form-data
Body (multipart/form-data):
receiptFile (file, obrigatório) — arquivo do recibo (imagem/PDF)Exemplo de resposta de sucesso (200)
{ "receipt": { "originalFilename": "rodas-pintadas", "path": "/tmp/aii8m2goy0eyutg7ui07lz0i", "extname": "jpeg", "filename": "rodas-pintadas-u3nd3Eiipi", "id": "3813f678-2ad7-4c68-9a39-55fa8780b323", "createdAt": "2025-10-07T20:32:24.543+00:00", "updatedAt": "2025-10-07T20:32:24.543+00:00" }
/receipts/{id} — Lista um recibo específicoRetorna metadados de um recibo.
Path params:
id (uuid, obrigatório)Exemplo de resposta de sucesso (200)
{ "receipt": { "id": "3813f678-2ad7-4c68-9a39-55fa8780b323", "originalFilename": "rodas-pintadas", "filename": "rodas-pintadas-u3nd3Eiipi", "path": "uploads/rodas-pintadas-u3nd3Eiipi.jpeg", "extname": "jpeg", "refundId": "a0dfc724-5369-4962-9c95-4250f1d928fb", "createdAt": "2025-10-07T20:32:24.000+00:00", "updatedAt": "2025-10-07T20:32:33.000+00:00"
/receipts/{id} — Deleta um recibo específicoRemove um recibo. Essa rota também dispara a remoção do arquivo físico no sistema.
Path params:
id (uuid, obrigatório)Exemplo de resposta de sucesso (200)
{ "message": "receipt rodas-pintadas-UzS2-fsrEx deleted succesfully." }
/receipts/download/{id} — Gera uma URL assinada do recibo para downloadRetorna uma URL assinada do recibo, permitindo o download do arquivo caso o usuário queira. O link é válido por 60 segundos.
Path params:
id (uuid, obrigatório)Exemplo de resposta de sucesso (200)
Redireciona para a rota que exibe o arquivo binário
/refunds — Lista todos os reembolsosLista reembolsos de forma pagina, com busca textual pelo nome da solicitação.
Query params (opcional):
q (string) — termo de buscapage (number) - número da página da paginação.Exemplo de resposta de sucesso (200)
{ "refunds": { "meta": { "total": 1, "perPage": 10, "currentPage": 1, "lastPage": 1, "firstPage": 1, "firstPageUrl": "/?page=1", "lastPageUrl": "/?page=1",
/refunds/{id} — Lista reembolso específicoRetorna um reembolso específico.
Path params:
id (uuid, obrigatório)Exemplo de resposta de sucesso (200)
{ "refund": { "id": "a0dfc724-5369-4962-9c95-4250f1d928fb", "title": "Elias", "category": "hosting", "value": 0, "deletedAt": null, "createdAt": "2025-10-07T20:32:33.000+00:00", "updatedAt": "2025-10-07T20:32:33.000+00:00", "receipt": {
/refunds — Cria um reembolsoCria um novo reembolso associado a um recibo. É obrigatório o fornecimento do ID do recibo criado previamente.
Dica: recomendamos chamar a rota de criação do recibo assim que o usuário selecionar o arquivo, armazenar o ID e informá-lo no body dessa requisição juntamente com os outros campos.
Content-Type: application/jsontitle (string, obrigatório)category (string, obrigatório) — Precisa necessariamente atender a pelo menos um dos seguintes valores: food, hosting, transport, services, other.value (number, obrigatório) — valor do reembolso. Esse valor deve ser informado em centavos, ou seja, sem casas decimais.receipt (uuid, obrigatório) — ID do recibo associado{ "title": "Elias", "category": "hosting", "value": 50050, "receipt": "3813f678-2ad7-4c68-9a39-55fa8780b323" }
Exemplo de resposta de sucesso (200)
{ "refund": { "title": "Elias", "category": "hosting", "value": 50050, "id": "a87d7af3-0aad-457e-95d8-8b15edf496ec", "createdAt": "2025-10-07T21:31:23.569+00:00", "updatedAt": "2025-10-07T21:31:23.569+00:00", "receipt": { "id": "5c0d2fd6-95d6-4236-835f-dc44f93fb7d1",
/refunds/{id} — Remoção de um reembolso específicoRemove um reembolso.
id (uuid, obrigatório){ "message": "refund Elias deleted succesfully." }
Para desenvolver esse projeto, recomendamos utilizar as principais ferramentas que utilizamos durante o desenvolvimento do primeiro módulo da formação.
Caso você tenha alguma dificuldade você pode ir no nosso fórum e deixar sua dúvida por lá!
Após terminar o desafio, caso você queira, você pode tentar dar o próximo passo e deixar a aplicação com a sua cara. Tente mudar o layout, cores, ou até adicionar novas funcionalidades para ir além 🚀
Após concluir o desafio, você deve enviar a URL do seu código no Github.
Além disso, que tal fazer um post no LinkedIn compartilhando o seu aprendizado e contando como foi a experiência?
É uma excelente forma de demonstrar seus conhecimentos e atrair novas oportunidades!
Obs: Se você se sentir à vontade, pode postar um print do resultado final e nos marcar! Vai ser incrível acompanhar a sua evolução! 💜
Feito com 💜 por Rocketseat 👋
Construir um aplicativo de sistema de reembolso funcional, aplicando os seguintes pontos:
Para desenvolver esse projeto, recomendamos utilizar as principais ferramentas que utilizamos durante o desenvolvimento do projeto Álbum de fotos dessa formação.
Além disso, você deve consumir a API que preparamos para esse projeto, assim você pode se concentrar em desenvolver apenas a parte web frontend. Nas 2 próximas seções, abordaremos com mais detalhes sobre a estrutura e como utilizá-la.
Para que você consiga utilizar a API, é preciso baixar o código no repositório, seja clonando utilizando o comando git clone git@github.com:rocketseat-education/refund-api.git ou clicando na opção Download ZIP.
Após o download, você deve acessar a pasta do seu projeto e instalar as dependências com o comando npm i. Para executar o projeto, é preciso preparar o banco de dados primeiro. Para isso, execute o comando npm run db:prepare, isso criará o banco de dados SQLite. Por fim, para executar a aplicação basta executar o comando npm run dev.
Com isso, a sua API estará pronta para ser consumida no endereço http://localhost:3333.
A API desse desafio foi estruturada seguindo a opinião do framework Adonis. Porém, você não é obrigado a entender o framework/node para entender as rotas, pois documentaremos elas mais abaixo. Para interagir com o banco e API, sugerimos duas ferramentas para te auxiliar:
db.sqlite3 gerado na pasta tmp após a execução do comando npm run db:prepare.Base URL: http://localhost:3333
/receipts — Cria um reciboFaz upload de um comprovante/nota fiscal.
Headers: Content-Type: multipart/form-data
Body (multipart/form-data):
receiptFile (file, obrigatório) — arquivo do recibo (imagem/PDF)Exemplo de resposta de sucesso (200)
{ "receipt": { "originalFilename": "rodas-pintadas", "path": "/tmp/aii8m2goy0eyutg7ui07lz0i", "extname": "jpeg", "filename": "rodas-pintadas-u3nd3Eiipi", "id": "3813f678-2ad7-4c68-9a39-55fa8780b323", "createdAt": "2025-10-07T20:32:24.543+00:00", "updatedAt": "2025-10-07T20:32:24.543+00:00" }
/receipts/{id} — Lista um recibo específicoRetorna metadados de um recibo.
Path params:
id (uuid, obrigatório)Exemplo de resposta de sucesso (200)
{ "receipt": { "id": "3813f678-2ad7-4c68-9a39-55fa8780b323", "originalFilename": "rodas-pintadas", "filename": "rodas-pintadas-u3nd3Eiipi", "path": "uploads/rodas-pintadas-u3nd3Eiipi.jpeg", "extname": "jpeg", "refundId": "a0dfc724-5369-4962-9c95-4250f1d928fb", "createdAt": "2025-10-07T20:32:24.000+00:00", "updatedAt": "2025-10-07T20:32:33.000+00:00"
/receipts/{id} — Deleta um recibo específicoRemove um recibo. Essa rota também dispara a remoção do arquivo físico no sistema.
Path params:
id (uuid, obrigatório)Exemplo de resposta de sucesso (200)
{ "message": "receipt rodas-pintadas-UzS2-fsrEx deleted succesfully." }
/receipts/download/{id} — Gera uma URL assinada do recibo para downloadRetorna uma URL assinada do recibo, permitindo o download do arquivo caso o usuário queira. O link é válido por 60 segundos.
Path params:
id (uuid, obrigatório)Exemplo de resposta de sucesso (200)
Redireciona para a rota que exibe o arquivo binário
/refunds — Lista todos os reembolsosLista reembolsos de forma pagina, com busca textual pelo nome da solicitação.
Query params (opcional):
q (string) — termo de buscapage (number) - número da página da paginação.Exemplo de resposta de sucesso (200)
{ "refunds": { "meta": { "total": 1, "perPage": 10, "currentPage": 1, "lastPage": 1, "firstPage": 1, "firstPageUrl": "/?page=1", "lastPageUrl": "/?page=1",
/refunds/{id} — Lista reembolso específicoRetorna um reembolso específico.
Path params:
id (uuid, obrigatório)Exemplo de resposta de sucesso (200)
{ "refund": { "id": "a0dfc724-5369-4962-9c95-4250f1d928fb", "title": "Elias", "category": "hosting", "value": 0, "deletedAt": null, "createdAt": "2025-10-07T20:32:33.000+00:00", "updatedAt": "2025-10-07T20:32:33.000+00:00", "receipt": {
/refunds — Cria um reembolsoCria um novo reembolso associado a um recibo. É obrigatório o fornecimento do ID do recibo criado previamente.
Dica: recomendamos chamar a rota de criação do recibo assim que o usuário selecionar o arquivo, armazenar o ID e informá-lo no body dessa requisição juntamente com os outros campos.
Content-Type: application/jsontitle (string, obrigatório)category (string, obrigatório) — Precisa necessariamente atender a pelo menos um dos seguintes valores: food, hosting, transport, services, other.value (number, obrigatório) — valor do reembolso. Esse valor deve ser informado em centavos, ou seja, sem casas decimais.receipt (uuid, obrigatório) — ID do recibo associado{ "title": "Elias", "category": "hosting", "value": 50050, "receipt": "3813f678-2ad7-4c68-9a39-55fa8780b323" }
Exemplo de resposta de sucesso (200)
{ "refund": { "title": "Elias", "category": "hosting", "value": 50050, "id": "a87d7af3-0aad-457e-95d8-8b15edf496ec", "createdAt": "2025-10-07T21:31:23.569+00:00", "updatedAt": "2025-10-07T21:31:23.569+00:00", "receipt": { "id": "5c0d2fd6-95d6-4236-835f-dc44f93fb7d1",
/refunds/{id} — Remoção de um reembolso específicoRemove um reembolso.
id (uuid, obrigatório){ "message": "refund Elias deleted succesfully." }
Para desenvolver esse projeto, recomendamos utilizar as principais ferramentas que utilizamos durante o desenvolvimento do primeiro módulo da formação.
Caso você tenha alguma dificuldade você pode ir no nosso fórum e deixar sua dúvida por lá!
Após terminar o desafio, caso você queira, você pode tentar dar o próximo passo e deixar a aplicação com a sua cara. Tente mudar o layout, cores, ou até adicionar novas funcionalidades para ir além 🚀
Após concluir o desafio, você deve enviar a URL do seu código no Github.
Além disso, que tal fazer um post no LinkedIn compartilhando o seu aprendizado e contando como foi a experiência?
É uma excelente forma de demonstrar seus conhecimentos e atrair novas oportunidades!
Obs: Se você se sentir à vontade, pode postar um print do resultado final e nos marcar! Vai ser incrível acompanhar a sua evolução! 💜
Feito com 💜 por Rocketseat 👋
Use este checklist para ajudar a organizar a sua entrega