# Agenda do Médico — Especificação (v1.0)

**Documentos desta funcionalidade:** [01 - Definição](./01%20-%20Defini%C3%A7%C3%A3o%20v1.5.md) (v1.5) · [02 - Especificação](./02%20-%20Especifica%C3%A7%C3%A3o%20v1.0.md) (v1.0) · Protótipo (Seção 3): **pendente** · Mapeamento de Banco de Dados (Seção 4): **pendente**.

---

## SEÇÃO 2 — ESPECIFICAÇÃO

Premissa de design: toda decisão de design nesta especificação é justificada pelo workflow documentado na Seção 1 — o médico chega aqui a partir do painel "Consultas" do Cockpit quando precisa da visão completa do dia (não só os próximos atendimentos) ou quer bloquear um horário.

### Histórias de Usuário

- **US-AGM-001:** Como médico, quero ver minha agenda do dia em lista, com os mesmos elementos de identificação de paciente já usados no Cockpit, para organizar meu trabalho do dia.
- **US-AGM-002:** Como médico, quero navegar entre dias — dia a dia ou pulando direto para o próximo dia com consulta — para checar minha agenda com agilidade, mesmo em dias sem nenhum compromisso.
- **US-AGM-003:** Como médico, quero bloquear um horário vago da minha agenda, para reservar tempo para atividades não assistenciais (reunião, ausência).
- **US-AGM-004:** Como médico, quero desfazer um bloqueio que eu mesmo criei, para corrigir um bloqueio feito por engano ou cujo motivo não existe mais.
- **US-AGM-005:** Como médico, quero que consultas já realizadas ou canceladas fiquem agrupadas e fora do caminho, para manter o foco nas consultas pendentes sem perder a visão de que o dia inteiro está ali.

### Descrição Funcional Detalhada

#### Cabeçalho de Navegação

Barra fixa no topo da tela, abaixo do cabeçalho padrão do sistema, com três elementos:

1. **Data atual em destaque** — dia da semana + data completa (ex.: "Segunda-feira, 31 de agosto"). Quando o dia exibido é hoje, um rótulo "Hoje" aparece ao lado.
2. **Navegação por dia (RN-AGM-003):** dois mecanismos, lado a lado, combinando as duas formas de navegação confirmadas pelo solicitante:
    - Setas sequenciais (◂ ▸) avançam ou retrocedem um dia por vez — o uso mais frequente, sempre visível.
    - Um segundo par de ícones de atalho (ex.: ◂| |▸), imediatamente ao lado das setas sequenciais, pula direto para o próximo/anterior dia que tenha ao menos uma consulta agendada — evita percorrer, um a um, dias sem nenhum compromisso. Fica desabilitado quando não há nenhum dia com consulta naquela direção (passado ou futuro).
    - Um ícone de calendário abre um seletor de data em formato de mini-calendário mensal; os dias com ao menos uma consulta aparecem marcados visualmente (ponto ou destaque sob o número do dia) — permite pular direto para qualquer dia específico, não só o próximo/anterior imediato. Selecionar um dia no calendário fecha o seletor e carrega a agenda daquele dia.
    - Botão "Hoje" — sempre visível, retorna ao dia atual em um toque, independentemente de quantos dias o médico tenha navegado.
3. **Botão "Bloquear horário"** — ação secundária, sempre visível no cabeçalho (não depende de selecionar um horário específico primeiro; o próprio horário é escolhido dentro do fluxo, ver "Fluxo de Bloqueio de Horário").

Motivador: os dois mecanismos de pular dias (atalho sequencial + calendário) atendem necessidades diferentes do mesmo touchpoint — o atalho sequencial é mais rápido para "o próximo dia que eu trabalho", o calendário é necessário quando o médico já sabe a data exata que quer checar (ex.: "como está minha agenda daqui a duas semanas").

#### Lista de Consultas do Dia

