Épico 5 — Menu Lateral — Especificação (v1.7)
Documentos deste épico: 01 - Definição (v1.9) · 02 - Especificação (v1.7) · 03 - Protótipo (v1.8, código executável em 03 - Protótipo v1.8.html) · 04 - Mapeamento de Banco de Dados (v1.7). Este épico faz parte do documento guarda-chuva Check-in de Usuários.
SEÇÃO 2 — ESPECIFICAÇÃO
Histórias de Usuário
- US-CIU-010: Como usuário autenticado, quero navegar entre os módulos que meu perfil de acesso libera a partir de um único menu lateral, para encontrar rapidamente as funcionalidades da minha rotina sem me perder em opções que não uso.
- US-CIU-011: Como usuário trabalhando numa clínica de um Ambiente de teste, quero perceber isso a todo momento, sem perder espaço de tela, para não confundir o teste com o atendimento real.
Descrição Funcional Detalhada
Cabeçalho do Menu (identificação da clínica)
No topo do menu, antes dos grupos, um indicador visual (círculo colorido) e o nome da clínica em que o usuário está trabalhando nesta sessão (E1, E6) — ex.: “Clínica Onco”. No mobile, o mesmo nome aparece na barra superior fixa, sem o indicador visual. Quando o menu está recolhido no desktop (ver “Comportamento Responsivo”), só o indicador visual permanece; o nome é ocultado junto com o restante do texto do menu recolhido.
Motivador: dar ao usuário uma referência constante de em qual clínica está trabalhando, especialmente relevante para quem atua em mais de uma (RN-CIU-009, em CIU-E1) — sem essa identificação, trocar de clínica (ver “Botão Trocar” abaixo) não teria uma confirmação visual de que a troca realmente ocorreu.
Estrutura do Menu
Ao carregar, o menu busca a árvore de grupos e itens já filtrada pelo perfil de acesso do usuário na clínica atual (RN-CIU-027). Cada grupo é exibido com seu nome e a lista de itens que contém, na ordem definida para aquele perfil de acesso; itens sem grupo aparecem soltos, na lista principal, junto dos grupos. Um grupo sem nenhum item liberado pelo perfil de acesso não é exibido (RN-CIU-026) — o back-end já não o devolve. Um grupo começa recolhido, exibindo apenas seu nome (ver “Premissas”, 01 - Definição), e pode ser expandido/recolhido individualmente ao ser tocado, sem afetar os demais grupos (RN-CIU-026). Cada item exibe um ícone e o nome do módulo; ao ser selecionado, navega para a rota daquele item.
Motivador: a filtragem no carregamento (RN-CIU-027), em vez de itens desabilitados na tela, evita qualquer ambiguidade sobre o que o usuário pode ou não acessar — o item simplesmente não existe ali para ele.
Seção Favoritos
Exibida no topo do menu, acima dos grupos, apenas quando o usuário tem ao menos um item favoritado nesta clínica (RN-CIU-028) — sem favoritos, a seção não é renderizada. Cada item favoritado aparece com o mesmo ícone e nome de sua entrada original, e um indicador de estrela preenchida; o mesmo indicador aparece junto ao item em seu grupo de origem, permitindo favoritar/desfavoritar a partir de qualquer um dos dois lugares. Os itens da seção Favoritos são listados em ordem alfabética pelo nome, conforme a collation do banco — a lista já chega ordenada do back-end (RN-CIU-028). Só aparecem favoritos de itens que continuam liberados pelo perfil de acesso na clínica atual; um favorito de item que deixou de ser liberado não é exibido (RN-CIU-028). A busca não afeta esta seção: durante uma busca, todos os favoritos continuam visíveis, sem filtro (RN-CIU-030). Tocar na estrela de um item não favoritado o adiciona à seção Favoritos (CA-010.2); tocar na estrela preenchida de um item já favoritado o remove da seção, sem afetar sua presença no grupo de origem (CA-010.3).
Quando o menu está recolhido no desktop (ver “Comportamento Responsivo”), apenas os ícones dos itens desta seção permanecem visíveis — sem nenhum favorito, o menu recolhido fica vazio.
Motivador: separar Favoritos da árvore normal, em vez de reordenar os itens dentro dos próprios grupos, evita que o usuário perca a referência de onde cada módulo mora na estrutura fixa do sistema (RN-CIU-028, Seção 1).
Busca
Campo de busca no topo do menu, abaixo da seção Favoritos (quando presente). A cada caractere digitado, filtra a lista de itens pelo nome, em tempo real, sem exigir confirmação (RN-CIU-030). A busca é por aproximação: não diferencia maiúsculas de minúsculas nem letras acentuadas de não acentuadas — “medico”, “MEDICO” e “Médico” encontram os mesmos itens. A busca só afeta a árvore (grupos e itens); a seção Favoritos permanece intacta. Durante uma busca com texto, os grupos são ignorados como unidade de exibição — a lista mostra diretamente os itens cujo nome corresponde ao texto buscado, independentemente do grupo a que pertencem estarem expandidos ou recolhidos (CA-010.4). Limpar o campo de busca restaura a exibição normal, com os grupos no estado de expansão em que estavam antes da busca. Quando nenhum item corresponde ao texto buscado, é exibido um estado vazio (EX-E5-02).
Motivador: a busca é uma ferramenta de atalho para quem já sabe o nome do que procura — achatar a árvore evita a etapa extra de abrir manualmente o grupo certo.
Comportamento Responsivo
No desktop (largura suficiente para o menu ao lado do conteúdo), o menu tem dois estados: expandido (padrão) e recolhido, alternados por um controle posicionado fora do próprio menu, numa posição fixa que não se desloca entre os dois estados — evita que o usuário precise localizar o controle em lugares diferentes da tela conforme o menu muda de largura. Expandido, ocupa uma faixa lateral fixa com grupos e itens por extenso; o conteúdo principal ocupa o espaço restante. Recolhido, mostra apenas os ícones dos itens da seção Favoritos, em coluna estreita; o conteúdo principal se redimensiona para ocupar o espaço liberado (CA-010.7). Sem nenhum favorito, a coluna recolhida fica vazia — nenhum ícone de navegação (RN-CIU-029). Um ícone do menu recolhido navega direto para o item ao ser clicado — não é necessário expandir o menu antes.
No mobile (largura insuficiente para o menu ao lado do conteúdo), o menu fica oculto por padrão; um ícone no cabeçalho da tela o abre como uma camada sobreposta ao conteúdo principal, sem redimensionar nada por baixo (CA-010.8). Selecionar um item ou tocar fora da camada fecha o menu, revelando o conteúdo como estava.
Motivador: RN-CIU-029, Seção 1 — os dois comportamentos (redimensionar vs. sobrepor) são deliberadamente opostos, cada um adequado ao espaço disponível na respectiva largura de tela.
Botão Trocar (clínica)
Botão compacto com ícone e o rótulo de texto “Trocar” (fonte reduzida em relação ao restante do cabeçalho), posicionado no cabeçalho do menu, ao lado do nome da clínica — não um botão largo separado abaixo do cabeçalho. Exibido apenas quando o usuário tem acesso a mais de uma clínica (RN-CIU-009, em CIU-E1) — com exatamente 1 clínica acessível, o botão não aparece (CA-010.5). Ao ser tocado, leva o usuário à tela de seleção de clínica (E6, RN-CIU-025), onde pode escolher outra clínica de trabalho (CA-010.6). Trocar de clínica reconstrói o menu inteiro (itens, favoritos e a identificação da clínica no cabeçalho) a partir do perfil de acesso da nova clínica (RN-CIU-028, Seção 1) — não há tentativa de preservar o estado da clínica anterior. Some junto com o resto do texto do cabeçalho quando o menu está recolhido no desktop (ver “Comportamento Responsivo”).
Motivador: ocultar o botão para quem só tem uma clínica evita oferecer uma ação sem efeito útil; reconstruir o menu do zero ao trocar reflete o fato de que itens e favoritos são específicos da combinação vínculo × perfil × clínica (RN-CIU-028). Posição e tamanho discretos junto ao nome da clínica, em vez de um botão de destaque separado, refletem que trocar de clínica é uma ação pouco frequente para a maioria dos usuários — não deve competir visualmente com a navegação principal do menu; o rótulo de texto (retomado nesta versão, após uma rodada anterior só com ícone) evita a ambiguidade de um ícone isolado sem contexto textual.
Sinalização de Ambiente de teste (RN-CIU-032)
Aplica os itens 1 a 3 de RN-CIU-032. A origem do dado é o campo ambienteTipo de GET /api/v1/menu (ver “Integração com Backend”): "homologacao" liga a sinalização, "producao" não liga nada. O app-shell (a moldura comum a todas as telas, que contém o menu) aplica os três efeitos abaixo a cada resposta desse endpoint — ou seja, no carregamento inicial após o login/seleção de clínica, a cada troca de clínica (que já reconstrói o menu inteiro, ver “Botão Trocar”) e a cada recarregamento da página.
- Fundo do menu. O painel lateral inteiro — cabeçalho, área de itens e rodapé — troca o fundo
--color-base-purepor--color-env-test-surface(amarelo claro; Design System, seção 8), nos três estados: desktop expandido, desktop recolhido (a coluna estreita continua pintada mesmo sem nenhum favorito) e overlay mobile. Nada mais no menu muda: textos, ícones, item ativo, estrela de favorito, campo de busca e botão Trocar mantêm os tokens de sempre — com uma única exceção: o realce de hover da estrela de favorito, que normalmente usa--color-highlight-lighte ficaria invisível sobre o mesmo amarelo, passa a--color-highlight-medium. A barra superior mobile, o conteúdo principal e o controle de recolher/expandir (que fica fora do menu) também não mudam. - Barra de status do celular. Ao entrar em teste, o app-shell guarda o estado atual da tag
<meta name="theme-color">(valor, ou ausência da tag) e passa a defini-la com o valor de--color-env-test-surfacecalculado no:rootno tema vigente. Recalcula esse valor sempre que o tema muda durante a sessão — tanto pela preferência do sistema operacional (modo Automático, eventochangedematchMedia('(prefers-color-scheme: dark)')) quanto pela escolha fixada no menu do usuário (mudança do atributodata-themedo<html>; Design System, seção 6). Ao sair do teste, restaura exatamente o estado guardado. Em produção, esta regra não toca a tag. O efeito depende do navegador — alguns ignoramtheme-color, ou o ignoram no tema escuro; nesses casos não há sinal substituto (pendência [A DEFINIR] de RN-CIU-032), e no celular o aviso fica visível só com o menu aberto. - Título da aba. As telas não escrevem o título da aba diretamente: informam ao app-shell apenas o título base (ex.: “Central do Médico”). O app-shell compõe o título final — em teste, prefixo MSG-T5-02 no idioma do usuário + um espaço + título base (ex.: “[TESTE] Central do Médico”); em produção, só o título base. A composição parte sempre do título base, nunca do título já exibido, para que o prefixo não se repita; e é refeita a cada navegação, a cada mudança de Ambiente e a cada mudança de idioma.
Enquanto GET /api/v1/menu não respondeu (skeleton) ou falhou (EX-E5-04), o tipo de Ambiente é desconhecido e nenhum dos três efeitos é aplicado — o menu nesse momento também não permite navegar, e a sinalização aparece assim que o menu carrega. Uma resposta de sucesso sem nenhum item liberado (EX-E5-01) já traz o tipo de Ambiente, e a sinalização é aplicada normalmente.
Ao sair do app-shell — botão Trocar (indo para a seleção de clínica, E6), saída do sistema ou sessão expirada (resposta 401) —, os três efeitos são retirados antes de a próxima tela aparecer: fundo padrão, theme-color restaurada e título sem prefixo (RN-CIU-032: fora de uma clínica de trabalho definida, a regra não se aplica).
No tema escuro, --color-env-test-surface assume o valor escuro definido no Design System (mesma regra de conversão dos demais tons tingidos) — o fundo do menu continua diferente do de produção. Os textos do menu em tokens neutros mantêm contraste mínimo de 4,5:1 sobre o amarelo nos dois temas (valores no Design System, seção 8). O rótulo do botão Trocar (--color-secondary-dark, 10px) fica em 3,2:1 sobre o amarelo claro — já abaixo de 4,5:1 sobre o branco de produção (3,4:1); é uma pendência do Design System, anterior a esta regra, não introduzida por ela.
Motivador: RN-CIU-032 — sinalizar o Ambiente de teste sem acrescentar elemento nem ocupar altura da tela. O menu já é uma faixa fixa no computador; no celular, onde ele fica fechado, a barra de status do aparelho assume o papel; o prefixo da aba resolve a confusão entre abas abertas lado a lado. A cor é a mesma do cabeçalho do Ambiente de teste na lista de clínicas (E6, RN-CIU-031), para que o usuário reconheça o mesmo sinal antes e depois de escolher a clínica.
Rodapé
Faixa fixa na base do menu com o texto “Powered by Interprocess TI” (MSG-T5-01) — rótulo estático, sem link nem ação associada.
Critérios de Aceitação
CA-010.1: Dado um usuário autenticado com um perfil de acesso definido, quando o sistema monta o menu, então só aparecem os itens permitidos por esse perfil (RN-CIU-027).
CA-010.2: Dado um item não favoritado, quando o usuário toca na estrela ao lado dele, então o item passa a aparecer na seção Favoritos.
CA-010.3: Dado um item na seção Favoritos, quando o usuário toca na estrela preenchida, então o item some dos Favoritos (mas continua na árvore, desfavoritado).
CA-010.4: Dado o usuário digitando no campo de busca, quando o texto corresponde a um ou mais itens permitidos, então só esses itens aparecem, independentemente do estado de expansão dos grupos.
CA-010.5: Dado um usuário com acesso a exatamente 1 clínica, quando o menu é exibido, então o botão “Trocar” não aparece.
CA-010.6: Dado um usuário com acesso a mais de 1 clínica, quando toca em “Trocar”, então é redirecionado à tela de seleção de clínica (E6).
CA-010.7: Dado o menu expandido no desktop, quando o usuário o recolhe, então o conteúdo principal se redimensiona para ocupar o espaço liberado, e só os ícones dos favoritos permanecem visíveis.
CA-010.8: Dado o mobile, quando o usuário aciona o ícone de abertura, então o menu aparece sobre o conteúdo, sem redimensioná-lo.
CA-010.9: Dado um grupo recolhido, quando o usuário toca nele, então ele expande mostrando seus itens, sem afetar o estado dos demais grupos.
CA-011.1: Dado um usuário numa clínica de Ambiente de teste, quando o menu carrega, então o fundo do menu fica amarelo claro no desktop expandido, no desktop recolhido e no overlay mobile, e o restante da tela permanece como em produção.
CA-011.2: Dado um usuário numa clínica de Ambiente de produção, quando o menu carrega, então o fundo do menu é o padrão, o título da aba não tem prefixo e a tag theme-color está como estaria sem esta regra.
CA-011.3: Dado um usuário numa clínica de Ambiente de teste, quando navega entre telas, então o título da aba sempre começa com “[TESTE] ” seguido do título da tela, sem repetir o prefixo.
CA-011.4: Dado um usuário numa clínica de Ambiente de teste, num celular cujo navegador aplica theme-color, quando o menu carrega, então a barra de status do aparelho fica na mesma cor do fundo do menu, inclusive com o menu fechado.
CA-011.5: Dado um usuário com acesso a uma clínica de produção e a uma clínica de teste, quando troca de uma para a outra pelo botão Trocar, então a sinalização é aplicada (produção → teste) ou retirada (teste → produção) assim que o menu da nova clínica carrega.
CA-011.6: Dado um usuário numa clínica de Ambiente de teste usando o tema escuro, quando o menu carrega, então o fundo do menu usa o valor escuro de --color-env-test-surface, diferente do fundo padrão do menu no tema escuro, e a tag theme-color recebe esse mesmo valor (a cor efetiva da barra de status depende de o navegador aplicar theme-color no tema escuro).
CA-011.7: Dado um usuário numa clínica de Ambiente de teste, quando sai do app-shell (botão Trocar, saída do sistema ou sessão expirada), então o fundo do menu, a tag theme-color e o título da aba voltam ao estado sem sinalização antes de a próxima tela aparecer.
Fluxos de Exceção
EX-E5-01 — Perfil de acesso sem nenhum item de menu liberado
Gatilho: perfil de acesso do usuário, na clínica atual, não libera nenhum item para exibição no menu (RN-CIU-027). Comportamento: menu exibido vazio, com mensagem informativa orientando a contatar o administrador da clínica (MSG-I5-01). Recuperação: usuário aguarda o administrador configurar seu perfil de acesso. Nota: cenário de baixa probabilidade nesta versão do sistema — a Central do Médico é hoje o único módulo com item de menu real cadastrado, e todo médico deveria ter perfil de acesso a ele — mas o comportamento vale para qualquer perfil, presente ou futuro, que eventualmente fique sem nenhum item liberado.
EX-E5-02 — Busca sem nenhum resultado
Gatilho: texto digitado no campo de busca não corresponde a nenhum item permitido pelo perfil de acesso. Comportamento: estado vazio no lugar da lista, com mensagem orientando a limpar o filtro (MSG-I5-02). Recuperação: usuário apaga ou ajusta o texto buscado.
EX-E5-03 — Falha ao favoritar/desfavoritar um item
Gatilho: erro de rede ou falha do back-end ao processar a ação de favoritar ou desfavoritar um item. Comportamento: o estado visual da estrela é revertido ao que era antes do toque, e uma mensagem de erro é exibida (MSG-E5-01). Recuperação: usuário tenta novamente.
EX-E5-04 — Falha ao carregar os itens do menu no login
Gatilho: erro de rede ou falha do back-end ao buscar a árvore de itens do menu para o usuário autenticado. Comportamento: estado de erro no lugar do menu, com mensagem (MSG-E5-03) e ação “Tentar novamente” (MSG-B5-01) — sem menu carregado, o usuário não tem como navegar para lugar nenhum. Recuperação: usuário aciona “Tentar novamente”; se persistir, orientação a contatar o suporte.
Validações de Campos
O único campo de entrada desta funcionalidade é o campo de busca — texto livre, sem obrigatoriedade, sem validação de formato: qualquer texto digitado (incluindo vazio, que restaura a exibição normal) é aceito e usado para filtrar a lista de itens.
Mapeamento de Componentes de Interface
| Componente | Variante | Estados | Tokens aplicados | Uso nesta tela |
|---|---|---|---|---|
| Painel lateral | Menu (desktop expandido) | default | --color-base-pure bg, --shadow-level-medium, largura fixa | Estrutura principal do menu, desktop |
| Painel lateral | Menu (desktop recolhido) | default | --color-base-pure bg, largura reduzida a ícones | Estado recolhido, só ícones de favoritos |
| Painel overlay | Menu (mobile) | default, entrando/saindo | --shadow-level-heavy, sobreposto ao conteúdo com camada de fundo semitransparente | Estado aberto do menu em mobile |
| Painel lateral e painel overlay | Ambiente de teste | default (os três estados acima) | --color-env-test-surface bg no lugar de --color-base-pure; demais tokens inalterados | Clínica atual em Ambiente de teste (RN-CIU-032, CA-011.1) |
Meta tag theme-color | Ambiente de teste | — | valor resolvido de --color-env-test-surface no tema vigente | Barra de status do celular (RN-CIU-032, CA-011.4) |
| Item de grupo (accordion) | Grupo | default, expandido, recolhido | --spacing-sm padding, --color-neutral-pure texto de rótulo, ícone de chevron rotativo | Cada grupo do menu (RN-CIU-026) |
| Item de menu | Padrão / Favorito | default, hover, active (rota atual), focus | --radius-m, --color-primary-pure no item ativo, --spacing-xs entre ícone e texto | Cada item dentro de um grupo, da lista sem grupo ou da seção Favoritos |
| Ícone de estrela | Favoritar | vazia (não favoritado), preenchida (favoritado), loading | --color-highlight-pure (preenchida), --color-neutral-light (vazia) | Ação de favoritar/desfavoritar, junto de cada item |
| Input de busca | Busca do menu | default, focus, com texto | --input-height reduzido (32px), --radius-pill, --color-neutral-lighter bg | Campo de busca, topo do menu (RN-CIU-030) |
| Indicador + texto | Marca/Identificação da clínica | default | --color-primary-pure (indicador), --font-size-lg (nome) | Cabeçalho do menu — nome da clínica atual, oculto (só o indicador permanece) no menu recolhido |
| Button (compacto) | Secondary compacto (Trocar) | default, hover | 24px altura, --font-size-xs, borda --color-secondary-pure | Botão “Trocar” (ícone + rótulo) no cabeçalho do menu, ao lado do nome da clínica, quando visível (CA-010.5/6) |
| Button (icon-only) | Ghost (Recolher/expandir) | default, hover, pressed | --icon-btn 36px, borda --color-neutral-lighter, --shadow-level-medium | Controle de recolher/expandir o menu, fora do menu, em posição fixa (desktop, CA-010.7) |
| Banner/Ícone informativo | Info | default | --color-secondary-pure | Mensagem de perfil sem itens (MSG-I5-01) e de busca sem resultado (MSG-I5-02) |
| Toast | Error | default | --color-error-pure | Falha ao favoritar (MSG-E5-01) |
| Estado de erro em tela cheia | Erro de carregamento | default | --color-error-light bg do ícone, --color-error-dark texto do ícone | Falha ao carregar o menu (EX-E5-04) |
| Skeleton | Menu | loading | --color-neutral-lighter | Carregamento inicial do menu |
| Rodapé | Marca | default | --font-size-xs, --color-neutral-pure | Texto estático “Powered by Interprocess TI” (MSG-T5-01) |
Integração com Backend
GET /api/v1/menu
Função: retorna, para o usuário autenticado, a árvore de grupos e itens de menu já filtrada pelo perfil de acesso vigente na clínica atual, com a marcação de quais itens estão favoritados.
Request: nenhum parâmetro (usuário e clínica atual identificados pelo token de sessão, já resolvido em E1/E6).
Response: { clinicaAtual: { clienteEmpresaId, nome, caminhoLogo }, ambienteTipo, grupos: [{ processoGrupoId, nome, itens: [{ clientePerfilAcessoProcessoId, processoId, nome, icone, rota, favorito }] }], itensSemGrupo: [{ clientePerfilAcessoProcessoId, processoId, nome, icone, rota, favorito }], favoritos: [{ clientePerfilAcessoProcessoId, processoId, nome, icone, rota }] } — os itens já vêm na ordem definida para o perfil de acesso (RN-CIU-027); favoritos é a lista já pronta para a seção Favoritos e para o menu recolhido, evitando que o front-end precise recalculá-la a partir dos grupos — contém só itens ainda liberados pelo perfil de acesso (subconjunto dos itens de grupos/itensSemGrupo), ordenados por nome conforme a collation do banco; grupos só contém grupos com ao menos um item. A quantidade de clínicas acessíveis, que decide a visibilidade do ícone Trocar (CA-010.5/6), não é recalculada aqui — reaproveita o campo clinicasAcessiveis já retornado pelo login (E1). [PROPOSTA] clinicaAtual é campo novo nesta versão, para o cabeçalho do menu (nome/logo da clínica atual) sobreviver a um recarregamento de página sem depender de o front-end reter o dado desde o login/E6 — mesmos campos (nome, caminhoLogo) já usados em ClienteEmpresa por E3/E6; nenhuma tabela nova. [PROPOSTA] ambienteTipo é campo novo nesta versão: tipo do Ambiente de trabalho da clínica atual, "producao" ou "homologacao" (Ambiente de teste), sempre presente — mesmo nome de campo, mesmos valores e mesma tradução de ClienteBD.Tipo (P → "producao", T → "homologacao") já usados por GET .../clinic-selection na Seleção de Clínica (E6) (casos de dado ausente ou fora do domínio: Seção 4, 4.1); liga ou não a sinalização de Ambiente de teste (RN-CIU-032). Vem nesta resposta, e não do login, porque o Ambiente só é conhecido depois que a clínica de trabalho é definida e muda a cada troca de clínica — exatamente os momentos em que este endpoint é chamado. O nome do Ambiente não é enviado: não é exibido em lugar nenhum desta funcionalidade (RN-CIU-032).
Códigos: 200 (sucesso — grupos, itensSemGrupo e favoritos podem vir vazios); 401 (não autenticado); 500 (falha ao carregar — EX-E5-04).
POST /api/v1/menu/items/{clientePerfilAcessoProcessoId}/favorite
Função: favorita um item do menu para o usuário autenticado, na clínica atual.
Request: nenhum corpo — clientePerfilAcessoProcessoId no path identifica o item já filtrado pelo perfil de acesso vigente.
Response: { clientePerfilAcessoProcessoId, favorito: true }.
Códigos: 201 (favoritado); 404 (item não encontrado ou não liberado pelo perfil de acesso atual); 500 (falha — EX-E5-03).
DELETE /api/v1/menu/items/{clientePerfilAcessoProcessoId}/favorite
Função: desfavorita um item do menu para o usuário autenticado, na clínica atual.
Request: nenhum corpo — clientePerfilAcessoProcessoId no path.
Response: { clientePerfilAcessoProcessoId, favorito: false }.
Códigos: 200 (desfavoritado); 404 (item não estava favoritado); 500 (falha — EX-E5-03).
O mapeamento das tabelas consultadas por estes 3 endpoints, com o detalhamento de campos, domínios e filtros, está na Seção 4 (Mapeamento de Banco de Dados, v1.6) — não repetido aqui (Lição #10 da Skill Designer).
Nota: a busca (RN-CIU-030) não tem endpoint próprio — opera em memória, no front-end, sobre a árvore já retornada por GET /api/v1/menu, filtrando por nome a cada caractere digitado, sem diferenciar maiúsculas/minúsculas nem acentos (a comparação é feita no front-end, não pela collation do banco). Isso evita uma chamada de rede a cada tecla, num campo cujo próprio propósito é agilizar a navegação.
Catálogo de Mensagens do Sistema e Termos de Interface (i18n)
Erros:
| ID | Contexto | pt-BR | en-US | es-419 |
|---|---|---|---|---|
| MSG-E5-01 | Falha ao favoritar/desfavoritar um item (EX-E5-03) | “Não foi possível atualizar seus favoritos. Tente novamente." | "Could not update your favorites. Please try again." | "No fue posible actualizar sus favoritos. Inténtelo de nuevo.” |
| MSG-E5-03 | Falha ao carregar os itens do menu (EX-E5-04) | “Não foi possível carregar o menu. Tente novamente." | "Could not load the menu. Please try again." | "No fue posible cargar el menú. Inténtelo de nuevo.” |
Informativas / estado vazio:
| ID | Contexto | pt-BR | en-US | es-419 |
|---|---|---|---|---|
| MSG-I5-01 | Perfil de acesso sem nenhum item liberado (EX-E5-01) | “Seu perfil de acesso ainda não libera nenhum item de menu. Entre em contato com o administrador da sua clínica." | "Your access profile doesn’t release any menu item yet. Contact your clinic’s administrator." | "Su perfil de acceso aún no libera ningún elemento de menú. Comuníquese con el administrador de su clínica.” |
| MSG-I5-02 | Busca sem nenhum resultado (EX-E5-02) | “Nenhum item encontrado. Tente limpar o filtro de busca." | "No items found. Try clearing the search filter." | "No se encontraron elementos. Intente borrar el filtro de búsqueda.” |
Placeholder:
| ID | Contexto | pt-BR | en-US | es-419 |
|---|---|---|---|---|
| MSG-P5-01 | Campo de busca do menu | ”Buscar no menu" | "Search menu" | "Buscar en el menú” |
Textos orientadores:
| ID | Contexto | pt-BR | en-US | es-419 |
|---|---|---|---|---|
| MSG-T5-01 | Rodapé do menu (rótulo estático, sem tradução de marca) | “Powered by Interprocess TI" | "Powered by Interprocess TI" | "Powered by Interprocess TI” |
| MSG-T5-02 | Prefixo do título da aba em Ambiente de teste (RN-CIU-032), seguido de um espaço e do título da tela | ”[TESTE]" | "[TEST]" | "[PRUEBA]” |
Botões/links:
| ID | Contexto | pt-BR | en-US | es-419 |
|---|---|---|---|---|
| MSG-B5-01 | Ação de recuperação (erro de carregamento do menu) | “Tentar novamente" | "Try again" | "Intentar de nuevo” |
| MSG-B5-02 | Botão de troca de clínica no cabeçalho do menu | ”Trocar" | "Switch" | "Cambiar” |
Conformidade SBIS (detalhamento)
ECF.17.18 — Idioma do S-RES (estágio 1, obrigatório) — todos os rótulos, ícones textuais e mensagens do menu são exibidos em português do Brasil, com suporte adicional a en-US e es-419 (catálogo acima); o requisito cita “menus” explicitamente entre os elementos que devem seguir essa regra. O prefixo de Ambiente de teste no título da aba (MSG-T5-02) segue a mesma regra. A sinalização de Ambiente de teste (RN-CIU-032) não corresponde a nenhum requisito SBIS próprio.
ECF.17.19 — Mensagens do sistema (estágio 1, obrigatório) — todas as mensagens do menu (erro, informativa, estado vazio, orientadora) estão catalogadas acima, em linguagem não técnica, sem termos de banco de dados ou de infraestrutura visíveis ao usuário.
NGS1.03.01 — Impedir acesso por pessoas não autorizadas (estágio 1, obrigatório) — o menu nunca exibe um item para o qual o usuário não tenha permissão: a filtragem por perfil de acesso (RN-CIU-027) ocorre no carregamento da árvore, no back-end, não como uma regra visual aplicada depois de uma lista completa chegar ao front-end.
NGS1.03.03 — Gerenciamento de perfis (estágio 1, obrigatório) — o menu consome, sem redefinir, a atribuição de permissões por perfil de acesso já gerenciada no Contexto de Segurança; cada alteração de quais itens um perfil libera se reflete no menu no próximo carregamento.
NGS1.03.07 — Atribuição de mais de um perfil para um usuário (estágio 1, obrigatório) — como um usuário pode ter um perfil de acesso diferente em cada clínica, o menu (itens e favoritos) é recarregado por completo a cada troca de clínica (RN-CIU-028), refletindo sempre o perfil vigente naquela clínica, nunca um acúmulo de permissões de clínicas diferentes.
Histórico de Versões
- v1.0 (15/09/2026) — versão inicial do épico. Especificação construída a partir dos critérios de aceitação e fluxos de exceção já confirmados, e da estrutura de dados de menu/RBAC/favoritos localizada na Biblioteca de Schema (DDL) — nenhuma tabela nova, 3 endpoints (leitura do menu, favoritar, desfavoritar), busca resolvida inteiramente no front-end sobre a árvore já carregada.
- v1.1 (15/09/2026) — Terminologia revisada de “profissional” para “usuário”, termo próprio do Contexto de Check-in de Usuários (ver 01 - Definição, Histórico de Versões, v1.1). Sem mudança de conteúdo funcional.
- v1.2 (15/09/2026) — grupo passa a começar recolhido (não expandido) a cada nova sessão; seção Favoritos passa a listar os itens em ordem alfabética pelo nome — ambos confirmados pelo solicitante (ver 01 - Definição, Histórico de Versões, v1.2).
- v1.3 (15/09/2026) — pedido do solicitante ao revisar o protótipo: nova subseção “Cabeçalho do Menu (identificação da clínica)”, documentando pela primeira vez o indicador + nome da clínica no topo do menu (antes só a marca do produto, sem essa informação — gap não documentado). “Botão Trocar” reescrito para a nova posição discreta, ao lado do nome da clínica. “Comportamento Responsivo” ganhou nota sobre o controle de recolher/expandir ficar fora do menu, em posição fixa. Mapeamento de Componentes atualizado (nova linha para a identificação da clínica, linha do Trocar revisada para ícone, nova linha para o controle de recolher/expandir, antes ausente da tabela).
GET /api/v1/menuganhou o campoclinicaAtual([PROPOSTA]) na resposta, eClienteEmpresaentrou na lista de tabelas envolvidas do endpoint. - v1.4 (15/09/2026) — pedido do solicitante ao revisar o protótipo: “Botão Trocar” reescrito — volta a ter rótulo de texto “Trocar” (fonte reduzida, botão mais baixo), em vez do ícone isolado da v1.3, mantendo a posição discreta ao lado do nome da clínica. Linha do Trocar no Mapeamento de Componentes atualizada de “ícone apenas” para “compacto com rótulo”.
- v1.5 (16/09/2026) — “Integração com Backend”: removida a linha inline “Tabelas envolvidas: …” de cada um dos 3 endpoints, substituída por uma nota única apontando para a Seção 4 (Mapeamento de Banco de Dados, v1.5), que passou a detalhar tabelas, campos, domínios e filtros por endpoint — mesma convenção já usada em Central do Médico e Agenda do Médico, escolhida pelo solicitante para este épico. Nenhuma mudança de comportamento, request/response ou código HTTP dos 3 endpoints — só a localização de onde a ligação com o banco de dados é documentada (Lição #10 da Skill Designer).
- v1.6 (07/10/2026) — aplicação de RN-CIU-032 (sinalização de Ambiente de teste, guarda-chuva v2.26), decidida pelo solicitante: nova história US-CIU-011; nova subseção “Sinalização de Ambiente de teste” (fundo do menu com uma exceção no hover da estrela,
theme-color, prefixo da aba, comportamento durante skeleton/erro/perfil sem itens e no tema escuro); 7 critérios de aceitação novos (CA-011.1 a CA-011.7, o último acrescentado na revisão de crítico abaixo); 2 linhas novas no Mapeamento de Componentes; campoambienteTipo([PROPOSTA]) na resposta deGET /api/v1/menu; nova mensagem MSG-T5-02 (“[TESTE]” / “[TEST]” / “[PRUEBA]” — traduções escolhidas pelo Designer); nota em ECF.17.18. Escolhas do Designer, não pedidas pelo solicitante: o app-shell (e não cada tela) aplica o prefixo; em produção a tagtheme-colornão é tocada por esta regra; sem sinal substituto quando o navegador ignoratheme-color; nenhum efeito enquanto o menu carrega ou falha; o nome do Ambiente não é enviado pela API, por não ser exibido. Revisão por Dois Críticos (crítico técnico, subagente independente, mesma sessão; cada achado conferido contra o texto antes de aplicar):theme-colorpassa a ser guardada e restaurada ao sair do teste (antes, a especificação só dizia que produção não toca a tag, sem dizer como desfazer a mudança); mecanismo de atualização datheme-colorao mudar o tema descrito (matchMedia+ atributodata-theme); contrato do título da aba (telas informam só o título base; o app-shell compõe, sem repetir o prefixo, e recompõe ao mudar idioma); retirada dos efeitos ao sair do app-shell (Trocar, saída do sistema, 401) e novo CA-011.7; a afirmação de contraste mínimo de 4,5:1 “dos textos do menu” era falsa para o rótulo do Trocar (3,2:1 sobre o amarelo, 3,4:1 já sobre branco) — restrita aos tokens neutros e o rótulo do Trocar registrado como pendência do Design System; CA-011.2 e CA-011.6 reescritos para não depender do navegador; coluna do menu recolhido continua pintada mesmo sem favoritos. Total: 7 CA novos (CA-011.1 a CA-011.7). - v1.7 (07/10/2026) — acompanha 01 - Definição v1.9 (6 decisões do solicitante). “Estrutura do Menu”: grupo sem nenhum item liberado não é exibido. “Seção Favoritos”: ordem alfabética conforme a collation do banco; só favoritos de itens ainda liberados; a busca não afeta a seção; menu recolhido sem favoritos fica vazio. “Busca”: por aproximação, sem diferenciar maiúsculas/minúsculas nem acentos; só afeta a árvore. “Comportamento Responsivo”: coluna recolhida vazia sem favoritos. “Integração com Backend”: descrição de
favoritosegruposnoGET /api/v1/menue nota da busca atualizadas. Nenhum endpoint, campo, código HTTP, critério de aceitação ou mensagem novos.