Interface web do e-commerce escalável. SPA React que consome microsserviços via gateway único. Cobre catálogo, carrinho/pedidos, estoque (admin), notificações e contas de usuário.
SPA renderizada no cliente. Roteamento por react-router-dom. Cada módulo de negócio (catalog, stock, order, user, notification) tem pasta própria em src/frontend/<modulo>/ com pages/, components/ e rotas locais (*Routes.tsx) montadas em App.tsx. Estilização via Tailwind CSS v4 (utility-first); sem biblioteca de componentes — componentes próprios em src/frontend/components/ (Toast, Modal, Header, etc.).
Elementos da tela:
- Header (topo): logo, navegação (Catálogo, Estoque, Pedidos), sino de notificações com badge, avatar do usuário.
- Cabeçalho da página: título "Estoque" e botão primário "+ Novo item".
- Busca: input full-width filtrando por SKU, nome ou código.
- Tabela: imagem | produto (nome + código + tamanho) | SKU (clicável para copiar) | Disponível | Reservado | Custo (BRL) | Ações (Reabastecer, Ajustar, Histórico).
- Modais: Novo item (SKU UUID, quantidade, custo), Reabastecer (quantidade), Ajustar (delta, motivo).
- Drawer lateral (Histórico): lista de movimentos com tipo, quantidade com sinal, data e — quando aplicável — pedido associado ou motivo.
Como implementar:
- Página em
src/frontend/stock/pages/stockListPage.tsx. - Tabela alimentada por
GET /stock/detailed-itemsviastockClientService.getAllStockItemsDetailed(). - Busca client-side com
useMemofiltrando porskuId,product.name,product.code. - Modais (
CreateStockModal,RestockModal,AdjustModal) controlados por estado local;onSuccessrecebe oStockItematualizado e faz merge na lista sem refetch. - Histórico como
HistoryDrawer(overlay + painel à direita); carrega viaGET /stock/{skuId}/historyao abrir.
| Item | Definição |
|---|---|
| Cores | Tailwind defaults: slate-* (texto/bg), indigo-600 (primary), emerald-500 (sucesso), rose-500 (erro/perigo), amber-500 (alerta). |
| Tipografia | Stack system-ui, sans-serif. Pesos: 400 corpo, 600 títulos, 700 hero. Tamanhos via escala Tailwind (text-sm a text-3xl). |
| Ícones | react-icons (Feather/Heroicons via Fi*). |
| Layout | Container central max-w-7xl mx-auto px-4. Cards rounded-2xl shadow-sm. Modais via portal próprio, overlay bg-black/40. |
| Moeda/data | Intl.NumberFormat('pt-BR', {style:'currency',currency:'BRL'}), Intl.DateTimeFormat('pt-BR'). |
| Feedback | Toast (components/Toast.tsx) com tipos success/error/info, auto-dismiss. |
Como implementar: classes utilitárias Tailwind direto no JSX. Sem CSS custom além de index.css (reset + variáveis Tailwind v4). Tokens visuais consistentes via reuso de classes (btn-primary, etc.) — não há config de tema custom; valores literais.
React (browser)
│
│ fetch → VITE_API_URL
▼
Gateway Nginx — roteia por prefixo de URL
│
├─► /api/catalog/* → catalogapi
├─► /api/stock/* → stockapi
├─► /api/orders/* → orderapi ──► reserve/confirm/release em stockapi
├─► /api/users/* → usersapi
├─► /api/auth/* → usersapi
└─► /api/notifications/* → notificationworker
Estado no cliente:
- useState/useEffect locais por página (sem Redux/Zustand).
- Sessão (token + perfil) em LocalStorage, lido por authHeader().
Como implementar:
- Camada de acesso em
src/frontend/services/*ClientService.ts(um por domínio). Todas usamHttpClient(services/httpClient.ts) que injeta base URL, headers e faz parse de erro. VITE_API_URLdefinido em.envaponta para o gateway. Frontend não conhece serviços individuais — só fala com o gateway.- Autenticação:
authHeader()lê token do storage e devolve{ Authorization: 'Bearer ...' }. - Erros do backend chegam como JSON
{error, message}—HttpClientlançaErrorcom a mensagem; páginas exibem via Toast.
| Camada | Tecnologia | Por quê |
|---|---|---|
| UI framework | React 19 | Equipe familiar; ecossistema maduro. |
| Build/dev | Vite 8 | HMR rápido, build leve, TS nativo. |
| Linguagem | TypeScript 5 | Tipos compartilhados com DTOs do backend. |
| Roteamento | react-router-dom 7 | Rotas aninhadas por módulo. |
| Estilo | Tailwind CSS 4 (@tailwindcss/vite) |
Utility-first; zero CSS custom relevante. |
| Ícones | react-icons | Cobertura ampla (Feather, Hero, etc.). |
| HTTP | fetch nativo + wrapper HttpClient |
Sem dependência extra (axios). |
| Lint | ESLint 10 + typescript-eslint | Regras hooks/refresh. |
| Gateway | Nginx (containerizado) | Único host:porta para a SPA; CORS evitado. |
Como implementar: cd src/frontend && npm install && npm run dev (porta 3000 ou 3001). Build de produção: npm run build (gera dist/).
| Tópico | Estado atual / como implementar |
|---|---|
| Autenticação | POST /auth/login → token JWT salvo em LocalStorage. authHeader() injeta em chamadas autenticadas. |
| Autorização | Rotas admin (/stock, /admin/usuarios) protegidas por RequireAuth/RequireAdmin (HOC em user/) que checam role do perfil decodificado. |
| Transporte | HTTPS obrigatório em produção (terminação no gateway). Em dev usa HTTP local. |
| CORS | Gateway expõe single-origin → sem CORS cross-domain no browser. |
| XSS | React faz escape automático em {}; evitar dangerouslySetInnerHTML. Nenhum uso atual. |
| Storage de token | LocalStorage (aceitável para projeto acadêmico). Migrar para cookie httpOnly em produção. |
| Validação | Client valida campos antes de submit (CPF, e-mail, senha ≥ 8); backend revalida. |
| Erros sensíveis | Mensagens do backend exibidas via Toast sem stack trace; logs detalhados ficam no servidor. |
Atualmente a aplicação roda apenas em ambiente local via Docker Compose. Implantação em produção (provedor de nuvem, domínio público, HTTPS) ainda não foi configurada e está fora do escopo desta etapa.
Execução local:
- Pré-requisitos: Docker Desktop e Node.js 20+ instalados.
- Na raiz do repositório, subir o stack completo:
Isso sobe gateway, banco, serviços de backend e RabbitMQ.
cd src docker compose up -d - Em outro terminal, rodar o frontend em modo dev (HMR):
cd src/frontend npm install npm run dev - Acessar a aplicação no endereço informado pelo Vite (
http://localhost:3000ou:3001). - Build de produção local (gera
dist/):npm run build
Verificação após subir:
- Login com usuário cadastrado.
- Abrir
/productse confirmar que a lista carrega. - Abrir
/stockcomo admin e confirmar que itens aparecem. - Adicionar item ao carrinho e finalizar pedido.
Testes funcionais manuais executados em ambiente local, cobrindo as interações do módulo de Estoque (Stock) no frontend web. Cada caso descreve apenas o caminho feliz. Validações de entrada, mensagens de erro, estados vazios, autenticação, performance, segurança e automação ficam fora deste escopo.
Origem: src/frontend/stock/, src/frontend/services/stockClientService.ts. Página única em /stock.
| ID | Interação | Componente | API back-end |
|---|---|---|---|
| I1 | Listar itens com dados de produto | stockListPage.tsx |
GET /stock/detailed-items |
| I2 | Buscar item por SKU/nome/código | stockListPage.tsx (filtro client-side) |
— |
| I3 | Copiar SKU para clipboard | stockListPage.tsx (handleCopy) |
— |
| I4 | Criar item de estoque | CreateStockModal.tsx |
POST /stock |
| I5 | Reabastecer item | RestockModal.tsx |
PUT /stock/{skuId}/restock |
| I6 | Ajustar item (delta + motivo) | AdjustModal.tsx |
PUT /stock/{skuId}/adjust |
| I7 | Visualizar histórico de movimentos | HistoryDrawer.tsx |
GET /stock/{skuId}/history |
- Pré-condições:
- Back-end ativo.
- Há ≥ 1 item cadastrado.
- Passos:
- Abrir
/stock.
- Abrir
- Resultado esperado:
- Tabela exibe colunas: Produto, SKU, Disponível, Reservado, Custo, Ações.
- Cada linha mostra imagem, nome, código/tamanho, quantidades e custo formatado em BRL.
- Evidência:

- Pré-condições:
- Lista carregada com ≥ 2 itens de SKUs distintos.
- Passos:
- Digitar um trecho do SKU de um item no campo de busca.
- Resultado esperado:
- Tabela mantém apenas linhas cujo SKU contém o trecho informado.
- Evidência:

- Pré-condições:
- Lista carregada.
- Passos:
- Digitar parte do nome de um produto no campo de busca.
- Resultado esperado:
- Tabela exibe apenas itens cujo nome contém o trecho.
- Evidência:

- Pré-condições:
- Lista carregada com produtos que possuem
SKUdefinido.
- Lista carregada com produtos que possuem
- Passos:
- Digitar parte de um código no campo de busca.
- Resultado esperado:
- Tabela exibe apenas itens cujo código contém o trecho.
- Evidência:

- Pré-condições:
- Filtro ativo na busca.
- Passos:
- Apagar o conteúdo do campo de busca.
- Resultado esperado:
- Tabela retorna ao conjunto completo de itens.
- Evidência:

- Pré-condições:
- Lista carregada.
- Passos:
- Clicar sobre o SKU exibido em uma linha.
- Resultado esperado:
- Conteúdo do SKU é gravado no clipboard do sistema.
- Evidência:

- Pré-condições:
- Existe SKU UUID válido sem item de estoque associado.
- Passos:
- Clicar em Novo item.
- Informar o SKU UUID válido.
- Definir Quantidade inicial =
10. - Definir Custo =
40. - Clicar em Criar.
- Resultado esperado:
- Modal fecha.
- Lista é recarregada e exibe o novo item com
quantityAvailable = 10e custo R$ 19,90.
- Evidência:

- Pré-condições:
- Item de estoque existente com
quantityAvailable = N.
- Item de estoque existente com
- Passos:
- Na linha do item, clicar em Reabastecer.
- Definir Quantidade =
5. - Clicar em Reabastecer.
- Resultado esperado:
- Modal fecha.
- Linha do item passa a exibir
quantityAvailable = N + 5.
- Evidência:

- Pré-condições:
- Item com
quantityAvailable = N.
- Item com
- Passos:
- Na linha do item, clicar em Ajustar.
- Definir Delta =
+3. - Informar Motivo =
entrada extra de fornecedor. - Clicar em Ajustar.
- Resultado esperado:
- Modal fecha.
- Linha do item passa a exibir
quantityAvailable = N + 3.
- Evidência:

- Pré-condições:
- Item com
quantityAvailable ≥ 2.
- Item com
- Passos:
- Na linha do item, clicar em Ajustar.
- Definir Delta =
-2. - Informar Motivo =
contagem física. - Clicar em Ajustar.
- Resultado esperado:
- Modal fecha.
- Linha do item passa a exibir
quantityAvailable = N - 2.
- Evidência:

- Pré-condições:
- Item com ≥ 1 movimento registrado.
- Passos:
- Na linha do item, clicar em Histórico.
- Resultado esperado:
- Drawer lateral abre.
- Lista exibe cada movimento com tipo, quantidade (com sinal) e data formatada em pt-BR.
- Evidência:

- Pré-condições:
- Existe movimento
reserve,releaseouconfirmcomorderIdpreenchido.
- Existe movimento
- Passos:
- Abrir o histórico do SKU correspondente.
- Resultado esperado:
- Item do histórico exibe a linha
Pedido: <uuid>.
- Item do histórico exibe a linha
- Evidência:

- Pré-condições:
- Existe movimento de
adjustmentcomreasonpreenchido.
- Existe movimento de
- Passos:
- Abrir o histórico do SKU correspondente.
- Resultado esperado:
- Item do histórico exibe a linha
Motivo: <texto>.
- Item do histórico exibe a linha
- Evidência:

- Pré-condições:
- Existem movimentos de tipos distintos no SKU.
- Passos:
- Abrir o histórico.
- Resultado esperado:
- Cada movimento exibe o rótulo PT-BR correspondente: Reserva, Liberação, Confirmação, Reabastecimento, Ajuste.
- Evidência:

Origem: src/frontend/order/, src/frontend/services/orderApi.js
Páginas: /CartPage, /CheckoutPage, /OrdersPage, /orders/:id
| ID | Interação | Componente | API back-end |
|---|---|---|---|
| I12 | Visualizar itens do carrinho | CartPage.tsx |
GET /cart |
| I13 | Adicionar item ao carrinho | ProductPage.tsx |
POST /cart/items |
| I14 | Remover item do carrinho | CartPage.tsx |
DELETE /cart/items/{id} |
| I15 | Alterar quantidade do item | CartPage.tsx |
PUT /cart/items/{id} |
| I16 | Finalizar compra (checkout) | CheckoutPage.tsx |
POST /orders |
| I17 | Listar pedidos do usuário | OrdersPage.tsx |
GET /orders/user/{userId} |
| I18 | Visualizar detalhes do pedido | OrderDetailsPage.tsx |
GET /orders/{id} |
| I19 | Cancelar pedido | OrderDetailsPage.tsx |
POST /orders/{id}/cancel |
-
Pré-condições:
- Carrinho possui ≥ 1 item.
-
Passos:
- Acessar
/CartPage.
- Acessar
-
Resultado esperado:
- Lista de itens exibida contendo:
- Imagem do produto
- Nome
- Preço unitário
- Quantidade
- Subtotal por item
- Total geral do carrinho calculado corretamente.
- Lista de itens exibida contendo:
-
Pré-condições:
- Carrinho sem itens.
-
Passos:
- Acessar
/CartPage.
- Acessar
-
Resultado esperado:
- Mensagem de carrinho vazio exibida.
- Botão “Voltar as compras” visível.
-
Pré-condições:
- Produto disponível.
-
Passos:
- Acessar
frontend/catalog/pages/ProductPage. - Selecionar a quantidade, cor e tamanho do produto.
- Clicar em Adicionar ao carrinho.
- Acessar
-
Resultado esperado:
- Produto adicionado ao carrinho.
- Carrinho atualizado em tempo real.
- Modal informando que o produto foi adicionado ao carrinho
- Modal exibe botões "Ver carrinho" e "Continuar comprando"
-
Pré-condições:
- Produto já presente no carrinho.
-
Passos:
- Clicar novamente em Adicionar ao carrinho.
-
Resultado esperado:
- Quantidade do item é incrementada.
- Nenhum item duplicado é criado.
-
Pré-condições:
- Carrinho possui ≥ 1 item.
-
Passos:
- Acessar
/CartPage. - Clicar no ícone de lixeira.
- Confirmar remoção no modal.
- Acessar
-
Resultado esperado:
- Item removido da lista.
- Total recalculado corretamente.
- UI atualizada imediatamente.
-
Pré-condições:
- Modal de confirmação aberto.
-
Passos:
- Clicar em Cancelar ou fora do modal.
-
Resultado esperado:
- Modal fechado.
- Nenhuma alteração no carrinho.
-
Pré-condições:
- Carrinho possui ≥ 1 item.
-
Passos:
- Clicar em +.
-
Resultado esperado:
- Quantidade incrementada.
- Subtotal atualizado.
- Total recalculado.
-
Pré-condições:
- Quantidade ≥ 2.
-
Passos:
- Clicar em -.
-
Resultado esperado:
- Quantidade reduzida.
- Não permite valor menor que 1.
- Totais atualizados corretamente.
-
Pré-condições:
- Quantidade = 1.
-
Passos:
- Clicar em -.
-
Resultado esperado:
- Quantidade não é alterada.
- Nenhum erro exibido.
-
Pré-condições:
- Carrinho possui ≥ 2 itens.
-
Passos:
- Clicar em botão "check".
-
Resultado esperado:
- Quantidade decrementada.
- Subtotal atualizado.
- Total recalculado.
-
Pré-condições:
- Quantidade = 1.
-
Passos:
- Clicar em botão "check".
-
Resultado esperado:
- Quantidade decrementada.
- Subtotal atualizado.
- Total recalculado.
- Impossibilidade de proseguir para o checkout.
-
Pré-condições:
- Usuário autenticado.
- Carrinho possui ≥ 1 item.
- Botão "check" marcado em
/CartPage
-
Passos:
- Acessar
/CheckoutPage. - Preencher formulário de informações pessoais.
- Confirmar compra.
- Acessar
-
Resultado esperado:
- Pedido criado.
- Modal exibe mensagem "Pedido realizado com sucesso!"
- Item comprado é removido automaticamente de
CartPagee enviado paraOrdersPage. - Usuário redirecionado para
/OrdersPage.
-
Pré-condições:
- Carrinho vazio.
-
Passos:
- Tentar acessar
/checkout.
- Tentar acessar
-
Resultado esperado:
- Usuário impedido de continuar.
- Redirecionamento ou mensagem de aviso.
-
Pré-condições:
- Usuário autenticado.
- Usuário possui ≥ 1 pedidos.
-
Passos:
- Acessar
/OrdersCard.
- Acessar
-
Resultado esperado:
- Lista exibida contendo:
- ID do pedido
- Data
- Status
- Valor total
- Lista exibida contendo:
-
Pré-condições:
- Usuário autenticado.
- Usuário sem pedidos.
-
Passos:
- Acessar
/OrdersCard.
- Acessar
-
Resultado esperado:
- Mensagem “Você não tem pedidos.”.
- Exibição de botão "voltar a pagina inicial".
-
Pré-condições:
- Usuário autenticado.
- Usuário sem pedidos.
- Pedido com status diferente de "Entregue".
-
Passos:
- Acessar
/OrdersCard. - Clicar em "cancelar pedido"
- Confirmar cancelamento de pedido
- Acessar
-
Resultado esperado:
- Pedido removido.
- Pagina atualizada.
-
Pré-condições:
- Usuário autenticado.
- Pedido com status "Entregue".
-
Passos:
- Acessar
/OrdersCard. - Clicar em "cancelar pedido"
- Acessar
-
Resultado esperado:
- Exibição de mensagem "Pedidos já entregues não podem ser cancelados.".
-
Pré-condições:
- Usuário autenticado.
- Pedido já cancelado.
-
Passos:
- Acessar
/OrdersCard. - Clicar em "Excluir pedido"
- Acessar
-
Resultado esperado:
- Pedido é removida da lista de cancelados.
- Pagina atualizada.
Origem: src/frontend/catalog/pages/ProductsPage.jsx,
src/frontend/services/api.js. Página em /products.
| ID | Interação | Componente | API back-end |
|---|---|---|---|
| I19 | Listar e filtrar produtos | ProductsPage.jsx |
GET /catalog/products?name=&categoryId=&minPrice=&maxPrice= |
| I20 | Criar produto | ProductModal (admin) |
POST /catalog/products |
| I21 | Editar produto | ProductModal (admin) |
PUT /catalog/products/{id} |
| I22 | Deletar produto | ConfirmModal (admin) |
DELETE /catalog/products/{id} |
- Pré-condições:
- Back-end ativo.
- Há ≥ 1 produto cadastrado.
- Passos:
- Abrir
/products.
- Abrir
- Resultado esperado:
- Cards de produto são exibidos com: imagem, categoria, nome, descrição resumida e preço a partir de (formatado em BRL).
- Contador de resultados é exibido acima da grade.
- Pré-condições:
- Lista carregada com ≥ 2 produtos de nomes distintos.
- Passos:
- Digitar parte do nome de um produto no campo "Buscar por nome...".
- Clicar em Filtrar.
- Resultado esperado:
- A grade exibe apenas produtos cujo nome contém o trecho informado.
- Pré-condições:
- Lista carregada com produtos de categorias distintas.
- Passos:
- Selecionar uma categoria no campo de seleção.
- Clicar em Filtrar.
- Resultado esperado:
- A grade exibe apenas produtos pertencentes à categoria selecionada.
- Pré-condições:
- Existem produtos com preços variados.
- Passos:
- Informar Preço mínimo e Preço máximo.
- Clicar em Filtrar.
- Resultado esperado:
- A grade exibe apenas produtos com ao menos um SKU cujo preço está dentro da faixa informada.
- Pré-condições:
- Filtros ativos com resultados parciais.
- Passos:
- Clicar em Limpar.
- Resultado esperado:
- Campos de filtro são resetados e a lista completa de produtos é recarregada.
- Pré-condições:
- Usuário autenticado com perfil
admin.
- Usuário autenticado com perfil
- Passos:
- Clicar em + Novo Produto.
- Preencher Nome, Descrição, URL da imagem e selecionar uma Categoria.
- Clicar em Criar produto.
- Resultado esperado:
- Modal fecha.
- Novo card do produto aparece no início da grade sem recarregar a página.
- Pré-condições:
- Usuário autenticado com perfil
admin. - Há ≥ 1 produto cadastrado.
- Usuário autenticado com perfil
- Passos:
- Passar o cursor sobre o card do produto — botões Editar e Deletar ficam visíveis.
- Clicar em Editar.
- Alterar ao menos um campo (ex.: nome).
- Clicar em Salvar alterações.
- Resultado esperado:
- Modal fecha.
- Card do produto na grade reflete os novos dados sem recarregar a página.
- Pré-condições:
- Usuário autenticado com perfil
admin. - Há ≥ 1 produto cadastrado.
- Usuário autenticado com perfil
- Passos:
- Passar o cursor sobre o card do produto.
- Clicar em Deletar.
- Clicar em Deletar no modal de confirmação.
- Resultado esperado:
- Modal de confirmação fecha.
- Card do produto é removido da grade imediatamente.
- Pré-condições:
- Modal de confirmação de exclusão aberto.
- Passos:
- Clicar em Cancelar ou na área escurecida fora do modal.
- Resultado esperado:
- Modal fecha.
- Produto permanece na grade.
Origem: src/frontend/catalog/pages/CategoriesPage.jsx,
src/frontend/services/api.js. Página em /categories.
Testes — Módulo de Catálogo: Categorias Mapeamento de interações Origem: src/frontend/catalog/pages/CategoriesPage.jsx, src/frontend/services/api.js. Página em /categories.
| ID | Interação | Componente | API back-end |
|---|---|---|---|
| I23 | Listar categorias | CategoriesPage.jsx |
GET /catalog/categories |
| I24 | Listar produtos das categorias | CategoriesPage.jsx |
GET /products?categoryId={id} |
| I25 | Criar categoria | CategoriesPage.jsx |
POST /catalog/categories |
| I26 | Editar categoria | CategoriesPage.jsx |
PUT /catalog/categories/{id} |
| I27 | Deletar categoria | CategoriesPage.jsx |
DELETE /catalog/categories/{id} |
- Pré-condições:
- Back-end ativo.
- Há ≥ 1 categoria cadastrada.
- Passos:
- Abrir
/categories.
- Abrir
- Resultado esperado:
- Grade exibe cartões com nome e descrição (quando disponível) de cada categoria.
- Cada cartão exibe o link Ver produtos →.
- Pré-condições:
- Página
/categoriescarregada com ≥ 1 categoria.
- Página
- Passos:
- Clicar em qualquer cartão de categoria.
- Resultado esperado:
- Navegação para
/products?categoryId={id}da categoria selecionada. - Página de produtos abre já filtrada pela categoria correspondente.
- Navegação para
- Pré-condições:
- Back-end ativo.
- Passos:
- Clicar em + Nova Categoria.
- Preencher Nome =
Calçados. - Preencher Descrição =
Tênis, sapatos e sandálias. - Clicar em Criar categoria.
- Resultado esperado:
- Modal fecha.
- Grid é atualizado e exibe o novo card
Calçadosno topo.
- Pré-condições:
- Modal de criação aberto.
- Passos:
- Deixar o campo Nome vazio.
- Clicar em Criar categoria.
- Resultado esperado:
- Mensagem de erro "Nome é obrigatório." exibida; modal permanece aberto.
- Pré-condições:
- Lista carregada com ≥ 1 categoria.
- Passos:
- Passar o cursor sobre um card para revelar os botões de ação.
- Clicar em Editar.
- Alterar o nome para
Acessórios. - Clicar em Salvar alterações.
- Resultado esperado:
- Modal fecha.
- Card exibe o nome atualizado
Acessórios.
- Pré-condições:
- Lista carregada com ≥ 1 categoria.
- Passos:
- Passar o cursor sobre um card para revelar os botões de ação.
- Clicar em Deletar.
- Confirmar no modal de confirmação.
- Resultado esperado:
- Modal fecha.
- Card removido do grid.
- Pré-condições:
- Modal de confirmação de exclusão aberto.
- Passos:
- Clicar em Cancelar.
- Resultado esperado:
- Modal fecha sem alterações no grid.
Origem: src/frontend/user/pages/, src/frontend/services/userApi.ts.
| ID | Interação | Componente | API back-end |
|---|---|---|---|
| I25 | Login com e-mail e senha | LoginPage.tsx |
POST /auth/login |
| I26 | Cadastro de novo usuário | RegisterPage.tsx |
POST /auth/register |
| I27 | Visualizar perfil | ProfilePage.tsx |
GET /users/{id} |
| I28 | Editar dados pessoais e endereço | EditProfilePage.tsx |
PUT /users/{id} |
| I29 | Alterar senha | ChangePasswordPage.tsx |
PUT /users/{id}/password |
| I30 | Desativar conta | ProfilePage.tsx |
DELETE /users/{id} |
| I31 | Listar todos os usuários (admin) | AdminUsersPage.tsx |
GET /admin/users |
| I32 | Desativar / reativar usuário (admin) | AdminUsersPage.tsx |
DELETE /users/{id} / PUT /users/{id}/reactivate |
| I33 | Excluir usuário permanentemente (admin) | AdminUsersPage.tsx |
DELETE /admin/users/{id}/hard |
- Pré-condições:
- Usuário cadastrado e ativo no sistema.
- Passos:
- Acessar
/login. - Preencher e-mail e senha corretos.
- Clicar em Entrar.
- Acessar
- Resultado esperado:
- Usuário é autenticado e redirecionado para
/products. - Header exibe avatar e nome do usuário.
- Usuário é autenticado e redirecionado para
- Pré-condições:
- Página de login aberta.
- Passos:
- Preencher e-mail correto e senha errada.
- Clicar em Entrar.
- Resultado esperado:
- Mensagem de erro exibida abaixo do formulário.
- Usuário permanece na página de login.
- Pré-condições:
- Página de login aberta.
- Passos:
- Digitar um e-mail com formato inválido (ex.:
usuario@). - Sair do campo (blur).
- Digitar um e-mail com formato inválido (ex.:
- Resultado esperado:
- Ícone de erro exibido no campo e-mail.
- Mensagem de validação visível antes de submeter o formulário.
- Pré-condições:
- Usuário já autenticado.
- Passos:
- Tentar acessar
/logindiretamente pela URL.
- Tentar acessar
- Resultado esperado:
- Sistema redireciona automaticamente para
/products.
- Sistema redireciona automaticamente para
- Pré-condições:
- Nenhuma conta com o e-mail informado existe.
- Passos:
- Acessar
/cadastro. - Passo 1: preencher nome (≥ 3 chars), e-mail válido, senha (≥ 8 chars).
- Clicar em Continuar.
- Passo 2: preencher CPF e telefone (opcionais) ou prosseguir em branco.
- Clicar em Criar conta.
- Acessar
- Resultado esperado:
- Conta criada com sucesso.
- Usuário é autenticado e redirecionado para
/products.
- Pré-condições:
- Passo 2 do cadastro visível.
- Passos:
- Digitar 11 dígitos no campo CPF.
- Resultado esperado:
- Campo exibe automaticamente o formato
000.000.000-00.
- Campo exibe automaticamente o formato
- Pré-condições:
- Passo 2 do cadastro visível.
- Passos:
- Digitar 11 dígitos no campo Telefone.
- Resultado esperado:
- Campo exibe automaticamente o formato
(00) 00000-0000.
- Campo exibe automaticamente o formato
- Pré-condições:
- Campo Senha no passo 1 visível.
- Passos:
- Digitar senhas de diferentes complexidades (só letras, com número, com símbolo).
- Resultado esperado:
- Barra de força muda de cor e nível (fraca → média → forte) conforme a complexidade.
- Pré-condições:
- Usuário autenticado.
- Passos:
- Acessar
/perfil.
- Acessar
- Resultado esperado:
- Hero exibe nome, e-mail, data de membro e iniciais do avatar.
- Strip de estatísticas exibe CPF, telefone e cidade (ou
—se não informado). - Cards exibem dados pessoais, endereço, segurança e zona de perigo.
- Pré-condições:
- Usuário não autenticado.
- Passos:
- Tentar acessar
/perfildiretamente pela URL.
- Tentar acessar
- Resultado esperado:
- Sistema redireciona para
/login.
- Sistema redireciona para
- Pré-condições:
- Usuário autenticado em
/perfil/editar.
- Usuário autenticado em
- Passos:
- Alterar o campo Nome completo.
- Alterar o campo E-mail.
- Clicar em Salvar alterações.
- Resultado esperado:
- Toast de sucesso exibido.
- Botão Salvar muda para Salvo! com ícone de check.
- Usuário é redirecionado para
/perfilapós 1,6 s. - Header reflete o novo nome imediatamente.
- Pré-condições:
- Formulário de edição aberto.
- Passos:
- Digitar 8 dígitos no campo CEP.
- Resultado esperado:
- Campo exibe automaticamente o formato
00000-000.
- Campo exibe automaticamente o formato
- Pré-condições:
- Usuário autenticado em
/perfil/senha.
- Usuário autenticado em
- Passos:
- Preencher Senha atual corretamente.
- Preencher Nova senha (≥ 8 chars).
- Repetir a nova senha em Confirmar nova senha.
- Clicar em Salvar nova senha.
- Resultado esperado:
- Toast de sucesso exibido.
- Formulário é resetado.
- Pré-condições:
- Formulário de alteração de senha aberto.
- Passos:
- Preencher Nova senha e Confirmar nova senha com valores diferentes.
- Clicar em Salvar nova senha.
- Resultado esperado:
- Mensagem de erro indicando que as senhas não coincidem.
- Requisição não é enviada ao back-end.
- Pré-condições:
- Usuário autenticado na página
/perfil.
- Usuário autenticado na página
- Passos:
- Clicar em Desativar minha conta.
- Confirmar no modal clicando em Confirmar.
- Resultado esperado:
- Toast de sucesso exibido.
- Usuário é deslogado e redirecionado para
/loginapós 2 s.
- Pré-condições:
- Modal de confirmação aberto.
- Passos:
- Clicar em Cancelar.
- Resultado esperado:
- Modal fecha sem nenhuma ação.
- Conta permanece ativa.
- Pré-condições:
- Usuário autenticado com perfil
admin.
- Usuário autenticado com perfil
- Passos:
- Acessar
/admin/usuarios.
- Acessar
- Resultado esperado:
- Hero exibe estatísticas: total, ativos, inativos e admins.
- Tabela lista todos os usuários com nome, e-mail, CPF, telefone, cargo e status.
- Pré-condições:
- Lista carregada com usuários ativos e inativos.
- Passos:
- Clicar na aba Ativos.
- Resultado esperado:
- Tabela exibe apenas usuários com status ativo.
- Toast exibe contagem:
Exibindo N usuários ativos.
- Pré-condições:
- Lista carregada.
- Passos:
- Digitar parte do nome ou e-mail no campo de busca.
- Resultado esperado:
- Tabela filtra em tempo real exibindo apenas os registros correspondentes.
- Pré-condições:
- Página de admin carregada.
- Passos:
- Clicar no botão Atualizar.
- Resultado esperado:
- Ícone do botão gira enquanto carrega.
- Toast de sucesso exibe o total de usuários carregados.
- Pré-condições:
- Admin autenticado. Há ao menos 1 usuário ativo na lista.
- Passos:
- Clicar em Desativar na linha do usuário.
- Confirmar no modal.
- Resultado esperado:
- Status do usuário muda para Inativo na tabela sem recarregar a página.
- Toast de sucesso exibido.
- Pré-condições:
- Admin autenticado. Há ao menos 1 usuário inativo.
- Passos:
- Clicar na aba Inativos.
- Clicar em Reativar na linha do usuário.
- Confirmar no modal.
- Resultado esperado:
- Status muda para Ativo na tabela.
- Toast de sucesso exibido.
- Pré-condições:
- Admin autenticado. Há ao menos 1 usuário na lista.
- Passos:
- Clicar no ícone de lixeira (excluir) na linha do usuário.
- Ler o aviso de ação irreversível no modal.
- Clicar em Excluir permanentemente.
- Resultado esperado:
- Usuário é removido da tabela imediatamente.
- Toast de sucesso exibido.
- Estatísticas do hero são atualizadas.
- Pré-condições:
- Usuário autenticado com perfil
customer.
- Usuário autenticado com perfil
- Passos:
- Tentar acessar
/admin/usuariospela URL.
- Tentar acessar
- Resultado esperado:
- Sistema redireciona para
/.
- Sistema redireciona para
Inclua todas as referências (livros, artigos, sites, etc) utilizados no desenvolvimento do trabalho.
Origem: src/frontend/notification/, src/services/notification/Program.cs
Página principal: /notifications
| ID | Interação | Componente | API back-end |
|---|---|---|---|
| I8 | Listar notificações do usuário | NotificationPage.tsx |
GET /api/notifications |
| I9 | Exibir contador de não lidas (Badge) | NotificationBell.jsx |
GET /api/notifications/unread-count |
| I10 | Marcar todas as notificações como lidas | NotificationPage.tsx |
PUT /api/notifications/mark-all-read |
| I11 | Redirecionamento para a central | Header (sino) |
— |
Observação: A implementação atual marca todas as notificações como lidas de uma vez (
mark-all-read), não individualmente.
- Pré-condições:
- Back-end (
NotificationService) ativo emhttp://localhost:5000. - Ao menos uma notificação registrada no banco.
- Back-end (
- Passos:
- Abrir a página
/notifications.
- Abrir a página
- Resultado esperado:
- A tela exibe cards com: Título, Mensagem, Data de recebimento e Tipo (
info,success,warning). - Notificações não lidas possuem destaque visual com ponto azul e opacidade plena.
- Notificações lidas aparecem com opacidade reduzida (60%).
- O rodapé do card exibe a data/hora formatada em pt-BR.
- A tela exibe cards com: Título, Mensagem, Data de recebimento e Tipo (
- Pré-condições:
- Back-end ativo.
- Página
/notificationsaberta no navegador.
- Passos:
- Sem recarregar a página, disparar uma nova notificação via
POST /api/demo/payment. - Aguardar até 5 segundos.
- Sem recarregar a página, disparar uma nova notificação via
- Resultado esperado:
- O novo card aparece automaticamente no topo da lista sem necessidade de recarregar a página.
- O texto "Atualizado às HH:MM:SS · atualiza a cada 5s" é atualizado.
- Pré-condições:
- Back-end inativo.
- Passos:
- Abrir a página
/notificationscom o serviço parado.
- Abrir a página
- Resultado esperado:
- Exibe mensagem de erro:
⚠ Sem conexão com o servidor. Tentando reconectar... - Notificações previamente carregadas permanecem visíveis (não são apagadas).
- Exibe mensagem de erro:
- Pré-condições:
- Back-end ativo.
- Usuário possui ≥ 1 notificação não lida.
- Passos:
- Observar o ícone de sino no cabeçalho em qualquer página.
- Resultado esperado:
- Badge vermelho exibe o numeral correspondente ao total de notificações não lidas.
- O badge atualiza automaticamente a cada 5 segundos sem recarregar a página.
- Pré-condições:
- Todas as notificações marcadas como lidas ou banco vazio.
- Passos:
- Observar o ícone de sino no cabeçalho.
- Resultado esperado:
- O sino é exibido sem badge vermelho.
- Pré-condições:
- Lista carregada com ao menos uma notificação não lida.
- Passos:
- Verificar que o botão
Marcar todas como lidas (N)está visível no cabeçalho da página. - Clicar no botão.
- Verificar que o botão
- Resultado esperado:
- Todos os cards perdem o destaque visual de "não lida" (ponto azul some, opacidade reduz).
- O botão "Marcar todas como lidas" desaparece da interface.
- O badge do sino no Header é zerado.
- Pré-condições:
- Usuário em qualquer rota do sistema.
- Passos:
- Clicar sobre o ícone do sino no Header.
- Resultado esperado:
- O sistema redireciona o usuário para a página
/notifications. - A lista de notificações é carregada corretamente.
- O sistema redireciona o usuário para a página
- Evidência:

Para validar o módulo completo sem depender dos demais serviços:
# 1. Disparar eventos de demonstração
Invoke-WebRequest -Uri http://localhost:5000/api/demo/login -Method POST
Invoke-WebRequest -Uri http://localhost:5000/api/demo/order -Method POST
Invoke-WebRequest -Uri http://localhost:5000/api/demo/payment -Method POST
Invoke-WebRequest -Uri http://localhost:5000/api/demo/stock -Method POST
# 2. Verificar resposta da API
# Acessar no navegador: http://localhost:5000/api/notificationsResultado esperado: 4 notificações retornadas em JSON, visíveis em http://localhost:3000/notifications.
Testes funcionais manuais cobrindo o fluxo de pagamento integrado ao checkout web. Pré-condição global: usuário autenticado, ao menos 1 item no carrinho.
| ID | Componente / Tela | Arquivo |
|---|---|---|
| P1 | Seletor de método de pagamento | CheckoutPage.jsx |
| P2 | Botão "Confirmar e pagar" | CheckoutPage.jsx |
| P3 | Modal de sucesso (OrderSuccessModal) |
modals/OrderSuccessModal.jsx |
| P4 | Modal de recusa (PaymentDeclinedModal) |
modals/PaymentDeclinedModal.jsx |
| P5 | Código PIX copiável | modals/OrderSuccessModal.jsx |
| P6 | transactionId no card de pedido |
OrderCard.jsx |
| P7 | transactionId no detalhe do pedido |
modals/OrderDetailsModal.jsx |
- Pré-condições:
- Carrinho com produto cujo total não termina em
.99.
- Carrinho com produto cujo total não termina em
- Passos:
- Acessar
/checkout. - Selecionar Cartão de crédito.
- Clicar em Confirmar e pagar.
- Acessar
- Resultado esperado:
OrderSuccessModalabre com statusPAIDetransactionIdexibido.- Carrinho é esvaziado.
- Evidência:

- Pré-condições:
- Carrinho com produto cujo total termina exatamente em
.99(ex: R$ 9,99).
- Carrinho com produto cujo total termina exatamente em
- Passos:
- Acessar
/checkout, selecionar método, clicar Confirmar e pagar.
- Acessar
- Resultado esperado:
PaymentDeclinedModalabre com mensagem de recusa.- Status do pedido =
PAYMENT_FAILED. - Botão Tentar novamente visível.
- Evidência:

- Pré-condições:
- Carrinho com valor redondo (aprovação simulada).
- Passos:
- Selecionar PIX no seletor de método.
- Confirmar pagamento.
- No
OrderSuccessModal, clicar em Copiar código PIX.
- Resultado esperado:
- Botão muda para Copiado! por ~2 s.
- Código PIX na área de transferência.
- Evidência:

- Pré-condições:
- Pedido
PAIDexistente na listagem/orders.
- Pedido
- Passos:
- Acessar
/orders.
- Acessar
- Resultado esperado:
- Card exibe linha
Transação: TRX-XXXXXX.
- Card exibe linha
- Evidência:

- Pré-condições:
- Pedido
PAIDexistente.
- Pedido
- Passos:
- Acessar
/orders, clicar em Página do produto no card.
- Acessar
- Resultado esperado:
- Modal exibe
Transação: TRX-XXXXXX.
- Modal exibe
- Evidência:

src/services/notification/Program.cssrc/frontend/notification/NotificationPage.tsxsrc/frontend/notification/NotificationBell.jsxsrc/frontend/notification/NotificationRoutes.jsxsrc/frontend/Order/pages/CheckoutPage.jsxsrc/frontend/Order/components/modals/OrderSuccessModal.jsxsrc/frontend/Order/components/modals/PaymentDeclinedModal.jsxsrc/frontend/Order/components/OrderCard.jsxsrc/frontend/Order/components/modals/OrderDetailsModal.jsxsrc/frontend/App.tsx
