Compare commits
1 Commits
main
...
feat/man-1
| Author | SHA1 | Date | |
|---|---|---|---|
| 70d19a7c55 |
@@ -79,4 +79,4 @@ Default vocabulary: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-
|
|||||||
|
|
||||||
### Domain docs
|
### Domain docs
|
||||||
|
|
||||||
Single-context repo. There is no `CONTEXT.md` — the domain is documented in `SPEC.md` (§8 is the domain model and database schema) and `PRODUCT.md`, with current capabilities described per-capability under `openspec/specs/`. `docs/adr/README.md` is an index only: ADR-001 through ADR-010 are decided in `SPEC.md` §21, and there are no standalone ADR files. `docs/agents/domain.md` describes the generic `CONTEXT.md`/`CONTEXT-MAP.md` layout that the engineering skills look for and instructs them to proceed silently when it's absent, which is the case here.
|
Single-context repo. There is no `CONTEXT.md` on purpose — **`SPEC.md` §8.0 is the ubiquitous-language SSOT** (domain model/schema continue in §8.1+). `PRODUCT.md` covers positioning; capabilities live under `openspec/specs/`. `docs/adr/README.md` is an index only: ADR-001 through ADR-010 are decided in `SPEC.md` §21. `docs/agents/domain.md` tells skills to use `SPEC.md` §8 instead of inventing a parallel `CONTEXT.md`.
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ Site-wide content is a singleton row reached via `SiteSetting::instance()`. Publ
|
|||||||
- **Livewire/Filament temp uploads are pinned to the `local` disk** when `FILESYSTEM_DISK=r2`, because the S3 driver would make the browser PUT straight to R2 and hit CORS. Final media still lands on `r2` via `App\Support\PublicImageUploadRules`. Set `LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK` explicitly to override.
|
- **Livewire/Filament temp uploads are pinned to the `local` disk** when `FILESYSTEM_DISK=r2`, because the S3 driver would make the browser PUT straight to R2 and hit CORS. Final media still lands on `r2` via `App\Support\PublicImageUploadRules`. Set `LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK` explicitly to override.
|
||||||
- **Contact form is rate limited**: named limiter `contact-briefing`, 5/min per IP, registered in `AppServiceProvider` and applied in `routes/web.php`.
|
- **Contact form is rate limited**: named limiter `contact-briefing`, 5/min per IP, registered in `AppServiceProvider` and applied in `routes/web.php`.
|
||||||
- **Filament 5 nested resource layout**: resources are split into `app/Filament/Resources/<Resource>/{Pages,Schemas,Tables,RelationManagers}` rather than a flat resource class. Follow the existing shape in `Resources/PortfolioCases/`.
|
- **Filament 5 nested resource layout**: resources are split into `app/Filament/Resources/<Resource>/{Pages,Schemas,Tables,RelationManagers}` rather than a flat resource class. Follow the existing shape in `Resources/PortfolioCases/`.
|
||||||
- **Everything user-facing is pt-BR**: routes are `/servicos`, `/portfolio`, `/portfolio/{slug}`, `/sobre`, `/privacidade`, `/contato`. `APP_LOCALE=pt_BR`, `APP_TIMEZONE=America/Sao_Paulo` (`config/app.php:68`).
|
- **Everything user-facing is pt-BR**: routes are `/servicos`, `/pacotes/{slug}`, `/portfolio`, `/portfolio/{slug}`, `/sobre`, `/briefing`, `/contato`, `/privacidade`. `APP_LOCALE=pt_BR`, `APP_TIMEZONE=America/Sao_Paulo` (`config/app.php:68`). Glossário canônico: `SPEC.md` §8.0.
|
||||||
- **Design tokens** live in `resources/css/tokens.css` (Heritage Editorial; see `DESIGN.md`). `tests/Feature/PublicSite/HeritageEditorialTokensTest.php` reads that file and asserts the exact hex values, `EB Garamond`, zero border radii, `--amare-container-max: 1120px`, and the *absence* of shadow tokens — so any token edit is a deliberate test change too. Motion lives in `resources/js/motion.js` and is asserted by `tests/Feature/PublicSite/MotionMarkupTest.php` + `tests/Browser/MotionTest.php`.
|
- **Design tokens** live in `resources/css/tokens.css` (Heritage Editorial; see `DESIGN.md`). `tests/Feature/PublicSite/HeritageEditorialTokensTest.php` reads that file and asserts the exact hex values, `EB Garamond`, zero border radii, `--amare-container-max: 1120px`, and the *absence* of shadow tokens — so any token edit is a deliberate test change too. Motion lives in `resources/js/motion.js` and is asserted by `tests/Feature/PublicSite/MotionMarkupTest.php` + `tests/Browser/MotionTest.php`.
|
||||||
|
|
||||||
## Navigating the normative docs
|
## Navigating the normative docs
|
||||||
|
|||||||
42
SPEC.md
42
SPEC.md
@@ -283,11 +283,15 @@ Uma funcionalidade fora do MVP só poderá entrar quando:
|
|||||||
| Método | Rota | Nome sugerido | Finalidade |
|
| Método | Rota | Nome sugerido | Finalidade |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| GET | `/` | `home` | Home editorial |
|
| GET | `/` | `home` | Home editorial |
|
||||||
| GET | `/servicos` | `services.index` | Lista de serviços publicados |
|
| GET | `/servicos` | `services.index` | Lista de serviços / modalidades publicadas |
|
||||||
|
| GET | `/pacotes/{slug}` | `packages.show` | Detalhe de uma modalidade de casamento |
|
||||||
| GET | `/portfolio` | `portfolio.index` | Lista de casos publicados |
|
| GET | `/portfolio` | `portfolio.index` | Lista de casos publicados |
|
||||||
| GET | `/portfolio/{slug}` | `portfolio.show` | Detalhe de caso |
|
| GET | `/portfolio/{slug}` | `portfolio.show` | Detalhe de caso |
|
||||||
| GET | `/sobre` | `about` | História, método e credenciais |
|
| GET | `/sobre` | `about` | História, método e credenciais |
|
||||||
| GET | `/contato` | `contact` | Briefing de contato |
|
| GET | `/briefing` | `briefing` | Briefing comercial (pedido de proposta) |
|
||||||
|
| POST | `/briefing` | `briefing.store` | Envio do briefing comercial |
|
||||||
|
| GET | `/contato` | `contact` | Contato de parceiro / fornecedor (não é briefing) |
|
||||||
|
| POST | `/contato` | `contact.store` | Envio da consulta de parceiro |
|
||||||
| GET | `/privacidade` | `privacy` | Política de privacidade |
|
| GET | `/privacidade` | `privacy` | Política de privacidade |
|
||||||
| GET | `/sitemap.xml` | `sitemap` | Sitemap público |
|
| GET | `/sitemap.xml` | `sitemap` | Sitemap público |
|
||||||
| GET | `/robots.txt` | `robots` | Política de crawling |
|
| GET | `/robots.txt` | `robots` | Política de crawling |
|
||||||
@@ -324,7 +328,8 @@ Administração
|
|||||||
|
|
||||||
- Dashboard: `Filament Page` customizada com widgets orientados a exceção.
|
- Dashboard: `Filament Page` customizada com widgets orientados a exceção.
|
||||||
- Detalhe do evento: página customizada do Resource com resumo operacional.
|
- Detalhe do evento: página customizada do Resource com resumo operacional.
|
||||||
- Briefing público: Blade + Controller (`POST /contato`), ver §11.2.
|
- Briefing comercial: Blade + Controller (`POST /briefing`), ver §11.2.
|
||||||
|
- Contato de parceiro: Blade + Controller (`POST /contato`) — canal separado do briefing.
|
||||||
- Home: Blade com componentes de design reutilizáveis.
|
- Home: Blade com componentes de design reutilizáveis.
|
||||||
|
|
||||||
### 5.4 Decisões de UX YAGNI
|
### 5.4 Decisões de UX YAGNI
|
||||||
@@ -1243,6 +1248,35 @@ Auditoria não precisa ser um event sourcing. Registrar apenas operações crít
|
|||||||
|
|
||||||
## 8. Modelo de domínio e banco de dados
|
## 8. Modelo de domínio e banco de dados
|
||||||
|
|
||||||
|
Esta seção é a **fonte única de verdade** do vocabulário de domínio do produto. Issues Linear, OpenSpec, código e copy devem usar estes termos. Não criar glossário paralelo em `CONTEXT.md`.
|
||||||
|
|
||||||
|
### 8.0 Linguagem ubíqua (glossário)
|
||||||
|
|
||||||
|
**Vertente**:
|
||||||
|
Frente de marca da Amare — **Casamentos** ou **Corporate**.
|
||||||
|
_Avoid_: linha de negócio, vertical de produto (em copy pública), “área”
|
||||||
|
|
||||||
|
**Modalidade**:
|
||||||
|
Pacote/formato de acompanhamento de casamento gerenciado no CMS (`WeddingPackage`: Essenza, Conduzione, Grand Jour).
|
||||||
|
_Avoid_: pacote (em copy pública preferir “modalidade”), serviço genérico, plano
|
||||||
|
|
||||||
|
**Briefing**:
|
||||||
|
Pedido comercial de um potencial cliente descrevendo o evento e solicitando atendimento/proposta. Rota canônica: `/briefing`.
|
||||||
|
_Avoid_: contato (quando o sentido é pedido comercial), formulário de parceiro
|
||||||
|
|
||||||
|
**Contato parceiro**:
|
||||||
|
Consulta de fornecedor ou proposta de parceria. Rota canônica: `/contato`. Não mistura com Briefing.
|
||||||
|
_Avoid_: briefing, lead comercial
|
||||||
|
|
||||||
|
**CTA contextual**:
|
||||||
|
Link de conversão de uma Modalidade escolhida — WhatsApp com mensagem que nomeia a modalidade, ou fallback para `/briefing?servico_interesse=` quando não há número oficial válido.
|
||||||
|
|
||||||
|
**CTA orientação**:
|
||||||
|
Link de conversão para visitante que ainda não escolheu Modalidade — WhatsApp com mensagem de orientação humana (sem quiz), ou fallback para `/briefing` quando não há número oficial válido.
|
||||||
|
|
||||||
|
**Boutique**:
|
||||||
|
Conceito de posicionamento (cuidado, especialização, múltiplos serviços sob a mesma marca) — não é entidade de domínio nem rota.
|
||||||
|
|
||||||
### 8.1 Módulos
|
### 8.1 Módulos
|
||||||
|
|
||||||
| Módulo | Responsabilidade |
|
| Módulo | Responsabilidade |
|
||||||
@@ -1795,7 +1829,7 @@ Não transformar seções estáticas em componentes Livewire. Usar Blade quando
|
|||||||
|
|
||||||
### 11.2 Formulário de briefing
|
### 11.2 Formulário de briefing
|
||||||
|
|
||||||
> **Estado atual:** o formulário é implementado em Blade + Controller (`POST /contato`, `ContactBriefingRequest`), conforme WEB-05, e essa é a abordagem aceita — não um estágio provisório. Os requisitos abaixo valem independentemente da tecnologia; a criação de Lead segue para a Fase 2.
|
> **Estado atual:** o formulário de **Briefing** é Blade + Controller (`GET/POST /briefing`, `ContactBriefingRequest`), conforme WEB-05. A rota `/contato` é o canal de **Contato parceiro** (consulta não persistente), separado do briefing. A criação de Lead comercial persistente segue para a Fase 2.
|
||||||
|
|
||||||
O formulário deve:
|
O formulário deve:
|
||||||
|
|
||||||
|
|||||||
@@ -8,20 +8,45 @@ use App\Models\SiteSetting;
|
|||||||
|
|
||||||
final class PackageContactLink
|
final class PackageContactLink
|
||||||
{
|
{
|
||||||
|
private const ORIENTATION_MESSAGE = 'Olá, ainda não sei qual modalidade de acompanhamento combina com o meu casamento e gostaria de orientação da Amare.';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the contextual contact link for a wedding package modality.
|
* Resolve the contextual contact link for a wedding package modality.
|
||||||
*
|
*
|
||||||
* @return array{href: string, isWhatsapp: bool}
|
* @return array{href: string, isWhatsapp: bool}
|
||||||
*/
|
*/
|
||||||
public static function for(SiteSetting $settings, string $packageName): array
|
public static function for(SiteSetting $settings, string $packageName): array
|
||||||
|
{
|
||||||
|
return self::resolve(
|
||||||
|
$settings,
|
||||||
|
'Olá, gostaria de conversar sobre a modalidade '.$packageName.' para meu casamento.',
|
||||||
|
['servico_interesse' => $packageName],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the orientation CTA for visitors who have not chosen a modality yet.
|
||||||
|
*
|
||||||
|
* @return array{href: string, isWhatsapp: bool}
|
||||||
|
*/
|
||||||
|
public static function forOrientation(SiteSetting $settings): array
|
||||||
|
{
|
||||||
|
return self::resolve($settings, self::ORIENTATION_MESSAGE, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, string> $briefingQuery
|
||||||
|
* @return array{href: string, isWhatsapp: bool}
|
||||||
|
*/
|
||||||
|
private static function resolve(SiteSetting $settings, string $whatsappMessage, array $briefingQuery): array
|
||||||
{
|
{
|
||||||
$digits = preg_replace('/\D/', '', (string) $settings->whatsapp_number);
|
$digits = preg_replace('/\D/', '', (string) $settings->whatsapp_number);
|
||||||
$isWhatsapp = strlen($digits) >= 10;
|
$isWhatsapp = strlen($digits) >= 10;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'href' => $isWhatsapp
|
'href' => $isWhatsapp
|
||||||
? 'https://wa.me/'.$digits.'?text='.rawurlencode('Olá, gostaria de conversar sobre a modalidade '.$packageName.' para meu casamento.')
|
? 'https://wa.me/'.$digits.'?text='.rawurlencode($whatsappMessage)
|
||||||
: route('briefing', ['servico_interesse' => $packageName]),
|
: route('briefing', $briefingQuery),
|
||||||
'isWhatsapp' => $isWhatsapp,
|
'isWhatsapp' => $isWhatsapp,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +1,28 @@
|
|||||||
# Domain Docs
|
# Domain Docs
|
||||||
|
|
||||||
How the engineering skills should consume this repo's domain documentation when exploring the codebase.
|
How engineering skills should consume this repo's domain documentation.
|
||||||
|
|
||||||
## Before exploring, read these
|
## Single source of truth
|
||||||
|
|
||||||
- **`CONTEXT.md`** at the repo root, or
|
**`SPEC.md` §8** (especially **§8.0 Linguagem ubíqua**) is the glossary and domain model for Amare. There is no root `CONTEXT.md` on purpose — do not create one. Prefer `SPEC.md` over Linear copy or OpenSpec prose when terms conflict.
|
||||||
- **`CONTEXT-MAP.md`** at the repo root if it exists — it points at one `CONTEXT.md` per context. Read each one relevant to the topic.
|
|
||||||
- **`docs/adr/`** — read ADRs that touch the area you're about to work in. In multi-context repos, also check `src/<context>/docs/adr/` for context-scoped decisions.
|
|
||||||
|
|
||||||
If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved.
|
Also useful:
|
||||||
|
|
||||||
## File structure
|
- **`PRODUCT.md`** — positioning and audience (not the glossary)
|
||||||
|
- **`openspec/specs/`** — current capability contracts
|
||||||
|
- **`docs/adr/README.md`** — index only; ADR-001–010 live in `SPEC.md` §21
|
||||||
|
|
||||||
Single-context repo (most repos):
|
## Before exploring
|
||||||
|
|
||||||
```
|
1. Read `SPEC.md` §8.0 for vocabulary; skim §5.1 for public routes and §8.2+ for persistence shape when relevant.
|
||||||
/
|
2. If a skill expects `CONTEXT.md` / `CONTEXT-MAP.md` and finds neither, **proceed using `SPEC.md` §8** — do not invent a parallel glossary file.
|
||||||
├── CONTEXT.md
|
|
||||||
├── docs/adr/
|
|
||||||
│ ├── 0001-event-sourced-orders.md
|
|
||||||
│ └── 0002-postgres-for-write-model.md
|
|
||||||
└── src/
|
|
||||||
```
|
|
||||||
|
|
||||||
Multi-context repo (presence of `CONTEXT-MAP.md` at the root):
|
|
||||||
|
|
||||||
```
|
|
||||||
/
|
|
||||||
├── CONTEXT-MAP.md
|
|
||||||
├── docs/adr/ ← system-wide decisions
|
|
||||||
└── src/
|
|
||||||
├── ordering/
|
|
||||||
│ ├── CONTEXT.md
|
|
||||||
│ └── docs/adr/ ← context-specific decisions
|
|
||||||
└── billing/
|
|
||||||
├── CONTEXT.md
|
|
||||||
└── docs/adr/
|
|
||||||
```
|
|
||||||
|
|
||||||
## Use the glossary's vocabulary
|
## Use the glossary's vocabulary
|
||||||
|
|
||||||
When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.
|
When output names a domain concept (issue title, refactor, hypothesis, test name), use the term as defined in `SPEC.md` §8.0. Don't drift to synonyms the glossary explicitly avoids (`_Avoid_`).
|
||||||
|
|
||||||
If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`).
|
If the concept isn't in §8.0 yet, either you're inventing language the project doesn't use (reconsider) or there's a real gap — resolve it by updating `SPEC.md` §8.0 via `/grill-with-docs` / domain-modeling, not by adding `CONTEXT.md`.
|
||||||
|
|
||||||
## Flag ADR conflicts
|
## Flag ADR conflicts
|
||||||
|
|
||||||
If your output contradicts an existing ADR, surface it explicitly rather than silently overriding:
|
If output contradicts an ADR in `SPEC.md` §21, surface it explicitly rather than silently overriding.
|
||||||
|
|
||||||
> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_
|
|
||||||
|
|||||||
@@ -15,7 +15,9 @@
|
|||||||
])
|
])
|
||||||
|
|
||||||
@php
|
@php
|
||||||
$bandHref = $bandCtaHref ?? route('briefing');
|
$orientationLink = \App\Support\PackageContactLink::forOrientation($settings);
|
||||||
|
$bandHref = $bandCtaHref ?? $orientationLink['href'];
|
||||||
|
$bandIsWhatsapp = $bandCtaHref === null && $orientationLink['isWhatsapp'];
|
||||||
@endphp
|
@endphp
|
||||||
<section
|
<section
|
||||||
aria-labelledby="packages-heading"
|
aria-labelledby="packages-heading"
|
||||||
@@ -77,7 +79,11 @@
|
|||||||
<h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight">Ainda não sabe qual modalidade é ideal?</h3>
|
<h3 class="text-[clamp(1.5625rem,2.7vw,2.125rem)] font-medium leading-tight">Ainda não sabe qual modalidade é ideal?</h3>
|
||||||
<p class="text-amare-accent-text/80">{{ $bandBody }}</p>
|
<p class="text-amare-accent-text/80">{{ $bandBody }}</p>
|
||||||
</div>
|
</div>
|
||||||
<a href="{{ $bandHref }}" class="inline-flex min-h-[48px] items-center justify-center self-start border border-amare-accent-text px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-text transition-colors hover:bg-amare-accent-text hover:text-amare-accent-deep md:self-auto">
|
<a
|
||||||
|
href="{{ $bandHref }}"
|
||||||
|
@if ($bandIsWhatsapp) target="_blank" rel="noopener noreferrer" @endif
|
||||||
|
class="inline-flex min-h-[48px] items-center justify-center self-start border border-amare-accent-text px-6 text-xs font-bold uppercase tracking-[0.09em] text-amare-accent-text transition-colors hover:bg-amare-accent-text hover:text-amare-accent-deep md:self-auto"
|
||||||
|
>
|
||||||
Conversar com a Amare
|
Conversar com a Amare
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -47,7 +47,6 @@
|
|||||||
:show-intro="false"
|
:show-intro="false"
|
||||||
kicker="tag"
|
kicker="tag"
|
||||||
:show-subtitle="true"
|
:show-subtitle="true"
|
||||||
:band-cta-href="route('briefing')"
|
|
||||||
band-body="Conte um pouco sobre o casamento. A Amare entende o momento de vocês e orienta o melhor formato de acompanhamento sem depender de um quiz automático."
|
band-body="Conte um pouco sobre o casamento. A Amare entende o momento de vocês e orienta o melhor formato de acompanhamento sem depender de um quiz automático."
|
||||||
:show-note="false"
|
:show-note="false"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -213,7 +213,26 @@ class HomePageContentTest extends TestCase
|
|||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
->assertSee('target="_blank"', false)
|
->assertSee('target="_blank"', false)
|
||||||
->assertDontSee(route('briefing', ['servico_interesse' => 'Grand Jour']), false);
|
->assertDontSee(route('briefing', ['servico_interesse' => 'Grand Jour']), false)
|
||||||
|
->assertSee(
|
||||||
|
'https://wa.me/5511988887777?text='.rawurlencode('Olá, ainda não sei qual modalidade de acompanhamento combina com o meu casamento e gostaria de orientação da Amare.'),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_orientation_cta_falls_back_to_briefing_without_whatsapp_number(): void
|
||||||
|
{
|
||||||
|
SiteSetting::instance()->update(['whatsapp_number' => null]);
|
||||||
|
|
||||||
|
$response = $this->get(route('home'));
|
||||||
|
|
||||||
|
$response
|
||||||
|
->assertOk()
|
||||||
|
->assertSee('href="'.route('briefing').'"', false)
|
||||||
|
->assertDontSee(
|
||||||
|
'Olá, ainda não sei qual modalidade de acompanhamento combina com o meu casamento e gostaria de orientação da Amare.',
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_corporate_steps_and_placeholder_render_from_settings(): void
|
public function test_corporate_steps_and_placeholder_render_from_settings(): void
|
||||||
|
|||||||
@@ -50,4 +50,18 @@ class ServicesPageCtaTest extends TestCase
|
|||||||
->assertSee('href="'.route('briefing', ['servico_interesse' => 'Essenza']).'"', false)
|
->assertSee('href="'.route('briefing', ['servico_interesse' => 'Essenza']).'"', false)
|
||||||
->assertDontSee('wa.me/', false);
|
->assertDontSee('wa.me/', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_orientation_cta_uses_distinct_whatsapp_message_when_a_number_is_configured(): void
|
||||||
|
{
|
||||||
|
SiteSetting::instance()->update(['whatsapp_number' => '+55 11 98888-7777']);
|
||||||
|
|
||||||
|
$response = $this->get(route('services.index'));
|
||||||
|
|
||||||
|
$response
|
||||||
|
->assertOk()
|
||||||
|
->assertSee(
|
||||||
|
'https://wa.me/5511988887777?text='.rawurlencode('Olá, ainda não sei qual modalidade de acompanhamento combina com o meu casamento e gostaria de orientação da Amare.'),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user