Rocketseat
Rocketseat
/
Projetos

Sistema de reembolso

FrontendFrontendIntermediárioIntermediário
ReactReactRest APIReact Query
Sistema de reembolso

Conheça o projeto

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.

Recursos

Materiais para você usar como base para o desenvolvimento

Exemplo de solução

Exemplo de solução

Link

Figma

Figma

Layout · Figma

API do Projeto

API do Projeto

Código · GitHub

Arquivo do Insomnia

Arquivo do Insomnia

Link · GitHub

Exemplo de solução

Exemplo de solução

Link

Figma

Figma

Layout · Figma

API do Projeto

API do Projeto

Código · GitHub

Arquivo do Insomnia

Arquivo do Insomnia

Link · GitHub

Instruções

Estrutura, regras e requisitos do projeto

1. Objetivo

Construir um aplicativo de sistema de reembolso funcional, aplicando os seguintes pontos:

  • Criação, listagem e exclusão de reembolsos.
  • Upload de recibo da solicitação.
  • Paginação da listagem de reembolsos.
  • Busca pelo nome do autor da solicitação.
  • Página de detalhes da solicitação.
  • Exibição do recibo enviado.
  • Consumo da API fornecida pela Rocketseat.

2. Conceitos e Regras

  1. Consumo de API
    • Utilizar Axios para chamadas HTTP.
    • Integrar com a API disponibilizada do desafio.
    • Integrar com React Query para melhor gerenciamento do estados assíncronos
    • Gerenciar erros e exibir mensagens de feedback para o usuário.
  2. Formulários
    • Utilizar React Hook Form para formulários, com validação.
    • Criar formulários para cadastro de reembolso.
  3. Imagem e Upload
    • Enviar um recibo em formato JPG, PNG ou PDF.
    • A imagem não deve ser maior do que 2mb.
  4. Funcionalidades do App
    • Home: página que lista reembolsos de forma paginada, com barra de busca.
    • Detalhes do Reembolso: página que exibe detalhes do reembolso. Nessa página deve ser possível exibir o recibo e excluir o reembolso.
    • Criar Reembolso: modal que exibe formulário com os seguintes campos: nome da solicitação, valor, categoria e arquivo do recibo.
    • Sucesso da solicitação: página que exibe uma mensagem de sucesso ao registrar o reembolso.
    • Confirmação de exlusão: modal que exibe uma confirmação se o usuário quer realmente apagar aquele reembolso.

3. Desenvolvendo o projeto

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.


3.1 Como utilizar a API?

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.

3.2 Estrutura da API

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:

  • Beekeeper: Recomendamos o uso do Beekeeper para visualização dos dados do banco de dados. Basta apontar para o arquivo db.sqlite3 gerado na pasta tmp após a execução do comando npm run db:prepare.
  • Insomnia: Caso queira interagir com a API de uma maneira bem direta e fácil, você pode utilizar um API Rest Client como o Insomnia. Basta executar o download dele e importar as configurações que disponibilizamos aqui. Dessa forma, você terá acesso a todas as rotas e poderá fazer as requisições diretamente por ele.

3.3 Rotas

Clique aqui para expandir

Refund API — Documentação da API

Base URL: http://localhost:3333

Receipts

POST /receipts — Cria um recibo

Faz 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" }

GET /receipts/{id} — Lista um recibo específico

Retorna 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"

DELETE /receipts/{id} — Deleta um recibo específico

Remove 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." }

GET /receipts/download/{id} — Gera uma URL assinada do recibo para download

Retorna 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

GET /refunds — Lista todos os reembolsos

