# MediConnect - Sistema de Agendamento Médico

Sistema completo de gestão médica com agendamento inteligente, prontuários eletrônicos e gerenciamento de pacientes.

**Stack:** React + TypeScript + Vite + TailwindCSS + Supabase  
**Deploy:** Cloudflare Pages

---

## 🚀 Acesso ao Sistema

- **URL Principal:** https://mediconnectbrasil.app/
- **URL Cloudflare:** https://mediconnect-5oz.pages.dev/

### Credenciais de Teste

**Médico:**

- Email: medico@teste.com
- Senha: senha123

**Paciente:**

- Email: paciente@teste.com
- Senha: senha123

**Secretária:**

- Email: secretaria@teste.com
- Senha: senha123

---

## 🏗️ Arquitetura

```
Frontend (React/Vite)
    ↓
Supabase Backend
    ├── Auth (JWT + Magic Link)
    ├── PostgreSQL (PostgREST)
    ├── Edge Functions (Slots, Criação de Usuários)
    └── Storage (Avatares, Documentos)
    ↓
Cloudflare Pages (Deploy)
```

---

## � Instalação e Execução

### Pré-requisitos

- Node.js 18+
- pnpm (recomendado) ou npm

### Instalação

```bash
# Instalar dependências
pnpm install

# Iniciar desenvolvimento
pnpm dev

# Acessar em http://localhost:5173
```

### Build e Deploy

```bash
# Build de produção
pnpm build

# Deploy para Cloudflare Pages
pnpm wrangler pages deploy dist --project-name=mediconnect --branch=production
```

---

## ✨ Funcionalidades Principais

### 🏥 Para Médicos

- ✅ Agenda personalizada com disponibilidade configurável
- ✅ 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
- ✅ Teleconsulta e presencial
- ✅ Chatbot AI para suporte

### 👥 Para Pacientes

- ✅ Agendamento inteligente com slots disponíveis em tempo real
- ✅ Histórico completo de consultas
- ✅ 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
- ✅ Chatbot AI para dúvidas e suporte

### 🏢 Para Secretárias

- ✅ 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
- ✅ Boas-vindas personalizadas com nome real

### 🔐 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 (médico/paciente/secretária)

---

## 🔧 Tecnologias

### Frontend

- **React 18** - Interface moderna e reativa
- **TypeScript** - Tipagem estática
- **Vite** - Build ultra-rápido
- **TailwindCSS** - Estilização utilitária
- **React Router** - Navegação SPA
- **Axios** - Cliente HTTP
- **date-fns** - Manipulação de datas
- **jsPDF** - Geração de PDFs
- **Lucide Icons** - Ícones modernos

### Backend (Supabase)

- **PostgreSQL** - Banco de dados relacional
- **PostgREST** - API REST automática
- **Edge Functions** - Funções serverless (Deno)
- **Storage** - Armazenamento de arquivos
- **Auth** - Autenticação e autorização

### Deploy

- **Cloudflare Pages** - Hospedagem global com CDN

---

## 📁 Estrutura do Projeto

```
MEDICONNECT 2/
├── src/
│   ├── components/         # Componentes React
│   │   ├── auth/          # Login, cadastro, recuperação
│   │   ├── secretaria/    # Painéis da secretária
│   │   ├── agenda/        # Sistema de agendamento
│   │   ├── consultas/     # Gerenciamento de consultas
│   │   └── ui/            # Componentes reutilizáveis
│   ├── pages/             # Páginas da aplicação
│   │   ├── Home.tsx
│   │   ├── PainelMedico.tsx
│   │   ├── PainelSecretaria.tsx
│   │   └── AgendamentoPaciente.tsx
│   ├── services/          # Camada de API
│   │   ├── api/           # Cliente HTTP
│   │   ├── auth/          # Autenticação
│   │   ├── appointments/  # Agendamentos
│   │   ├── doctors/       # Médicos
│   │   ├── patients/      # Pacientes
│   │   ├── availability/  # Disponibilidade
│   │   └── avatars/       # Avatares
│   ├── context/           # Context API
│   ├── hooks/             # Custom hooks
│   ├── types/             # TypeScript types
│   └── utils/             # Funções utilitárias
├── public/                # Arquivos estáticos
├── scripts/               # Scripts de utilidade
└── dist/                  # Build de produção
```

---

## 🔑 APIs e Serviços

### Principais Endpoints

#### Agendamentos

```typescript
// Buscar slots disponíveis (Edge Function)
POST /functions/v1/get-available-slots
{
  "doctor_id": "uuid",
  "date": "2025-10-30"
}

// Criar agendamento
POST /rest/v1/appointments
{
  "doctor_id": "uuid",
  "patient_id": "uuid",
  "scheduled_at": "2025-10-30T09:00:00Z",
  "duration_minutes": 30,
  "appointment_type": "presencial"
}
```

#### Disponibilidade

```typescript
// Listar disponibilidade do médico
GET /rest/v1/doctor_availability?doctor_id=eq.{uuid}

// Criar horário de atendimento
POST /rest/v1/doctor_availability

// Atualizar disponibilidade
PATCH /rest/v1/doctor_availability?id=eq.{uuid}
```

#### Usuários

```typescript
// Criar médico (Edge Function com validações)
POST /functions/v1/create-doctor

// Criar paciente
POST /rest/v1/patients

// Listar médicos
GET /rest/v1/doctors?select=*

// Atualizar perfil
PATCH /rest/v1/doctors?id=eq.{uuid}
```

**Documentação completa:** Ver [AGENDAMENTO-SLOTS-API.md](./AGENDAMENTO-SLOTS-API.md)

---

## 🔒 Autenticação e Permissões

### Sistema de Autenticação

- **JWT Tokens** com refresh automático
- **Magic Link** - Login sem senha via email
- **Recuperação de senha** com email
- **Interceptors** adicionam token automaticamente
- **Renovação automática** quando token expira

### Roles e Permissões (RLS)

**Admin/Gestor:**

- Acesso completo a todos os recursos
- Criar/editar/deletar usuários
- Visualizar todos os dados

**Médicos:**

- Gerenciar agenda e disponibilidade
- Visualizar todos os pacientes
- Criar e editar prontuários
- Ver apenas próprios agendamentos

**Pacientes:**

- Agendar consultas
- Visualizar histórico próprio
- Editar perfil pessoal
- Download de relatórios médicos

**Secretárias:**

- Cadastrar médicos e pacientes
- Gerenciar agendamentos
- Configurar agendas médicas
- Busca e filtros avançados

---

## 🎨 Recursos de Acessibilidade

- ✅ Modo de alto contraste
- ✅ Ajuste de tamanho de fonte
- ✅ Navegação por teclado
- ✅ Leitores de tela compatíveis
- ✅ Menu de acessibilidade flutuante

---

## 📊 Dashboards e Relatórios

### Médico

- Total de pacientes atendidos
- Consultas do dia/semana/mês
- Próximas consultas
- Histórico de atendimentos

### Paciente

- Histórico de consultas
- Relatórios médicos com download PDF
- Próximos agendamentos
- Acompanhamento médico

### Secretária

- Visão geral de agendamentos
- Filtros por médico, data e status
- Busca de pacientes e médicos
- Estatísticas gerais

---

## 🚀 Melhorias Recentes (Novembro 2025)

### 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://<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 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> = ({ ...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**
