sass-imobiliaria/.specify/features/003-property-listing/spec.md

3.9 KiB
Raw Permalink Blame History

Feature Specification: Listagem de Imóveis com Filtros

Feature Branch: 003-property-listing Created: 2026-04-13 Status: Approved

Contexto

Página pública /imoveis onde visitantes navegam e filtram o catálogo completo de imóveis. Os filtros utilizam dados dinâmicos cadastrados pela área administrativa (tipos, características, lazer, condomínio, segurança).

User Stories

US1 — Visitante navega no catálogo (P1)

Given o visitante acessa /imoveis, When a página carrega, Then vê a grade de imóveis ativos com paginação, foto, preço, tipo, dormitórios, banheiros, área e vagas.

US2 — Visitante filtra por tipo de imóvel (P1)

Given o painel de filtros está visível, When seleciona categoria "Residencial" e subtipo "Apartamento", Then a lista atualiza mostrando apenas apartamentos residenciais.

US3 — Visitante filtra por preço (P1)

Given o filtro de preço está disponível, When define min R$ 500.000 e max R$ 1.500.000, Then apenas imóveis nesse intervalo aparecem. Com a opção "incluir condomínio" marcada, o backend soma price + condo_fee antes de comparar.

US4 — Visitante filtra por quartos/banheiros/vagas (P1)

Given os sliders numéricos estão disponíveis, When define mínimo 2 quartos, Then apenas imóveis com ≥ 2 quartos aparecem.

US5 — Visitante filtra por área (P1)

Given o filtro de área em m² está disponível, When define 50150 m², Then apenas imóveis nesse intervalo aparecem.

US6 — Visitante filtra por características (P2)

Given a lista de características está visível (Aceita animais, Ar-condicionado, etc.), When seleciona múltiplas, Then apenas imóveis que possuem TODAS as características selecionadas aparecem.

US7 — Visitante filtra lazer, condomínio e segurança (P2)

Mesmo comportamento do US6 para os grupos adicionais.

API Contract

Endpoints necessários

GET /api/v1/property-types → lista hierárquica de categorias e subtipos

[
  {
    "id": 1, "name": "Residencial", "slug": "residencial",
    "subtypes": [{"id": 10, "name": "Apartamento", "slug": "apartamento"}, ...]
  }
]

GET /api/v1/amenities → lista agrupada de amenidades

[
  {"id": 1, "name": "Aceita animais", "group": "caracteristica", "count": 37},
  ...
]

GET /api/v1/properties (atualizar) — aceitar query params:

Param Tipo Descrição
subtype_id int ID do subtipo
listing_type venda|aluguel tipo da transação
price_min number preço mínimo
price_max number preço máximo
include_condo bool somar condomínio ao preço
bedrooms_min int quartos mínimo
bedrooms_max int quartos máximo
bathrooms_min int banheiros mínimo
bathrooms_max int banheiros máximo
parking_min int vagas mínimo
parking_max int vagas máximo
area_min int área m² mínimo
area_max int área m² máximo
amenity_ids int[] (CSV) IDs de amenidades (AND)
page int página (default 1)
per_page int itens por página (default 24, max 48)
featured bool retorna destaques (comportamento existente)

Resposta paginada:

{
  "items": [...],
  "total": 120,
  "page": 1,
  "per_page": 24,
  "pages": 5
}

Modelos necessários

PropertyType (novo)

  • id, name, slug, parent_id (nullable → hierarquia)

Amenity (novo)

  • id, name, slug, group (enum: caracteristica | lazer | condominio | seguranca), count (denormalizado)

PropertyAmenity (nova tabela N:N)

  • property_id, amenity_id

Atualizar Property (novo campo)

  • subtype_id FK → PropertyType
  • parking_spots INT
  • condo_fee NUMERIC(10,2) nullable

Out of Scope

  • Detalhe do imóvel (feature 004)
  • Mapa/geolocalização
  • Ordenação customizada (entregue com default created_at desc)
  • Favoritos / comparador