{{-- Partner Billing Page — Plan Overview & Subscription Management Adapts to manual (plan info + limits) and Stripe (+ status + portal) modes. --}} @extends('partner.layouts.default') @section('page_title', trans('common.billing_my_plan') . config('default.page_title_delimiter') . config('default.app_name')) @section('content') @php $entitlements = app(\App\Services\EntitlementService::class); $currentPlanKey = $summary['plan']['key']; $status = $summary['status']; $isRestricted = $summary['is_restricted']; // Status display config $statusConfig = match($status) { 'active' => ['label' => trans('common.billing_status_active'), 'color' => 'emerald', 'icon' => 'check-circle'], 'trialing' => ['label' => trans('common.billing_status_trialing'), 'color' => 'blue', 'icon' => 'clock'], 'past_due' => ['label' => trans('common.billing_status_past_due'), 'color' => 'amber', 'icon' => 'alert-triangle'], 'cancelled' => ['label' => trans('common.billing_status_cancelled'), 'color' => 'red', 'icon' => 'x-circle'], 'incomplete' => ['label' => trans('common.billing_status_incomplete'), 'color' => 'amber', 'icon' => 'alert-circle'], 'suspended' => ['label' => trans('common.billing_status_suspended'), 'color' => 'red', 'icon' => 'ban'], 'legacy' => ['label' => trans('common.billing_status_legacy'), 'color' => 'secondary', 'icon' => 'shield'], default => ['label' => trans('common.billing_status_manual'), 'color' => 'secondary', 'icon' => 'wallet'], }; @endphp
{{-- Header --}}

{{ trans('common.billing_my_plan') }}

{{ trans('common.billing_page_subtitle') }}

@if($billingEnabled && $portalUrl) {{ trans('common.billing_manage_billing') }} @endif
{{-- Status Banner (restricted states only) --}} @if($isRestricted)
@php $bannerColor = in_array($status, ['past_due', 'incomplete']) ? 'amber' : 'red'; $bannerMessage = match($status) { 'past_due' => trans('common.billing_past_due_notice'), 'cancelled' => trans('common.billing_cancelled_notice'), 'incomplete' => trans('common.billing_incomplete_notice'), 'suspended' => trans('common.billing_suspended_notice'), default => '', }; @endphp

{{ $statusConfig['label'] }}

{{ $bannerMessage }}

@if($portalUrl) {{ trans('common.billing_update_payment') }} @endif
@endif {{-- Trial Banner --}} @if($status === 'trialing')

{{ trans('common.billing_status_trialing') }}

{{ trans('common.billing_trial_notice') }}

@endif {{-- Plan Card --}}

{{ $summary['plan']['name'] }}

@if($billingEnabled) $statusConfig['color'] === 'emerald', 'bg-blue-100 dark:bg-blue-500/15 text-blue-700 dark:text-blue-400' => $statusConfig['color'] === 'blue', 'bg-amber-100 dark:bg-amber-500/15 text-amber-700 dark:text-amber-400' => $statusConfig['color'] === 'amber', 'bg-red-100 dark:bg-red-500/15 text-red-700 dark:text-red-400' => $statusConfig['color'] === 'red', 'bg-secondary-100 dark:bg-secondary-800 text-secondary-600 dark:text-secondary-400' => $statusConfig['color'] === 'secondary', ])> {{ $statusConfig['label'] }} @endif
@if($summary['plan']['description'])

{{ $summary['plan']['description'] }}

@endif
@if(!$billingEnabled)
{{ trans('common.billing_manual_mode') }}
@endif
{{-- Features --}}

{{ trans('common.billing_plan_features') }}

@foreach($summary['features'] as $featureKey => $enabled) @php $featureNames = [ 'loyalty_cards' => trans('common.loyalty_cards'), 'stamp_cards' => trans('common.stamp_cards'), 'vouchers' => trans('common.vouchers'), 'voucher_batches' => trans('common.batches'), 'email_campaigns' => trans('common.email_campaigns'), 'activity_log' => trans('common.activity_logs'), 'agent_api' => trans('agent.agent_keys'), ]; $featureIcons = [ 'loyalty_cards' => 'credit-card', 'stamp_cards' => 'stamp', 'vouchers' => 'ticket', 'voucher_batches' => 'layers', 'email_campaigns' => 'mail', 'activity_log' => 'activity', 'agent_api' => 'bot', ]; @endphp
$enabled, 'bg-secondary-100 dark:bg-secondary-800' => !$enabled, ])> $enabled, 'text-secondary-400 dark:text-secondary-600' => !$enabled, ]) />
$enabled, 'text-secondary-400 dark:text-secondary-600 line-through' => !$enabled, ])> {{ $featureNames[$featureKey] ?? $featureKey }} @if($enabled) @else @endif
@endforeach
{{-- Resource Usage --}} @php $activeLimits = collect($summary['limits'])->filter(fn($data) => !$data['unlimited']); $limitLabels = [ 'cards' => trans('common.loyalty_cards'), 'stamp_cards' => trans('common.stamp_cards'), 'vouchers' => trans('common.vouchers'), 'staff' => trans('common.staff_members'), 'rewards' => trans('common.rewards'), 'clubs' => trans('common.clubs'), 'agent_keys' => trans('agent.agent_keys'), ]; $limitIcons = [ 'cards' => 'credit-card', 'stamp_cards' => 'stamp', 'vouchers' => 'ticket', 'staff' => 'briefcase', 'rewards' => 'gift', 'clubs' => 'layers', 'agent_keys' => 'bot', ]; $limitColors = [ 'cards' => 'primary', 'stamp_cards' => 'emerald', 'vouchers' => 'purple', 'staff' => 'amber', 'rewards' => 'pink', 'clubs' => 'blue', 'agent_keys' => 'violet', ]; @endphp @if($activeLimits->isNotEmpty())

