sass-imobiliaria/specs/033-video-apresentacao-imovel/research.md
MatheusAlves96 e1a1f71fbd
Some checks failed
CI/CD → Deploy via SSH / Build & Push Docker Images (push) Successful in 1m6s
CI/CD → Deploy via SSH / Deploy via SSH (push) Successful in 4m18s
CI/CD → Deploy via SSH / Validate HTTPS & Endpoints (push) Has been cancelled
chore: seed sample video data, add spec 033 and update instructions
2026-04-22 23:57:50 -03:00

2.8 KiB

Research: Vídeo de Apresentação do Imóvel (033)

Gerado por: /speckit.plan
Data: 2026-04-22


Decisão 1 — Estratégia de embed de vídeo

Decision: Utilitário puro getEmbedUrl no frontend (sem lógica no backend) que faz parse client-side.
Rationale: O backend não precisa transformar URLs — salva o valor bruto e devolve sem alteração. O parse pode falhar silenciosamente no cliente sem impactar dados. Reduz complexidade no servidor.
Alternatives considered: Validar domínio no backend via Pydantic @field_validator — rejeitado porque geraria 422 em URLs válidas de domínios futuros; validação de formato basta no backend.


Decisão 2 — Posição do vídeo: VARCHAR(20) vs ENUM SQL

Decision: VARCHAR(20) NOT NULL DEFAULT 'section' — sem ENUM SQL.
Rationale: O projeto já usa db.Enum apenas para property_type onde os valores são críticos para queries. Para posição de vídeo, a validação é feita no Pydantic (Literal['carousel', 'section']); usar ENUM SQL adicionaria complexidade em migrations sem benefício mensurável.
Alternatives considered: db.Enum('carousel', 'section', name='video_position') — rejeitado por custo de migration mais alto.


Decisão 3 — Integração do vídeo no carrossel vs componente separado

Decision: Modificar PhotoCarousel para aceitar videoUrl?: string | null e renderizar o VideoPlayer como slide virtual no índice 0 quando a posição for carousel. Para posição section, renderizar <VideoPlayer> fora do carrossel em PropertyDetailPage.
Rationale: Reuso do sistema de navegação (setas, dots, touch swipe) já testado no carrossel. Não cria um segundo carrossel, não duplica lógica de gestos.
Alternatives considered: Criar carrossel separado MediaCarousel — rejeitado por YAGNI (sobrecomplexidade para suportar um único slide de vídeo).


Decisão 4 — Sanitização de URL no backend

Decision: Aplicar str.strip() antes de persistir e tratar string vazia como None.
Rationale: Previne persistência de URLs com espaços acidentais (edge case da spec). Simples de implementar no update handler existente, sem dependência externa.
Alternatives considered: Pydantic AnyUrl — rejeitado porque URLs de arquivos diretos (ex.: CDN sem https://) precisam ser aceitas; AnyUrl restringiria demais.


Decisão 5 — Preview no admin (debounce)

Decision: Debounce de 600ms no campo de URL; o preview re-renderiza apenas quando getEmbedUrl retorna tipo != 'unknown'.
Rationale: Evita re-renders a cada keystroke enquanto o administrador digita. Valor de 600ms é suficiente para não parecer lento.
Alternatives considered: Preview apenas on-blur — rejeitado porque a spec exige "em tempo real" (FR-011).