Item por consulta, em ordem cronológica pelo horário de início. Cada item exibe (RN-AGM-009, elementos herdados do Cockpit — mesma origem e lógica já especificadas em Central do Médico, Seção 2.3):

- Paciente: nome (preferido, com o nome legal como alternativa), foto, diagnóstico oncológico.
- Horário (início–fim).
- Status do atendimento (chip colorido, mesma paleta e lógica do Cockpit).
- Modo de atendimento.
- Indicador de primeira consulta.
- Tags do paciente — aqui restritas ao subconjunto habilitado para exibição em agenda (RN-AGM-006).

Nota de nomenclatura: "Modo de atendimento" (campo `attendanceMode` na API — presencial, telemedicina etc.) e "Tipo de consulta" (campo `appointmentType`, RN-AGM-008) são dois campos distintos, apesar do nome parecido — o primeiro descreve o canal do atendimento, o segundo é um domínio configurável pela clínica (ex.: primeira consulta, retorno, revisão).

Mais dois elementos exclusivos desta tela:

- **Complemento** (RN-AGM-007) — quando preenchido, exibido como uma linha de texto secundária abaixo do horário, sem rótulo (o formato livre já deixa claro que é uma observação).
- **Tipo de consulta** (RN-AGM-008) — quando a clínica configurou esse domínio, exibido como um chip ou rótulo curto ao lado do horário; ausente quando a clínica não configurou.

Toque em qualquer parte do item (exceto a ação de desfazer bloqueio, ver abaixo) abre o PEP do paciente (RN-AGM-009).

**Itens de horário bloqueado (RN-AGM-004):** aparecem na mesma lista, na posição cronológica correspondente, mas visualmente diferenciados dos itens de consulta — sem foto, diagnóstico ou tags (não há paciente real associado a exibir), com um ícone de cadeado, o rótulo "Bloqueado", o horário e o complemento (quando preenchido no momento do bloqueio). Não abrem o PEP ao toque — em vez disso, exibem a ação "Desfazer bloqueio" (US-AGM-004).

#### Bloco de Consultas Já Realizadas (RN-AGM-010)

Consultas com status `finished` ou `canceled` não aparecem como itens individuais na lista — são substituídas por um único item recolhido, no topo da lista, com o formato "N consultas já realizadas ▸" (N = contagem do dia). Tocar no item expande o bloco, revelando as consultas individuais (mesmo formato de item da lista normal); tocar novamente recolhe. Mesmo comportamento já demonstrado na exploração `Comparação de Formato — Lista vs Grade (exploração).html`, mantido aqui como referência de comportamento (não é a Seção 3 final).

Logo abaixo do bloco (recolhido ou expandido), uma linha de ancoragem "AGORA · HH:MM" marca a posição do horário atual — **somente quando o dia exibido é hoje**. A tela abre com a rolagem já posicionada nessa linha, deixando a próxima consulta pendente visível sem necessidade de rolagem. Em qualquer outro dia (passado ou futuro), a linha "AGORA" não aparece — a tela abre com a rolagem no topo da lista, já que não há um "agora" que faça sentido dentro daquele dia.

**[A DEFINIR]** Horários bloqueados no passado (já ocorridos) não são cobertos literalmente por RN-AGM-010, que fala apenas em "consultas" — nesta versão, um bloqueio já ocorrido permanece como item individual na lista, fora do bloco recolhido. Se isso poluir a visão do dia na prática, é um ajuste a avaliar numa versão futura; não presumido aqui por não ter sido pedido.

#### Fluxo de Bloqueio de Horário (RN-AGM-004, US-AGM-003)

Ao tocar em "Bloquear horário": abre um formulário simples (modal ou tela dedicada — detalhe de camada visual para a Seção 3) com:

- **Horário** — seleção de início e duração. **[PROPOSTA]** intervalos de 15 minutos, com opções de duração pré-definidas (15/30/45/60 min) e uma opção "outro" para duração customizada — não especificado pelo solicitante; alinhado ao menor incremento comum de agendamento de consulta, a confirmar.
- **Complemento** (RN-AGM-007) — campo de texto livre, opcional (confirmado pelo solicitante), até 128 caracteres — mesmo campo e limite já usados nas consultas.
- Botão "Confirmar bloqueio".

