# MediConnect - Sistema de Gestão Médica Completo Sistema completo de gestão médica com agendamento inteligente, teleconsultas, prontuários eletrônicos e gerenciamento multi-nível. **Stack:** React + TypeScript + Vite + TailwindCSS + Supabase Edge Functions **Deploy:** Cloudflare Pages **Última Atualização:** 29/11/2025 --- ## 🚀 Acesso ao Sistema - **URL Principal:** https://mediconnectbrasil.app/ - **URL Cloudflare:** https://mediconnect-5oz.pages.dev/ ### Credenciais de Teste **Admin/Gestor:** - Email: admin@mediconnect.app - Senha: admin123 - Acesso: Todos os painéis **Médico:** - Email: medico@teste.com - Senha: senha123 - Acesso: Painel Médico, Sala de Espera, Teleconsultas **Paciente:** - Email: paciente@teste.com - Senha: senha123 - Acesso: Agendamento, Acompanhamento, Teleconsultas **Secretária:** - Email: secretaria@teste.com - Senha: senha123 - Acesso: Gerenciamento de Consultas, Pacientes e Médicos --- ## 🏗️ Arquitetura ``` Frontend (React/Vite + TypeScript) ↓ API Gateway (Edge Functions - Deno) ↓ Dual Supabase Architecture ├── EXTERNAL Supabase (Auth + RLS) │ ├── Auth (JWT + Magic Link) │ ├── PostgreSQL (Source of Truth) │ └── Storage (Avatares, Documentos) └── NEW Supabase (Functions + No RLS) ├── 65 Edge Functions (CORS Fixed) ├── 34 Tabelas (Gamification, Analytics) └── Real-time Subscriptions ↓ Integrations ├── Jitsi (Teleconsultas) ├── Twilio (SMS) └── Resend (Email) ↓ Cloudflare Pages (Deploy Global) ``` --- ## ✨ Funcionalidades Principais ### 🎯 **NOVO: Painel do Gestor** - ✅ Dashboard executivo com KPIs - ✅ Visão geral do sistema (pacientes, médicos, consultas) - ✅ Métricas de atividade (hoje, semana, mês) - ✅ Lista de consultas recentes com status - ✅ Filtros de período (7d, 30d, 90d, 1 ano) - ✅ Tabs: Dashboard, Análises, Relatórios, Usuários, Configurações - ✅ Design moderno com gradientes e animações ### 🏥 Para Médicos - ✅ **Painel modernizado** com design da Landing Page - ✅ Agenda personalizada com disponibilidade configurável - ✅ **Sala de Espera Virtual** - Pacientes com check-in em tempo real - ✅ **Teleconsulta integrada** com Jitsi (vídeo HD) - ✅ Gerenciamento completo de disponibilidade semanal - ✅ Sistema de exceções (bloqueios e horários extras) - ✅ Prontuário eletrônico completo - ✅ Histórico de consultas do paciente - ✅ Dashboard com métricas e estatísticas - ✅ Consultas presenciais e remotas - ✅ Confirmação/Cancelamento/Remarcar consultas - ✅ Status dinâmicos (scheduled, confirmed, in_progress, completed, cancelled, no_show) ### 👥 Para Pacientes - ✅ **Dashboard modernizado** com gradientes e animações hover - ✅ **Teleconsulta** - Entrar em videochamada com médico - ✅ Verificação automática de dispositivos (câmera/microfone) - ✅ Agendamento inteligente com slots disponíveis em tempo real - ✅ Histórico completo de consultas com filtros - ✅ Visualização detalhada de laudos médicos com modal - ✅ Visualização e download de relatórios médicos (PDF) - ✅ Perfil com avatar e dados pessoais - ✅ Filtros por médico, especialidade e data - ✅ Gamificação (pontos, streaks, badges) - ✅ Cards de estatísticas com cores dinâmicas ### 🏢 Para Secretárias - ✅ **Painel modernizado** com tabs em gradiente - ✅ Gerenciamento completo de médicos, pacientes e consultas - ✅ Cadastro com validação de CPF e CRM - ✅ Configuração de agenda médica (horários e exceções) - ✅ Relatórios com nomes de médicos (não apenas IDs) - ✅ Busca e filtros avançados - ✅ Confirmação profissional para exclusões - ✅ Gestão de sala de espera - ✅ Envio de notificações (SMS, Email, WhatsApp) ### 🔐 Para Administradores - ✅ **Painel modernizado** com design consistente - ✅ Gerenciamento de usuários e permissões (roles) - ✅ CRUD completo de Pacientes, Médicos e Secretárias - ✅ Controle de acesso granular - ✅ Logs de auditoria - ✅ Configurações globais do sistema - ✅ Tabs organizadas (Pacientes, Usuários, Médicos) ### 🔐 Sistema de Autenticação - ✅ Login com email/senha - ✅ Magic Link (login sem senha) - ✅ Recuperação de senha - ✅ Tokens JWT com refresh automático - ✅ Controle de acesso por role (admin, gestor, médico, paciente, secretária) - ✅ Dual Supabase (EXTERNAL para auth, NEW para functions) --- ## 🎨 Design System (Atualizado 29/11/2025) ### Padrões Visuais da Landing Page Todos os painéis foram modernizados seguindo o design da Landing Page: **Cores e Gradientes:** ```css /* Gradientes principais */ from-blue-600 to-purple-600 /* Títulos e botões ativos */ from-blue-500 to-cyan-600 /* Ícones e destaques */ from-purple-500 to-pink-600 /* Variações */ from-green-500 to-teal-600 /* Status positivos */ /* Backgrounds */ bg-gradient-to-br from-blue-50 via-purple-50 to-pink-50 /* Fundo dos painéis */ bg-white/80 backdrop-blur-md /* Cards glassmorphism */ ``` **Componentes:** ```css /* Cards */ rounded-2xl shadow-lg hover:shadow-2xl hover:-translate-y-1 transition-all /* Botões */ px-6 py-3 bg-gradient-to-r text-white rounded-xl hover:shadow-lg hover:scale-105 /* Ícones em containers */ w-14 h-14 bg-gradient-to-br rounded-xl group-hover:scale-110 transition-transform /* Tabs ativos */ bg-gradient-to-r from-blue-600 to-purple-600 text-white shadow-lg scale-105 /* Bordas sutis */ border border-gray-100 /* Ao invés de gray-200 */ ``` **Tipografia:** ```css /* Títulos */ text-3xl sm:text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r /* Títulos com gradiente */ /* Valores de métricas */ text-3xl font-bold text-blue-600 /* Números destacados */ ``` --- ## 🔧 Tecnologias ### Frontend - **React 18** - Interface moderna e reativa - **TypeScript** - Tipagem estática - **Vite** - Build ultra-rápido (HMR em <200ms) - **TailwindCSS** - Estilização utilitária + Design System customizado - **React Router** - Navegação SPA com rotas protegidas - **Axios** - Cliente HTTP com interceptors - **date-fns** - Manipulação de datas (i18n pt-BR) - **jsPDF** - Geração de PDFs - **Lucide Icons** - 1000+ ícones SVG modernos - **React Hot Toast** - Notificações elegantes ### Backend (Supabase) - **PostgreSQL 15** - Banco de dados relacional - **PostgREST** - API REST automática - **Edge Functions (Deno)** - 65 funções serverless - ✅ CORS corrigido (status: 200 explícito) - ✅ Auth bypass com SERVICE_ROLE_KEY - ✅ URL normalization (/ → -) - **Storage** - Armazenamento de arquivos (avatares, PDFs) - **Auth** - JWT + RLS (EXTERNAL Supabase) - **Real-time** - Subscriptions via WebSocket ### Integrações - **Jitsi Meet** - Teleconsultas HD (vpaas-magic-cookie) - **Twilio** - SMS notifications (+1 978-981-4520) - **Resend** - Email transacional (noreply@mediconnectbrasil.app) ### Deploy - **Cloudflare Pages** - Hospedagem global com CDN - **Wrangler CLI** - Deploy automatizado - **GitHub Actions** - CI/CD pipeline --- ## 📦 Instalação e Execução ### Pré-requisitos - Node.js 18+ - pnpm (recomendado) ou npm - Supabase CLI (para deploy de functions) ### Instalação ```bash # Clone o repositório git clone https://github.com/seu-usuario/mediconnect.git cd riseup-squad18 # Instalar dependências pnpm install # Configurar variáveis de ambiente cp .env.example .env # Edite .env com suas credenciais Supabase, Jitsi, Twilio, Resend # Iniciar desenvolvimento pnpm dev # Acessar em http://localhost:5173 ``` ### Build e Deploy ```bash # Build de produção pnpm build # Preview do build pnpm preview # Deploy para Cloudflare Pages pnpm wrangler pages deploy dist --project-name=mediconnect --branch=production ``` ### Deploy de Edge Functions ```powershell # Deploy individual supabase functions deploy --project-ref etblfypcxxtvvuqjkrgd --no-verify-jwt # Deploy em massa (17 funções corrigidas) .\deploy-fixed-functions.ps1 # Deploy de todas as funções supabase functions deploy --project-ref etblfypcxxtvvuqjkrgd ``` --- ## 🚀 Melhorias Recentes (Novembro 2025) ### 🎨 Modernização de UI (29/11/2025) **4 Painéis Modernizados:** - ✅ **PainelMedico.tsx** - Design da Landing Page aplicado - ✅ **PainelSecretaria.tsx** - Tabs com gradiente, glassmorphism - ✅ **PainelAdmin.tsx** - Header e tabs modernizados - ✅ **AcompanhamentoPaciente.tsx** - Cards com hover effects, gradientes dinâmicos **1 Painel Novo:** - 🆕 **PainelGestor.tsx** - Dashboard executivo com KPIs e analytics - Métricas do sistema (pacientes, médicos, consultas, relatórios) - Atividade temporal (hoje, semana, mês) - Filtros de período (7d, 30d, 90d, 1 ano) - Lista de consultas recentes - Tabs: Dashboard, Análises, Relatórios, Usuários, Configurações **Padrões Aplicados:** - Gradientes: `from-blue-600 to-purple-600`, `from-blue-500 to-cyan-600` - Cards: `rounded-2xl shadow-lg hover:shadow-2xl hover:-translate-y-1` - Glassmorphism: `bg-white/80 backdrop-blur-md` - Ícones com gradiente: `bg-gradient-to-br rounded-xl group-hover:scale-110` - Bordas sutis: `border-gray-100` (ao invés de gray-200) ### 🔧 Correção Massiva de CORS (29/11/2025) **17 Edge Functions Corrigidas:** Todas agora têm `status: 200` explícito no OPTIONS handler: ```typescript if (req.method === "OPTIONS") { return new Response("ok", { status: 200, // ✅ EXPLÍCITO! headers: corsHeaders(), }); } ``` **Funções corrigidas:** - appointments: checkin, confirm, no-show, reschedule, suggest-slot - gamification: add-points, doctor-badges, patient-streak - notifications: send, confirm - teleconsult: start, end, status - offline: agenda-today, patient-basic - reports: export - virtual-queue: advance **Script de Deploy:** - Criado `deploy-fixed-functions.ps1` para deploy automatizado - Flag `--no-verify-jwt` para bypass de autenticação - Deploy em massa de todas as 17 funções ### 🎥 Sistema de Teleconsulta (Implementado) **Painel do Paciente:** - ✅ Botão "Entrar na Consulta" visível em consultas agendadas - ✅ Verificação automática de dispositivos (câmera/microfone) - ✅ Integração com Jitsi Meet (vpaas-magic-cookie) - ✅ Abertura de sala em nova janela - ✅ Toast notifications para feedback **Painel do Médico:** - ✅ Botão de videochamada nas consultas - ✅ Tab "Sala de Espera" dedicada - ✅ Componente WaitingRoom integrado - ✅ Status de consultas em tempo real **Services:** - ✅ `teleconsultService.ts` completo - ✅ Funções: start(), end(), getStatus(), openRoom(), checkMediaDevices() - ✅ Edge Functions: teleconsult-start, teleconsult-end, teleconsult-status ### 🔔 Sistema de Notificações (Implementado) **Services:** - ✅ `notificationService.ts` com CRUD completo - ✅ Tipos: SMS, Email, WhatsApp - ✅ Status: pending, sent, failed, scheduled - ✅ Integração com Twilio (SMS) e Resend (Email) **Edge Functions:** - ✅ notifications-send (envio multi-canal) - ✅ notifications-confirm (confirmação de leitura) - ✅ notifications-subscription (push notifications) ### 📅 Sistema de Agendamento Completo **Status de Consultas:** - scheduled → confirmed → checked_in → in_progress → completed - Também: cancelled, no_show **Edge Functions:** - ✅ appointments-create (criar consulta) - ✅ appointments-update (atualizar) - ✅ appointments-cancel (cancelar) - ✅ appointments-confirm (confirmar) - ✅ appointments-checkin (check-in para sala de espera) - ✅ appointments-no-show (marcar falta) - ✅ appointments-reschedule (reagendar) - ✅ appointments-suggest-slot (sugerir novo horário) **Componentes:** - ✅ WaitingRoom.tsx - Sala de espera virtual - ✅ ConsultaModal.tsx - Modal de gerenciamento - ✅ Integração completa nos painéis ### 🎮 Sistema de Gamificação **Features:** - ✅ Pontos por ações (consultas, check-ins, etc) - ✅ Streaks de pacientes (dias consecutivos) - ✅ Badges de médicos (conquistas) - ✅ Edge Functions: add-points, patient-streak, doctor-badges ### 🚀 Melhorias de Navegação **Command Palette (Ctrl+K):** - ✅ Adicionado "Painel Gestor" aos comandos - ✅ Adicionado "Painel Admin" aos comandos - ✅ Keywords: gestor, gerencial, analytics, métricas **Header:** - ✅ Link para "Gestor" (roxo/indigo) entre Admin e Médico - ✅ Versão mobile com ícone 📈 - ✅ Navegação consistente em todos os painéis **Rotas:** - ✅ `/painel-gestor` protegida (roles: admin, gestor) - ✅ Importação e integração no App.tsx - ✅ ProtectedRoute com verificação de roles ### Chatbot AI 🤖 - ✅ Assistente virtual inteligente com IA - ✅ Interface de chat moderna e responsiva - ✅ Posicionamento otimizado (canto inferior esquerdo) - ✅ Respostas personalizadas sobre o sistema - ✅ Suporte a dúvidas sobre agendamento e funcionalidades ### Gerenciamento de Disponibilidade Médica 📅 - ✅ Painel completo de disponibilidade no painel do médico - ✅ Criação e edição de horários semanais - ✅ Sistema de exceções (bloqueios e horários extras) - ✅ Visualização em abas (Horário Semanal e Exceções) - ✅ Interface intuitiva com validações completas ### Visualização de Laudos 🔍 - ✅ Botão de visualização (ícone de olho) no painel do paciente - ✅ Modal detalhado com informações completas do laudo - ✅ Exibição de: número do pedido, status, exame, diagnóstico, CID, conclusão - ✅ Suporte a modo escuro - ✅ Formatação de datas em português ### Melhorias no Painel da Secretária 👩‍💼 - ✅ Relatórios mostram nome do médico ao invés de ID - ✅ Mensagem de boas-vindas personalizada com nome real - ✅ Busca e resolução automática de nomes de médicos - ✅ Fallback para email caso nome não esteja disponível ### Sistema de Agendamento - ✅ API de slots disponíveis (Edge Function) - ✅ Cálculo automático de horários - ✅ Validação de antecedência mínima - ✅ Verificação de conflitos - ✅ Interface otimizada ### UX/UI - ✅ Toast único de boas-vindas após login (removidas mensagens duplicadas) - ✅ Chatbot responsivo adaptado ao tamanho da tela - ✅ Diálogos de confirmação profissionais - ✅ Filtros de busca em todas as listas - ✅ Feedback visual melhorado - ✅ Loading states consistentes - ✅ Mensagens de erro claras ### Performance - ✅ Build otimizado (~467KB) - ✅ Code splitting - ✅ Lazy loading de rotas - ✅ Cache de assets - ✅ Remoção de dependências não utilizadas --- ## 📝 Convenções de Código ### TypeScript - Interfaces para todas as entidades - Tipos explícitos em funções - Evitar `any` (usar `unknown` quando necessário) ### Componentes React - Functional components com hooks - Props tipadas com interfaces - Estado local com useState/useContext - Effects para side effects ### Serviços - Um serviço por entidade (doctorService, patientService) - Métodos assíncronos com try/catch - Logs de debug no console - Tratamento de erros consistente ### Nomenclatura - **Componentes:** PascalCase (ex: `AgendamentoConsulta`) - **Arquivos:** kebab-case ou PascalCase conforme tipo - **Variáveis:** camelCase (ex: `selectedDate`) - **Constantes:** UPPER_SNAKE_CASE (ex: `API_CONFIG`) --- ## 🐛 Troubleshooting ### Erro 401 (Unauthorized) - Verificar se token está no localStorage - Tentar logout e login novamente - Verificar permissões RLS no Supabase ### Slots não aparecem - Verificar se médico tem disponibilidade configurada - Verificar se data é futura - Verificar logs da Edge Function ### Upload de avatar falha - Verificar tamanho do arquivo (max 2MB) - Verificar formato (jpg, png) - Verificar permissões do Storage no Supabase ### Build falha - Limpar cache: `rm -rf node_modules dist` - Reinstalar: `pnpm install` - Verificar versão do Node (18+) --- ## 👥 Equipe **RiseUp Squad 18** - Desenvolvimento: GitHub Copilot + Equipe - Data: Outubro 2025 --- ## 📄 Licença Este projeto é privado e desenvolvido para fins educacionais. --- ## � Links Úteis - [Supabase Docs](https://supabase.com/docs) - [React Docs](https://react.dev/) - [Vite Docs](https://vitejs.dev/) - [TailwindCSS Docs](https://tailwindcss.com/) - [Cloudflare Pages](https://pages.cloudflare.com/) --- **Última atualização:** 30 de Outubro de 2025 - ✅ Veem apenas **seus próprios dados** - ✅ Veem apenas **seus próprios laudos** (filtro: `patient_id = paciente`) - ✅ Veem apenas **seus próprios agendamentos** - ✅ Podem agendar consultas #### 👩‍💼 Secretárias: - ✅ Veem **todos os pacientes** - ✅ Veem **todos os agendamentos** - ✅ Veem **todos os laudos** - ✅ Podem criar/editar agendamentos --- ## 📡 API e Serviços ### Estrutura de Services O projeto usa uma arquitetura de **services** que encapsulam toda comunicação com o Supabase: ``` src/services/ ├── api/ │ ├── client.ts # Cliente HTTP (Axios configurado) │ └── config.ts # Configurações da API ├── auth/ │ ├── authService.ts # Login, signup, recuperação de senha │ └── types.ts ├── users/ │ └── userService.ts # getUserInfo, createUser, deleteUser ├── patients/ │ └── patientService.ts # CRUD de pacientes ├── doctors/ │ └── doctorService.ts # CRUD de médicos ├── appointments/ │ └── appointmentService.ts # Agendamentos └── availability/ └── availabilityService.ts # Disponibilidade médica ``` ### Principais Endpoints #### 🔐 Autenticação (authService) ```typescript // Login com Email e Senha await authService.login({ email, password }); // Retorna: { access_token, refresh_token, user } // Magic Link (Login sem senha) await authService.sendMagicLink("email@example.com"); // Envia email com link de autenticação // Usuário clica no link e é automaticamente autenticado // Recuperação de senha await authService.requestPasswordReset("email@example.com"); // Envia email com link de reset // Atualizar senha await authService.updatePassword(accessToken, newPassword); // Usado na página /reset-password // Refresh token await authService.refreshToken(refreshToken); ``` **Fluxo Magic Link:** 1. Usuário solicita magic link na tela de login 2. `localStorage.setItem("magic_link_redirect", "/painel-medico")` salva contexto 3. Supabase envia email com link único 4. Usuário clica no link 5. `Home.tsx` detecta hash params e redireciona para `/auth/callback` 6. `AuthCallback.tsx` processa tokens, salva no localStorage 7. `window.location.href` redireciona para painel salvo 8. Página recarrega com `AuthContext` atualizado 9. Usuário autenticado no painel correto ✅ #### 👤 Usuários (userService) ```typescript // Buscar informações do usuário autenticado (com roles) const userInfo = await userService.getUserInfo(); // Retorna: { id, email, full_name, roles: ['medico', 'admin'] } // Criar usuário com role await userService.createUser({ email: "user@example.com", full_name: "Nome Completo", role: "medico", // ou 'admin', 'paciente', 'secretaria' }); // Deletar usuário await userService.deleteUser(userId); ``` #### 🏥 Pacientes (patientService) ```typescript // Listar pacientes const patients = await patientService.list(); // Buscar por ID const patient = await patientService.getById(id); // Criar paciente await patientService.create({ email: "paciente@example.com", full_name: "Nome Paciente", cpf: "12345678900", phone_mobile: "11999999999", }); // Atualizar paciente await patientService.update(id, { phone_mobile: "11888888888" }); // Deletar paciente await patientService.delete(id); ``` #### 👨‍⚕️ Médicos (doctorService) ```typescript // Listar médicos const doctors = await doctorService.list(); // Buscar por ID const doctor = await doctorService.getById(id); // Buscar disponibilidade const slots = await doctorService.getAvailableSlots(doctorId, date); ``` #### 📅 Agendamentos (appointmentService) ```typescript // Listar agendamentos (filtrado por role automaticamente) const appointments = await appointmentService.list(); // Criar agendamento await appointmentService.create({ patient_id: "uuid-paciente", doctor_id: "uuid-medico", scheduled_at: "2025-10-25T10:00:00", reason: "Consulta de rotina", }); // Atualizar status await appointmentService.updateStatus(id, "confirmed"); // Status: requested, confirmed, completed, cancelled // Cancelar await appointmentService.cancel(id, "Motivo do cancelamento"); ``` #### 📸 Avatares (avatarService) ```typescript // Upload de avatar (usa FormData com x-upsert: true) const file = event.target.files[0]; // File do input const result = await avatarService.upload({ userId: user.id, file: file, }); // Retorna: { Key: "url-publica-do-avatar" } // Obter URL pública do avatar const url = avatarService.getPublicUrl({ userId: user.id, ext: "png", // ou 'jpg', 'webp' }); // Retorna: https://yuanqfswhberkoevtmfr.supabase.co/storage/v1/object/avatars/{userId}/avatar.png // Auto-load de avatar (testa múltiplas extensões) const extensions = ["png", "jpg", "webp"]; for (const ext of extensions) { const url = avatarService.getPublicUrl({ userId: user.id, ext }); const response = await fetch(url, { method: "HEAD" }); if (response.ok) { setAvatarUrl(url); break; } } ``` **Detalhes importantes:** - Upload usa **multipart/form-data** via FormData - Header `x-upsert: true` permite sobrescrever avatares existentes - Suporta formatos: PNG, JPG, WEBP (máx 2MB) - URLs públicas não requerem autenticação - Avatar é carregado automaticamente nos painéis --- ## 🔧 Configuração da API ```typescript // src/services/api/config.ts export const API_CONFIG = { SUPABASE_URL: "https://yuanqfswhberkoevtmfr.supabase.co", SUPABASE_ANON_KEY: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", AUTH_URL: `${SUPABASE_URL}/auth/v1`, REST_URL: `${SUPABASE_URL}/rest/v1`, APP_URL: "https://mediconnectbrasil.app", TIMEOUT: 30000, STORAGE_KEYS: { ACCESS_TOKEN: "mediconnect_access_token", REFRESH_TOKEN: "mediconnect_refresh_token", USER: "mediconnect_user", }, }; ``` --- ## 🚀 Deploy no Cloudflare Pages ### Via Wrangler CLI ```powershell # Build pnpm build # Deploy para production npx wrangler pages deploy dist --project-name=mediconnect --branch=production # Deploy com mudanças não commitadas npx wrangler pages deploy dist --project-name=mediconnect --commit-dirty=true ``` ### Configuração do Projeto - **Production Branch:** `production` - **Build Command:** `pnpm build` - **Build Output:** `dist` - **Custom Domain:** `mediconnectbrasil.app` ### URLs - **Production:** https://mediconnectbrasil.app/ - **Preview:** https://mediconnect-5oz.pages.dev/ - **Branch Preview:** https://[branch].mediconnect-5oz.pages.dev/ --- ## 1. Variáveis de Ambiente (`.env` / `.env.local`) | Variável | Obrigatória | Descrição | | ------------------------ | ----------- | --------------------------------------------------------------- | | `VITE_SUPABASE_URL` | Sim | URL base do projeto Supabase (`https://.supabase.co`) | | `VITE_SUPABASE_ANON_KEY` | Sim | Chave pública (anon) usada para Auth password grant e PostgREST | | `VITE_APP_ENV` | Não | Identifica ambiente (ex: `dev`, `staging`, `prod`) | **Nota:** As variáveis já estão configuradas no código em `src/services/api/config.ts`. Não é necessário criar arquivo `.env` para desenvolvimento local. Boas práticas: - Nunca exponha Service Role Key no frontend. - Não comitar `.env` – usar `.env.example` como referência (se houver). --- ## 2. Fluxo de Login e Validação de Roles ### Exemplo: Login de Médico ```typescript // pages/LoginMedico.tsx const handleLogin = async (e: FormEvent) => { e.preventDefault(); try { // 1. Autenticar com Supabase const loginResponse = await authService.login({ email, password }); // 2. Salvar tokens localStorage.setItem("access_token", loginResponse.access_token); localStorage.setItem("refresh_token", loginResponse.refresh_token); // 3. Buscar informações do usuário com roles const userInfo = await userService.getUserInfo(); const roles = userInfo.roles || []; // 4. Validar permissões const isAdmin = roles.includes("admin"); const isGestor = roles.includes("gestor"); const isMedico = roles.includes("medico"); if (!isAdmin && !isGestor && !isMedico) { toast.error("Você não tem permissão para acessar esta área"); await authService.logout(); return; } // 5. Redirecionar para o painel navigate("/painel-medico"); } catch (error) { toast.error("Email ou senha incorretos"); } }; ``` --- ## 3. Recuperação de Senha ### Fluxo Completo 1. **Usuário clica em "Esqueceu a senha?"** 2. **Sistema envia email com link de recuperação** 3. **Usuário clica no link → redireciona para `/reset-password`** 4. **Sistema extrai token do URL (#access_token=...)** 5. **Usuário define nova senha** 6. **Sistema atualiza senha e redireciona para login** ### Implementação ```typescript // Solicitar recuperação (páginas de login) const handlePasswordReset = async () => { try { await authService.requestPasswordReset(email); toast.success("Link de recuperação enviado para seu email"); } catch (error) { toast.error("Erro ao enviar email de recuperação"); } }; // Página de reset (ResetPassword.tsx) useEffect(() => { // Extrair token do URL const hash = window.location.hash; const params = new URLSearchParams(hash.substring(1)); const token = params.get("access_token"); if (token) { setAccessToken(token); setIsLoading(false); } }, []); const handleSubmit = async (e: FormEvent) => { try { await authService.updatePassword(accessToken, newPassword); toast.success("Senha atualizada com sucesso!"); navigate("/login-paciente"); } catch (error) { toast.error("Erro ao atualizar senha"); } }; ``` --- ## 5. Estrutura do Banco de Dados ### Tabelas Principais #### `profiles` ```sql - id (uuid, PK) - email (text, unique) - full_name (text) - phone (text) - created_at (timestamp) - updated_at (timestamp) ``` #### `patients` ```sql - id (uuid, PK, FK -> profiles) - email (text, unique) - full_name (text) - cpf (text, unique) - phone_mobile (text) - birth_date (date) - address (text) - created_at (timestamp) ``` #### `doctors` ```sql - id (uuid, PK, FK -> profiles) - email (text, unique) - full_name (text) - specialty (text) - crm (text, unique) - phone (text) - created_at (timestamp) ``` #### `appointments` ```sql - id (uuid, PK) - patient_id (uuid, FK -> patients) - doctor_id (uuid, FK -> doctors) - scheduled_at (timestamp) - status (enum: requested, confirmed, completed, cancelled) - reason (text) - notes (text) - created_at (timestamp) ``` #### `user_roles` ```sql - user_id (uuid, FK -> profiles) - role (text: admin, gestor, medico, secretaria, paciente) - created_at (timestamp) ``` --- ## 6. Armazenamento de Tokens O sistema usa uma estratégia híbrida para máxima segurança: | Tipo | Local | Expiração Natural | | ------------- | ------------ | --------------------------------- | | Access Token | localStorage | 1 hora (renovado automaticamente) | | Refresh Token | localStorage | 30 dias (ou revogação backend) | | User Snapshot | localStorage | Limpo em logout | **Segurança:** - Tokens são limpos automaticamente no logout - Refresh automático quando access_token expira (401) - Interceptors garantem tokens válidos em todas as requisições Riscos remanescentes: - XSS ainda pode ler refresh token dentro da mesma aba. - Ataques supply-chain podem capturar tokens em runtime. Mitigações planejadas: 1. CSP + bloqueio de inline script não autorizado. 2. Auditoria de dependências e lockfile imutável. 3. (Opcional) Migrar refresh para cookie httpOnly + rotacionamento curto (exige backend/proxy). Fallback / Migração: - Em primeira utilização o `tokenStore` migra chaves legacy (`authToken`, `refreshToken`, `authUser`) e remove do `localStorage`. Operações: - `tokenStore.setTokens(access, refresh?)` atualiza memória e session. - `tokenStore.clear()` remove tudo (usado em logout e erro crítico de refresh). Fluxo de Refresh: 1. Requisição falha com 401. 2. Wrapper (`http.ts`) obtém refresh do `tokenStore`. --- ## 7. Scripts Utilitários ### Gerenciamento de Usuários ```bash # Listar todos os usuários node scripts/manage-users.js list # Criar usuário node scripts/manage-users.js create email@example.com "Nome Completo" # Deletar usuário node scripts/manage-users.js delete user-id # Limpar usuários de teste node scripts/cleanup-users.js ``` ### Testes de API ```bash # Testar recuperação de senha node test-password-recovery.js # Criar usuário Fernando (exemplo) node create-fernando.cjs # Buscar usuário Fernando node search-fernando.cjs ``` --- ## 8. Padrões de Código ### Nomenclatura - **Componentes:** PascalCase (`LoginPaciente.tsx`) - **Serviços:** camelCase (`authService.ts`) - **Hooks:** camelCase com prefixo `use` (`useAuth.ts`) - **Tipos:** PascalCase (`LoginInput`, `AuthUser`) ### Estrutura de Componentes ```typescript // Imports import React, { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import { serviceImport } from "../services"; // Types interface Props { // ... } // Component const ComponentName: React.FC = ({ ...props }) => { // Hooks const navigate = useNavigate(); const [state, setState] = useState(); // Effects useEffect(() => { // ... }, []); // Handlers const handleAction = async () => { // ... }; // Render return
{/* JSX */}
; }; export default ComponentName; ``` --- ## 9. Tecnologias Utilizadas ### Frontend - **React** 18.3.1 - Biblioteca UI - **TypeScript** 5.9.3 - Tipagem estática - **Vite** 7.1.10 - Build tool - **React Router** 6.30.1 - Roteamento - **Tailwind CSS** 3.4.17 - Estilização - **Axios** 1.12.2 - Cliente HTTP - **React Hot Toast** 2.4.1 - Notificações - **date-fns** 4.1.0 - Manipulação de datas ### Backend - **Supabase** - Backend as a Service - **PostgreSQL** - Banco de dados relacional - **Supabase Auth** - Autenticação JWT ### Deploy - **Cloudflare Pages** - Hospedagem frontend - **Wrangler** 4.44.0 - CLI Cloudflare --- ## 10. Suporte e Contato - **Equipe:** Squad 18 - Rise Up - **Repositório:** https://git.popcode.com.br/RiseUP/riseup-squad18.git - **Trello:** [Squad 18 - Idealização/Planejamento](https://trello.com/b/CCl3Azxk/squad-18-idealizacao-planejamento) --- **Desenvolvido com ❤️ pela Squad 18**