Files
amare/openspec/changes/package-detail-pages/design.md

5.2 KiB

Context

WeddingPackage já cobre cards ordenados + CTA WhatsApp/briefing (change restructure-home-weddings-corporate, capability ainda só no delta completo). Campos atuais: name, level, summary, scope_items (json), cta_label, sort_order, published_at. Sem slug, sem corpo de detalhe, sem imagens. Portfólio (portfolio.show, FindPublishedPortfolioCaseBySlug, PageMeta, sitemap) é o padrão de detalhe a espelhar. Mock visual: /home/manoelfreitas/Downloads/amare-assessoria-completa.html. Tokens: DESIGN.md / resources/css/tokens.css (Heritage Editorial) — não Cormorant/Inter do HTML estático.

Goals / Non-Goals

Goals:

  • Detalhe CMS-driven /pacotes/{slug} para as 3 modalidades, publish-gated.
  • Composição mock → tokens do projeto (olive accent, EB Garamond via stack existente, bg cream).
  • CTA final = mesmo canal contextual dos cards (wa.me ou /briefing?servico_interesse=).
  • SEO mínimo: meta por registro, canonical, OG image (hero ou default), entrada no sitemap.
  • Admin Filament editável sem deploy de copy.

Non-Goals:

  • Rota índice /pacotes; substituir cards da home; WhatsApp Business API; preços; multi-idioma; Livewire público; gallery multi-imagem além de hero + audience.

Decisions

Estender WeddingPackage, não criar modelo novo

Uma entidade comercial já existe e é o que home/serviços já consomem. Detalhe é projeção do mesmo agregado. Modelo paralelo geraria sync de publicação/slug e viola YAGNI.

Slug único + publicação por published_at

Igual portfólio: URL estável, scope published(), query Application FindPublishedWeddingPackageBySlug. Draft/inexistente → 404 HTTP, sem vazar campos internos.

Campos de detalhe (additive)

Campo Uso
slug string unique
eyebrow ex. "Assessoria"
title_line parte romana do H1
title_emphasis parte itálica do H1
hero_lead parágrafo do hero
hero_image_path / hero_image_alt foto hero
benefits jsonb [{icon_key,label}] — faixa escura
included_items jsonb [{icon_key,title,description}] — grid 3 col
audience_heading default editorial se vazio ok
audience_intro texto
audience_points jsonb string[] checklist
audience_image_path / audience_image_alt foto 50/50
final_cta_heading / final_cta_body bloco final
meta_title / meta_description SEO opcional

Manter summary + scope_items para cards. Não migrar cards para included_items neste ciclo.

Catálogo fechado de ícones (PackageIconCatalog)

Select Filament → icon_key string. Map PHP/Blade para SVGs inline (ou partials). Sem upload de SVG arbitrário (XSS/ops). Chaves mínimas cobrem mock (ex.: calendar, checklist, users, map, heart, spark — nomes estáveis kebab).

Hero de pacote vs photo-hero genérico

Mock exige H1 bipartido (linha + ênfase itálica), divisor vertical, CTA outline no hero e foto. Preferir componente dedicado x-public.package-hero (ou estender photo-hero só se API ficar genérica sem branching feio). Seções: package-benefits, package-included, package-audience, reutilizar final-cta se encaixar.

CTA WhatsApp

Reutilizar VO/helper já usado nos cards (digits de SiteSetting.whatsapp_number, mensagem com nome da modalidade). Mesma regra de fallback briefing. Não duplicar lógica de normalização.

Card: título/área → route('packages.show', $package) quando slug presente; botão CTA continua WhatsApp/briefing. Sem quebrar testes de CTA existentes.

Imagens

PublicImageUploadRules + disk público existente + x-media.image. Paths nullable; se hero ausente, layout degrada (omitir slot de imagem).

Camada Application

  • FindPublishedWeddingPackageBySlug
  • Estender GetSitemapEntries com slugs de pacotes publicados
  • PageMeta no controller (espelhar PortfolioCaseController)

Sem repository genérico / BaseAction.

Risks / Trade-offs

  • [Capability wedding-packages ainda não está em openspec/specs/] → delta ADDED nesta change; ao arquivar, consolidar com requirements de cards do change completo ou arquivar ambos em ordem.
  • [Copy das 3 modalidades incompleta] → seeder: Essenza = mock; Conduzione/Grand Jour estrutura paralela adaptada; admin pode editar.
  • [Ícones insuficientes no catálogo] → adicionar chave no map + opção Filament; sem free-text SVG.
  • [Cards sem slug durante migrate] → migration backfill slug a partir do name; seeder garante os 3 oficiais.
  • [Duplicação visual mock vs tokens] → testes de tokens existentes + asserts de classes/roles; não copiar hex do HTML.

Migration Plan

  1. Deploy migration additive + código + assets Blade juntos.
  2. Rodar seeder/update das 3 modalidades (slug + detalhe).
  3. Verificar /pacotes/essenza (etc.), 404 draft, sitemap, CTA WA.
  4. Rollback: remover rota/views; colunas additive podem permanecer; unpublish pacotes se necessário.

Open Questions

  • Nenhuma bloqueante (decisões de produto já confirmadas: detalhe-only, extend model, 3 modalidades, WA CTA).
  • WEB-ID dedicado a package detail: não existe no SPEC; rastrear via WEB-02 + padrão WEB-03 até SPEC ganhar ID explícito.