Validação: o horário escolhido não pode sobrepor uma consulta já agendada nem outro bloqueio existente (EX-AGM-01). **[PROPOSTA]** o horário escolhido também não pode estar no passado (data/hora já decorridas) — não especificado pelo solicitante; proposto porque um bloqueio retroativo não tem efeito prático (não libera nem ocupa nada que já aconteceu) e poderia confundir a leitura do dia — a confirmar. Ao confirmar com sucesso, o modal/tela fecha e o novo item bloqueado aparece na lista, na posição cronológica correspondente.

#### Fluxo de Desfazer Bloqueio (US-AGM-004)

Cada item bloqueado exibe uma ação "Desfazer bloqueio". Ao tocar: **[PROPOSTA]** confirmação leve inline (ex.: o botão vira "Confirmar?" por alguns segundos, sem modal completo) antes de efetivar — evita desfazer por toque acidental sem impor a fricção de um modal para uma ação de baixo risco e reversível (o horário só volta a ficar vago; nenhum dado de paciente é afetado). Ao confirmar, o item sai da lista e o horário volta a ficar vago (disponível para a Recepção agendar uma consulta real ali).

### Critérios de Aceitação

**CA-001.1**: Dado que o médico abre a Agenda a partir do Cockpit, quando a tela carrega, então exibe a agenda do dia atual, em formato de lista, com as consultas em ordem cronológica.

**CA-001.2**: Dado que uma consulta tem tags do paciente cadastradas, quando o item é exibido, então só as tags com `MostrarEm` habilitado para agendas aparecem (RN-AGM-006) — as demais, mesmo existindo, não são exibidas.

**CA-001.3**: Dado que uma consulta tem o campo de complemento preenchido, quando o item é exibido, então o complemento aparece como texto secundário abaixo do horário.

**CA-001.4**: Dado que a clínica não configurou tipos de consulta, quando os itens são exibidos, então nenhum chip de tipo de consulta aparece em nenhum item.

**CA-001.5**: Dado que o médico toca em um item de consulta, então o sistema abre o PEP do paciente correspondente.

**CA-001.6**: Dado que ocorre erro de rede ou falha do back-end ao carregar a agenda do dia, então a tela exibe o estado de erro (EX-AGM-02) com MSG-EAGM-03 e a ação "Tentar novamente", sem nenhum item exibido.

**CA-001.7**: Dado que o médico navega para um dia sem nenhuma consulta nem bloqueio, então a tela exibe o estado vazio (EX-AGM-03) com MSG-TAGM-01, e o botão "Bloquear horário" continua disponível.

**CA-002.1**: Dado que o médico toca na seta sequencial "próximo dia", então a tela recarrega mostrando o dia seguinte ao atualmente exibido, independentemente de haver ou não consulta nele.

**CA-002.2**: Dado que o médico toca no atalho "próximo dia com consulta", então a tela pula diretamente para a data da próxima consulta agendada do médico, ignorando dias vazios no caminho.

**CA-002.3**: Dado que não existe nenhuma consulta futura agendada para o médico, quando ele toca no atalho "próximo dia com consulta", então o atalho aparece desabilitado (não há para onde pular).

**CA-002.4**: Dado que o médico abre o seletor de calendário, quando o mini-calendário é exibido, então os dias com ao menos uma consulta aparecem marcados visualmente, diferenciados dos dias sem consulta.

**CA-002.5**: Dado que o médico está em qualquer dia diferente de hoje, quando toca em "Hoje", então a tela recarrega mostrando o dia atual.

**CA-003.1**: Dado que o médico toca em "Bloquear horário" e escolhe um horário vago, quando confirma sem preencher o complemento, então o bloqueio é criado com sucesso e aparece na lista.

