sass-imobiliaria/specs/024-filtro-busca-avancada/spec.md

15 KiB
Raw Blame History

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:

  1. 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.
  2. 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.
  3. 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:

  1. Given a página /imoveis com 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.
  2. 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".
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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:

  1. Given a página /imoveis carregada sem filtros ativos, When o sidebar renderiza, Then apenas a seção "Preço" está expandida (defaultOpen = true); todas as demais seções têm defaultOpen = false.
  2. 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.
  3. 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:

  1. 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.
  2. 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".
  3. 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.
  4. 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.
  5. 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).
  6. 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_type muda 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 FilterSidebar DEVE 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 FilterSidebar sem filtros pré-ativos na URL, apenas a seção "Preço" DEVE ter defaultOpen = true; todas as demais seções DEVEM ter defaultOpen = 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_count indicando quantos imóveis ativos estão associados.
  • SugestãoDeFiltro: Resultado da busca cross-categoria, composto por category (grupo), label (texto exibido), value (identificador) e filterKey (chave do filtro a ser aplicado em PropertyFilters).
  • EstadoDeExpansãoDaSeção: Mapeamento interno de sectionKey → boolean controlando 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-imoveis continuam passando.

Assumptions

  • Os dados de catálogo (tipos, cidades, bairros, comodidades) já estão disponíveis via catalog.ts no momento em que o FilterSidebar renderiza; 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_count por item), não um endpoint separado.
  • O número de itens por seção raramente ultrapassa 2030 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 localStorage nesta 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.