@extends('layouts.public')
@section('title', 'Pricing')
@section('content')
@php
try {
$heroTitle = (string) \App\Models\Setting::get('pricing_section_title', (string) \App\Models\Setting::get('pricing_hero_title', 'Simple, transparent pricing'));
$heroSubtitle = (string) \App\Models\Setting::get('pricing_section_subtitle', (string) \App\Models\Setting::get('pricing_hero_subtitle', "Choose the plan that's right for your business. All plans include a 14-day free trial."));
$popularBadge = (string) \App\Models\Setting::get('pricing_section_popular_badge', (string) \App\Models\Setting::get('pricing_popular_badge', 'Most Popular'));
$ctaAuth = (string) \App\Models\Setting::get('pricing_cta_auth', 'Get Started');
$ctaGuest = (string) \App\Models\Setting::get('pricing_cta_guest', 'Start Free Trial');
$faqTitle = (string) \App\Models\Setting::get('pricing_faq_title', 'Frequently asked questions');
} catch (\Throwable $e) {
$heroTitle = 'Simple, transparent pricing';
$heroSubtitle = "Choose the plan that's right for your business. All plans include a 14-day free trial.";
$popularBadge = 'Most Popular';
$ctaAuth = 'Get Started';
$ctaGuest = 'Start Free Trial';
$faqTitle = 'Frequently asked questions';
}
$heroTitle = is_string($heroTitle) && trim($heroTitle) !== '' ? $heroTitle : 'Simple, transparent pricing';
$heroSubtitle = is_string($heroSubtitle) && trim($heroSubtitle) !== '' ? $heroSubtitle : "Choose the plan that's right for your business. All plans include a 14-day free trial.";
$popularBadge = is_string($popularBadge) && trim($popularBadge) !== '' ? $popularBadge : 'Most Popular';
$ctaAuth = is_string($ctaAuth) && trim($ctaAuth) !== '' ? $ctaAuth : 'Get Started';
$ctaGuest = is_string($ctaGuest) && trim($ctaGuest) !== '' ? $ctaGuest : 'Start Free Trial';
$faqTitle = is_string($faqTitle) && trim($faqTitle) !== '' ? $faqTitle : 'Frequently asked questions';
try {
$featuredPlanId = (int) \App\Models\Setting::get('pricing_featured_plan_id', 0);
} catch (\Throwable $e) {
$featuredPlanId = 0;
}
if (isset($plans) && $plans instanceof \Illuminate\Support\Collection) {
$popularPlan = $plans->firstWhere('is_popular', true);
if ($popularPlan) {
$featuredPlanId = (int) $popularPlan->id;
}
}
if ($featuredPlanId <= 0 && isset($plans) && $plans instanceof \Illuminate\Support\Collection) {
$featuredPlanId = (int) optional($plans->first())->id;
}
$faqRows = isset($faq) && is_array($faq) ? $faq : [
[
'q' => 'Can I change plans later?',
'a' => 'Yes, you can upgrade or downgrade your plan at any time. Changes will be prorated and reflected in your next billing cycle.',
],
[
'q' => 'What payment methods do you accept?',
'a' => 'We accept all major credit cards, PayPal, and bank transfers for annual plans.',
],
[
'q' => 'Is there a free trial?',
'a' => 'Yes, all plans include a 14-day free trial. No credit card required to start.',
],
[
'q' => 'What happens if I exceed my plan limits?',
'a' => "We'll notify you when you're approaching your limits. You can upgrade your plan or purchase additional credits as needed.",
],
];
$pricingPlansMonthly = isset($plans) && $plans instanceof \Illuminate\Support\Collection
? $plans->where('billing_cycle', 'monthly')->values()
: collect();
$pricingPlansYearly = isset($plans) && $plans instanceof \Illuminate\Support\Collection
? $plans->where('billing_cycle', 'yearly')->values()
: collect();
$pricingAnnualDefault = $pricingPlansMonthly->count() === 0 && $pricingPlansYearly->count() > 0;
try {
$pricingForceShowAll = (bool) \App\Models\Setting::get('pricing_section_show_all', false);
$pricingColumns = (int) \App\Models\Setting::get('pricing_section_columns', 3);
} catch (\Throwable $e) {
$pricingForceShowAll = false;
$pricingColumns = 3;
}
if ($pricingColumns < 1) {
$pricingColumns = 1;
}
if ($pricingColumns > 5) {
$pricingColumns = 5;
}
try {
$pricingToggleMonthly = (string) \App\Models\Setting::get('pricing_section_toggle_monthly', 'Pay Monthly');
$pricingToggleAnnual = (string) \App\Models\Setting::get('pricing_section_toggle_annual', 'Pay Annually');
$pricingToggleSave = (string) \App\Models\Setting::get('pricing_section_toggle_save', '(save 20%)');
} catch (\Throwable $e) {
$pricingToggleMonthly = 'Pay Monthly';
$pricingToggleAnnual = 'Pay Annually';
$pricingToggleSave = '(save 20%)';
}
$showBillingToggle = !$pricingForceShowAll && $pricingPlansMonthly->count() > 0 && $pricingPlansYearly->count() > 0;
$gridClassForColumns = function (int $columns): string {
if ($columns <= 1) {
return 'grid-cols-1 gap-8';
}
if ($columns === 2) {
return 'grid-cols-1 gap-8 sm:grid-cols-2';
}
if ($columns === 3) {
return 'grid-cols-1 gap-8 lg:grid-cols-3';
}
if ($columns === 4) {
return 'grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-4';
}
return 'grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-5';
};
$gridClass = $gridClassForColumns($pricingColumns);
@endphp
@if($showBillingToggle)
{{ $pricingToggleMonthly }}
{{ $pricingToggleAnnual }} {{ $pricingToggleSave }}
@endif
@foreach(($pricingForceShowAll ? $pricingPlansMonthly->concat($pricingPlansYearly) : $pricingPlansMonthly) as $plan)
@php
$hasPopular = $plans instanceof \Illuminate\Support\Collection && $plans->where('is_popular', true)->count() > 0;
$isFeatured = $hasPopular ? (($plan->is_popular ?? false) === true) : (((int) $plan->id) === (int) $featuredPlanId);
$cycle = $plan->billing_cycle === 'yearly' ? 'year' : 'month';
$quota = $plan->customerGroup?->limit('sending_quota.monthly_quota', 0);
$maxSubscribers = $plan->customerGroup?->limit('lists.limits.max_subscribers', 0);
$maxCampaigns = $plan->customerGroup?->limit('campaigns.limits.max_campaigns', 0);
$quotaLabel = $quota !== null ? number_format((float) $quota) : '—';
$subsLabel = $maxSubscribers !== null ? number_format((int) $maxSubscribers) : '—';
$campaignsLabel = $maxCampaigns !== null ? number_format((int) $maxCampaigns) : '—';
$featuresView = [
'type' => 'legacy',
'pros' => [],
'cons' => [],
'legacyItems' => [],
];
$planFeatures = $plan->features ?? null;
if (is_array($planFeatures) && (array_key_exists('pros', $planFeatures) || array_key_exists('cons', $planFeatures))) {
$featuresView['type'] = 'proscons';
$featuresView['pros'] = is_array($planFeatures['pros'] ?? null) ? $planFeatures['pros'] : [];
$featuresView['cons'] = is_array($planFeatures['cons'] ?? null) ? $planFeatures['cons'] : [];
} elseif (is_array($planFeatures) && count($planFeatures) > 0) {
$featuresView['type'] = 'proscons';
$featuresView['pros'] = $planFeatures;
$featuresView['cons'] = [];
} else {
$features = $plan->customerGroup?->displayAccessAndLimits() ?? [];
foreach ($features as $row) {
if (!is_array($row)) {
continue;
}
$label = is_string($row['label'] ?? null) ? (string) $row['label'] : '';
$value = is_string($row['value'] ?? null) ? (string) $row['value'] : '';
$text = trim($label) !== '' ? trim($label) . ': ' . $value : $value;
$text = trim($text);
if ($text === '') {
continue;
}
$featuresView['legacyItems'][] = [
'status' => ($row['status'] ?? true) !== false,
'text' => $text,
];
}
}
$planCta = is_string($plan->cta_text ?? null) && trim((string) $plan->cta_text) !== '' ? (string) $plan->cta_text : null;
@endphp
@if($isFeatured)
{{ $popularBadge }}
@endif
{{ $plan->name }}
{{ $plan->description }}
/{{ $cycle }}
@if(($featuresView['type'] ?? 'legacy') === 'proscons')
{{ __('Features') }}
@foreach(($featuresView['pros'] ?? []) as $f)
@if(is_string($f) && trim($f) !== '')
-
{{ $f }}
@endif
@endforeach
@foreach(($featuresView['cons'] ?? []) as $f)
@if(is_string($f) && trim($f) !== '')
-
{{ $f }}
@endif
@endforeach
@else
@foreach(($featuresView['legacyItems'] ?? []) as $row)
-
@if(($row['status'] ?? true) === false)
@else
@endif
{{ $row['text'] ?? '' }}
@endforeach
@endif
@endforeach
@if(!$pricingForceShowAll)
@foreach($pricingPlansYearly as $plan)
@php
$isFeatured = ($plan->is_popular ?? false) === true;
if (!$isFeatured && $pricingPlansYearly->where('is_popular', true)->count() === 0) {
$isFeatured = ((int) $loop->index) === 1;
}
$cycle = $plan->billing_cycle === 'yearly' ? 'year' : 'month';
$quota = $plan->customerGroup?->limit('sending_quota.monthly_quota', 0);
$maxSubscribers = $plan->customerGroup?->limit('lists.limits.max_subscribers', 0);
$maxCampaigns = $plan->customerGroup?->limit('campaigns.limits.max_campaigns', 0);
$quotaLabel = $quota !== null ? number_format((float) $quota) : '—';
$subsLabel = $maxSubscribers !== null ? number_format((int) $maxSubscribers) : '—';
$campaignsLabel = $maxCampaigns !== null ? number_format((int) $maxCampaigns) : '—';
$featuresView = [
'type' => 'legacy',
'pros' => [],
'cons' => [],
'legacyItems' => [],
];
$planFeatures = $plan->features ?? null;
if (is_array($planFeatures) && (array_key_exists('pros', $planFeatures) || array_key_exists('cons', $planFeatures))) {
$featuresView['type'] = 'proscons';
$featuresView['pros'] = is_array($planFeatures['pros'] ?? null) ? $planFeatures['pros'] : [];
$featuresView['cons'] = is_array($planFeatures['cons'] ?? null) ? $planFeatures['cons'] : [];
} elseif (is_array($planFeatures) && count($planFeatures) > 0) {
$featuresView['type'] = 'proscons';
$featuresView['pros'] = $planFeatures;
$featuresView['cons'] = [];
} else {
$features = $plan->customerGroup?->displayAccessAndLimits() ?? [];
foreach ($features as $row) {
if (!is_array($row)) {
continue;
}
$label = is_string($row['label'] ?? null) ? (string) $row['label'] : '';
$value = is_string($row['value'] ?? null) ? (string) $row['value'] : '';
$text = trim($label) !== '' ? trim($label) . ': ' . $value : $value;
$text = trim($text);
if ($text === '') {
continue;
}
$featuresView['legacyItems'][] = [
'status' => ($row['status'] ?? true) !== false,
'text' => $text,
];
}
}
$planCta = is_string($plan->cta_text ?? null) && trim((string) $plan->cta_text) !== '' ? (string) $plan->cta_text : null;
@endphp
@if($isFeatured)
{{ $popularBadge }}
@endif
{{ $plan->name }}
{{ $plan->description }}
/{{ $cycle }}
@if(($featuresView['type'] ?? 'legacy') === 'proscons')
{{ __('Features') }}
@foreach(($featuresView['pros'] ?? []) as $f)
@if(is_string($f) && trim($f) !== '')
-
{{ $f }}
@endif
@endforeach
@foreach(($featuresView['cons'] ?? []) as $f)
@if(is_string($f) && trim($f) !== '')
-
{{ $f }}
@endif
@endforeach
@else
@foreach(($featuresView['legacyItems'] ?? []) as $row)
-
@if(($row['status'] ?? true) === false)
@else
@endif
{{ $row['text'] ?? '' }}
@endforeach
@endif
@endforeach
@endif
@foreach($faqRows as $row)
@php
$q = is_array($row) && is_string($row['q'] ?? null) ? (string) $row['q'] : '';
$a = is_array($row) && is_string($row['a'] ?? null) ? (string) $row['a'] : '';
@endphp
@if(trim($q) !== '' || trim($a) !== '')
@if(trim($q) !== '')
{{ $q }}
@endif
@if(trim($a) !== '')
{{ $a }}
@endif
@endif
@endforeach
@endsection