**CA-003.2**: Dado que o médico escolhe, no formulário de bloqueio, um horário que sobrepõe uma consulta já agendada, quando tenta confirmar, então o sistema impede a confirmação e exibe MSG-EAGM-01.

**CA-003.3**: Dado que o médico preenche o complemento com mais de 128 caracteres, quando tenta confirmar, então o sistema impede a confirmação e exibe MSG-EAGM-02.

**CA-003.4**: Dado que o back-end retorna erro ao tentar salvar um bloqueio já validado no front, então o sistema exibe o toast MSG-EAGM-04 (EX-AGM-04) e mantém o formulário aberto com os dados preenchidos.

**CA-004.1**: Dado que o médico toca em "Desfazer bloqueio" em um item bloqueado por ele, quando confirma a ação, então o item sai da lista e o horário volta a ficar vago.

**CA-004.2**: Dado que o médico toca em "Desfazer bloqueio" mas não confirma dentro do intervalo de confirmação leve, então nenhuma alteração é feita e o item permanece bloqueado.

**CA-004.3**: Dado que o back-end retorna erro ao tentar remover um bloqueio já confirmado, então o sistema exibe o toast MSG-EAGM-05 (EX-AGM-05) e o item permanece na lista, marcado como bloqueado.

**CA-005.1**: Dado que existem consultas com status `finished` ou `canceled` no dia, quando a tela carrega, então elas aparecem agrupadas em um único item recolhido no topo da lista, com a contagem correta.

**CA-005.2**: Dado que o médico toca no bloco recolhido, então ele expande, revelando cada consulta individualmente, no mesmo formato dos demais itens da lista.

**CA-005.3**: Dado que a tela carrega, então a posição de rolagem já está ancorada na linha "AGORA", sem necessidade de o médico rolar manualmente para encontrar a próxima consulta pendente.

**CA-005.4**: Dado que nenhuma consulta do dia tem status `finished` ou `canceled`, quando a tela carrega, então o bloco recolhido não aparece.

### Fluxos de Exceção

**EX-AGM-01 — Horário de bloqueio sobreposto**

Gatilho: o médico tenta confirmar um bloqueio cujo horário sobrepõe uma consulta já agendada ou outro bloqueio existente. Comportamento: a confirmação é impedida, com mensagem inline MSG-EAGM-01 apontando o conflito. Recuperação: o médico ajusta o horário e tenta novamente.

**EX-AGM-02 — Falha ao carregar a agenda do dia**

Gatilho: erro de rede ou falha do back-end ao buscar a agenda do dia solicitado. Comportamento: estado de erro na tela (mensagem MSG-EAGM-03 + ação "Tentar novamente"), sem nenhum item exibido. Recuperação: o médico aciona "Tentar novamente"; se persistir, orientação a contatar o suporte.

**EX-AGM-03 — Dia sem nenhuma consulta nem bloqueio**

Gatilho: o médico navega para um dia em que não há nenhuma consulta agendada nem horário bloqueado. Comportamento: estado vazio com mensagem orientativa MSG-TAGM-01 e o botão "Bloquear horário" continua disponível. Não é um erro — é um estado esperado (ex.: fim de semana, dia de folga).

**EX-AGM-04 — Falha ao criar bloqueio**

Gatilho: o back-end retorna erro ao tentar salvar um bloqueio já validado no front (ex.: condição de corrida — outro processo ocupou o horário entre a validação local e o envio). Comportamento: toast de erro MSG-EAGM-04; o formulário permanece aberto com os dados preenchidos, para o médico ajustar e tentar de novo. Recuperação: o médico escolhe outro horário ou tenta novamente.

**EX-AGM-05 — Falha ao desfazer bloqueio**

Gatilho: o back-end retorna erro ao tentar remover um bloqueio. Comportamento: toast de erro MSG-EAGM-05; o item permanece na lista, marcado como bloqueado. Recuperação: o médico tenta novamente.

