Compare commits
1 Commits
feat/man-1
...
research/m
| Author | SHA1 | Date | |
|---|---|---|---|
| 17060c054c |
@@ -4,10 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Application\Queries\Marketing;
|
||||
|
||||
use App\Domain\Marketing\PortfolioVertical;
|
||||
use App\Models\PortfolioCase;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
final class GetPublishedPortfolioCases
|
||||
@@ -15,37 +12,12 @@ final class GetPublishedPortfolioCases
|
||||
/**
|
||||
* @return Collection<int, PortfolioCase>
|
||||
*/
|
||||
public function __invoke(?PortfolioVertical $vertical = null): Collection
|
||||
public function __invoke(): Collection
|
||||
{
|
||||
return $this->baseQuery($vertical)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LengthAwarePaginator<int, PortfolioCase>
|
||||
*/
|
||||
public function paginate(?PortfolioVertical $vertical = null, int $perPage = 9): LengthAwarePaginator
|
||||
{
|
||||
return $this->baseQuery($vertical)->paginate($perPage)->withQueryString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<PortfolioCase>
|
||||
*/
|
||||
private function baseQuery(?PortfolioVertical $vertical): Builder
|
||||
{
|
||||
$query = PortfolioCase::query()
|
||||
return PortfolioCase::query()
|
||||
->published()
|
||||
->with(['images'])
|
||||
->orderBy('sort_order');
|
||||
|
||||
if ($vertical !== null) {
|
||||
$query->where(function (Builder $builder) use ($vertical): void {
|
||||
foreach ($vertical->eventTypePatterns() as $pattern) {
|
||||
$builder->orWhere('event_type', 'ilike', $pattern);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return $query;
|
||||
->orderBy('sort_order')
|
||||
->get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\Marketing;
|
||||
|
||||
/**
|
||||
* Public portfolio verticals used to separate Casamentos and Corporate proof.
|
||||
*
|
||||
* Matching is intentionally tolerant of free-text `event_type` values already
|
||||
* stored in the CMS (e.g. "Casamento", "Mini wedding", "Corporativo").
|
||||
*/
|
||||
enum PortfolioVertical: string
|
||||
{
|
||||
case Casamentos = 'casamentos';
|
||||
case Corporate = 'corporate';
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::Casamentos => 'Casamentos',
|
||||
self::Corporate => 'Corporate',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function eventTypePatterns(): array
|
||||
{
|
||||
return match ($this) {
|
||||
self::Casamentos => ['%casamento%', '%wedding%', '%social%'],
|
||||
self::Corporate => ['%corporat%', '%empresa%', '%business%'],
|
||||
};
|
||||
}
|
||||
|
||||
public static function tryFromQuery(?string $value): ?self
|
||||
{
|
||||
if ($value === null || $value === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::tryFrom($value);
|
||||
}
|
||||
}
|
||||
@@ -6,35 +6,33 @@ namespace App\Http\Controllers\PublicSite;
|
||||
|
||||
use App\Application\Data\PageMeta;
|
||||
use App\Application\Queries\Marketing\FindPublishedPortfolioCaseBySlug;
|
||||
use App\Application\Queries\Marketing\GetPublishedPortfolioCases;
|
||||
use App\Domain\Marketing\PortfolioVertical;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\PortfolioCase;
|
||||
use App\Models\SiteSetting;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
final class PortfolioController extends Controller
|
||||
{
|
||||
public function index(Request $request, GetPublishedPortfolioCases $getPublishedPortfolioCases): View
|
||||
public function index(): View
|
||||
{
|
||||
$settings = SiteSetting::instance();
|
||||
$vertical = PortfolioVertical::tryFromQuery($request->query('vertente'));
|
||||
$cases = $getPublishedPortfolioCases->paginate($vertical);
|
||||
|
||||
/** @var LengthAwarePaginator<int, PortfolioCase> $cases */
|
||||
$cases = PortfolioCase::query()
|
||||
->published()
|
||||
->with(['images'])
|
||||
->orderBy('sort_order')
|
||||
->paginate(9);
|
||||
|
||||
return view('pages.portfolio.index', [
|
||||
'cases' => $cases,
|
||||
'vertical' => $vertical,
|
||||
'siteSettings' => $settings,
|
||||
'pageMeta' => PageMeta::forPage(
|
||||
canonical: route('portfolio.index', array_filter([
|
||||
'vertente' => $vertical?->value,
|
||||
])),
|
||||
canonical: route('portfolio.index'),
|
||||
settings: $settings,
|
||||
title: PageMeta::withBrandSuffix(
|
||||
$vertical === null ? 'Portfólio' : 'Portfólio — '.$vertical->label(),
|
||||
$settings,
|
||||
),
|
||||
title: PageMeta::withBrandSuffix('Portfólio', $settings),
|
||||
description: 'Casos reais de eventos conduzidos pela '.$settings->brand_name.'.',
|
||||
),
|
||||
]);
|
||||
|
||||
118
docs/research/man-135-classify-amare-mvp.md
Normal file
118
docs/research/man-135-classify-amare-mvp.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# MAN-135 — Classificar issues Amare MVP vs Gitea `main`
|
||||
|
||||
**Issue:** [Research: classificar issues Amare MVP vs Gitea main](https://linear.app/maneco-workspace/issue/MAN-135/research-classificar-issues-amare-mvp-vs-gitea-main)
|
||||
**Mapa:** [MAN-134](https://linear.app/maneco-workspace/issue/MAN-134/mapa-classificar-amare-mvp-linear-gitea)
|
||||
**Branch:** `research/man-135-classify-amare-mvp`
|
||||
**HEAD canônico inventariado:** `origin/main` @ `93b680c` (`docs: require Linear issues and auto-ship PRs (#4)`)
|
||||
**Data:** 2026-08-13
|
||||
|
||||
## Regras (de MAN-134)
|
||||
|
||||
| Regra | Aplicação |
|
||||
| --- | --- |
|
||||
| Code truth | Gitea `origin/main` (`manoel-freitas/amare`) |
|
||||
| Done = shipped | commit presente em `origin/main` |
|
||||
| GitHub | só pista (`amore-site`); não canônico |
|
||||
| Pós-MVP | fora de escopo: MAN-111, 112, 113, 114, 115, 131 |
|
||||
| Status Linear | **não** alterados neste research (exceto fechar MAN-135) |
|
||||
|
||||
## Fontes
|
||||
|
||||
| Fonte | Uso |
|
||||
| --- | --- |
|
||||
| Linear MCP `list_issues` / `get_issue` project **Amare — Lançamento MVP** | universo, status, labels, ACs |
|
||||
| `git fetch origin` + `git log origin/main` | evidência shipped |
|
||||
| `tea pr list --state all` (0 open; #1–#4 merged) | PRs Gitea |
|
||||
| `gh pr list` / `gh pr view` (GitHub mirror) | pistas #63, #64 |
|
||||
| Branches `origin/*` | trabalho em voo |
|
||||
| Cross-check | [MAN-136 orphans](https://linear.app/maneco-workspace/issue/MAN-136/research-inventariar-merges-orfaos-no-gitea), [MAN-137 MAN-126 state](https://linear.app/maneco-workspace/issue/MAN-137/research-estado-real-de-casamentos-corporate-man-126) (branches locais; **não** em `main` ainda) |
|
||||
|
||||
## Contagens (36 issues in-scope)
|
||||
|
||||
| Bucket | Count |
|
||||
| --- | ---: |
|
||||
| **shipped** | 14 |
|
||||
| **em voo** | 5 |
|
||||
| **não começou** | 12 |
|
||||
| · cliente | 5 |
|
||||
| · engenharia | 5 |
|
||||
| · ops-lançamento | 2 |
|
||||
| **Linear podre** | 5 |
|
||||
| **Total classificado** | **36** |
|
||||
| Excluídos Pós-MVP | 6 |
|
||||
| Issues no projeto | 42 |
|
||||
|
||||
---
|
||||
|
||||
## Tabela canônica
|
||||
|
||||
| Issue | Linear status | Bucket | Evidência / nota |
|
||||
| --- | --- | --- | --- |
|
||||
| [Implementar Home e páginas institucionais do MVP](https://linear.app/maneco-workspace/issue/MAN-102/implementar-home-e-paginas-institucionais-do-mvp) | Done | **shipped** | Site público + home editorial em `main` (ex. `#53`, heros, `/sobre`, `/servicos`) |
|
||||
| [Implementar portfólio e depoimentos](https://linear.app/maneco-workspace/issue/MAN-103/implementar-portfolio-e-depoimentos) | Done | **shipped** | Portfólio/depoimentos + seed fix `49fbc0f` (MAN-103) |
|
||||
| [Implementar formulário de solicitação de proposta](https://linear.app/maneco-workspace/issue/MAN-104/implementar-formulario-de-solicitacao-de-proposta) | Done | **shipped** | Briefing/contato em `main` (ex. `eed8240`) |
|
||||
| [Implementar tracking simples da origem dos leads](https://linear.app/maneco-workspace/issue/MAN-105/implementar-tracking-simples-da-origem-dos-leads) | Done | **shipped** | `37296f7` (MAN-105) / GH #37 |
|
||||
| [Definir e implementar atualização simples de conteúdo](https://linear.app/maneco-workspace/issue/MAN-106/definir-e-implementar-atualizacao-simples-de-conteudo) | Done | **shipped** | `4001cd0` (MAN-106 AC4) / GH #33 |
|
||||
| [Finalizar SEO técnico e metadados sociais](https://linear.app/maneco-workspace/issue/MAN-107/finalizar-seo-tecnico-e-metadados-sociais) | Done | **shipped** | SEO desde ship público (`3dc1f44` et al.) |
|
||||
| [Rodar auditoria Lighthouse e corrigir performance do site público](https://linear.app/maneco-workspace/issue/MAN-109/rodar-auditoria-lighthouse-e-corrigir-performance-do-site-publico) | Done | **shipped** | `0ecae4c` (MAN-109) / GH #43 |
|
||||
| [Auditar se Vue + Livewire faz sentido na arquitetura atual](https://linear.app/maneco-workspace/issue/MAN-117/auditar-se-vue-livewire-faz-sentido-na-arquitetura-atual) | Done | **shipped** | `2e28603` reconcilia stack declarada |
|
||||
| [Portar identidade visual do site público para o admin em Filament](https://linear.app/maneco-workspace/issue/MAN-118/portar-identidade-visual-do-site-publico-para-o-admin-em-filament) | Done | **shipped** | `63c0269` (MAN-118) / GH #40 |
|
||||
| [Estabilizar baselines de regressão visual no CI (paridade local×CI)](https://linear.app/maneco-workspace/issue/MAN-119/estabilizar-baselines-de-regressao-visual-no-ci-paridade-localci) | Done | **shipped** | Trabalho de baselines chegou em `main`; remoção posterior `#44` é resolução intencional, não “Done sem merge” |
|
||||
| [Fechar portões de qualidade e deploy da Fase 0 antes do lançamento](https://linear.app/maneco-workspace/issue/MAN-120/fechar-portoes-de-qualidade-e-deploy-da-fase-0-antes-do-lancamento) | Done | **shipped** | `7e68c0e` (MAN-120) / GH #39 |
|
||||
| [Reencodar imagens de marca e regerar baselines visuais](https://linear.app/maneco-workspace/issue/MAN-122/reencodar-imagens-de-marca-e-regerar-baselines-visuais) | Done | **shipped** | Era de baselines/imagem em `main` (série #24/#7 + follow-ups) |
|
||||
| [Deploy de staging falha no Dokploy desde 08/08 — causa server-side, sem log acessível](https://linear.app/maneco-workspace/issue/MAN-123/deploy-de-staging-falha-no-dokploy-desde-0808-causa-server-side-sem) | Done | **shipped** | Pipeline/fixes Dokploy+staging em `main` (ex. `#6`–`#9`, `ac08b5f`, `26a68e1`) |
|
||||
| [Reconciliar documentação e changes OpenSpec após os PRs #41–#49](https://linear.app/maneco-workspace/issue/MAN-124/reconciliar-documentacao-e-changes-openspec-apos-os-prs-41-49) | Done | **shipped** | `213d684` (MAN-124) / GH #50 |
|
||||
| [Reestruturar jornada pública em Amare Casamentos e Amare Corporate](https://linear.app/maneco-workspace/issue/MAN-126/reestruturar-jornada-publica-em-amare-casamentos-e-amare-corporate) | In Progress | **em voo** | `origin/feat/man-126-casamentos-corporate` (1 commit ahead, não em `main`); GH PR [#63](https://github.com/manoel-freitas/amore-site/pull/63) open; **0** PR Gitea. Ver MAN-137 |
|
||||
| [Executar QA de responsividade e acessibilidade](https://linear.app/maneco-workspace/issue/MAN-108/executar-qa-de-responsividade-e-acessibilidade) | In Progress | **em voo** | Status coerente com QA aberto; PRs de suporte (#44–#49) já em `main`, ACs manuais não fechados; sem PR Gitea aberto só desta issue |
|
||||
| [Configurar domínio, ambiente de produção e checklist de lançamento](https://linear.app/maneco-workspace/issue/MAN-110/configurar-dominio-ambiente-de-producao-e-checklist-de-lancamento) | In Progress | **em voo** | Ops de lançamento em curso (staging/deploy em `main`; produção/DNS/checklist incompletos) |
|
||||
| [Ajustar CTAs consultivos no WhatsApp e briefing comercial](https://linear.app/maneco-workspace/issue/MAN-127/ajustar-ctas-consultivos-no-whatsapp-e-briefing-comercial) | Todo | **em voo** | Fluxo 1 parcial em `main` via Gitea [#2](https://git.hellomanoel.com/manoel-freitas/amare/pulls/2) (`e2af1f6`); Fluxo 2 (indecisos) + fechamento de ACs ainda abertos; Linear Todo atrasa vs código parcial |
|
||||
| [Research: classificar issues Amare MVP vs Gitea main](https://linear.app/maneco-workspace/issue/MAN-135/research-classificar-issues-amare-mvp-vs-gitea-main) | Backlog→Done* | **em voo** | Este arquivo / branch `research/man-135-classify-amare-mvp` — **ainda não** em `origin/main` (*Done só no Linear após resolução; ver podre se Done sem merge) |
|
||||
| [Exigir issue Linear em todo trabalho e PR](https://linear.app/maneco-workspace/issue/MAN-132/exigir-issue-linear-em-todo-trabalho-e-pr) | In Progress | **Linear podre** | Conteúdo em `main` via Gitea [#4](https://git.hellomanoel.com/manoel-freitas/amare/pulls/4) (`93b680c`); Linear ainda In Progress. GH [#64](https://github.com/manoel-freitas/amore-site/pull/64) open = mirror stale |
|
||||
| [Adicionar PR template no Gitea e no GitHub](https://linear.app/maneco-workspace/issue/MAN-133/adicionar-pr-template-no-gitea-e-no-github) | In Progress | **Linear podre** | `.gitea/PULL_REQUEST_TEMPLATE.md` + `.github/pull_request_template.md` em `origin/main` (mesmo PR #4); Linear In Progress |
|
||||
| [Fechar arquitetura e copy final do MVP](https://linear.app/maneco-workspace/issue/MAN-97/fechar-arquitetura-e-copy-final-do-mvp) | In Progress | **Linear podre** | In Progress sem branch/PR abertos; arquitetura/home editorial já em `main` (#46–#53, #52…). Residual de copy/conteúdo vive em tickets cliente (MAN-98…) e MAN-126 |
|
||||
| [Research: inventariar merges órfãos no Gitea](https://linear.app/maneco-workspace/issue/MAN-136/research-inventariar-merges-orfaos-no-gitea) | Done | **Linear podre** | Done no Linear; deliverable em `origin/research/man-136-orphan-gitea-merges` — **não** merged em `main` |
|
||||
| [Research: estado real de Casamentos × Corporate (MAN-126)](https://linear.app/maneco-workspace/issue/MAN-137/research-estado-real-de-casamentos-corporate-man-126) | Done | **Linear podre** | Done no Linear; `docs/research/man-137-man-126-state.md` em branch local ahead — **não** em `origin/main` |
|
||||
| [Receber e consolidar conteúdo institucional e serviços da Michelle](https://linear.app/maneco-workspace/issue/MAN-98/receber-e-consolidar-conteudo-institucional-e-servicos-da-michelle) | Todo | **não começou · cliente** | Labels Conteúdo/Cliente; sem branch/PR |
|
||||
| [Fechar portfólio e banco de imagens do lançamento](https://linear.app/maneco-workspace/issue/MAN-99/fechar-portfolio-e-banco-de-imagens-do-lancamento) | Todo | **não começou · cliente** | Labels Conteúdo/Cliente; sem branch/PR |
|
||||
| [Consolidar depoimentos reais para o MVP](https://linear.app/maneco-workspace/issue/MAN-100/consolidar-depoimentos-reais-para-o-mvp) | Todo | **não começou · cliente** | Labels Conteúdo/Cliente; sem branch/PR |
|
||||
| [Confirmar WhatsApp Business e canais de contato](https://linear.app/maneco-workspace/issue/MAN-101/confirmar-whatsapp-business-e-canais-de-contato) | Todo | **não começou · cliente** | Labels Conteúdo/Cliente; sem branch/PR |
|
||||
| [Aplicar identidade visual oficial e rodada de revisão da cliente](https://linear.app/maneco-workspace/issue/MAN-128/aplicar-identidade-visual-oficial-e-rodada-de-revisao-da-cliente) | Todo | **não começou · cliente** | Labels Cliente/Design; sem branch/PR |
|
||||
| [Papel Assistant não tem nenhuma permissão funcional](https://linear.app/maneco-workspace/issue/MAN-121/papel-assistant-nao-tem-nenhuma-permissao-funcional) | Backlog | **não começou · engenharia** | Enum `Assistant` existe; permissões funcionais não entregues; sem branch |
|
||||
| [Provar falha dos gates e rollback antes de arquivar complete-foundation-parity](https://linear.app/maneco-workspace/issue/MAN-125/provar-falha-dos-gates-e-rollback-antes-de-arquivar-complete) | Todo | **não começou · engenharia** | ACs de prova controlada abertos; experiência **não** deve mergear em `main` |
|
||||
| [Revisar privacidade, LGPD e consentimentos do MVP](https://linear.app/maneco-workspace/issue/MAN-116/revisar-privacidade-lgpd-e-consentimentos-do-mvp) | Todo | **não começou · engenharia** | Página privacidade existe; revisão/consentimentos ACs abertos; sem branch |
|
||||
| [Mapa: classificar Amare MVP (Linear × Gitea)](https://linear.app/maneco-workspace/issue/MAN-134/mapa-classificar-amare-mvp-linear-gitea) | Todo | **não começou · engenharia** | Wayfinder map — inventário ainda em research filhos |
|
||||
| [Grilling: lista de ações de sync após inventário](https://linear.app/maneco-workspace/issue/MAN-138/grilling-lista-de-acoes-de-sync-apos-inventario) | Backlog | **não começou · engenharia** | Depende do inventário (este + MAN-136/137) |
|
||||
| [Configurar Search Console, Meta Pixel e mensuração de lançamento](https://linear.app/maneco-workspace/issue/MAN-129/configurar-search-console-meta-pixel-e-mensuracao-de-lancamento) | Todo | **não começou · ops-lançamento** | Mensuração de go-live; sem branch |
|
||||
| [Preparar acesso e treinamento do painel administrativo](https://linear.app/maneco-workspace/issue/MAN-130/preparar-acesso-e-treinamento-do-painel-administrativo) | Todo | **não começou · ops-lançamento** | Acesso/treino go-live (label Cliente+Engenharia); sem branch |
|
||||
|
||||
### Fora de escopo (Pós-MVP)
|
||||
|
||||
| Issue | Nota |
|
||||
| --- | --- |
|
||||
| [MAN-111](https://linear.app/maneco-workspace/issue/MAN-111/pos-mvp-produzir-pdf-comercial-estatico-de-servicos) … [MAN-115](https://linear.app/maneco-workspace/issue/MAN-115/pos-mvp-mapear-convivencia-com-o-assessoria-vip), [MAN-131](https://linear.app/maneco-workspace/issue/MAN-131/pos-mvp-formulario-para-fornecedores-e-parcerias) | Não classificados (mapa Out of scope) |
|
||||
|
||||
---
|
||||
|
||||
## Hints verificados
|
||||
|
||||
| Hint | Resultado |
|
||||
| --- | --- |
|
||||
| MAN-132 + MAN-133 via Gitea PR #4, Linear In Progress | **Confirmado → Linear podre** (código shipped; status podre). Também GH #64 ainda open |
|
||||
| MAN-126: GH #63 + branch, sem PR Gitea | **Confirmado → em voo** |
|
||||
| Gitea 0 open PRs; #1–#4 merged | **Confirmado** (`tea pr list`) |
|
||||
|
||||
## Ações de sync sugeridas (não executadas aqui)
|
||||
|
||||
1. Marcar **Done** no Linear: MAN-132, MAN-133 (e fechar GH #64 stale).
|
||||
2. Reavaliar MAN-97 → Done ou decompor residual em tickets cliente/MAN-126.
|
||||
3. Abrir **PR Gitea** para `feat/man-126-casamentos-corporate`; fechar ou ignorar GH #63 após mirror.
|
||||
4. MAN-127: mover para In Progress; fechar Fluxo 2 / ACs restantes ou fatiar ticket.
|
||||
5. Mergear (ou aceitar exceção) branches de research MAN-136/137/135 se “Done” exigir `main`.
|
||||
6. Lista priorizada fica para [MAN-138](https://linear.app/maneco-workspace/issue/MAN-138/grilling-lista-de-acoes-de-sync-apos-inventario).
|
||||
|
||||
## Ambiguidades
|
||||
|
||||
- **Wayfinder research Done:** mapa diz Done = `main`; prática atual marca Done após comentário Linear com arquivo só na branch → classificado **Linear podre** para MAN-136/137.
|
||||
- **MAN-119/122:** remoção de regressão visual (`#44`) após estabilizar — tratados como shipped (resolução chegou em `main`).
|
||||
- **MAN-127:** bucket **em voo** (parcial shipped + resto aberto); alternativa seria “não começou” só do residual — preferimos um bucket por issue.
|
||||
- **MAN-108/110:** sem branch dedicada; “em voo” = processo In Progress, não PR aberta.
|
||||
11
package-lock.json
generated
11
package-lock.json
generated
@@ -5,7 +5,6 @@
|
||||
"packages": {
|
||||
"": {
|
||||
"devDependencies": {
|
||||
"@fontsource/eb-garamond": "^5.2.7",
|
||||
"@tailwindcss/vite": "^4.0.0",
|
||||
"concurrently": "^9.0.1",
|
||||
"daisyui": "^5.7.16",
|
||||
@@ -50,16 +49,6 @@
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource/eb-garamond": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/eb-garamond/-/eb-garamond-5.3.0.tgz",
|
||||
"integrity": "sha512-VplwHpB8FLuzl+4G5LDci1b3Z4SghiuXH8XEgaxjnOb5aue5mEt1njmDKeO6iyLeGa73LffU7PC7hzncLRx0ZA==",
|
||||
"dev": true,
|
||||
"license": "OFL-1.1",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
"prepare": "husky"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fontsource/eb-garamond": "^5.2.7",
|
||||
"@tailwindcss/vite": "^4.0.0",
|
||||
"concurrently": "^9.0.1",
|
||||
"daisyui": "^5.7.16",
|
||||
|
||||
@@ -134,8 +134,7 @@
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
[id$='-heading'],
|
||||
.home-chapter[id] {
|
||||
[id$='-heading'] {
|
||||
scroll-margin-top: 5.5rem;
|
||||
}
|
||||
|
||||
@@ -189,18 +188,6 @@
|
||||
overflow-x: clip;
|
||||
}
|
||||
|
||||
.link-editorial {
|
||||
background-image: linear-gradient(currentColor, currentColor);
|
||||
background-position: 0 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 1px;
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
.nav-link-editorial {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:where(a, button, input, textarea, select) {
|
||||
transition-duration: var(--amare-motion-feedback);
|
||||
@@ -212,45 +199,6 @@
|
||||
transform: translateY(1px);
|
||||
}
|
||||
|
||||
:where(button[aria-busy='true'], button:disabled):active {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.field-editorial {
|
||||
transition:
|
||||
border-color var(--amare-motion-feedback) var(--amare-ease-arrival),
|
||||
background-color var(--amare-motion-feedback) var(--amare-ease-arrival);
|
||||
}
|
||||
|
||||
.field-editorial:focus,
|
||||
.field-editorial:focus-visible {
|
||||
background-color: var(--amare-color-bg-deep);
|
||||
}
|
||||
|
||||
.link-editorial {
|
||||
transition: color var(--amare-motion-feedback) var(--amare-ease-arrival);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.nav-link-editorial::after {
|
||||
background-color: var(--amare-color-accent);
|
||||
bottom: 0.55rem;
|
||||
content: '';
|
||||
height: 1px;
|
||||
left: 0.75rem;
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
transform: scaleX(0);
|
||||
transform-origin: left center;
|
||||
transition: transform var(--amare-motion-feedback) var(--amare-ease-arrival);
|
||||
}
|
||||
|
||||
.nav-link-editorial:hover::after,
|
||||
.nav-link-editorial:focus-visible::after {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Transform/clip only — never fade text opacity (axe + WCAG mid-transition). */
|
||||
html[data-motion="enhance"] [data-motion="page-open"]:not(.is-active) [data-motion-beat] {
|
||||
transform: translateY(var(--amare-motion-distance-y));
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<div class="lg:col-span-6 lg:col-start-7">
|
||||
<p class="max-w-xl text-amare-text-muted">Uma composição de eventos sociais e corporativos para apresentar a versatilidade da Amare.</p>
|
||||
<a href="{{ route('portfolio.index') }}" class="btn btn-ghost mt-5 min-h-0 px-0 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent hover:bg-transparent hover:text-amare-accent-deep">
|
||||
<span class="link-editorial">Ver portfólio completo</span>
|
||||
<span class="border-b border-amare-accent pb-1">Ver portfólio completo</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
autocomplete="name"
|
||||
maxlength="120"
|
||||
placeholder="Seu nome"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('nome') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('nome') input-error @enderror"
|
||||
@error('nome') aria-invalid="true" aria-describedby="briefing-nome-error" @enderror
|
||||
>
|
||||
@error('nome')
|
||||
@@ -69,7 +69,7 @@
|
||||
autocomplete="email"
|
||||
maxlength="254"
|
||||
placeholder="voce@email.com"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('email') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('email') input-error @enderror"
|
||||
@error('email') aria-invalid="true" aria-describedby="briefing-email-error" @enderror
|
||||
>
|
||||
@error('email')
|
||||
@@ -88,7 +88,7 @@
|
||||
autocomplete="tel"
|
||||
maxlength="40"
|
||||
placeholder="(11) 90000-0000"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('telefone') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('telefone') input-error @enderror"
|
||||
@error('telefone') aria-invalid="true" aria-describedby="briefing-telefone-error" @enderror
|
||||
>
|
||||
@error('telefone')
|
||||
@@ -102,7 +102,7 @@
|
||||
id="briefing-tipo_evento"
|
||||
name="tipo_evento"
|
||||
required
|
||||
class="select field-editorial w-full text-amare-text @error('tipo_evento') select-error @enderror"
|
||||
class="select w-full text-amare-text @error('tipo_evento') select-error @enderror"
|
||||
@error('tipo_evento') aria-invalid="true" aria-describedby="briefing-tipo_evento-error" @enderror
|
||||
>
|
||||
<option value="" selected disabled>Selecione...</option>
|
||||
@@ -125,7 +125,7 @@
|
||||
value="{{ old('data_periodo') }}"
|
||||
maxlength="80"
|
||||
placeholder="Ex.: novembro de 2027"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('data_periodo') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('data_periodo') input-error @enderror"
|
||||
@error('data_periodo') aria-invalid="true" aria-describedby="briefing-data_periodo-error" @enderror
|
||||
>
|
||||
@error('data_periodo')
|
||||
@@ -143,7 +143,7 @@
|
||||
required
|
||||
maxlength="80"
|
||||
placeholder="Ex.: São Paulo"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('cidade') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('cidade') input-error @enderror"
|
||||
@error('cidade') aria-invalid="true" aria-describedby="briefing-cidade-error" @enderror
|
||||
>
|
||||
@error('cidade')
|
||||
@@ -163,7 +163,7 @@
|
||||
inputmode="numeric"
|
||||
autocomplete="off"
|
||||
placeholder="Ex.: 120"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('convidados') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('convidados') input-error @enderror"
|
||||
@error('convidados') aria-invalid="true" aria-describedby="briefing-convidados-error" @enderror
|
||||
>
|
||||
@error('convidados')
|
||||
@@ -180,7 +180,7 @@
|
||||
value="{{ old('servico_interesse') }}"
|
||||
maxlength="120"
|
||||
placeholder="Ex.: planejamento completo"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('servico_interesse') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('servico_interesse') input-error @enderror"
|
||||
@error('servico_interesse') aria-invalid="true" aria-describedby="briefing-servico_interesse-error" @enderror
|
||||
>
|
||||
@error('servico_interesse')
|
||||
@@ -198,7 +198,7 @@
|
||||
rows="5"
|
||||
maxlength="3000"
|
||||
placeholder="O que já está definido? Em que ponto você precisa de ajuda?"
|
||||
class="textarea field-editorial w-full min-h-[110px] text-amare-text placeholder:text-amare-muted/60 @error('mensagem') textarea-error @enderror"
|
||||
class="textarea w-full min-h-[110px] text-amare-text placeholder:text-amare-muted/60 @error('mensagem') textarea-error @enderror"
|
||||
@error('mensagem') aria-invalid="true" aria-describedby="briefing-mensagem-error" @enderror
|
||||
>{{ old('mensagem') }}</textarea>
|
||||
@error('mensagem')
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
@if (filled($settings->hero_secondary_cta_label))
|
||||
<a href="{{ route('portfolio.index') }}" class="btn btn-ghost min-h-0 px-0 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent hover:bg-transparent hover:text-amare-accent-deep">
|
||||
<span class="link-editorial">{{ $settings->hero_secondary_cta_label }}</span>
|
||||
<span class="border-b border-amare-accent pb-1">{{ $settings->hero_secondary_cta_label }}</span>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
href="{{ route('packages.show', $package->slug) }}"
|
||||
class="btn btn-ghost min-h-0 px-0 text-xs font-semibold uppercase tracking-[0.09em] text-amare-accent hover:bg-transparent hover:text-amare-accent-deep"
|
||||
>
|
||||
<span class="link-editorial">Conhecer esta modalidade</span>
|
||||
<span class="border-b border-amare-accent pb-1">Conhecer esta modalidade</span>
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
</ul>
|
||||
<p>
|
||||
<a href="{{ route('about') }}" class="btn btn-ghost min-h-0 px-0 text-sm font-semibold text-amare-accent hover:bg-transparent hover:text-amare-accent-deep">
|
||||
<span class="link-editorial">Conhecer a Amare</span>
|
||||
<span class="border-b border-amare-accent pb-1">Conhecer a Amare</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<p>
|
||||
<a href="{{ route('services.index') }}" class="btn btn-ghost min-h-0 px-0 text-sm font-semibold text-amare-accent hover:bg-transparent hover:text-amare-accent-deep">
|
||||
<span class="link-editorial">Ver todos os serviços</span>
|
||||
<span class="border-b border-amare-accent pb-1">Ver todos os serviços</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<ol class="grid gap-8 border-t border-amare-border pt-6 md:grid-cols-3">
|
||||
@foreach ($packages as $package)
|
||||
@php($contactLink = \App\Support\PackageContactLink::for($settings, $package->name))
|
||||
<li class="space-y-5 border-t border-amare-border pt-4" data-reveal data-reveal-from="up"><p class="text-xs font-semibold uppercase tracking-[.14em] text-amare-accent">{{ $package->level }}</p><h3 class="text-3xl font-medium">{{ $package->name }}</h3><p class="text-amare-muted">{{ $package->summary }}</p><ul class="space-y-2 text-sm text-amare-text-muted">@foreach ($package->scope_items as $item)<li class="border-l border-amare-border pl-3">{{ $item }}</li>@endforeach</ul><div class="space-y-2"><a href="{{ $contactLink['href'] }}" @if ($contactLink['isWhatsapp']) target="_blank" rel="noopener" @endif class="btn btn-ghost min-h-0 px-0 text-sm font-semibold text-amare-accent hover:bg-transparent hover:text-amare-accent-deep"><span class="link-editorial">{{ $package->cta_label }}</span></a><a href="{{ route('packages.show', $package->slug) }}" class="btn btn-ghost min-h-0 px-0 text-sm font-semibold text-amare-accent hover:bg-transparent hover:text-amare-accent-deep"><span class="link-editorial">Conhecer esta modalidade</span></a></div></li>
|
||||
<li class="space-y-5 border-t border-amare-border pt-4" data-reveal data-reveal-from="up"><p class="text-xs font-semibold uppercase tracking-[.14em] text-amare-accent">{{ $package->level }}</p><h3 class="text-3xl font-medium">{{ $package->name }}</h3><p class="text-amare-muted">{{ $package->summary }}</p><ul class="space-y-2 text-sm text-amare-text-muted">@foreach ($package->scope_items as $item)<li class="border-l border-amare-border pl-3">{{ $item }}</li>@endforeach</ul><div class="space-y-2"><a href="{{ $contactLink['href'] }}" @if ($contactLink['isWhatsapp']) target="_blank" rel="noopener" @endif class="btn btn-ghost min-h-0 px-0 text-sm font-semibold text-amare-accent hover:bg-transparent hover:text-amare-accent-deep"><span class="border-b border-amare-accent pb-1">{{ $package->cta_label }}</span></a><a href="{{ route('packages.show', $package->slug) }}" class="btn btn-ghost min-h-0 px-0 text-sm font-semibold text-amare-accent hover:bg-transparent hover:text-amare-accent-deep"><span class="border-b border-amare-accent pb-1">Conhecer esta modalidade</span></a></div></li>
|
||||
@endforeach
|
||||
</ol>
|
||||
@endif
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
@props([
|
||||
'seal' => 'Recebido',
|
||||
'title',
|
||||
'body',
|
||||
'homeLabel' => 'Voltar para a home',
|
||||
'whatsappLabel' => 'Falar no WhatsApp',
|
||||
'whatsappText' => 'Olá, enviei um briefing e gostaria de acompanhar.',
|
||||
])
|
||||
|
||||
@php
|
||||
$settings = $siteSettings ?? \App\Models\SiteSetting::instance();
|
||||
$digits = preg_replace('/\D/', '', (string) ($settings->whatsapp_number ?? ''));
|
||||
$whatsappHref = strlen($digits) >= 10
|
||||
? 'https://wa.me/'.$digits.'?text='.rawurlencode($whatsappText)
|
||||
: null;
|
||||
@endphp
|
||||
|
||||
<div
|
||||
role="status"
|
||||
data-form-success
|
||||
class="mt-10 max-w-2xl space-y-6 border border-amare-border bg-amare-bg-deep px-6 py-10 md:px-10"
|
||||
data-motion="page-open"
|
||||
{{ $attributes }}
|
||||
>
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.14em] text-amare-accent" data-motion-beat="seal">{{ $seal }}</p>
|
||||
<h3 class="text-3xl font-medium tracking-tight text-amare-text md:text-4xl" data-motion-beat="title">{{ $title }}</h3>
|
||||
<p class="max-w-xl text-lg leading-relaxed text-amare-muted" data-motion-beat="heading">{{ $body }}</p>
|
||||
|
||||
<div class="flex flex-col items-start gap-4 pt-2 sm:flex-row sm:items-center sm:gap-8" data-motion-beat="cta">
|
||||
<a href="{{ route('home') }}" class="btn btn-primary min-h-11 px-6 text-xs font-bold uppercase tracking-[0.09em]">
|
||||
{{ $homeLabel }}
|
||||
</a>
|
||||
@if ($whatsappHref)
|
||||
<a
|
||||
href="{{ $whatsappHref }}"
|
||||
class="btn btn-ghost min-h-0 px-0 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent hover:bg-transparent hover:text-amare-accent-deep"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<span class="link-editorial">{{ $whatsappLabel }}</span>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@@ -5,7 +5,7 @@
|
||||
} catch (\Throwable $e) {
|
||||
$pageMeta = new \App\Application\Data\PageMeta(
|
||||
title: 'Página não encontrada - Amare Assessoria',
|
||||
description: 'Não encontramos este endereço. Volte à home e continue por ali.',
|
||||
description: 'A página que você procura não existe ou foi movida.',
|
||||
canonical: '',
|
||||
robots: 'noindex, nofollow',
|
||||
);
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="container-amare max-w-2xl space-y-6 py-20 text-center" data-motion="page-open" data-reveal-group>
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.14em] text-amare-accent" data-motion-beat="seal">Erro 404</p>
|
||||
<h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Página não encontrada</h1>
|
||||
<p class="text-amare-muted" data-reveal data-reveal-from="up">Não encontramos este endereço — talvez tenha mudado de lugar. A home continua sendo o melhor ponto de partida.</p>
|
||||
<p class="text-amare-muted" data-reveal data-reveal-from="up">O endereço que você tentou abrir não existe ou foi movido.</p>
|
||||
<p data-reveal data-reveal-from="up">
|
||||
<a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]">
|
||||
Voltar para a home
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
} catch (\Throwable $e) {
|
||||
$pageMeta = new \App\Application\Data\PageMeta(
|
||||
title: 'Sessão expirada - Amare Assessoria',
|
||||
description: 'Sua sessão ficou quieta demais. Volte e envie de novo com calma.',
|
||||
description: 'Sua sessão expirou. Volte e tente enviar novamente.',
|
||||
canonical: '',
|
||||
robots: 'noindex, nofollow',
|
||||
);
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="container-amare max-w-2xl space-y-6 py-20 text-center" data-motion="page-open" data-reveal-group>
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.14em] text-amare-accent" data-motion-beat="seal">Erro 419</p>
|
||||
<h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Sessão expirada</h1>
|
||||
<p class="text-amare-muted" data-reveal data-reveal-from="up">Sua sessão ficou quieta demais e precisamos recomeçar. Volte à página anterior e envie de novo — os dados ainda estão seguros.</p>
|
||||
<p class="text-amare-muted" data-reveal data-reveal-from="up">Sua sessão expirou. Volte e tente enviar novamente.</p>
|
||||
<p data-reveal data-reveal-from="up">
|
||||
<a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]">
|
||||
Voltar para a home
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
} catch (\Throwable $e) {
|
||||
$pageMeta = new \App\Application\Data\PageMeta(
|
||||
title: 'Muitas solicitações - Amare Assessoria',
|
||||
description: 'Recebemos muitos pedidos em pouco tempo. Aguarde um instante e tente de novo.',
|
||||
description: 'Você enviou muitas solicitações em pouco tempo. Aguarde um instante e tente novamente.',
|
||||
canonical: '',
|
||||
robots: 'noindex, nofollow',
|
||||
);
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="container-amare max-w-2xl space-y-6 py-20 text-center" data-motion="page-open" data-reveal-group>
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.14em] text-amare-accent" data-motion-beat="seal">Erro 429</p>
|
||||
<h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Muitas solicitações</h1>
|
||||
<p class="text-amare-muted" data-reveal data-reveal-from="up">Recebemos vários pedidos em pouco tempo. Espere um instante — assim que pudermos, tentamos de novo com calma.</p>
|
||||
<p class="text-amare-muted" data-reveal data-reveal-from="up">Você enviou muitas solicitações em pouco tempo. Aguarde um instante e tente novamente.</p>
|
||||
<p data-reveal data-reveal-from="up">
|
||||
<a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]">
|
||||
Voltar para a home
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
} catch (\Throwable $e) {
|
||||
$pageMeta = new \App\Application\Data\PageMeta(
|
||||
title: 'Algo deu errado - Amare Assessoria',
|
||||
description: 'Algo saiu do roteiro do nosso lado. Tente novamente em instantes.',
|
||||
description: 'Não foi possível concluir o pedido. Tente novamente em instantes.',
|
||||
canonical: '',
|
||||
robots: 'noindex, nofollow',
|
||||
);
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="container-amare max-w-2xl space-y-6 py-20 text-center" data-motion="page-open" data-reveal-group>
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.14em] text-amare-accent" data-motion-beat="seal">Erro 500</p>
|
||||
<h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Algo deu errado</h1>
|
||||
<p class="text-amare-muted" data-reveal data-reveal-from="up">Algo saiu do roteiro do nosso lado. Já estamos cuidando disso — tente novamente em instantes.</p>
|
||||
<p class="text-amare-muted" data-reveal data-reveal-from="up">Não foi possível concluir o pedido agora. Tente novamente em instantes.</p>
|
||||
<p data-reveal data-reveal-from="up">
|
||||
<a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]">
|
||||
Voltar para a home
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
} catch (\Throwable $e) {
|
||||
$pageMeta = new \App\Application\Data\PageMeta(
|
||||
title: 'Em manutenção - Amare Assessoria',
|
||||
description: 'Estamos em uma pausa breve de manutenção. Voltamos em instantes.',
|
||||
description: 'Estamos realizando uma breve manutenção. Tente novamente em instantes.',
|
||||
canonical: '',
|
||||
robots: 'noindex, nofollow',
|
||||
);
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="container-amare max-w-2xl space-y-6 py-20 text-center" data-motion="page-open" data-reveal-group>
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.14em] text-amare-accent" data-motion-beat="seal">Erro 503</p>
|
||||
<h1 class="text-4xl font-medium tracking-tight text-amare-text" data-motion-beat="title">Em manutenção</h1>
|
||||
<p class="text-amare-muted" data-reveal data-reveal-from="up">Estamos em uma pausa breve para deixar tudo no lugar. Voltamos em instantes — obrigado pela paciência.</p>
|
||||
<p class="text-amare-muted" data-reveal data-reveal-from="up">Estamos realizando uma breve manutenção. Tente novamente em instantes.</p>
|
||||
<p data-reveal data-reveal-from="up">
|
||||
<a href="{{ route('home') }}" class="btn btn-primary text-sm font-semibold uppercase tracking-[0.12em]">
|
||||
Voltar para a home
|
||||
|
||||
@@ -58,10 +58,10 @@
|
||||
<header class="site-header sticky top-0 z-40 border-b border-amare-border bg-amare-bg/95 backdrop-blur-sm">
|
||||
<div class="container-amare grid grid-cols-[auto_1fr_auto] items-center gap-4 py-4 md:grid-cols-[1fr_auto_1fr] md:h-[74px] md:py-0">
|
||||
<nav id="main-nav" class="main-nav order-3 col-span-3 hidden flex-col gap-4 border-t border-amare-border pt-4 md:order-1 md:col-span-1 md:flex md:flex-row md:items-center md:gap-1 md:border-0 md:pt-0" aria-label="Principal" data-main-nav>
|
||||
<a href="{{ url('/#casamentos') }}" class="nav-link-editorial btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:bg-transparent hover:text-amare-accent md:px-3">Casamentos</a>
|
||||
<a href="{{ url('/#corporate') }}" class="nav-link-editorial btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:bg-transparent hover:text-amare-accent md:px-3">Corporate</a>
|
||||
<a href="{{ route('portfolio.index') }}" class="nav-link-editorial btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:bg-transparent hover:text-amare-accent md:px-3">Portfólio</a>
|
||||
<a href="{{ route('about') }}" class="nav-link-editorial btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:bg-transparent hover:text-amare-accent md:px-3">Amare</a>
|
||||
<a href="{{ route('home') }}" class="btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:text-amare-accent md:px-3">Início</a>
|
||||
<a href="{{ route('services.index') }}" class="btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:text-amare-accent md:px-3">Serviços</a>
|
||||
<a href="{{ route('portfolio.index') }}" class="btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:text-amare-accent md:px-3">Portfólio</a>
|
||||
<a href="{{ route('about') }}" class="btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:text-amare-accent md:px-3">Amare</a>
|
||||
<a href="{{ route('briefing') }}" class="btn btn-ghost min-h-0 px-0 py-3 text-[13px] font-semibold uppercase tracking-[0.08em] text-amare-muted hover:text-amare-accent md:hidden">Solicitar proposta</a>
|
||||
</nav>
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
<a href="{{ route('briefing') }}" class="btn btn-outline hidden min-h-0 px-6 text-xs font-bold uppercase tracking-[0.09em] md:inline-flex">
|
||||
Conte seu evento
|
||||
</a>
|
||||
</a>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
@@ -110,11 +111,10 @@
|
||||
$footerSocials = collect($siteSettings->social_links ?? [])->filter(static fn ($url) => filled($url));
|
||||
@endphp
|
||||
|
||||
<div class="container-amare flex flex-col gap-10 py-14 md:py-[58px]">
|
||||
<div class="flex flex-col gap-8 md:flex-row md:items-end md:justify-between">
|
||||
<div class="container-amare flex flex-col gap-8 py-14 md:flex-row md:items-end md:justify-between md:py-[58px]">
|
||||
<div class="space-y-3">
|
||||
<x-brand.logo variant="on-light" class="h-10 w-auto" />
|
||||
<p class="text-sm text-amare-muted">Boutique de assessoria & produção • São Paulo</p>
|
||||
<p class="text-sm text-amare-muted">Assessoria & produção de eventos • São Paulo</p>
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-amare-muted md:text-right">
|
||||
@@ -128,21 +128,12 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<nav aria-label="Rodapé" class="flex flex-col gap-4 border-t border-amare-border pt-8 text-sm text-amare-muted md:flex-row md:flex-wrap md:items-center md:gap-x-6 md:gap-y-2">
|
||||
<a href="{{ url('/#casamentos') }}" class="inline-flex min-h-11 items-center transition-colors hover:text-amare-accent">Casamentos</a>
|
||||
<a href="{{ url('/#corporate') }}" class="inline-flex min-h-11 items-center transition-colors hover:text-amare-accent">Corporate</a>
|
||||
<a href="{{ route('services.index') }}" class="inline-flex min-h-11 items-center transition-colors hover:text-amare-accent">Serviços</a>
|
||||
<a href="{{ route('portfolio.index') }}" class="inline-flex min-h-11 items-center transition-colors hover:text-amare-accent">Portfólio</a>
|
||||
<a href="{{ route('about') }}" class="inline-flex min-h-11 items-center transition-colors hover:text-amare-accent">Sobre</a>
|
||||
<a href="{{ route('briefing') }}" class="inline-flex min-h-11 items-center transition-colors hover:text-amare-accent">Briefing</a>
|
||||
<a href="{{ route('contact') }}" class="inline-flex min-h-11 items-center transition-colors hover:text-amare-accent">Parcerias</a>
|
||||
<a href="{{ route('privacy') }}" class="inline-flex min-h-11 items-center transition-colors hover:text-amare-accent">Privacidade</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-amare-border">
|
||||
<div class="container-amare flex flex-col gap-2 py-6 text-sm text-amare-muted md:flex-row md:items-center md:justify-between">
|
||||
<p>© {{ now()->year }} {{ $siteSettings->brand_name }}. Todos os direitos reservados.</p>
|
||||
<p>
|
||||
<a href="{{ route('privacy') }}" class="inline-flex min-h-11 items-center transition-colors hover:text-amare-accent">Política de privacidade</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -42,11 +42,10 @@
|
||||
</p>
|
||||
|
||||
@if (session('status') === 'briefing-sent')
|
||||
<x-public.form-success
|
||||
seal="Briefing recebido"
|
||||
title="Recebemos sua ficha."
|
||||
body="Vamos ler com atenção e retornar em breve pelo canal que você informou. Enquanto isso, pode seguir explorando o portfólio."
|
||||
/>
|
||||
<div role="status" class="alert mt-8 border border-amare-border bg-amare-bg-deep">
|
||||
<p class="font-semibold text-amare-text">Mensagem enviada.</p>
|
||||
<p class="mt-1 text-amare-muted">Recebemos seu briefing e retornaremos em breve pelo canal informado.</p>
|
||||
</div>
|
||||
@else
|
||||
<form
|
||||
method="POST"
|
||||
@@ -80,7 +79,7 @@
|
||||
autocomplete="name"
|
||||
maxlength="120"
|
||||
placeholder="Seu nome"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('nome') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('nome') input-error @enderror"
|
||||
@error('nome') aria-invalid="true" aria-describedby="nome-error" @enderror
|
||||
>
|
||||
@error('nome')
|
||||
@@ -99,7 +98,7 @@
|
||||
autocomplete="email"
|
||||
maxlength="254"
|
||||
placeholder="voce@email.com"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('email') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('email') input-error @enderror"
|
||||
@error('email') aria-invalid="true" aria-describedby="email-error" @enderror
|
||||
>
|
||||
@error('email')
|
||||
@@ -118,7 +117,7 @@
|
||||
autocomplete="tel"
|
||||
maxlength="40"
|
||||
placeholder="(11) 90000-0000"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('telefone') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('telefone') input-error @enderror"
|
||||
@error('telefone') aria-invalid="true" aria-describedby="telefone-error" @enderror
|
||||
>
|
||||
@error('telefone')
|
||||
@@ -132,7 +131,7 @@
|
||||
id="tipo_evento"
|
||||
name="tipo_evento"
|
||||
required
|
||||
class="select field-editorial w-full text-amare-text @error('tipo_evento') select-error @enderror"
|
||||
class="select w-full text-amare-text @error('tipo_evento') select-error @enderror"
|
||||
@error('tipo_evento') aria-invalid="true" aria-describedby="tipo_evento-error" @enderror
|
||||
>
|
||||
<option value="" selected disabled>Selecione...</option>
|
||||
@@ -155,7 +154,7 @@
|
||||
value="{{ old('data_periodo') }}"
|
||||
maxlength="80"
|
||||
placeholder="Ex.: novembro de 2027"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('data_periodo') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('data_periodo') input-error @enderror"
|
||||
@error('data_periodo') aria-invalid="true" aria-describedby="data_periodo-error" @enderror
|
||||
>
|
||||
@error('data_periodo')
|
||||
@@ -173,7 +172,7 @@
|
||||
required
|
||||
maxlength="80"
|
||||
placeholder="Ex.: São Paulo"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('cidade') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('cidade') input-error @enderror"
|
||||
@error('cidade') aria-invalid="true" aria-describedby="cidade-error" @enderror
|
||||
>
|
||||
@error('cidade')
|
||||
@@ -193,7 +192,7 @@
|
||||
inputmode="numeric"
|
||||
autocomplete="off"
|
||||
placeholder="Ex.: 120"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('convidados') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('convidados') input-error @enderror"
|
||||
@error('convidados') aria-invalid="true" aria-describedby="convidados-error" @enderror
|
||||
>
|
||||
@error('convidados')
|
||||
@@ -210,7 +209,7 @@
|
||||
value="{{ old('servico_interesse', request('servico_interesse')) }}"
|
||||
maxlength="120"
|
||||
placeholder="Ex.: planejamento completo"
|
||||
class="input field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('servico_interesse') input-error @enderror"
|
||||
class="input w-full text-amare-text placeholder:text-amare-muted/60 @error('servico_interesse') input-error @enderror"
|
||||
@error('servico_interesse') aria-invalid="true" aria-describedby="servico_interesse-error" @enderror
|
||||
>
|
||||
@error('servico_interesse')
|
||||
@@ -228,7 +227,7 @@
|
||||
rows="6"
|
||||
maxlength="3000"
|
||||
placeholder="Conte sobre o seu evento, expectativas e principais preocupações."
|
||||
class="textarea field-editorial w-full text-amare-text placeholder:text-amare-muted/60 @error('mensagem') textarea-error @enderror"
|
||||
class="textarea w-full text-amare-text placeholder:text-amare-muted/60 @error('mensagem') textarea-error @enderror"
|
||||
@error('mensagem') aria-invalid="true" aria-describedby="mensagem-error" @enderror
|
||||
>{{ old('mensagem') }}</textarea>
|
||||
@error('mensagem')
|
||||
|
||||
@@ -20,12 +20,7 @@
|
||||
<div class="container-amare py-16 md:py-24" data-reveal-group>
|
||||
<h2 id="partner-form-heading" class="text-3xl font-medium text-amare-text" data-reveal data-reveal-from="up">Apresente seu trabalho</h2>
|
||||
@if (session('status') === 'partner-inquiry-sent')
|
||||
<x-public.form-success
|
||||
seal="Apresentação recebida"
|
||||
title="Recebemos sua apresentação."
|
||||
body="Vamos avaliar a aderência com o cuidado que cada parceria merece. Se fizer sentido, entraremos em contato."
|
||||
whatsapp-text="Olá, enviei uma apresentação de parceria e gostaria de acompanhar."
|
||||
/>
|
||||
<div role="status" class="mt-8 border border-amare-border bg-amare-bg px-6 py-5"><p class="font-semibold">Mensagem enviada.</p><p class="mt-1 text-amare-muted">Recebemos sua apresentação e entraremos em contato se houver aderência.</p></div>
|
||||
@else
|
||||
<form method="POST" action="{{ route('contact.store') }}" class="mt-10 max-w-3xl space-y-8" data-contact-form data-reveal data-reveal-from="up">
|
||||
@csrf
|
||||
@@ -33,10 +28,10 @@
|
||||
@if ($errors->any())<div role="alert" class="border border-amare-error/40 px-6 py-5">Revise os campos destacados abaixo.</div>@endif
|
||||
<div class="grid gap-8 sm:grid-cols-2">
|
||||
@foreach (['nome' => 'Nome *', 'empresa' => 'Nome profissional ou empresa', 'email' => 'E-mail *', 'atuacao' => 'Atuação ou serviço *', 'area_atendimento' => 'Área de atendimento *', 'portfolio_redes' => 'Portfólio ou redes', 'telefone' => 'Telefone'] as $field => $label)
|
||||
<div><label class="mb-2 block text-xs font-semibold uppercase tracking-[.14em]" for="{{ $field }}">{{ $label }}</label><input class="field-editorial w-full border-0 border-b border-amare-border bg-transparent py-3 focus:border-amare-accent focus:outline-none @error($field) border-amare-error @enderror" id="{{ $field }}" name="{{ $field }}" value="{{ old($field) }}" maxlength="{{ $field === 'portfolio_redes' ? 500 : ($field === 'email' ? 254 : 160) }}" @required(in_array($field, ['nome','email','atuacao','area_atendimento'], true)) @error($field) aria-invalid="true" @enderror>@error($field)<p class="mt-2 text-sm text-amare-error">{{ $message }}</p>@enderror</div>
|
||||
<div><label class="mb-2 block text-xs font-semibold uppercase tracking-[.14em]" for="{{ $field }}">{{ $label }}</label><input class="w-full border-0 border-b border-amare-border bg-transparent py-3 focus:border-amare-accent focus:outline-none @error($field) border-amare-error @enderror" id="{{ $field }}" name="{{ $field }}" value="{{ old($field) }}" maxlength="{{ $field === 'portfolio_redes' ? 500 : ($field === 'email' ? 254 : 160) }}" @required(in_array($field, ['nome','email','atuacao','area_atendimento'], true)) @error($field) aria-invalid="true" @enderror>@error($field)<p class="mt-2 text-sm text-amare-error">{{ $message }}</p>@enderror</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div><label class="mb-2 block text-xs font-semibold uppercase tracking-[.14em]" for="mensagem">Mensagem *</label><textarea class="field-editorial w-full border border-amare-border bg-transparent p-3 focus:border-amare-accent focus:outline-none" id="mensagem" name="mensagem" rows="6" required maxlength="3000">{{ old('mensagem') }}</textarea>@error('mensagem')<p class="mt-2 text-sm text-amare-error">{{ $message }}</p>@enderror</div>
|
||||
<div><label class="mb-2 block text-xs font-semibold uppercase tracking-[.14em]" for="mensagem">Mensagem *</label><textarea class="w-full border border-amare-border bg-transparent p-3 focus:border-amare-accent focus:outline-none" id="mensagem" name="mensagem" rows="6" required maxlength="3000">{{ old('mensagem') }}</textarea>@error('mensagem')<p class="mt-2 text-sm text-amare-error">{{ $message }}</p>@enderror</div>
|
||||
<p class="max-w-2xl text-sm text-amare-muted">Ao enviar, você reconhece o uso destes dados exclusivamente para analisar uma possível parceria, conforme a <a class="text-amare-accent underline" href="{{ route('privacy') }}">política de privacidade</a>.</p>
|
||||
<button type="submit" data-submit-button class="btn btn-primary text-sm font-semibold uppercase tracking-[.12em]">Enviar apresentação</button>
|
||||
</form>
|
||||
|
||||
@@ -5,38 +5,9 @@
|
||||
|
||||
<div class="border-b border-amare-border bg-amare-bg-deep">
|
||||
<div class="container-amare space-y-10 py-16 md:py-24">
|
||||
<nav aria-label="Vertentes do portfólio" class="flex flex-wrap gap-x-6 gap-y-2 border-b border-amare-border pb-6 text-sm">
|
||||
<a
|
||||
href="{{ route('portfolio.index') }}"
|
||||
@class([
|
||||
'inline-flex min-h-11 items-center uppercase tracking-[0.08em] transition-colors',
|
||||
'font-semibold text-amare-accent' => $vertical === null,
|
||||
'text-amare-muted hover:text-amare-accent' => $vertical !== null,
|
||||
])
|
||||
>Todos</a>
|
||||
@foreach (\App\Domain\Marketing\PortfolioVertical::cases() as $option)
|
||||
<a
|
||||
href="{{ route('portfolio.index', ['vertente' => $option->value]) }}"
|
||||
@class([
|
||||
'inline-flex min-h-11 items-center uppercase tracking-[0.08em] transition-colors',
|
||||
'font-semibold text-amare-accent' => $vertical === $option,
|
||||
'text-amare-muted hover:text-amare-accent' => $vertical !== $option,
|
||||
])
|
||||
>{{ $option->label() }}</a>
|
||||
@endforeach
|
||||
</nav>
|
||||
|
||||
@if ($cases->isEmpty())
|
||||
@if ($vertical === \App\Domain\Marketing\PortfolioVertical::Corporate)
|
||||
<div class="flex min-h-[280px] flex-col items-center justify-center gap-4 bg-amare-bg p-10 text-center">
|
||||
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">Portfólio Corporate</p>
|
||||
<h2 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight text-amare-text">Conteúdo em construção</h2>
|
||||
<p class="max-w-lg text-amare-text-muted">Ainda não publicamos cases corporativos autorizados. Em vez de inventar prova, mantemos este espaço pronto para projetos reais.</p>
|
||||
<a href="{{ route('briefing') }}" class="btn btn-outline mt-2 text-xs font-bold uppercase tracking-[0.09em]">Falar sobre um evento corporativo</a>
|
||||
</div>
|
||||
@else
|
||||
<p class="text-amare-muted">Novos casos serão publicados assim que o acervo estiver organizado. Enquanto isso, fale conosco para conhecer o nosso trabalho.</p>
|
||||
@endif
|
||||
@else
|
||||
@php
|
||||
$hasPrioritizedImage = false;
|
||||
@@ -82,9 +53,6 @@
|
||||
@endphp
|
||||
@endif
|
||||
<div class="space-y-2 border-t border-amare-border pt-4">
|
||||
@if (filled($case->event_type))
|
||||
<p class="text-xs font-bold uppercase tracking-[0.16em] text-amare-accent-deep">{{ $case->event_type }}</p>
|
||||
@endif
|
||||
<h2 class="text-2xl font-medium text-amare-text">
|
||||
<a href="{{ route('portfolio.show', $case->slug) }}" class="transition-colors hover:text-amare-accent">{{ $case->title }}</a>
|
||||
</h2>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
Conhecer os serviços
|
||||
</a>
|
||||
<a href="{{ route('contact') }}" class="btn btn-ghost min-h-0 px-0 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent hover:bg-transparent hover:text-amare-accent-deep">
|
||||
<span class="link-editorial">Tenho um evento em mente</span>
|
||||
<span class="border-b border-amare-accent pb-1">Tenho um evento em mente</span>
|
||||
</a>
|
||||
</div>
|
||||
</x-public.photo-hero>
|
||||
@@ -65,7 +65,7 @@
|
||||
<p class="text-amare-text-muted">{{ $package->compare_summary }}</p>
|
||||
</div>
|
||||
<a href="{{ route('packages.show', $package->slug) }}" class="btn btn-ghost min-h-0 self-start px-0 text-xs font-semibold uppercase tracking-[0.09em] text-amare-accent hover:bg-transparent hover:text-amare-accent-deep">
|
||||
<span class="link-editorial">Conhecer esta modalidade</span>
|
||||
<span class="border-b border-amare-accent pb-1">Conhecer esta modalidade</span>
|
||||
</a>
|
||||
</article>
|
||||
@endif
|
||||
|
||||
@@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||
namespace Tests\Feature\Application\Queries\Marketing;
|
||||
|
||||
use App\Application\Queries\Marketing\GetPublishedPortfolioCases;
|
||||
use App\Domain\Marketing\PortfolioVertical;
|
||||
use App\Models\PortfolioCase;
|
||||
use App\Models\PortfolioImage;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
@@ -59,26 +58,4 @@ class GetPublishedPortfolioCasesTest extends TestCase
|
||||
$this->assertTrue($cases->get(0)?->relationLoaded('images'));
|
||||
$this->assertCount(2, $cases->get(0)?->images ?? []);
|
||||
}
|
||||
|
||||
public function test_filters_published_cases_by_portfolio_vertical(): void
|
||||
{
|
||||
PortfolioCase::factory()->published()->create([
|
||||
'title' => 'Wedding Case',
|
||||
'event_type' => 'Mini wedding',
|
||||
'sort_order' => 10,
|
||||
]);
|
||||
PortfolioCase::factory()->published()->create([
|
||||
'title' => 'Corporate Case',
|
||||
'event_type' => 'Evento corporativo',
|
||||
'sort_order' => 20,
|
||||
]);
|
||||
|
||||
$weddings = (new GetPublishedPortfolioCases)(PortfolioVertical::Casamentos);
|
||||
$corporate = (new GetPublishedPortfolioCases)(PortfolioVertical::Corporate);
|
||||
|
||||
$this->assertCount(1, $weddings);
|
||||
$this->assertSame('Wedding Case', $weddings->first()?->title);
|
||||
$this->assertCount(1, $corporate);
|
||||
$this->assertSame('Corporate Case', $corporate->first()?->title);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,28 +89,6 @@ class ContactBriefingTest extends TestCase
|
||||
});
|
||||
}
|
||||
|
||||
public function test_successful_submission_shows_editorial_confirmation(): void
|
||||
{
|
||||
SiteSetting::instance()->update(['whatsapp_number' => '+55 11 98888-7777']);
|
||||
Mail::fake();
|
||||
|
||||
$response = $this
|
||||
->from(route('briefing'))
|
||||
->followingRedirects()
|
||||
->post(route('briefing.store'), $this->validPayload());
|
||||
|
||||
$response
|
||||
->assertOk()
|
||||
->assertSee('data-form-success', false)
|
||||
->assertSee('Briefing recebido')
|
||||
->assertSee('Recebemos sua ficha')
|
||||
->assertSee('role="status"', false)
|
||||
->assertSee('data-motion-beat="seal"', false)
|
||||
->assertSee(route('home'), false)
|
||||
->assertSee('https://wa.me/5511988887777', false)
|
||||
->assertDontSee('<form', false);
|
||||
}
|
||||
|
||||
public function test_submission_normalizes_email_and_phone_before_reaching_mailables(): void
|
||||
{
|
||||
$settings = SiteSetting::instance();
|
||||
|
||||
@@ -72,19 +72,7 @@ class HeritageEditorialTokensTest extends TestCase
|
||||
{
|
||||
$vite = (string) file_get_contents(base_path('vite.config.js'));
|
||||
|
||||
$this->assertMatchesRegularExpression(
|
||||
"/^import \\{ fontsource \\} from 'laravel-vite-plugin\\/fonts';/m",
|
||||
$vite,
|
||||
);
|
||||
$this->assertDoesNotMatchRegularExpression(
|
||||
'/^import \\{[^}]*\\bbunny\\b/m',
|
||||
$vite,
|
||||
);
|
||||
$this->assertDoesNotMatchRegularExpression(
|
||||
'/^import \\{[^}]*\\bgoogle\\b/m',
|
||||
$vite,
|
||||
);
|
||||
$this->assertStringContainsString("fontsource('EB Garamond'", $vite);
|
||||
$this->assertStringContainsString("bunny('EB Garamond'", $vite);
|
||||
$this->assertStringNotContainsString('Instrument Sans', $vite);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,9 +96,6 @@ class MotionMarkupTest extends TestCase
|
||||
$this->assertStringContainsString('[data-reveal]', $appCss);
|
||||
$this->assertStringNotContainsString('[data-chapter-index]', $appCss);
|
||||
$this->assertStringContainsString('prefers-reduced-motion: no-preference', $appCss);
|
||||
$this->assertStringContainsString('.field-editorial', $appCss);
|
||||
$this->assertStringContainsString('.nav-link-editorial', $appCss);
|
||||
$this->assertStringContainsString('.link-editorial', $appCss);
|
||||
|
||||
// Entrance motion must not fade text opacity — mid-fade fails WCAG contrast (axe).
|
||||
$this->assertDoesNotMatchRegularExpression(
|
||||
|
||||
@@ -66,22 +66,6 @@ class PartnerInquiryTest extends TestCase
|
||||
Mail::assertQueued(PartnerInquiry::class, 1);
|
||||
}
|
||||
|
||||
public function test_successful_partner_inquiry_shows_editorial_confirmation(): void
|
||||
{
|
||||
SiteSetting::instance();
|
||||
Mail::fake();
|
||||
|
||||
$this
|
||||
->from(route('contact'))
|
||||
->followingRedirects()
|
||||
->post(route('contact.store'), $this->validPayload())
|
||||
->assertOk()
|
||||
->assertSee('data-form-success', false)
|
||||
->assertSee('Apresentação recebida')
|
||||
->assertSee('Recebemos sua apresentação')
|
||||
->assertDontSee('name="atuacao"', false);
|
||||
}
|
||||
|
||||
public function test_partner_honeypot_reports_success_without_sending_mail(): void
|
||||
{
|
||||
SiteSetting::instance();
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature\PublicSite;
|
||||
|
||||
use App\Models\PortfolioCase;
|
||||
use App\Models\SiteSetting;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class PortfolioVerticalFilterTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_portfolio_index_filters_by_vertical_and_shows_corporate_empty_state(): void
|
||||
{
|
||||
SiteSetting::instance();
|
||||
|
||||
PortfolioCase::factory()->published()->create([
|
||||
'title' => 'Casamento Jardim',
|
||||
'slug' => 'casamento-jardim',
|
||||
'event_type' => 'Casamento',
|
||||
'sort_order' => 10,
|
||||
]);
|
||||
|
||||
PortfolioCase::factory()->published()->create([
|
||||
'title' => 'Convenção Anual',
|
||||
'slug' => 'convencao-anual',
|
||||
'event_type' => 'Corporativo',
|
||||
'sort_order' => 20,
|
||||
]);
|
||||
|
||||
$this->get(route('portfolio.index'))
|
||||
->assertOk()
|
||||
->assertSee('Casamento Jardim')
|
||||
->assertSee('Convenção Anual')
|
||||
->assertSee('Vertentes do portfólio')
|
||||
->assertSee('Casamentos')
|
||||
->assertSee('Corporate');
|
||||
|
||||
$this->get(route('portfolio.index', ['vertente' => 'casamentos']))
|
||||
->assertOk()
|
||||
->assertSee('Casamento Jardim')
|
||||
->assertDontSee('Convenção Anual');
|
||||
|
||||
$this->get(route('portfolio.index', ['vertente' => 'corporate']))
|
||||
->assertOk()
|
||||
->assertSee('Convenção Anual')
|
||||
->assertDontSee('Casamento Jardim');
|
||||
|
||||
PortfolioCase::query()->where('slug', 'convencao-anual')->update(['published_at' => null]);
|
||||
|
||||
$this->get(route('portfolio.index', ['vertente' => 'corporate']))
|
||||
->assertOk()
|
||||
->assertSee('Portfólio Corporate')
|
||||
->assertSee('Conteúdo em construção')
|
||||
->assertDontSee('Convenção Anual');
|
||||
}
|
||||
}
|
||||
@@ -54,8 +54,7 @@ class PublicLayoutSeoTest extends TestCase
|
||||
->assertSee('Amare Brand')
|
||||
->assertSee('hello@amare.test')
|
||||
->assertSee('(11) 91111-1111')
|
||||
->assertSee('Privacidade')
|
||||
->assertSee(route('privacy'), false)
|
||||
->assertSee('Política de privacidade')
|
||||
->assertSee('https://instagram.com/amare', false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Feature\PublicSite;
|
||||
|
||||
use App\Models\SiteSetting;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class PublicNavigationVerticalsTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_header_and_footer_expose_casamentos_and_corporate_without_implying_weddings_only(): void
|
||||
{
|
||||
SiteSetting::instance();
|
||||
|
||||
$response = $this->get(route('about'))->assertOk();
|
||||
|
||||
$homeCasamentos = url('/#casamentos');
|
||||
$homeCorporate = url('/#corporate');
|
||||
|
||||
$response
|
||||
->assertSee('id="main-nav"', false)
|
||||
->assertSee('href="'.$homeCasamentos.'"', false)
|
||||
->assertSee('>Casamentos</a>', false)
|
||||
->assertSee('href="'.$homeCorporate.'"', false)
|
||||
->assertSee('>Corporate</a>', false)
|
||||
->assertSee('href="'.route('portfolio.index').'"', false)
|
||||
->assertSee('href="'.route('about').'"', false)
|
||||
->assertSee('href="'.route('services.index').'"', false)
|
||||
->assertSee('href="'.route('privacy').'"', false)
|
||||
->assertSee('aria-label="Rodapé"', false)
|
||||
->assertSeeInOrder([
|
||||
'aria-label="Rodapé"',
|
||||
'href="'.$homeCasamentos.'"',
|
||||
'Casamentos',
|
||||
'href="'.$homeCorporate.'"',
|
||||
'Corporate',
|
||||
], false);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import laravel from 'laravel-vite-plugin';
|
||||
import { fontsource } from 'laravel-vite-plugin/fonts';
|
||||
import { bunny } from 'laravel-vite-plugin/fonts';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
|
||||
/**
|
||||
@@ -76,7 +76,7 @@ export default defineConfig({
|
||||
],
|
||||
refresh: true,
|
||||
fonts: [
|
||||
fontsource('EB Garamond', {
|
||||
bunny('EB Garamond', {
|
||||
weights: [400, 500, 600],
|
||||
}),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user