3.9 KiB
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 50–150 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_idFK → PropertyTypeparking_spotsINTcondo_feeNUMERIC(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