{{-- Hero --}}
{{ __('Pricing & plans') }}

{{ __('Pricing that') }} {{ __('grows with you') }}

{{ __('Pick the plan that fits today. Upgrade, downgrade or pause any time — no contracts, no surprises.') }}

{{-- billing toggle. Admin can hide the whole switcher via SystemSetting('pricing.yearly_toggle_enabled'). --}} @if ($yearlyEnabled)
@endif
@if (session('success'))
{{ session('success') }}
@endif @if (session('error'))
{{ session('error') }}
@endif {{-- Plan validity banner. plan_ends_at is set on checkout from the package's admin-configured duration (plan_duration × plan_unit); null = no expiry (free / lifetime / enterprise). --}} @if (!empty($planExpired))
{{ __('Your plan expired on') }} {{ optional($currentPlanEndsAt)->format('M j, Y') }}. {{ __('Paid features are paused — renew below to restore them.') }}
@elseif (!empty($currentPlanEndsAt))
@if (!empty($activeSubscription)) {{ __('Your plan auto-renews on') }} {{ $currentPlanEndsAt->format('M j, Y') }} ({{ $currentPlanEndsAt->diffForHumans() }}).
@csrf
@else {{ __('Your plan is active until') }} {{ $currentPlanEndsAt->format('M j, Y') }} ({{ $currentPlanEndsAt->diffForHumans() }}). @endif
@elseif (!empty($trialEndsAt))
{{ __('Free trial ends on') }} {{ $trialEndsAt->format('M j, Y') }} ({{ $trialEndsAt->diffForHumans() }}). {{ __('Choose a plan to keep your workspace active.') }}
@endif @if ($packages->isEmpty())
{{ __('No plans configured yet — ask your admin to create one at') }} /admin/packages/create.
@else @php $cols = min(4, max(1, $packages->count())); $gridCls = ['', 'md:grid-cols-1', 'md:grid-cols-2', 'md:grid-cols-3', 'md:grid-cols-2 lg:grid-cols-4'][ $cols ] ?? 'md:grid-cols-2 lg:grid-cols-4'; @endphp {{-- Plan cards. items-start so expanding one card's "Show all features" only grows THAT card — without it the grid stretches every card in the row to match the tallest. --}}
@foreach ($packages as $p) @php $isFree = $p->free || (float) $p->plan_amount === 0.0; $isCustom = $p->is_custom_quote; $highlighted = $p->is_highlighted; $amount = $p->plan_amount; if ($p->currency && strtoupper($p->currency) !== strtoupper($currency)) { $amount = \App\Support\FormatSettings::convert($p->plan_amount, $p->currency, $currency); } $yearlyAmount = round($amount * 12 * (1 - $yearlyDiscountPct / 100), 2); // admin-driven yearly discount $monthlyHuman = $isCustom ? 'Custom' : ($isFree ? 'Free' : \App\Support\FormatSettings::currency($amount)); $yearlyHuman = $isCustom ? 'Custom' : ($isFree ? 'Free' : \App\Support\FormatSettings::currency($yearlyAmount / 12)); // Set only on the in-app /account/plans render (PricingController). $isCurrent = ($currentPackageId ?? null) && (int) $p->id === (int) $currentPackageId; // Upgrade / downgrade gating: you can move UP to a pricier plan, but // the current plan + any cheaper paid plan are not directly buyable. $curAmt = $currentPlanAmount ?? null; // null = no active plan (free/trial) $isDowngrade = !$isCurrent && !$isCustom && !$isFree && $curAmt !== null && (float) $p->plan_amount < (float) $curAmt; $isUpgrade = !$isCurrent && !$isCustom && !$isFree && $curAmt !== null && (float) $p->plan_amount > (float) $curAmt; @endphp @if ($highlighted) {{-- Highlighted dark card (mirrors prototype's Pro plan) --}}
MOST POPULAR
{{ $p->pname }}
{!! $yearlyHuman !!} @if (!$isFree && !$isCustom) / month @endif
@if ($p->subtitle)

{{ $p->subtitle }}

@endif @if ($isCurrent) {{ __('Current plan') }} @elseif ($isCustom) {{ $p->cta_label ?: 'Talk to sales' }} @elseif ($isFree) {{ $p->cta_label ?: 'Continue free' }} @elseif ($isDowngrade) {{ __('Downgrade unavailable') }} @else {{ $isUpgrade ? __('Upgrade to :plan', ['plan' => $p->pname]) : ($p->cta_label ?: 'Choose ' . $p->pname) }} @endif
@include('pricing._features', [ 'p' => $p, 'iconCls' => 'text-wa-green', 'textCls' => 'text-paper-0/90', 'moreCls' => 'text-wa-green', ])
@else {{-- Plain card --}}
{{ $p->pname }}
{!! $yearlyHuman !!} @if (!$isFree && !$isCustom) / month @endif
@if ($p->subtitle)

{{ $p->subtitle }}

@endif @if ($isCurrent) {{ __('Current plan') }} @elseif ($isCustom) {{ $p->cta_label ?: 'Talk to sales' }} @elseif ($isFree) {{ $p->cta_label ?: 'Continue free' }} @elseif ($isDowngrade) {{ __('Downgrade unavailable') }} @else {{ $isUpgrade ? __('Upgrade to :plan', ['plan' => $p->pname]) : ($p->cta_label ?: 'Choose ' . $p->pname) }} @endif
@include('pricing._features', [ 'p' => $p, 'iconCls' => 'text-wa-deep', 'textCls' => 'text-ink-700', 'moreCls' => 'text-wa-deep', ])
@endif @endforeach
{{-- Comparison table (only when 2+ plans, otherwise it's noise) --}} @if ($packages->count() >= 2)

{{ __('Compare features') }}

{{ __('All plans include unlimited campaigns & templates') }}
@php // Every feature, straight from the single catalog — numeric limits // first, then capabilities. A row is hidden only if NO plan has it, // so the table never shows an all-empty line. $catalog = \App\Models\Package::featureCatalog(); $compareRows = []; foreach ($catalog['limits'] as $k => $l) { if ($packages->contains(fn($p) => ($p->{$k} ?? null) !== null)) { $compareRows[] = ['key' => $k, 'label' => $l]; } } foreach ($catalog['capabilities'] as $k => $l) { if ($packages->contains(fn($p) => (bool) ($p->{$k} ?? false))) { $compareRows[] = ['key' => $k, 'label' => $l, 'boolean' => true]; } } $highlightedId = optional($packages->firstWhere('is_highlighted', true))->id; $cmpCollapse = count($compareRows) > 12; // collapse long tables behind "Show all" @endphp
@foreach ($packages as $p) @endforeach @foreach ($compareRows as $row) @foreach ($packages as $p) @php $val = $p->{$row['key']} ?? null; $isHi = $p->id === $highlightedId; @endphp @endforeach @endforeach
{{ __('Feature') }} {{ $p->pname }}
{{ $row['label'] }} @if (!empty($row['boolean'])) @if ($val) @else @endif @else @if ($val === null) @elseif ((int) $val === 0) {{ __('unlimited') }} @else {{ $val >= 1000 ? number_format($val / 1000, $val >= 100000 ? 0 : 1) . 'k' : number_format($val) }} @endif @endif
@if ($cmpCollapse) @endif
@endif {{-- FAQ — admin-editable rows from pricing_faqs. Falls back gracefully to nothing when the table is empty (CheckoutDefaultsSeeder seeds a sensible set on a fresh install). --}} @if ($faqs->isNotEmpty())
@foreach ($faqs as $i => $faq)
{{ $faq->question }}

{{ $faq->answer }}

@endforeach
@endif @endif