Lista reembolsos de forma pagina, com busca textual pelo nome da solicitação.

  • Query params (opcional):

    • q (string) — termo de busca
    • page (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",

GET /refunds/{id} — Lista reembolso específico

Retorna 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": {

POST /refunds — Cria um reembolso

Cria 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.

  • Headers: Content-Type: application/json
  • Body (JSON):
    • title (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
  • Exemplo (body):
{ "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",

DELETE /refunds/{id} — Remoção de um reembolso específico

Remove um reembolso.

  • Path params:
    • id (uuid, obrigatório)
  • Exemplo de resposta de sucesso (200)
{ "message": "refund Elias deleted succesfully." }

4. Desenvolvendo o projeto

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 🚀


5. Entrega

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 👋

1. Objetivo

Construir um aplicativo de sistema de reembolso funcional, aplicando os seguintes pontos:

  • Criação, listagem e exclusão de reembolsos.
  • Upload de recibo da solicitação.
  • Paginação da listagem de reembolsos.
  • Busca pelo nome do autor da solicitação.
  • Página de detalhes da solicitação.
  • Exibição do recibo enviado.
  • Consumo da API fornecida pela Rocketseat.

2. Conceitos e Regras

  1. Consumo de API
    • Utilizar Axios para chamadas HTTP.
    • Integrar com a API disponibilizada do desafio.
    • Integrar com React Query para melhor gerenciamento do estados assíncronos
    • Gerenciar erros e exibir mensagens de feedback para o usuário.
  2. Formulários
    • Utilizar React Hook Form para formulários, com validação.
    • Criar formulários para cadastro de reembolso.
  3. Imagem e Upload
    • Enviar um recibo em formato JPG, PNG ou PDF.
    • A imagem não deve ser maior do que 2mb.
  4. Funcionalidades do App
    • Home: página que lista reembolsos de forma paginada, com barra de busca.
    • Detalhes do Reembolso: página que exibe detalhes do reembolso. Nessa página deve ser possível exibir o recibo e excluir o reembolso.
    • Criar Reembolso: modal que exibe formulário com os seguintes campos: nome da solicitação, valor, categoria e arquivo do recibo.
    • Sucesso da solicitação: página que exibe uma mensagem de sucesso ao registrar o reembolso.
    • Confirmação de exlusão: modal que exibe uma confirmação se o usuário quer realmente apagar aquele reembolso.

3. Desenvolvendo o projeto

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.


3.1 Como utilizar a API?

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.

3.2 Estrutura da API

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:

  • Beekeeper: Recomendamos o uso do Beekeeper para visualização dos dados do banco de dados. Basta apontar para o arquivo db.sqlite3 gerado na pasta tmp após a execução do comando npm run db:prepare.
  • Insomnia: Caso queira interagir com a API de uma maneira bem direta e fácil, você pode utilizar um API Rest Client como o Insomnia. Basta executar o download dele e importar as configurações que disponibilizamos aqui. Dessa forma, você terá acesso a todas as rotas e poderá fazer as requisições diretamente por ele.

3.3 Rotas

Clique aqui para expandir

Refund API — Documentação da API

Base URL: http://localhost:3333

Receipts

POST /receipts — Cria um recibo

Faz 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" }

GET /receipts/{id} — Lista um recibo específico

Retorna 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"

DELETE /receipts/{id} — Deleta um recibo específico

Remove 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." }

GET /receipts/download/{id} — Gera uma URL assinada do recibo para download

Retorna 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

GET /refunds — Lista todos os reembolsos

Lista reembolsos de forma pagina, com busca textual pelo nome da solicitação.

  • Query params (opcional):

    • q (string) — termo de busca
    • page (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",

GET /refunds/{id} — Lista reembolso específico

Retorna 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": {

POST /refunds — Cria um reembolso

Cria 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.

  • Headers: Content-Type: application/json
  • Body (JSON):
    • title (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
  • Exemplo (body):
{ "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",

DELETE /refunds/{id} — Remoção de um reembolso específico

Remove um reembolso.

  • Path params:
    • id (uuid, obrigatório)
  • Exemplo de resposta de sucesso (200)
{ "message": "refund Elias deleted succesfully." }

4. Desenvolvendo o projeto

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 🚀


5. Entrega

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 👋

Tarefas

Use este checklist para ajudar a organizar a sua entrega

0 de 11
Detalhes
Tipo de projetoDesafio prático
StatusNão iniciado
Sua entrega
React
React
Desafio prático da formação React

Acesse os módulos da formação para aprender os conceitos de aplicação deste projeto

Projetos relacionados