feat: add full project - backend, frontend, docker, specs and configs

This commit is contained in:
MatheusAlves96 2026-04-20 23:59:45 -03:00
parent b77c7d5a01
commit e6cb06255b
24489 changed files with 61341 additions and 36 deletions

View file

@ -0,0 +1,36 @@
# Specification Quality Checklist: Redesign da Lista de Imóveis com Carrossel 3D
**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2026-04-16
**Feature**: [spec.md](../spec.md)
## Content Quality
- [x] No implementation details (languages, frameworks, APIs)
- [x] Focused on user value and business needs
- [x] Written for non-technical stakeholders
- [x] All mandatory sections completed
## Requirement Completeness
- [x] No [NEEDS CLARIFICATION] markers remain
- [x] Requirements are testable and unambiguous
- [x] Success criteria are measurable
- [x] Success criteria are technology-agnostic (no implementation details)
- [x] All acceptance scenarios are defined
- [x] Edge cases are identified
- [x] Scope is clearly bounded
- [x] Dependencies and assumptions identified
## Feature Readiness
- [x] All functional requirements have clear acceptance criteria
- [x] User scenarios cover primary flows
- [x] Feature meets measurable outcomes defined in Success Criteria
- [x] No implementation details leak into specification
## Notes
- Spec passou por validação sem necessidade de clarificações — a descrição original era suficientemente detalhada.
- Assumption sobre CSS puro para efeito 3D documentada (sem libs externas).
- Edge cases cobrem 0, 1, 2 e 3+ fotos por imóvel.

View file

