Compare commits
1 Commits
docs/man-1
...
feat/whats
| Author | SHA1 | Date | |
|---|---|---|---|
| 400c147a74 |
@@ -67,6 +67,10 @@ class WeddingPackageForm
|
|||||||
->label('Texto do botão')
|
->label('Texto do botão')
|
||||||
->required()
|
->required()
|
||||||
->maxLength(255),
|
->maxLength(255),
|
||||||
|
Textarea::make('whatsapp_message')
|
||||||
|
->label('Mensagem do WhatsApp (deixe vazio para usar o padrão)')
|
||||||
|
->helperText('Texto enviado ao cliente ao tocar no botão de contato. O nome da modalidade é citado automaticamente se vazio.')
|
||||||
|
->rows(3),
|
||||||
TextInput::make('compare_heading')
|
TextInput::make('compare_heading')
|
||||||
->label('Comparação — título (leitura rápida)')
|
->label('Comparação — título (leitura rápida)')
|
||||||
->maxLength(255),
|
->maxLength(255),
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ use Illuminate\Support\Str;
|
|||||||
* @property string $summary
|
* @property string $summary
|
||||||
* @property list<string> $scope_items
|
* @property list<string> $scope_items
|
||||||
* @property string $cta_label
|
* @property string $cta_label
|
||||||
|
* @property string|null $whatsapp_message
|
||||||
* @property string|null $compare_heading
|
* @property string|null $compare_heading
|
||||||
* @property string|null $compare_summary
|
* @property string|null $compare_summary
|
||||||
* @property string|null $eyebrow
|
* @property string|null $eyebrow
|
||||||
@@ -54,6 +55,7 @@ use Illuminate\Support\Str;
|
|||||||
'summary',
|
'summary',
|
||||||
'scope_items',
|
'scope_items',
|
||||||
'cta_label',
|
'cta_label',
|
||||||
|
'whatsapp_message',
|
||||||
'compare_heading',
|
'compare_heading',
|
||||||
'compare_summary',
|
'compare_summary',
|
||||||
'sort_order',
|
'sort_order',
|
||||||
|
|||||||
@@ -11,17 +11,47 @@ final class PackageContactLink
|
|||||||
/**
|
/**
|
||||||
* Resolve the contextual contact link for a wedding package modality.
|
* Resolve the contextual contact link for a wedding package modality.
|
||||||
*
|
*
|
||||||
|
* Uses the package-specific WhatsApp message when provided; otherwise
|
||||||
|
* falls back to the default template with the modality name.
|
||||||
|
*
|
||||||
* @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, ?string $customMessage = null): array
|
||||||
|
{
|
||||||
|
$message = filled($customMessage)
|
||||||
|
? $customMessage
|
||||||
|
: 'Olá, gostaria de conversar sobre a modalidade '.$packageName.' para meu casamento.';
|
||||||
|
|
||||||
|
return self::build($settings, $message, $packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a generic contact link (no specific modality), used by the
|
||||||
|
* "Conversar com a Amare" guidance band.
|
||||||
|
*
|
||||||
|
* @return array{href: string, isWhatsapp: bool}
|
||||||
|
*/
|
||||||
|
public static function generic(SiteSetting $settings): array
|
||||||
|
{
|
||||||
|
return self::build(
|
||||||
|
$settings,
|
||||||
|
'Olá, ainda estou decidindo a modalidade ideal para o meu casamento. Podemos conversar?',
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{href: string, isWhatsapp: bool}
|
||||||
|
*/
|
||||||
|
private static function build(SiteSetting $settings, string $message, ?string $packageName): 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($message)
|
||||||
: route('briefing', ['servico_interesse' => $packageName]),
|
: route('briefing', $packageName !== null ? ['servico_interesse' => $packageName] : []),
|
||||||
'isWhatsapp' => $isWhatsapp,
|
'isWhatsapp' => $isWhatsapp,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('wedding_packages', function (Blueprint $table): void {
|
||||||
|
$table->text('whatsapp_message')->nullable()->after('cta_label');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('wedding_packages', function (Blueprint $table): void {
|
||||||
|
$table->dropColumn('whatsapp_message');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -15,7 +15,9 @@
|
|||||||
])
|
])
|
||||||
|
|
||||||
@php
|
@php
|
||||||
$bandHref = $bandCtaHref ?? route('briefing');
|
$bandLink = $bandCtaHref
|
||||||
|
? ['href' => $bandCtaHref, 'isWhatsapp' => false]
|
||||||
|
: \App\Support\PackageContactLink::generic($settings);
|
||||||
@endphp
|
@endphp
|
||||||
<section
|
<section
|
||||||
aria-labelledby="packages-heading"
|
aria-labelledby="packages-heading"
|
||||||
@@ -52,7 +54,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="space-y-5">
|
<div class="space-y-5">
|
||||||
@php($contactLink = $ctaRoute ? null : \App\Support\PackageContactLink::for($settings, $package->name))
|
@php($contactLink = $ctaRoute ? null : \App\Support\PackageContactLink::for($settings, $package->name, $package->whatsapp_message))
|
||||||
<a
|
<a
|
||||||
href="{{ $ctaRoute ? route($ctaRoute) : $contactLink['href'] }}"
|
href="{{ $ctaRoute ? route($ctaRoute) : $contactLink['href'] }}"
|
||||||
@if ($ctaRoute === null && $contactLink['isWhatsapp']) target="_blank" rel="noopener noreferrer" @endif
|
@if ($ctaRoute === null && $contactLink['isWhatsapp']) target="_blank" rel="noopener noreferrer" @endif
|
||||||
@@ -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="{{ $bandLink['href'] }}"
|
||||||
|
@if ($bandLink['isWhatsapp']) 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>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
@else
|
@else
|
||||||
<ol class="grid gap-8 border-t border-amare-border pt-6 md:grid-cols-3">
|
<ol class="grid gap-8 border-t border-amare-border pt-6 md:grid-cols-3">
|
||||||
@foreach ($packages as $package)
|
@foreach ($packages as $package)
|
||||||
@php($contactLink = \App\Support\PackageContactLink::for($settings, $package->name))
|
@php($contactLink = \App\Support\PackageContactLink::for($settings, $package->name, $package->whatsapp_message))
|
||||||
<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>
|
<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
|
@endforeach
|
||||||
</ol>
|
</ol>
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
'heading' => null,
|
'heading' => null,
|
||||||
'body' => null,
|
'body' => null,
|
||||||
'packageName' => null,
|
'packageName' => null,
|
||||||
|
'packageMessage' => null,
|
||||||
])
|
])
|
||||||
|
|
||||||
@php
|
@php
|
||||||
$link = \App\Support\PackageContactLink::for($settings, $packageName ?? '');
|
$link = \App\Support\PackageContactLink::for($settings, $packageName ?? '', $packageMessage);
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<section aria-labelledby="final-cta-heading" class="border-b border-amare-border bg-amare-bg py-20 md:py-24" data-chapter="final-cta" data-reveal-group>
|
<section aria-labelledby="final-cta-heading" class="border-b border-amare-border bg-amare-bg py-20 md:py-24" data-chapter="final-cta" data-reveal-group>
|
||||||
|
|||||||
@@ -31,5 +31,6 @@
|
|||||||
:heading="$package->final_cta_heading"
|
:heading="$package->final_cta_heading"
|
||||||
:body="$package->final_cta_body"
|
:body="$package->final_cta_body"
|
||||||
:package-name="$package->name"
|
:package-name="$package->name"
|
||||||
|
:package-message="$package->whatsapp_message"
|
||||||
/>
|
/>
|
||||||
@endsection
|
@endsection
|
||||||
|
|||||||
@@ -216,6 +216,44 @@ class HomePageContentTest extends TestCase
|
|||||||
->assertDontSee(route('briefing', ['servico_interesse' => 'Grand Jour']), false);
|
->assertDontSee(route('briefing', ['servico_interesse' => 'Grand Jour']), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_package_cta_uses_custom_whatsapp_message_when_provided(): void
|
||||||
|
{
|
||||||
|
SiteSetting::instance()->update(['whatsapp_number' => '+55 11 98888-7777']);
|
||||||
|
|
||||||
|
WeddingPackage::factory()->published()->create([
|
||||||
|
'name' => 'Grand Jour',
|
||||||
|
'cta_label' => 'Quero conhecer a Grand Jour',
|
||||||
|
'whatsapp_message' => 'Olá, quero saber mais sobre a modalidade Grand Jour para o meu casamento em julho.',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = $this->get(route('home'));
|
||||||
|
|
||||||
|
$response
|
||||||
|
->assertOk()
|
||||||
|
->assertSee(
|
||||||
|
'https://wa.me/5511988887777?text='.rawurlencode('Olá, quero saber mais sobre a modalidade Grand Jour para o meu casamento em julho.'),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
->assertDontSee('gostaria de conversar sobre a modalidade Grand Jour para meu casamento', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_guidance_band_uses_whatsapp_when_a_number_is_configured(): void
|
||||||
|
{
|
||||||
|
SiteSetting::instance()->update(['whatsapp_number' => '+55 11 98888-7777']);
|
||||||
|
|
||||||
|
WeddingPackage::factory()->published()->create();
|
||||||
|
|
||||||
|
$response = $this->get(route('home'));
|
||||||
|
|
||||||
|
$response
|
||||||
|
->assertOk()
|
||||||
|
->assertSee(
|
||||||
|
'https://wa.me/5511988887777?text='.rawurlencode('Olá, ainda estou decidindo a modalidade ideal para o meu casamento. Podemos conversar?'),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
->assertSee('Conversar com a Amare');
|
||||||
|
}
|
||||||
|
|
||||||
public function test_corporate_steps_and_placeholder_render_from_settings(): void
|
public function test_corporate_steps_and_placeholder_render_from_settings(): void
|
||||||
{
|
{
|
||||||
SiteSetting::instance()->update([
|
SiteSetting::instance()->update([
|
||||||
|
|||||||
@@ -100,6 +100,26 @@ class PackageDetailTest extends TestCase
|
|||||||
->assertDontSee(route('briefing', ['servico_interesse' => 'Essenza']), false);
|
->assertDontSee(route('briefing', ['servico_interesse' => 'Essenza']), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_package_final_cta_uses_custom_whatsapp_message_when_provided(): void
|
||||||
|
{
|
||||||
|
SiteSetting::instance()->update(['whatsapp_number' => '+55 11 98888-7777']);
|
||||||
|
|
||||||
|
$package = WeddingPackage::factory()->published()->create([
|
||||||
|
'name' => 'Essenza',
|
||||||
|
'whatsapp_message' => 'Olá, tenho interesse na assessoria Essenza. Podem me passar mais detalhes?',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = $this->get(route('packages.show', $package->slug));
|
||||||
|
|
||||||
|
$response
|
||||||
|
->assertOk()
|
||||||
|
->assertSee(
|
||||||
|
'https://wa.me/5511988887777?text='.rawurlencode('Olá, tenho interesse na assessoria Essenza. Podem me passar mais detalhes?'),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
->assertDontSee('gostaria de conversar sobre a modalidade Essenza para meu casamento', false);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_package_cta_falls_back_to_briefing_without_whatsapp_number(): void
|
public function test_package_cta_falls_back_to_briefing_without_whatsapp_number(): void
|
||||||
{
|
{
|
||||||
SiteSetting::instance();
|
SiteSetting::instance();
|
||||||
|
|||||||
Reference in New Issue
Block a user