**EX-AGM-06 — Falha ao carregar dias com consulta (atalho/calendário)**

Gatilho: erro de rede ou falha do back-end ao consultar quais dias têm consulta (atalho sequencial ou seletor de calendário). Comportamento: degradação silenciosa — o atalho de pular dias e o marcador de dias-com-agenda no calendário ficam indisponíveis (atalho desabilitado; calendário abre sem os dias marcados), sem interromper nem exibir erro na tela principal, já que a navegação dia a dia continua funcionando normalmente. Recuperação: o médico continua navegando dia a dia; o recurso volta ao normal na próxima tentativa de abrir o calendário ou usar o atalho.

### Validações de Campos

| Campo | Tipo | Obrigatório | Validação |
|---|---|---|---|
| Horário do bloqueio | seleção de horário (início + duração) | Sim | Não pode sobrepor consulta já agendada nem outro bloqueio existente (EX-AGM-01). **[PROPOSTA]** não pode estar no passado (ver nota em "Fluxo de Bloqueio de Horário"). Duração: ver nota **[PROPOSTA]** em "Fluxo de Bloqueio de Horário". |
| Complemento (bloqueio) | texto livre | Não | Até 128 caracteres (mesmo limite do campo já usado nas consultas, RN-AGM-007). |

### Mapeamento de Componentes de Interface

| Componente | Variante | Estados | Tokens aplicados | Uso nesta tela |
|---|---|---|---|---|
| Card Highlight (Consulta) | Item de lista | default, hover, loading | Mesma anatomia e cores por status já definidas em Central do Médico (Painel de Consultas) | Cada consulta do dia |
| Card | Item bloqueado | default, hover | `--color-neutral-lighter` bg, ícone de cadeado (Lucide `lock`) | Cada horário bloqueado |
| Chip | Status (consulta) | default | Mesma paleta de status já usada no Cockpit | Status de cada consulta |
| Chip | Tag do paciente | default | Mesma paleta já usada no Cockpit, restrita ao subconjunto de RN-AGM-006 | Tags exibidas por consulta |
| Chip | Tipo de consulta | default | `--color-neutral-light` bg, `--color-neutral-darker` texto | Quando a clínica configurou tipos de consulta |
| Accordion/Collapsible | Bloco de já realizadas | recolhido, expandido | `--radius-m`, `--color-neutral-lighter` bg quando recolhido | Bloco de consultas `finished`/`canceled` (RN-AGM-010) |
| Divider com rótulo | Linha "AGORA" | default | `--color-error-pure` (linha e texto) | Âncora de rolagem no horário atual |
| Button | Secondary (Bloquear horário) | default, hover, loading | Mesmos tokens de botão secundário já usados no Cockpit | Botão do cabeçalho |
| Button | Tertiary (Desfazer bloqueio) | default, hover, confirming | `--color-error-pure` texto no estado "confirming" | Ação dentro do item bloqueado |
| Modal/Bottom Sheet | Formulário de bloqueio | default, loading, error | Mesma anatomia de modal já usada no Design System | Fluxo de bloqueio de horário |
| Date Picker (calendário) | Mini-calendário mensal | default, dia-com-agenda | Ponto/destaque sob o número do dia que tem consulta | Seletor de data no cabeçalho |
| Toast | Error | default | `--color-error-pure` | EX-AGM-04, 05 |
| Empty/Error State | Tela cheia (sem itens) | error | `--color-error-pure` ícone e texto, botão "Tentar novamente" | EX-AGM-02 (falha ao carregar a agenda do dia) |
| Empty/Error State | Tela cheia (sem itens) | empty | Mesma anatomia do estado de erro, sem o botão "Tentar novamente" | EX-AGM-03 (dia sem consulta nem bloqueio) |
| Skeleton | Lista | loading | `--color-neutral-lighter` | Carregamento inicial da agenda do dia |

### Integração com Backend

**GET /api/v1/agenda/doctor/day**

