Command Agenda
Sistema de Agendamento Médico — Documentação Técnica Completa v2.0
Introdução
O Command Agenda é um sistema completo de agendamento médico desenvolvido para a gestão de consultas em unidades de saúde. O sistema é composto por três módulos principais:
Painel Administrativo (ADM)
Interface para gestores e operadores gerenciarem agendas, pacientes, médicos, unidades, especialidades, grades de horários, fila de espera (backlog), cancelamento em massa e gestão de usuários com RBAC.
Portal do Paciente
Interface para pacientes se cadastrarem, solicitarem agendamentos, acompanharem solicitações na fila de espera, confirmarem ou recusarem propostas, e exportarem consultas confirmadas para calendários (Google / iCal).
API REST
Backend Cloudflare Workers (Hono) com 4 bancos D1 distribuídos, 14 módulos de rotas, autenticação JWT dupla (admin + paciente), RBAC com 5 níveis, upload R2 e integração WhatsApp/Mailjet.
Arquitetura do Sistema
Camada de Apresentação
Camada de API
Camada de Dados
Serviços Externos
Stack Tecnológico
Frontend (ADM e Paciente)
- React 18 — SPA com componentes funcionais e hooks
- Vite — Build tool e dev server
- Tailwind CSS — Estilização utilitária
- React Beautiful DnD — Drag-and-drop (ADM)
- Context API — AuthContext, LoadingContext, ToastContext
Backend (API)
- Cloudflare Workers — Serverless runtime
- Hono — Framework HTTP leve
- Cloudflare D1 — Banco SQLite distribuído (×4)
- Cloudflare R2 — Object storage (fotos)
- Wrangler — Deploy e gerenciamento
Autenticação
- JWT — Tokens com JTI e sessões (8h admin, 24h paciente)
- bcrypt — Hash de senhas
- RBAC — 5 níveis hierárquicos
- Primeiro Acesso — Token + e-mail + senha temporária
- Auth Dupla — Admin e Paciente compartilham rotas
Integrações
- Whapi.cloud — WhatsApp API (OTP + propostas + confirmações)
- Mailjet — E-mails transacionais (primeiro acesso)
- Google Calendar — Link direto para criar evento
- iCalendar (.ics) — Download para Outlook/Apple Calendar
Modelo de Dados
O sistema utiliza 4 bancos de dados Cloudflare D1 para isolamento e escalabilidade:
DB (Principal)
ca_gradeagenda— Grades de horários dos médicosca_slotagenda— Slots individuais de atendimentoca_grade_dia_cancelado— Dias cancelados/restaurados em grades
DB_HISTORICO
ca_agendamento— Agendamentos realizadosca_backlog— Fila de espera (solicitações)
DB_USUARIOS
ca_paciente— Cadastro de pacientesca_medico— Cadastro de médicosca_medico_especialidade— Médico × Especialidade (N:N)ca_paciente_tiposlot— Paciente × Tipo Slot (N:N)ca_usuario_admin— Usuários administrativosca_sessao— Sessões adminca_sessao_paciente— Sessões paciente
DB_PARAMETROS
ca_especialidade— Especialidades médicasca_especialidade_cota— Cotas de vagas por tipo de slotca_unidade— Unidades de saúde (com endereço e horários)ca_consultorio— Consultórios por unidadeca_tiposlot— Tipos de slot (Normal, Prioritário, etc.)
Principais Tabelas
| Tabela | Campos Principais | Banco |
|---|---|---|
ca_paciente | pacienteid, nomecompleto, cpf, datanascimento, telefone, email, senhahash, tipo (Comum/Prioritário/Gestante/Idoso/PcD), tipo_vinculo, nome_mae, status, telefone_validado, funcionario, origem | DB_USUARIOS |
ca_medico | medicoid, nomecompleto, crm, crm_uf, cpf, datanascimento, telefone, email, endereco, unidadeid, status, limitevagas, observacoes, foto_url, dadosbancarios | DB_USUARIOS |
ca_gradeagenda | gradeagendaid, medicoid, especialidadeid, unidadeid, consultorioid, vigencia, overbooking, limitevagas, status | DB |
ca_slotagenda | slotagendaid, gradeagendaid, medicoid, tiposlotid, datainicio, datafim, status (Livre/Ocupado/Cancelado), isoverbooking, periodo, limitevagas | DB |
ca_agendamento | agendamentoid, slotagendaid, pacienteid, protocolo, ordem, status (Ativo/Cancelado/Confirmado/Não Compareceu), datasolicitacao | DB_HISTORICO |
ca_backlog | backlogid, pacienteid, especialidadeid, medicoid, unidadeid, data_preferida, periodo_preferido, horario_preferido, prioridade, origem, status, tipos_slot_elegiveis, cpf, telefone, ativo | DB_HISTORICO |
ca_usuario_admin | usuarioid, nome, email, cpf, cargo, role, ativo, senhahash, senha_temporaria, token_primeiro_acesso, primeiro_acesso | DB_USUARIOS |
ca_unidade | unidadeid, nome, tipo, status, logradouro, numero, complemento, bairro, cidade, uf, cep, telefone, horario_abertura, horario_fechamento, dias_funcionamento, horarios_por_dia | DB_PARAMETROS |
ca_especialidade | especialidadeid, nome, limitevagas, status | DB_PARAMETROS |
ca_tiposlot | tiposlotid, nome, finalidade, status, canalorigem, cor, agendavel | DB_PARAMETROS |
Autenticação do Administrador
Fluxo de Login
E-mail e senha. Branding Prefeitura de Barueri / NIB.
POST /api/auth/login → JWT com JTI + sessão
Acesso baseado no role (RBAC)
Primeiro Acesso
- Admin cria usuário → sistema gera senha temporária + token de primeiro acesso
- E-mail enviado (Mailjet) com link contendo o token
- Novo usuário acessa link → informa e-mail + senha temporária + nova senha
- Requisitos: mínimo 10 caracteres, maiúscula, minúscula, número e símbolo
- Token expirado? Admin pode reenviar via
POST /api/auth/resend-first-access
Endpoints
/api/auth/login — Login com e-mail e senha/api/auth/logout — Revoga sessão JWT/api/auth/me — Dados do usuário logado/api/auth/validate-first-access — Valida token de primeiro acesso/api/auth/first-access — Define nova senha/api/auth/resend-first-access — Reenvia e-mail de primeiro acessoDashboard Principal
Tela principal do painel administrativo com visão completa da agenda médica.
Funcionalidades
Calendário Multi-Visão
Mês, Semana e Dia com indicadores de vagas disponíveis e ocupadas por dia.
Filtros Sincronizados
Filtre por unidade, especialidade e médico. Sincronização bidirecional com o backlog.
Drag-and-Drop
Arraste pacientes do backlog para o calendário para alocação inteligente.
Estatísticas da Grade
Totais de slots, médicos e especialidades por dia. API: GET /api/grade-stats/day/:date
Busca de Pacientes
Pesquise por nome ou CPF. API: GET /api/agendamentos/buscar-paciente
Detalhe do Dia
Modal com todos os agendamentos, filtros, confirmação de presença e marcação de não comparecimento.
Modal de Detalhe do Dia
- Estatísticas: Total, ativos, cancelados, especialidades e médicos
- Filtros: Nome/CPF, status, especialidade, médico, unidade
- Ordenação: Data cadastro, horário, paciente, médico
- Ações: Confirmar presença (
PUT /:id/confirmar-presenca), marcar não comparecimento (PUT /:id/nao-compareceu), expandir detalhes
Painel do Operador
Visão otimizada para operadores com layout dividido 60/40:
Painel Esquerdo (60%)
Agenda diária com grupos de slots por hora, vagas, médico e tipo de slot. Agendamento direto.
Painel Direito (40%)
Fila de espera com drag-and-drop para o painel esquerdo.
Alocação Inteligente
Auto-busca do melhor slot baseado nas preferências do paciente. API: POST /api/backlog/:id/alocar-inteligente
Detalhes do Paciente
Perfil completo: CPF, telefone (validado ✓), tipo, vínculo, tipos de slot elegíveis, tempo na fila, preferências.
Configurações
Abas filtradas por permissão RBAC:
Especialidades
- CRUD com inativação/reativação (soft delete)
- Cotas por tipo de slot: Distribuição de vagas (ex: 3 Normal, 2 Prioritário, 1 Encaixe)
- Validação: soma das cotas = limite de vagas da especialidade
- API:
GET/POST /api/especialidades,GET/POST /api/especialidades/:id/cotas
Médicos
- CRUD com inativação/reativação
- Multi-especialidades (N:N), upload/remoção de foto (R2), CRM/CPF/telefone
- Filtro por especialidade e status
- API:
GET/POST/PUT/DELETE /api/medicos,POST/DELETE /api/upload/medico/:id/foto
Unidades de Saúde
- CRUD com inativação/reativação. Tipos: Clínica, Hospital, Consultório, Outro
- Endereço completo (logradouro, número, bairro, cidade, UF, CEP)
- Horários de funcionamento: global ou individual por dia da semana
- Gestão inline de consultórios (criar, renomear, inativar)
- API:
GET/POST/PUT/DELETE /api/unidades,PATCH /api/unidades/:id/reativar
Tipos de Slot
- CRUD com soft delete. Campos: nome, finalidade, canal de origem, cor, flag "agendável"
- Exemplos: Normal, Prioritário, Encaixe, Retorno, Programa Municipal
- API:
GET/POST/PUT/DELETE /api/tipos-slot
Consultórios
- CRUD vinculado à unidade. Soft delete com verificação de grades ativas
- Reativação disponível
- API:
GET/POST/PUT/DELETE /api/consultorios,PATCH /api/consultorios/:id/reativar
Pacientes
- Listagem com busca (nome/CPF), estatísticas (total, ativos, inativos, telefone validado)
- Cadastro completo: CPF validado, tipo, vínculo, mãe, tipos de slot elegíveis
- Validação de telefone via SMS (6 dígitos), detecção automática de funcionário
- API:
/api/pacientes+ sub-rotas de validação e tipos-slot
Gerador de Grade de Horários
Wizard de 5 etapas para criação em massa de grades de agenda:
Unidade, especialidade, médico, consultório
Data início e fim
Horas para cada dia da semana (Seg-Sáb)
Quantidade por tipo de slot (auto-preenchimento via cotas)
Resumo com detecção de conflitos. Gera via POST /api/slots/generate-bulk
ca_gradeagenda e gera slots em massa para cada dia/hora configurado. O gerador reutiliza grades existentes para o mesmo médico/unidade/especialidade.Gestão de Dias da Grade
Mini-calendário para cancelar/restaurar dias específicos de grades recorrentes:
- Cancelar dia: Com motivo obrigatório. Cancela automaticamente slots livres do dia
- Restaurar dia: Mantém histórico e reativa slots cancelados
- Histórico: Quem cancelou, quando, e se foi restaurado
- Filtros: unidade, especialidade, médico
Endpoints
/api/grade-agenda/:id/cancelled-days — Dias cancelados/api/grade-agenda/:id/cancelled-days/range — Dias cancelados por período/api/grade-agenda/:id/cancel-day — Cancelar dia/api/grade-agenda/:id/restore-day — Restaurar dia/api/grade-agenda/:id/day-history/:data — Histórico do diaCancelamento em Massa
Ferramenta multi-etapa para cancelar slots em lote:
- Filtros: Intervalo de datas, período (manhã/tarde/noite), médico, especialidade, unidade, tipo de slot
- Preview: Lista de slots afetados antes da execução
- Realocação: Opção de mover pacientes com agendamentos cancelados para o backlog
Backlog / Fila de Espera
Gestão da fila de pacientes aguardando agendamento:
Priorização
🔴 Alta, 🟡 Média, 🟢 Baixa. Ordenação automática.
Multi-Filtros
Prioridade, especialidade, unidade, médico, status. Sincronização com calendário.
Alocação
Drag-and-drop, alocação inteligente, ou manual (modal 3 passos: data → unidade → horário).
Adicionar à Fila
Busca paciente (autocomplete), filtros cascata, preferências, prioridade e origem.
Fluxo de Status
Na fila aguardando
Proposta enviada (WhatsApp)
Confirma → cria agendamento. Recusa → volta para Pendente
Endpoints do Backlog
/api/backlog — Listar (paginado, filtros, RBAC)/api/backlog/:id — Detalhes (RBAC)/api/backlog — Criar solicitação/api/backlog/:id — Atualizar solicitação/api/backlog/:id/alocar — Alocar em slot/api/backlog/:id/confirmar — Paciente confirma/api/backlog/:id/recusar — Paciente recusa/api/backlog/:id/alocar-dia — Alocação por dia/api/backlog/:id/alocar-inteligente — Alocação inteligente/api/backlog/:id/inativar — Soft-delete/api/backlog/:id — Cancelar solicitaçãoRegra D-30
Gestão de Pacientes
Endpoints
/api/pacientes — Listar (filtros: cpf, search). Limite: 50/api/pacientes/:id — Detalhes/api/pacientes — Criar (com detecção de funcionário)/api/pacientes/:id — Atualizar/api/pacientes/:id — Inativar (soft delete)/api/pacientes/:id/reativar — Reativar/api/pacientes/:id/validar-telefone — Gerar código SMS/api/pacientes/:id/confirmar-telefone — Confirmar código/api/pacientes/:id/validacao-telefone — Remover validação/api/pacientes/:id/tipos-slot — Tipos de slot elegíveis/api/pacientes/:id/tipos-slot — Atualizar elegíveisGestão de Usuários
Apenas para administrador_master.
Endpoints
/api/usuarios — Listar (paginado, busca, filtros role/status)/api/usuarios/:id — Detalhes/api/usuarios — Criar (gera senha temp + envia e-mail)/api/usuarios/:id — Atualizar (nome, email, cpf, cargo, role, senha, ativo)Controle de Acesso (RBAC)
5 níveis hierárquicos:
Acesso total. Gerencia usuários e todas as configurações.
Todas as configurações, grades, backlog, dashboard. Sem gestão de usuários.
Configurações, geração de grades, backlog.
Opera backlog e dashboard. Agenda/cancela, sem alterar configurações.
Apenas leitura.
| Funcionalidade | visualizador | operador | gerenciador | administrador | admin_master |
|---|---|---|---|---|---|
| Dashboard (leitura) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Agendar / Cancelar | ❌ | ✅ | ✅ | ✅ | ✅ |
| Backlog (alocar) | ❌ | ✅ | ✅ | ✅ | ✅ |
| Configurações | ❌ | ❌ | ✅ | ✅ | ✅ |
| Gerar Grades | ❌ | ❌ | ✅ | ✅ | ✅ |
| Pacientes | ❌ | ✅ | ✅ | ✅ | ✅ |
| Gestão de Usuários | ❌ | ❌ | ❌ | ❌ | ✅ |
Cadastro do Paciente
Campos
- Nome completo (obrigatório), CPF (obrigatório, validação de dígitos), Senha (mínimo 6 caracteres)
- Data de nascimento, e-mail, telefone (validação WhatsApp OTP 4 dígitos), até 3 contatos adicionais
Validação WhatsApp OTP
Código 4 dígitos via Whapi.cloud
4 campos auto-foco, auto-submit, paste
5 min expiração, 3 tentativas, cooldown 60s
/api/auth/paciente/register — Cadastro (CPF + senha + nome)Login do Paciente
/api/auth/paciente/login — Login CPF + senha (JWT 24h)/api/auth/paciente/me — Dados do paciente logado/api/auth/paciente/logout — Revogar sessãoSolicitar Agendamento
Wizard de 3 etapas (adicionado ao backlog como "Pendente"):
Selecionar especialidade (obrigatório), unidade e médico (opcionais)
Data (amanhã a +60 dias), período, urgência, observações
Resumo e envio
Cálculo de Prioridade
- Alta: Urgência + sem data, ou urgência + data ≤ 7 dias
- Média: Urgência + data > 7 dias
- Baixa: Sem urgência
Minhas Solicitações
Abas
- Em Andamento: Pendente e Aguardando Confirmação
- Histórico: Agendadas, Canceladas, etc.
Proposta de Agendamento
Quando "Aguardando Confirmação":
- Detalhes do slot proposto (data, hora, médico, especialidade, unidade, endereço)
- Diferenças entre preferências e proposta
- Confirmar → cria agendamento + notificação WhatsApp
- Recusar → volta para "Pendente"
Histórico de Agendamentos
Via GET /api/agendamentos/meus:
- Data, hora, médico, especialidade, unidade, protocolo
- Status: Agendado, Confirmado, Cancelado, Não Compareceu
- Cancelamento de agendamentos futuros
- Exportação para calendário (Google / iCal)
Exportar para Calendário
Google Calendar
Link direto com título, detalhes (médico, especialidade, protocolo), local (unidade), duração 30 min.
Download .ics
Arquivo iCalendar para Outlook, Apple Calendar, etc. 2 lembretes: 1h e 1 dia antes.
Diagramas UML
Diagrama de Componentes
┌─────────────────────────────────────────────────────────────────┐ │ COMMAND AGENDA SYSTEM │ │ │ │ ┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ │ │ ADM Frontend │ │ Paciente Frontend │ │ API (Hono) │ │ │ │ (React) │ │ (React) │ │ Workers │ │ │ │ │ │ │ │ │ │ │ │ - Dashboard │ │ - Cadastro/Login │ │ - Auth (Admin) │ │ │ │ - Operador │ │ - Solicitar Ag. │ │ - Auth (Paciente)│ │ │ │ - Config │ │ - Solicitações │ │ - Agendamentos │ │ │ │ - Grade Gen │ │ - Histórico │ │ - Backlog │ │ │ │ - Grade Dias │ │ - Calendário │ │ - Slots │ │ │ │ - Cancel.Mas.│ │ - WhatsApp OTP │ │ - Grade Agenda │ │ │ │ - Backlog │ │ │ │ - Grade Stats │ │ │ │ - Pacientes │ │ │ │ - Médicos │ │ │ │ - Usuários │ │ │ │ - Pacientes │ │ │ │ │ │ │ │ - Especialidades │ │ │ └──────┬───────┘ └────────┬─────────┘ │ - Unidades │ │ │ │ │ │ - Consultórios │ │ │ │ HTTPS / JWT │ │ - Tipos Slot │ │ │ └────────┬───────────┘ │ - Usuários │ │ │ │ │ - Upload (R2) │ │ │ └──────────────────────────┤ │ │ │ └────────┬─────────┘ │ │ │ │ │ ┌───────────┐ ┌────────────┐ ┌───────────┐ ┌──────────────────┐ │ │ │ DB │ │ DB_HISTORICO│ │DB_USUARIOS│ │ DB_PARAMETROS │ │ │ │ Grades │ │ Agendament │ │ Pacientes │ │ Especialidades │ │ │ │ Slots │ │ Backlog │ │ Médicos │ │ Unidades │ │ │ │ DiasCan │ │ │ │ Admins │ │ Consultórios │ │ │ └──────────┘ └────────────┘ │ Sessões │ │ TiposSlot/Cotas │ │ │ └───────────┘ └──────────────────┘ │ │ Integrações: Whapi.cloud (WhatsApp) · Mailjet · R2 Storage │ └─────────────────────────────────────────────────────────────────┘
Fluxo: Solicitação → Backlog → Agendamento
Paciente Portal API DB_HISTORICO WhatsApp │ │ │ │ │ │ 1. Solicitar │ │ │ │ ├──────────────────→│ POST /backlog │ │ │ │ ├───────────────→│ INSERT ca_backlog │ │ │ │ │ (Pendente) │ │ │ │ ├───────────────────→│ │ │ ← "Na fila" │ │ │ │ │←─────────────────┤ │ │ │ │ │ │ │ │ │ ── OPERADOR ALOCA ── │ │ │ │ ADM │ │ │ │ │ │ PATCH /:id/alocar │ │ │ ├───────────────→│ UPDATE → │ │ │ │ │ "Ag. Confirmação" │ │ │ │ ├───────────────────→│ │ │ │ │ Notify │─────────→│ │ │ │ │ │ │ 2. Ver proposta │ │ │ │ ├──────────────────→│ GET /backlog │ │ │ │ ← detalhes │ │ │ │ │ │ │ │ │ │ 3. Confirmar │ │ │ │ ├──────────────────→│ PATCH /:id/confirmar │ │ │ ├───────────────→│ CREATE agendamento │ │ │ │ │ UPDATE → "Agendado"│ │ │ │ ├───────────────────→│ │ │ │ │ Notify confirmação │─────────→│ │ ← Agendado! │ │ │ │ │←─────────────────┤ │ │ │
Diagrama ER (Simplificado)
┌──────────────┐ ┌───────────────┐ ┌──────────────┐ ┌──────────────┐
│ ca_unidade │ │ca_especialidade│ │ ca_medico │ │ ca_tiposlot │
│──────────────│ │───────────────│ │──────────────│ │──────────────│
│PK unidadeid │ │PK especialid. │ │PK medicoid │ │PK tiposlotid │
│ nome │ │ nome │ │ nomecompleto│ │ nome │
│ tipo │ │ limitevagas │ │ crm │ │ cor │
│ endereco...│ │ status │ │ foto_url │ │ agendavel │
└──────┬───────┘ └───────┬───────┘ └──────┬───────┘ └──────────────┘
│ │ │
│ ┌──────┴──────┐ ┌──────┴──────┐
│ │ca_espec_cota│ │ca_med_espec │
│ │ vagas │ │ N:N │
│ └─────────────┘ └─────────────┘
│
┌──────┴───────┐ ┌───────────────┐
│ca_consultorio│ │ca_gradeagenda │──→ ca_slotagenda ──→ ca_agendamento
│ nome │ │ FK medico │
│ FK unidadeid │ │ FK especialid.│ ↑
└──────────────┘ │ FK unidade │ ca_paciente ──→ ca_backlog
│ FK consultorio│
└───────────────┘