{{ __('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)
{{ 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() }}).
@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) --}}
@endif
@endforeach
{{-- Comparison table (only when 2+ plans, otherwise it's noise) --}}
@if ($packages->count() >= 2)
MOST POPULAR
@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-green',
'textCls' => 'text-paper-0/90',
'moreCls' => 'text-wa-green',
])
{{ $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',
])
{{ __('Compare features') }}
{{ __('All plans include unlimited campaigns & templates') }}| {{ __('Feature') }} | @foreach ($packages as $p){{ $p->pname }} | @endforeach
|---|---|
| {{ $row['label'] }} | @foreach ($packages as $p) @php $val = $p->{$row['key']} ?? null; $isHi = $p->id === $highlightedId; @endphp@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 | @endforeach
@foreach ($faqs as $i => $faq)
@endforeach
@endif
@endif
{{ $faq->question }}
{{ $faq->answer }}