{{ trans('common.billing_resource_usage') }}

@foreach($activeLimits as $key => $data) @php $percentage = $data['limit'] > 0 ? min(100, round(($data['usage'] / $data['limit']) * 100)) : 0; $isAtLimit = $data['exceeded']; $colorKey = $limitColors[$key] ?? 'primary'; $barColor = $isAtLimit ? 'bg-red-500' : match($colorKey) { 'emerald' => 'bg-emerald-500', 'purple' => 'bg-purple-500', 'pink' => 'bg-pink-500', 'amber' => 'bg-amber-500', 'blue' => 'bg-blue-500', 'violet' => 'bg-violet-500', default => 'bg-primary-500', }; @endphp
{{ $limitLabels[$key] ?? $key }}
{{ $data['usage'] }} / {{ $data['limit'] }}
@if($isAtLimit)

{{ trans('common.billing_limit_reached') }}

@endif
@endforeach
@endif {{-- Unlimited Resources --}} @php $unlimitedLimits = collect($summary['limits'])->filter(fn($data) => $data['unlimited']); @endphp @if($unlimitedLimits->isNotEmpty())

{{ trans('common.billing_unlimited') }}

@foreach($unlimitedLimits as $key => $data)
{{ $limitLabels[$key] ?? $key }} ∞
@endforeach
@endif {{-- Available Plans (Stripe mode only) --}} @if($billingEnabled && $billingConfigured && $plans->count() > 1)

{{ trans('common.billing_available_plans') }}

{{-- Interval toggle --}} @php $hasYearlyPrices = $plans->contains(fn($p) => ($p['price_yearly'] ?? 0) > 0); @endphp @if($hasYearlyPrices)
@endif
@foreach($plans as $planKey => $plan) @php $isCurrent = $planKey === $currentPlanKey; $planName = isset($plan['name_key']) ? trans($plan['name_key']) : ($plan['name'] ?? $planKey); $planDesc = isset($plan['description_key']) ? trans($plan['description_key']) : ($plan['description'] ?? ''); $isFree = ($plan['price_monthly'] ?? 0) === 0; $currentSortOrder = $plans[$currentPlanKey]['sort_order'] ?? 0; $planSortOrder = $plan['sort_order'] ?? 0; $isUpgrade = $planSortOrder > $currentSortOrder; $isPopular = $plan['is_popular'] ?? false; $priceMonthly = $plan['price_monthly'] ?? 0; $priceYearly = $plan['price_yearly'] ?? 0; $planCurrency = $plan['currency'] ?? 'USD'; // Calculate monthly-equivalent for yearly and savings percentage $yearlyPerMonth = $priceYearly > 0 ? (int) round($priceYearly / 12) : 0; $yearlySavingsPercent = ($priceMonthly > 0 && $priceYearly > 0) ? (int) round((1 - ($priceYearly / ($priceMonthly * 12))) * 100) : 0; @endphp
$isCurrent, // Popular (non-current) — elevated with shadow 'bg-white dark:bg-secondary-900 border-secondary-200 dark:border-secondary-700/60 shadow-sm hover:shadow-md hover:border-secondary-300 dark:hover:border-secondary-600' => !$isCurrent && $isPopular, // Default — clean and minimal 'bg-white dark:bg-secondary-900 border-secondary-200 dark:border-secondary-800 hover:border-secondary-300 dark:hover:border-secondary-700' => !$isCurrent && !$isPopular, ])> {{-- Badges --}}

{{ $planName }}

@if($isCurrent) {{ trans('common.billing_current') }} @endif @if($isPopular) {{ trans('common.popular') }} @endif
{{-- Description --}} @if($planDesc)

{{ $planDesc }}

@endif {{-- Price — switches between monthly and yearly --}}
@if(!$isFree) {{-- Monthly price --}}

{!! moneyStyled($priceMonthly, $planCurrency) !!}/{{ trans('common.month') }}

{{-- Yearly price --}} @if($priceYearly > 0)

{!! moneyStyled($yearlyPerMonth, $planCurrency) !!}/{{ trans('common.month') }}

{!! moneyStyled($priceYearly, $planCurrency) !!}/{{ trans('common.year') }} @if($yearlySavingsPercent > 0) {{ trans('common.billing_save_percent', ['percent' => $yearlySavingsPercent]) }} @endif

@endif @else

{{ trans('common.free') }}

@endif
{{-- Action button (only when partner can self-service) --}} @if(!$isCurrent && $canUpgrade) @if($hasSubscription) {{-- Existing subscriber: Stripe portal handles both upgrade and downgrade --}}
@csrf
@elseif($isUpgrade) {{-- New subscriber: checkout for higher tiers only --}}
@csrf
@endif @endif
@endforeach
@if(!$canUpgrade)

{{ trans('common.billing_contact_admin') }}

@endif
@endif {{-- Manual Mode Footer --}} @if(!$billingEnabled)

{{ trans('common.billing_manual_mode') }}

{{ trans('common.billing_manual_description') }}

@endif
@stop