15 KiB
Feature Specification: Filtro de Busca Avançada — FilterSidebar
Feature Branch: 024-filtro-busca-avancada
Created: 2026-04-20
Status: Draft
Fonte: Solicitação de melhoria UX no sidebar de filtros da página /imoveis
Contexto
O FilterSidebar da página /imoveis já existe e é funcional, mas apresenta três lacunas de usabilidade que impactam a descoberta de imóveis:
- Ausência de busca cross-categoria dentro do sidebar: o usuário precisa abrir seção por seção para encontrar um tipo de imóvel ou bairro específico.
- Todas as seções abertas por padrão: ao carregar a página, o sidebar está completamente expandido, gerando sobrecarga visual e exigindo scroll antes mesmo de ver os resultados.
- Listas longas sem hierarquia de popularidade: bairros e tipos são listados em ordem arbitrária; itens raramente usados ocupam o mesmo espaço visual que os mais procurados, dificultando a seleção rápida.
User Scenarios & Testing
User Story 1 — Campo de Busca Cross-Categoria no Sidebar (Priority: P1)
Um visitante que sabe exatamente o que procura (ex.: "Copacabana", "Cobertura") digita o termo no campo de busca do sidebar e vê instantaneamente em qual categoria aquela opção se enquadra, podendo selecioná-la com um clique sem precisar abrir seções manualmente.
Why this priority: A busca cross-categoria resolve o maior obstáculo de navegação do sidebar: o usuário com intenção definida não sabe em qual seção procurar. É o ganho de UX mais alto com menor complexidade de implementação — nenhum dado novo de backend é necessário, pois os dados já chegam via catalog.ts.
Independent Test: Digitar "Copa" no campo de busca do sidebar e verificar que aparece uma lista de sugestões agrupadas mostrando "Copacabana" sob o grupo "Bairro"; clicar em "Copacabana" e confirmar que o filtro de bairro é aplicado.
Acceptance Scenarios:
- Given a página
/imoveiscom o sidebar visível, When o usuário vê o topo do sidebar, Then um campo de busca com placeholder "Buscar filtro…" está disponível acima das seções accordion. - Given o campo de busca do sidebar com o valor "apar", When o usuário para de digitar por 200ms, Then uma lista de sugestões aparece inline (não em dropdown popup) mostrando entradas agrupadas, por exemplo: grupo "Tipo de imóvel" → "Apartamento".
- Given sugestões de busca visíveis com múltiplas categorias correspondentes, When o usuário vê a lista, Then cada grupo tem um cabeçalho de categoria (ex.: "Tipo de imóvel", "Bairro", "Cidade") e os itens correspondentes abaixo.
- Given uma sugestão visível, When o usuário clica nela, Then o filtro correspondente é aplicado (equivalente a selecionar o item na seção accordion), o campo de busca é limpo e a seção relevante é expandida para mostrar o item selecionado.
- Given o campo de busca preenchido sem nenhuma correspondência, When a busca é executada, Then uma mensagem "Nenhum filtro encontrado para "[termo]"" é exibida no lugar das sugestões.
- Given o campo de busca preenchido, When o usuário pressiona Escape ou limpa o campo, Then as sugestões são ocultadas e o estado das seções retorna ao normal.
- Given a navegação por teclado com sugestões visíveis, When o usuário pressiona as teclas de seta (↓↑) e Enter, Then ele pode selecionar uma sugestão sem usar o mouse.
User Story 2 — Seção de Preço Aberta por Padrão, Demais Colapsadas (Priority: P1)
Um visitante que acaba de chegar na página /imoveis encontra o sidebar com uma experiência limpa: apenas a seção de preço está expandida, tornando o filtro mais importante imediatamente visível, enquanto as demais seções ficam colapsadas e acessíveis sob demanda.
Why this priority: Juntamente com a busca cross-categoria, esta mudança tem impacto imediato na percepção de organização do sidebar sem exigir dados adicionais do backend. A seção de preço é o filtro de maior influência na decisão do usuário, justificando seu destaque inicial.
Independent Test: Carregar /imoveis pela primeira vez (ou sem parâmetros de URL) e verificar que somente a seção "Preço" está expandida; todas as demais seções (Tipo, Quartos, Bairros, etc.) estão colapsadas.
Acceptance Scenarios:
- Given a página
/imoveiscarregada sem filtros ativos, When o sidebar renderiza, Then apenas a seção "Preço" está expandida (defaultOpen = true); todas as demais seções têmdefaultOpen = false. - Given filtros ativos presentes na URL (ex.:
?city=1&bedrooms=2), When o sidebar renderiza, Then as seções que contêm filtros ativos ficam automaticamente expandidas, além da seção de Preço. - Given o usuário colapsou manualmente a seção de Preço e navega para outra página e retorna, When o sidebar renderiza, Then o estado de colapso/expansão das seções volta ao padrão (Preço aberto, demais fechados), pois esse estado não é persistido.
User Story 3 — Listas com "Ver mais" e Ordenação por Popularidade (Priority: P2)
Um visitante que navega pelos filtros de bairro ou tipo de imóvel vê imediatamente os N itens mais relevantes (com mais imóveis disponíveis), pode expandir para ver todos com "Ver mais", e identifica visualmente os itens mais populares por meio de badges ou destaque.
Why this priority: Listas longas sem hierarquia sobrecarregam a interface e enterram as opções mais úteis. Exibir os mais populares primeiro e truncar com "Ver mais" é o padrão de portais imobiliários líderes. Requer dados de contagem do backend, tornando-o de implementação mais complexa que as stories P1.
Independent Test: Abrir a seção "Bairros" no sidebar e verificar que apenas os 5 bairros com mais imóveis são exibidos inicialmente, com badge "Popular" no primeiro; clicar em "Ver mais" e confirmar que todos os bairros são exibidos.
Acceptance Scenarios:
- Given uma seção de filtro com mais de 5 itens (ex.: Bairros), When o accordion é expandido, Then apenas os 5 primeiros itens são exibidos, ordenados do mais popular (mais imóveis associados) para o menos popular.
- Given uma seção com mais de 5 itens exibindo os primeiros 5, When o usuário clica no botão "Ver mais (N)", Then todos os itens restantes são exibidos inline (sem modal ou navegação), e o botão muda para "Ver menos".
- Given uma seção expandida com todos os itens visíveis, When o usuário clica em "Ver menos", Then a lista retorna a exibir apenas os 5 primeiros e o scroll retorna ao início da seção.
- Given os itens de uma seção ordenados por popularidade, When o usuário vê a lista, Then os 3 itens com mais imóveis associados exibem um badge "Popular" ao lado do nome.
- Given um filtro já selecionado que não está entre os 5 primeiros da lista, When o usuário reabre a seção com o filtro ativo, Then o item selecionado é exibido mesmo que esteja além dos 5 iniciais (o truncamento não oculta itens selecionados).
- Given uma seção com 5 itens ou menos, When o accordion é expandido, Then o botão "Ver mais" não é exibido.
Edge Cases
- O que acontece quando a busca cross-categoria retorna o mesmo item em múltiplas categorias (ex.: cidade e bairro com o mesmo nome)?
- Como o sistema lida com termos de busca contendo caracteres especiais (acentos, cedilha, hifens)?
- O que acontece quando um filtro selecionado não aparece mais na lista porque o backend não o retornou (ex.: cidade removida do catálogo)?
- Como o "Ver mais" se comporta quando um item selecionado está entre os ocultos — ele precisa estar visível mesmo sem clicar em "Ver mais"?
- O que acontece se os dados de popularidade (contagem de imóveis por bairro/tipo) ainda estão carregando quando o accordion é expandido?
- Como a seção de preço se comporta quando o parâmetro
listing_typemuda entre "venda" e "aluguel" (os presets já mudam — o estado de expansão da seção é preservado)? - Qual é o comportamento do campo de busca do sidebar quando o catálogo ainda está carregando (
catalogLoading = true)?
Requirements
Functional Requirements
Busca Cross-Categoria no Sidebar
- FR-001: O
FilterSidebarDEVE exibir um campo de busca textual no topo, acima de todas as seções accordion, com placeholder "Buscar filtro…". - FR-002: O campo de busca DEVE pesquisar simultaneamente em todas as categorias de filtro disponíveis: tipos de imóvel, cidades, bairros e comodidades.
- FR-003: A busca DEVE aplicar debounce de 200ms antes de exibir resultados, para não travar a interface durante digitação rápida.
- FR-004: Os resultados DEVEM ser apresentados agrupados por categoria, com o cabeçalho de cada grupo claramente identificado (ex.: "Tipo de imóvel", "Bairro", "Cidade", "Comodidade").
- FR-005: A busca DEVE ser case-insensitive e ignorar acentuação para maximizar correspondências (ex.: "copacabana" deve encontrar "Copacabana", "apto" deve encontrar "Apartamento").
- FR-006: Ao clicar em uma sugestão, o filtro correspondente DEVE ser aplicado imediatamente, o campo de busca DEVE ser limpo e a seção do accordion correspondente DEVE ser expandida.
- FR-007: Quando
catalogLoading = true, o campo de busca DEVE estar desabilitado com estado visual de loading (cursor não permitido, opacidade reduzida). - FR-008: A navegação por teclado (↑↓ para mover entre sugestões, Enter para selecionar, Escape para fechar) DEVE ser suportada para acessibilidade.
Estado Inicial das Seções
- FR-009: Ao carregar o
FilterSidebarsem filtros pré-ativos na URL, apenas a seção "Preço" DEVE terdefaultOpen = true; todas as demais seções DEVEM terdefaultOpen = false. - FR-010: Quando filtros pré-ativos existem na URL, as seções que contêm esses filtros ativos DEVEM ser inicialmente expandidas além da seção de Preço.
- FR-011: O estado de expansão das seções NÃO DEVE ser persistido entre sessões — cada carregamento de página retorna ao estado padrão.
Listas com Truncamento e Popularidade
- FR-012: Seções com mais de 5 itens DEVEM exibir apenas os 5 primeiros inicialmente, com um botão "Ver mais (N)" indicando quantos itens adicionais existem.
- FR-013: Os itens de cada seção DEVEM ser ordenados por popularidade, definida como a contagem de imóveis ativos associados àquele item (ex.: número de imóveis em cada bairro, número de imóveis de cada tipo).
- FR-014: Os 3 itens mais populares de cada seção DEVEM exibir um badge "Popular" ao lado do label.
- FR-015: Itens com filtro ativo (selecionados) DEVEM sempre ser visíveis, independentemente de estarem entre os 5 primeiros ou não.
- FR-016: O backend DEVE fornecer dados de contagem de imóveis por categoria (tipo de imóvel, cidade, bairro) para permitir ordenação por popularidade na camada de catálogo.
- FR-017: O botão "Ver mais" DEVE ter comportamento toggle: ao ser clicado novamente, exibe "Ver menos" e retorna a lista ao truncamento inicial.
Requisitos Não-Funcionais
- NFR-001: A busca cross-categoria DEVE executar inteiramente no cliente (sem chamadas adicionais à API), utilizando os dados de catálogo já carregados.
- NFR-002: A animação de expansão/colapso das sugestões de busca DEVE seguir a mesma curva de animação das seções accordion existentes (CSS grid trick,
duration-200 ease-out). - NFR-003: O visual de todos os elementos novos (campo de busca, badges, botão "Ver mais") DEVE seguir os design tokens do projeto:
textTertiary,textSecondary,borderSubtle,borderStandard,surface,brand. - NFR-004: Nenhuma alteração visual ou de comportamento DEVE impactar o funcionamento dos filtros existentes (os filtros aplicados via accordion continuam funcionando normalmente).
- NFR-005: A contagem de imóveis por categoria retornada pelo backend DEVE ser calculada apenas sobre imóveis ativos e disponíveis, sem expor dados de imóveis inativos.
Key Entities
- CatalogItem com Contagem: Extensão das entidades de catálogo existentes (tipo de imóvel, cidade, bairro) com o campo
property_countindicando quantos imóveis ativos estão associados. - SugestãoDeFiltro: Resultado da busca cross-categoria, composto por
category(grupo),label(texto exibido),value(identificador) efilterKey(chave do filtro a ser aplicado emPropertyFilters). - EstadoDeExpansãoDaSeção: Mapeamento interno de
sectionKey → booleancontrolando quais seções do accordion estão abertas; inicializado a partir dos filtros ativos da URL.
Success Criteria
Measurable Outcomes
- SC-001: Usuários com intenção definida (sabem o bairro ou tipo que buscam) conseguem aplicar o filtro desejado em menos de 3 interações a partir do campo de busca do sidebar.
- SC-002: A seção de preço é a primeira coisa interativa que o usuário vê ao abrir o sidebar em 100% dos carregamentos sem filtros pré-ativos.
- SC-003: Em seções com mais de 5 itens, os 5 exibidos inicialmente cobrem pelo menos 70% do volume de imóveis disponíveis (validação pelo ordenamento por popularidade).
- SC-004: O tempo de resposta do campo de busca cross-categoria (desde o fim do debounce até a exibição das sugestões) é imperceptível para o usuário (abaixo de 50ms, pois é processamento local).
- SC-005: Nenhum filtro previamente funcional quebra após a implementação — todos os cenários de aceitação da spec
023-ux-melhorias-imoveiscontinuam passando.
Assumptions
- Os dados de catálogo (tipos, cidades, bairros, comodidades) já estão disponíveis via
catalog.tsno momento em que oFilterSidebarrenderiza; não há nova chamada de API necessária para a busca cross-categoria. - A ordenação por popularidade requer uma única adição ao endpoint de catálogo existente (
property_countpor item), não um endpoint separado. - O número de itens por seção raramente ultrapassa 20–30 em produção para este SaaS (portfólio de uma imobiliária), tornando o processamento de busca local viável sem paginação.
- O estado de expansão das seções não será persistido em
localStoragenesta versão; a persistência pode ser adicionada em iteração futura se houver demanda. - O badge "Popular" é puramente visual e não afeta a lógica de filtragem.
- A busca cross-categoria opera sobre dados do catálogo (tipos, cidades, bairros, comodidades) e não sobre dados de imóveis individuais (endereços, códigos) — a busca por endereço/código já está coberta pelo campo de busca global da feature
023.
Fora do Escopo
- Salvar buscas favoritas ou histórico de filtros por usuário.
- Busca cross-categoria que inclua imóveis individuais (por código, endereço ou título) — isso é responsabilidade do campo de busca global já especificado em
023-ux-melhorias-imoveis. - Ordenação de resultados de imóveis por popularidade de bairro (apenas os filtros do sidebar são ordenados por popularidade, não os cards de imóveis).
- Criação de um sistema completo de analytics de filtros —
property_counté suficiente como proxy de popularidade nesta versão. - Filtros de busca cross-categoria em tela mobile (sheet/modal) — este spec cobre apenas o sidebar em desktop; a experiência mobile é tratada em feature separada.
- Internacionalização dos labels de categoria ou dos badges.