Função: retorna a agenda do médico logado para um dia específico — consultas e horários bloqueados.
Query params: `date` (obrigatório, `YYYY-MM-DD`).
Response 200: `{ "date": "2026-08-31", "items": [ { "kind": "appointment", "id": "uuid", "patient": { "id": "uuid", "preferredName": "", "legalName": "Maria da Silva", "photo": "url|null", "diagnosis": ["Ca. Mama"] }, "startTime": "08:00", "endTime": "08:30", "status": "finished", "attendanceMode": "in_person", "firstTime": false, "tags": ["quimioterapia"], "complement": "string|null", "appointmentType": "string|null" }, { "kind": "block", "id": "uuid", "startTime": "12:00", "endTime": "13:00", "complement": "Reunião administrativa|null" } ] }`
- `tags`: já filtradas para o subconjunto habilitado em agenda (RN-AGM-006) — o front não faz esse filtro.
- `status`: presente só quando `kind = "appointment"`; ausente (ou `null`) para `kind = "block"`. Refere-se ao status clínico do atendimento (`finished`, `canceled` etc.) — não confundir com o campo `result` da resposta de `DELETE /blocks/{id}` abaixo, que é o resultado da operação, não um status de atendimento.
- `attendanceMode`: modo de atendimento (presencial, telemedicina etc.) — distinto de `appointmentType` (tipo de consulta, RN-AGM-008); ver nota de nomenclatura em "Lista de Consultas do Dia".
- Mapeamento de BD: Seção 4 (a escrever).

**GET /api/v1/agenda/doctor/days-with-appointments**

Função: retorna as datas, dentro de um intervalo limitado, que têm ao menos uma consulta do médico logado — usado pelo marcador visual do seletor de calendário (RN-AGM-003), que exibe um mês por vez.
Query params: `from` (obrigatório, `YYYY-MM-DD`), `to` (obrigatório, `YYYY-MM-DD`).
Response 200: `{ "dates": ["2026-09-01", "2026-09-03", "2026-09-08"] }`
- O front consulta o mês exibido no mini-calendário a cada abertura/navegação de mês. Este endpoint, por ser limitado a um intervalo, não é usado pelo atalho de pular dias — ver `GET /next-appointment-date` abaixo, que resolve isso sem limite de horizonte (RN-AGM-003).

**GET /api/v1/agenda/doctor/next-appointment-date**

Função: retorna a data da próxima (ou anterior) consulta agendada do médico logado, sem limite de horizonte — usado pelo atalho sequencial de pular dias (RN-AGM-003). Existe como endpoint separado de `days-with-appointments` porque o atalho precisa de uma resposta sem limite de intervalo ("existe alguma consulta futura, não importa quando"), enquanto o calendário precisa apenas do mês visível.
Query params: `direction` (obrigatório, `next` ou `previous`), `from` (obrigatório, `YYYY-MM-DD` — data de referência, normalmente o dia exibido).
Response 200: `{ "date": "2026-09-15" }` ou `{ "date": null }` quando não há nenhuma consulta naquela direção (CA-002.3 usa esse `null` para desabilitar o atalho).

**POST /api/v1/agenda/doctor/blocks**

Função: cria um bloqueio de horário na agenda do médico logado (RN-AGM-004).
Request: `{ "date": "2026-08-31", "startTime": "12:00", "endTime": "13:00", "complement": "string|null" }`
Response 201: `{ "kind": "block", "id": "uuid", "date": "2026-08-31", "startTime": "12:00", "endTime": "13:00", "complement": "string|null" }`
Códigos: 201 (sucesso); 409 (conflito de horário — EX-AGM-01, retorna MSG-EAGM-01); 500 (falha ao salvar — EX-AGM-04).
Tabelas envolvidas: `Agenda`, `Paciente`, `Convenio` (GescomClienteAlfa) — mecanismo completo a detalhar na Seção 4.

