riseup-squad18/README.md
2025-12-06 19:13:27 -03:00

1165 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 <nome-funcao> --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.
---
## <20> 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://<ref>.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 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> = ({ ...props }) => {
// Hooks
const navigate = useNavigate();
const [state, setState] = useState();
// Effects
useEffect(() => {
// ...
}, []);
// Handlers
const handleAction = async () => {
// ...
};
// Render
return <div>{/* JSX */}</div>;
};
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**