Épico 5 — Menu Lateral — Especificação (v1.2)

Documentos deste épico: 01 - Definição (v1.4) · 02 - Especificação (v1.2) · 03 - Protótipo (v1.1, código executável em 03 - Protótipo v1.1.html) · 04 - Mapeamento de Banco de Dados (v1.3). 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.

Descrição Funcional Detalhada

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 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 (RN-CIU-028). 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.

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). 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 no próprio menu. 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). 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)

Exibido no cabeçalho do menu, 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 e favoritos) 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.

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).

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.

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

ComponenteVarianteEstadosTokens aplicadosUso nesta tela
Painel lateralMenu (desktop expandido)default--color-base-pure bg, --shadow-level-medium, largura fixaEstrutura principal do menu, desktop
Painel lateralMenu (desktop recolhido)default--color-base-pure bg, largura reduzida a íconesEstado recolhido, só ícones de favoritos
Painel overlayMenu (mobile)default, entrando/saindo--shadow-level-heavy, sobreposto ao conteúdo com camada de fundo semitransparenteEstado aberto do menu em mobile
Item de grupo (accordion)Grupodefault, expandido, recolhido--spacing-sm padding, --color-neutral-pure texto de rótulo, ícone de chevron rotativoCada grupo do menu (RN-CIU-026)
Item de menuPadrão / Favoritodefault, hover, active (rota atual), focus--radius-m, --color-primary-pure no item ativo, --spacing-xs entre ícone e textoCada item dentro de um grupo, da lista sem grupo ou da seção Favoritos
Ícone de estrelaFavoritarvazia (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 buscaBusca do menudefault, focus, com texto--input-height reduzido (32px), --radius-pill, --color-neutral-lighter bgCampo de busca, topo do menu (RN-CIU-030)
ButtonSecondary (Trocar)default, hover--btn-height-sm, borda --color-secondary-pureBotão “Trocar” no cabeçalho do menu, quando visível (CA-010.5/6)
Banner/Ícone informativoInfodefault--color-secondary-pureMensagem de perfil sem itens (MSG-I5-01) e de busca sem resultado (MSG-I5-02)
ToastErrordefault--color-error-pureFalha ao favoritar (MSG-E5-01)
Estado de erro em tela cheiaErro de carregamentodefault--color-error-light bg do ícone, --color-error-dark texto do íconeFalha ao carregar o menu (EX-E5-04)
SkeletonMenuloading--color-neutral-lighterCarregamento inicial do menu
RodapéMarcadefault--font-size-xs, --color-neutral-pureTexto 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: { 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. A quantidade de clínicas acessíveis, que decide a visibilidade do botão Trocar (CA-010.5/6), não é recalculada aqui — reaproveita o campo clinicasAcessiveis já retornado pelo login (E1). Códigos: 200 (sucesso — grupos, itensSemGrupo e favoritos podem vir vazios); 401 (não autenticado); 500 (falha ao carregar — EX-E5-04). Tabelas envolvidas: Processo, ProcessoGrupo, ClienteProcesso, ClientePerfilAcesso, ClientePerfilAcessoUsuario, ClientePerfilAcessoProcesso, ClienteUsuarioMenuFavorito (IpSeguranca).

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). Tabelas envolvidas: ClienteUsuarioMenuFavorito (insere o par ClientePerfilAcessoUsuarioId/ClientePerfilAcessoProcessoId — IpSeguranca).

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). Tabelas envolvidas: ClienteUsuarioMenuFavorito (remove o par — IpSeguranca).

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. 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:

IDContextopt-BRen-USes-419
MSG-E5-01Falha 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-03Falha 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:

IDContextopt-BRen-USes-419
MSG-I5-01Perfil 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-02Busca 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:

IDContextopt-BRen-USes-419
MSG-P5-01Campo de busca do menu”Buscar no menu""Search menu""Buscar en el menú”

Textos orientadores:

IDContextopt-BRen-USes-419
MSG-T5-01Rodapé do menu (rótulo estático, sem tradução de marca)“Powered by Interprocess TI""Powered by Interprocess TI""Powered by Interprocess TI”

Botões/links:

IDContextopt-BRen-USes-419
MSG-B5-01Ação de recuperação (erro de carregamento do menu)“Tentar novamente""Try again""Intentar de nuevo”
MSG-B5-02Botã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.

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.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.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.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.