**DELETE /api/v1/agenda/doctor/blocks/{id}**

Função: desfaz um bloqueio de horário (US-AGM-004).
Response 200: `{ "id": "uuid", "result": "removed" }`
Códigos: 200 (sucesso); 404 (bloqueio não encontrado — cobre tanto "já desfeito por outra sessão" quanto "não pertence ao médico logado": como o endpoint é escopado ao médico da sessão (RN-AGM-002), um bloqueio de outro médico simplesmente não existe nesse escopo — não há um 403 separado, para não revelar a outro médico que aquele horário está bloqueado); 500 (falha ao remover — EX-AGM-05).
Tabelas envolvidas: `Agenda` (GescomClienteAlfa).

### Catálogo de Mensagens do Sistema e Termos de Interface (i18n)

| ID | Contexto | pt-BR | en-US | es-419 |
|---|---|---|---|---|
| MSG-EAGM-01 | Horário de bloqueio sobreposto (EX-AGM-01) | "Esse horário já está ocupado por uma consulta ou outro bloqueio." | "That time slot is already taken by an appointment or another block." | "Ese horario ya está ocupado por una consulta u otro bloqueo." |
| MSG-EAGM-02 | Complemento acima do limite | "O complemento pode ter no máximo 128 caracteres." | "The note can have at most 128 characters." | "La nota puede tener como máximo 128 caracteres." |
| MSG-EAGM-03 | Falha ao carregar a agenda do dia (EX-AGM-02) | "Não foi possível carregar a agenda. Tente novamente." | "Could not load the schedule. Please try again." | "No fue posible cargar la agenda. Inténtelo de nuevo." |
| MSG-EAGM-04 | Falha ao criar bloqueio (EX-AGM-04) | "Não foi possível bloquear este horário. Tente novamente." | "Could not block this time slot. Please try again." | "No fue posible bloquear este horario. Inténtelo de nuevo." |
| MSG-EAGM-05 | Falha ao desfazer bloqueio (EX-AGM-05) | "Não foi possível desfazer o bloqueio. Tente novamente." | "Could not undo the block. Please try again." | "No fue posible deshacer el bloqueo. Inténtelo de nuevo." |
| MSG-TAGM-01 | Dia sem consulta nem bloqueio (EX-AGM-03) | "Nenhuma consulta ou bloqueio neste dia." | "No appointments or blocks on this day." | "Ninguna consulta o bloqueo en este día." |
| MSG-BAGM-01 | Botão de bloqueio de horário | "Bloquear horário" | "Block time slot" | "Bloquear horario" |
| MSG-BAGM-02 | Botão de desfazer bloqueio | "Desfazer bloqueio" | "Undo block" | "Deshacer bloqueo" |
| MSG-BAGM-03 | Botão de voltar para hoje | "Hoje" | "Today" | "Hoy" |
| MSG-BAGM-04 | Rótulo do item bloqueado | "Bloqueado" | "Blocked" | "Bloqueado" |

### Conformidade SBIS (detalhamento)

**ECF.05.02 — Bloqueios na agenda** (estágio 2, recomendado) — o fluxo de bloqueio de horário (US-AGM-003, `POST /api/v1/agenda/doctor/blocks`) implementa este requisito; o mecanismo de persistência (paciente/convênio reservados) é detalhado na Seção 4, quando escrita, junto da subseção "Seeds da Funcionalidade".

**ECF.05.04 — Especificação do tipo de consulta** (estágio 2, recomendado) — atendido pela exibição do tipo de consulta em cada item da lista, quando configurado pela clínica (RN-AGM-008).

**NGS1.07.03 / NGS1.07.04 — Eventos registrados na trilha de auditoria** (estágio 1 / 2) — a criação e a remoção de um bloqueio (`POST`/`DELETE` acima) devem gerar evento de auditoria, mesmo padrão já usado em outras funcionalidades assistenciais deste projeto (RN-AGM-004).