@ -0,0 +1,132 @@
# Feature Specification: Redesign da Lista de Imóveis com Carrossel 3D
**Feature Branch**: `017-properties-list-3d-carousel`
**Created**: 2026-04-16
**Status**: Draft
**Input**: Redesenhar a página /imoveis para exibir imóveis em linhas com carrossel 3D de fotos empilhadas em efeito fan/stack
---
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Visualizar Lista de Imóveis com Cards em Linha (Priority: P1)
Um visitante acessa a página `/imoveis` e vê os imóveis dispostos em uma lista vertical de cards horizontais. Cada card ocupa a largura total disponível e exibe as informações principais ao lado de um carrossel 3D de fotos.
**Why this priority**: É a mudança central da feature — sem o novo layout de lista, todo o restante não existe. Entrega valor imediato ao usuário que busca escanear imóveis com mais informação visível por item.
**Independent Test**: Pode ser testado acessando `/imoveis` e verificando que os imóveis aparecem em linhas horizontais (não em grid), cada uma com altura ~260px no desktop, com foto à esquerda e informações à direita.
**Acceptance Scenarios**:
1. **Given** o usuário acessa `/imoveis`, **When** a página carrega, **Then** os imóveis são apresentados em uma lista vertical com cards horizontais de altura fixa ~260px no desktop.
2. **Given** o card está visível, **When** o usuário o visualiza, **Then** vê à esquerda um bloco de fotos (~320px de largura) e à direita as informações do imóvel ocupando o espaço restante.
3. **Given** o usuário está em dispositivo móvel, **When** visualiza um card, **Then** o carrossel de fotos aparece acima e as informações aparecem abaixo (layout empilhado vertical).
4. **Given** os imóveis estão carregando, **When** a requisição ainda não completou, **Then** um skeleton no formato de linha é exibido no lugar dos cards.
---
### User Story 2 - Interagir com o Carrossel 3D de Fotos (Priority: P2)
Um visitante deseja ver diferentes fotos de um imóvel na listagem sem precisar entrar na página de detalhe. Ele clica nas fotos empilhadas atrás da principal para trazê-las à frente.
**Why this priority**: O carrossel 3D é o diferencial visual desta feature. Sem ele, os cards de linha seriam comuns; com ele, o usuário pode pré-visualizar fotos diretamente na listagem, reduzindo a necessidade de navegar para a página de detalhe.
**Independent Test**: Pode ser testado clicando em qualquer uma das fotos de fundo no carrossel de um card e verificando que a foto clicada passa para a posição frontal com animação suave.
**Acceptance Scenarios**:
1. **Given** um card de imóvel está visível, **When** o usuário o carrega, **Then** exibe 3 fotos empilhadas em perspectiva 3D: a primeira na frente (posição destaque) e as demais levemente rotacionadas e deslocadas atrás.
2. **Given** o carrossel exibe 3 fotos em stack, **When** o usuário clica em uma foto de fundo, **Then** ela é trazida para a posição frontal com animação de 300ms e as demais redistribuem-se para as posições de fundo.
3. **Given** o imóvel possui menos de 3 fotos, **When** o carrossel é renderizado, **Then** as posições restantes são preenchidas com a última foto disponível ou com um placeholder visual.
4. **Given** o imóvel possui 1 ou mais fotos, **When** o carrossel é renderizado, **Then** a animação de rotação ocorre apenas quando há mais de uma foto disponível.
---
### User Story 3 - Visualizar Informações e Navegar para Detalhe do Imóvel (Priority: P2)
Um visitante vê as informações essenciais do imóvel diretamente no card da listagem e pode, a partir dele, navegar para a página de detalhe ou acionar a comparação.
**Why this priority**: O card precisa transmitir informação suficiente para o usuário decidir se vale a pena ver o detalhe completo, sem sobrecarregar visualmente o layout de lista.
**Independent Test**: Pode ser testado verificando que cada card exibe título, localização, badge de tipo, preço, stats e contém links/botões funcionais para detalhe e comparação.
**Acceptance Scenarios**:
1. **Given** um card de imóvel está visível, **When** o usuário o vê, **Then** encontra: título do imóvel (até 2 linhas), bairro e cidade, badge Venda ou Aluguel, preço em destaque, e stats de quartos, banheiros, área m² e vagas.
2. **Given** o usuário vê o card, **When** clica no título ou no link de detalhe, **Then** é redirecionado para a página de detalhe do imóvel.
3. **Given** o usuário vê o card, **When** clica no botão "Comparar", **Then** o imóvel é adicionado à lista de comparação (comportamento existente mantido).
---
### User Story 4 - Filtrar Imóveis com Sidebar Preservada (Priority: P1)
Um visitante usa os filtros da sidebar para refinar os resultados. O novo layout de lista deve preservar a sidebar e atualizar os cards de forma idêntica ao comportamento atual.
**Why this priority**: A sidebar de filtros é funcionalidade central da página `/imoveis`. Qualquer redesign que quebre os filtros compromete o fluxo de busca do usuário.
**Independent Test**: Pode ser testado aplicando filtros na sidebar e verificando que os cards em linha refletem corretamente os resultados filtrados.
**Acceptance Scenarios**:
1. **Given** o usuário está na página `/imoveis`, **When** visualiza o layout, **Then** a FilterSidebar permanece à esquerda com largura fixa (w-56) e os cards de linha ocupam o espaço restante à direita.
2. **Given** o usuário aplica um filtro na sidebar, **When** os resultados atualizam, **Then** os cards em linha exibem apenas os imóveis que correspondem aos filtros selecionados.
---
### Edge Cases
- O que acontece quando um imóvel não possui nenhuma foto? → O carrossel exibe 3 placeholders visuais e a interação de clique fica desabilitada.
- O que acontece com a animação 3D em browsers sem suporte a `perspective` CSS? → O carrossel exibe as fotos em layout flat (sem 3D) como fallback gracioso.
- O que acontece quando a lista de imóveis retorna 0 resultados? → O estado vazio existente é exibido, adaptado para o novo layout de lista.
- O que acontece quando o usuário clica rapidamente em múltiplas fotos? → A animação de 300ms é respeitada; cliques durante a transição são enfileirados ou ignorados para evitar estados visuais inconsistentes.
- O que acontece com imóveis que possuem exatamente 1 foto? → A foto única ocupa a posição frontal; as 2 posições de fundo são preenchidas com a mesma foto ou placeholder.
---
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: A página `/imoveis` DEVE exibir imóveis em layout de lista vertical (linha por linha) ao invés do grid atual.
- **FR-002**: Cada card DEVE ter altura fixa de ~260px no desktop e layout responsivo empilhado (foto acima, info abaixo) no mobile.
- **FR-003**: A seção de fotos de cada card DEVE ter largura fixa de ~320px no desktop e ocupar a largura total no mobile.
- **FR-004**: O carrossel 3D DEVE sempre exibir 3 fotos em efeito fan/stack com perspectiva CSS: a primeira na frente (translateZ maior, sem rotação), e as demais atrás (rotateY + translateX progressivos).
- **FR-005**: Clicar em uma foto de fundo DEVE trazê-la para a posição frontal com animação smooth de 300ms via CSS transition.
- **FR-006**: Imóveis com menos de 3 fotos DEVEM preencher as posições faltantes repetindo a última foto disponível ou exibindo placeholder visual neutro.
- **FR-007**: Cada card DEVE exibir: título do imóvel (máx. 2 linhas), bairro e cidade, badge de tipo (Venda/Aluguel), preço em destaque, número de quartos, banheiros, área m² e vagas de garagem.
- **FR-008**: Cada card DEVE conter botão "Comparar" e link de navegação para a página de detalhe do imóvel.
- **FR-009**: A FilterSidebar DEVE ser preservada com largura fixa à esquerda da lista de cards.
- **FR-010**: O skeleton de carregamento DEVE ser atualizado para refletir o formato de linha (retângulo largo com seção de foto à esquerda e barras de texto à direita).
- **FR-011**: A interação de clique no carrossel NÃO DEVE disparar navegação para a página de detalhe.
### Key Entities
- **PropertyCard**: Representa um imóvel na listagem; contém dados de exibição (título, localização, preço, stats) e referência às fotos.
- **PhotoCarousel3D**: Componente visual do carrossel; gerencia o estado de qual foto está na posição frontal e as posições de fundo das demais.
- **CarouselPhoto**: Foto individual dentro do carrossel; possui posição (front/back-1/back-2) e índice de rotação 3D.
---
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: A página `/imoveis` exibe todos os imóveis no novo formato de lista sem perda de dados ou funcionalidade em relação ao layout anterior.
- **SC-002**: A transição de fotos no carrossel é visualmente fluida e completa em até 300ms, sem saltos ou flickering.
- **SC-003**: O layout é totalmente utilizável em dispositivos móveis: foto e informações acessíveis sem scroll horizontal.
- **SC-004**: Os filtros da sidebar continuam funcionando corretamente — os resultados em lista refletem exatamente os critérios selecionados.
- **SC-005**: Cards com imóveis de 0, 1, 2 ou 3+ fotos são renderizados sem erros visuais ou de console.
- **SC-006**: O tempo de carregamento percebido pelo usuário não aumenta em relação ao layout de grid anterior (skeleton mantém a experiência progressiva).
---
## Assumptions
- O componente `FilterSidebar` existente não precisa de alterações — somente o layout à direita é redesenhado.
- As fotos dos imóveis já estão acessíveis via as propriedades existentes do modelo `Property` (relação `photos`).
- O efeito 3D é implementado exclusivamente com CSS (`perspective`, `rotateY`, `translateZ`, `transition`) sem bibliotecas externas de animação.
- A funcionalidade de comparação (botão "Comparar") já existe e será reutilizada sem modificações de lógica.
- O comportamento de paginação ou scroll infinito existente é mantido sem alterações.
- O layout mobile usa breakpoint `md` do Tailwind CSS como ponto de corte entre desktop (horizontal) e mobile (empilhado).
- Imóveis sem nenhuma foto recebem um placeholder visual genérico (ícone de câmera ou cor sólida) nas 3 posições do carrossel.