# SaveInMed Marketplace Frontend Interface do usuário do marketplace B2B farmacêutico SaveInMed, desenvolvida com React e Vite. ## 🎯 Propósito Este é o frontend do marketplace SaveInMed, onde farmácias e distribuidoras podem: - Navegar e pesquisar produtos farmacêuticos - Adicionar produtos ao carrinho - Realizar pedidos e checkout - Gerenciar perfil e histórico de compras - Acompanhar status de pedidos - Processar pagamentos via Mercado Pago ## 🚀 Tecnologias - **React 18** - Biblioteca UI - **TypeScript** - Tipagem estática - **Vite 5** - Build tool e dev server ultra-rápido - **React Router DOM 6** - Roteamento - **TailwindCSS 3** - Framework CSS utility-first - **Zustand 4** - Gerenciamento de estado - **Axios** - Cliente HTTP - **Mercado Pago SDK React** - Integração de pagamentos - **React Window** - Virtualização de listas para performance ## 📋 Funcionalidades ### Catálogo de Produtos - Listagem de produtos com virtualização - Busca e filtros avançados - Detalhes de produtos - Informações de lote e validade ### Carrinho de Compras - Adicionar/remover produtos - Atualizar quantidades - Persistência local com Zustand - Cálculo automático de totais ### Checkout e Pagamentos - Fluxo de checkout simplificado - Integração com Mercado Pago - Múltiplas formas de pagamento - Confirmação de pedido ### Autenticação - Login de usuários - Rotas protegidas - Contexto de autenticação - Persistência de sessão ### Dashboard - Visão geral de pedidos - Histórico de compras - Estatísticas de uso ### Perfil - Gerenciamento de dados pessoais - Endereços de entrega - Preferências ## 🏗️ Arquitetura ``` marketplace/ ├── src/ │ ├── components/ │ │ └── ProtectedRoute.tsx # Componente de rota protegida │ ├── context/ │ │ └── AuthContext.tsx # Contexto de autenticação │ ├── hooks/ │ │ └── usePersistentFilters.ts # Hook para filtros persistentes │ ├── layouts/ │ │ └── Shell.tsx # Layout principal │ ├── pages/ │ │ ├── Cart.tsx # Página do carrinho │ │ ├── Checkout.tsx # Página de checkout │ │ ├── Company.tsx # Perfil da empresa [NEW] │ │ ├── Dashboard.tsx # Dashboard do usuário │ │ ├── Inventory.tsx # Gestão de estoque [NEW] │ │ ├── Login.tsx # Página de login │ │ ├── Orders.tsx # Pedidos [NEW] │ │ ├── Profile.tsx # Página de perfil │ │ └── SellerDashboard.tsx # Dashboard vendedor [NEW] │ ├── services/ │ │ └── apiClient.ts # Cliente API configurado │ ├── stores/ │ │ └── cartStore.ts # Store Zustand do carrinho │ ├── test/ │ │ └── setup.ts # Setup Vitest │ ├── types/ │ │ └── product.ts # Tipos TypeScript │ ├── App.tsx # Componente raiz │ ├── main.tsx # Entry point │ └── index.css # Estilos globais ├── index.html ├── vite.config.ts ├── vitest.config.ts # Config de testes ├── tailwind.config.ts ├── tsconfig.json └── README.md ``` ## 🧪 Testes O projeto utiliza **Vitest** para testes unitários: ```bash # Executar testes npm test # Executar testes com coverage npm run test:coverage # Executar testes uma vez (CI) npm test -- --run ``` ### Cobertura Atual | Categoria | Testes | |-----------|--------| | `cartStore` | 15 ✅ | | `apiClient` | 7 ✅ | | `usePersistentFilters` | 5 ✅ | | **Total** | **27** ✅ | ## 🔧 Configuração ### Variáveis de Ambiente Crie um arquivo `.env` na raiz do projeto: ```bash # API Backend VITE_API_URL=http://localhost:8080 # Mercado Pago VITE_MERCADOPAGO_PUBLIC_KEY=your-public-key-here # Ambiente VITE_ENV=development ``` ### Pré-requisitos - Node.js 20+ - npm ou yarn ## 🏃 Execução Local ```bash # Instalar dependências npm install # Modo desenvolvimento npm run dev # Aplicação estará disponível em http://localhost:5173 ``` ## 🏗️ Build e Produção ```bash # Build para produção npm run build # Preview do build npm run preview # Arquivos de produção estarão em ./dist ``` ## 🎨 Estilização O projeto utiliza TailwindCSS para estilização. Principais recursos: - **Utility-first**: Classes utilitárias para estilização rápida - **Responsivo**: Design mobile-first - **Dark mode**: Suporte a tema escuro (se implementado) - **Customização**: Configuração em `tailwind.config.ts` ### Exemplo de Componente ```tsx export function ProductCard({ product }: { product: Product }) { return (
{product.description}