**ECF.17.19 — Mensagens do sistema** (estágio 1, obrigatório) — todas as mensagens exibidas ao médico estão catalogadas acima, em linguagem não técnica, em português do Brasil, com suporte multilíngue para en-US e es-419.

---

## Histórico de Versões

- **v1.0** (31/08/2026) — Arquivo criado. Especificação completa a partir das RNs fechadas na Seção 1 (v1.5): cabeçalho de navegação (RN-AGM-003, com os dois mecanismos de atalho confirmados pelo solicitante — setas de atalho e seletor de calendário), lista de consultas com os elementos herdados e os dois campos novos (RN-AGM-006/007/008/009), bloco de consultas já realizadas (RN-AGM-010), e o fluxo completo de bloqueio de horário (RN-AGM-004), incluindo a confirmação do solicitante de que o próprio médico pode desfazer um bloqueio e que o complemento é opcional nesse fluxo. Duas decisões de UI ainda não pedidas ao solicitante ficaram marcadas **[PROPOSTA]** no corpo (granularidade de horário do formulário de bloqueio; confirmação leve inline ao desfazer) — a confirmar antes do Protótipo (Seção 3). Deixado **[A DEFINIR]** se um bloqueio já ocorrido também deveria entrar no bloco recolhido de RN-AGM-010, por não estar coberto pela redação literal da regra.
- **v1.0 (revisão)** (01/09/2026) — Submetido ao subagente crítico técnico antes de fechar a fase (Lição #20). Achados verificados contra o texto e corrigidos: (1) campo `type` renomeado para `attendanceMode` no JSON de exemplo, com nota de nomenclatura no corpo distinguindo-o de `appointmentType` — nomes muito parecidos, campos diferentes; (2) removido o campo `delayMinutes` do JSON de exemplo — não estava descrito em nenhuma regra nem na lista de elementos exibidos, ficou como campo "fantasma"; (3) resposta do `DELETE /blocks/{id}` renomeada de `status` para `result`, evitando colisão de nome com o `status` de atendimento clínico usado no `GET /day`; (4) adicionado `"kind": "block"` na resposta do `POST /blocks`, alinhando com o formato do item de bloqueio já usado no `GET /day`; (5) adicionadas CA-001.6, CA-001.7, CA-003.4 e CA-004.3, cobrindo os quatro Fluxos de Exceção (EX-AGM-02/03/04/05) que não tinham nenhum Critério de Aceitação correspondente; (6) corrigida a tabela de Mapeamento de Componentes — EX-AGM-02 estava listado como "Toast", mas o texto do próprio fluxo descreve um estado de erro em tela cheia; criadas linhas próprias para os estados de erro/vazio de tela cheia (EX-AGM-02, EX-AGM-03), mantendo Toast só para EX-AGM-04/05; (7) qualificada a linha "AGORA" (RN-AGM-010) como exclusiva do dia de hoje — em outro dia a lista abre no topo, sem a linha; (8) identificada e resolvida a tensão entre RN-AGM-003 ("sem limite de horizonte") e o endpoint `days-with-appointments`, que exige `from`/`to` limitados: criado um segundo endpoint, `GET /next-appointment-date`, sem limite de intervalo, dedicado ao atalho sequencial — `days-with-appointments` passa a servir só o marcador visual do calendário (mês exibido); (9) criado EX-AGM-06 (falha ao consultar dias com consulta), cobrindo um cenário de erro que não tinha nenhum tratamento especificado, com degradação silenciosa por não ser caminho crítico; (10) removido o código 403 do `DELETE /blocks/{id}` — como o endpoint já é escopado ao médico logado (RN-AGM-002), um bloqueio de outro médico não é alcançável nesse escopo; consolidado em 404, evitando revelar a existência de bloqueios de outros médicos; (11) adicionada validação **[PROPOSTA]** impedindo bloqueio de horário já no passado — não pedida ao solicitante, a confirmar. Nenhum achado do crítico foi descartado como falso positivo nesta rodada.
