CluPilotCloud/resources/views/livewire/billing.blade.php

128 lines
7.9 KiB
PHP

<?php use Illuminate\Support\Number; ?>
<div class="space-y-6" x-data="{ msgs: @js(['purchased' => __('billing.purchased')]) }">
@php $loc = app()->getLocale(); $eur = fn ($c) => Number::currency($c / 100, in: 'EUR', locale: $loc); @endphp
<div class="animate-rise">
<h1 class="text-2xl font-semibold tracking-tight text-ink">{{ __('billing.title') }}</h1>
<p class="mt-1 text-sm text-muted">{{ __('billing.subtitle') }}</p>
</div>
{{-- Current plan --}}
<div class="overflow-hidden rounded-xl border border-line bg-surface shadow-xs animate-rise [animation-delay:60ms]">
<div class="flex flex-wrap items-center justify-between gap-4 border-b border-line bg-surface-2 px-6 py-4">
<div>
<p class="text-xs font-semibold uppercase tracking-wider text-faint">{{ __('billing.current_plan') }}</p>
<p class="mt-0.5 text-lg font-semibold text-ink">{{ __('billing.plan.'.$currentKey) }}</p>
</div>
<div class="text-right">
<p class="text-2xl font-semibold text-ink">{{ $eur($current['price_cents'] ?? 0) }}</p>
<p class="text-xs text-muted">{{ __('billing.per_month') }}</p>
</div>
</div>
<div class="grid grid-cols-2 gap-px bg-line sm:grid-cols-4">
@foreach ([
['billing.storage', ($current['quota_gb'] ?? 0).' GB'],
['billing.seats', $current['seats'] ?? '—'],
['billing.performance', __('billing.perf.'.($current['performance'] ?? 'standard'))],
['billing.status', __('billing.status_active')],
] as [$label, $value])
<div class="bg-surface px-6 py-4">
<p class="text-xs text-muted">{{ __($label) }}</p>
<p class="mt-0.5 font-semibold text-ink">{{ $value }}</p>
</div>
@endforeach
</div>
</div>
@if ($pending->isNotEmpty())
<div class="flex items-start gap-3 rounded-xl border border-info-border bg-info-bg p-4 animate-rise">
<x-ui.icon name="bell" class="size-5 shrink-0 text-info" />
<p class="text-sm text-body">{{ __('billing.pending_note', ['count' => $pending->count()]) }}</p>
</div>
@endif
{{-- Upgrades --}}
@if (count($upgrades) > 0)
<div class="animate-rise [animation-delay:120ms]">
<h2 class="mb-3 font-semibold text-ink">{{ __('billing.upgrade_title') }}</h2>
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
@foreach ($upgrades as $key)
@php $p = $plans[$key]; @endphp
<div wire:key="upgrade-{{ $key }}" class="flex flex-col rounded-xl border border-line bg-surface p-5 shadow-xs transition hover:border-accent-border">
<div class="flex items-baseline justify-between">
<p class="font-semibold text-ink">{{ __('billing.plan.'.$key) }}</p>
<span class="rounded-pill bg-accent-subtle px-2 py-0.5 text-xs font-semibold text-accent-text">{{ __('billing.perf.'.($p['performance'] ?? 'standard')) }}</span>
</div>
<p class="mt-1 text-sm text-muted">{{ $p['quota_gb'] }} GB · {{ __('billing.seats_count', ['count' => $p['seats'] ?? 0]) }}</p>
<ul class="mt-3 space-y-1.5">
@foreach (array_slice($features[$key] ?? [], 0, 4) as $f)
<li class="flex items-center gap-2 text-sm text-body">
<x-ui.icon name="check" class="size-4 shrink-0 text-success-bright" />
{{ __('billing.feature.'.$f) }}
</li>
@endforeach
</ul>
<p class="mt-4 text-xl font-semibold text-ink">{{ $eur($p['price_cents']) }}<span class="text-sm font-normal text-muted"> / {{ __('billing.month_short') }}</span></p>
<x-ui.button variant="primary" size="sm" class="mt-4 w-full" wire:click="purchase('upgrade', '{{ $key }}')" wire:target="purchase('upgrade', '{{ $key }}')" wire:loading.attr="disabled">
{{ __('billing.upgrade_cta') }}
</x-ui.button>
</div>
@endforeach
</div>
</div>
@endif
{{-- Extra storage + Add-ons --}}
<div class="grid grid-cols-1 gap-4 lg:grid-cols-3 xl:grid-cols-4 animate-rise [animation-delay:180ms]">
{{-- Storage --}}
<div class="flex flex-col rounded-xl border border-accent-border bg-accent-subtle p-5">
<div class="flex items-center gap-2">
<x-ui.icon name="database" class="size-5 text-accent-active" />
<p class="font-semibold text-ink">{{ __('billing.storage_title') }}</p>
</div>
<p class="mt-2 text-sm text-body">{{ __('billing.storage_body', ['gb' => $storage['gb'], 'price' => $eur($storage['price_cents'])]) }}</p>
<x-ui.button variant="primary" size="sm" class="mt-4 w-full" wire:click="purchase('storage')" wire:target="purchase('storage')" wire:loading.attr="disabled">
{{ __('billing.storage_cta', ['gb' => $storage['gb']]) }}
</x-ui.button>
</div>
{{-- Traffic --}}
<div class="flex flex-col rounded-xl border {{ $trafficMeter && $trafficMeter->state() !== 'ok' ? 'border-warning-border bg-warning-bg' : 'border-line bg-surface shadow-xs' }} p-5">
<div class="flex items-center gap-2">
<x-ui.icon name="activity" class="size-5 {{ $trafficMeter && $trafficMeter->state() !== 'ok' ? 'text-warning' : 'text-muted' }}" />
<p class="font-semibold text-ink">{{ __('billing.traffic_title') }}</p>
</div>
<p class="mt-2 text-sm text-body">{{ __('billing.traffic_body', ['gb' => $trafficAddon['gb'], 'price' => $eur($trafficAddon['price_cents'])]) }}</p>
@if ($trafficMeter)
<p class="mt-2 font-mono text-xs text-muted">
{{ __('billing.traffic_used', [
'used' => \App\Support\Bytes::human($trafficMeter->usedBytes),
'quota' => \App\Support\Bytes::human($trafficMeter->quotaBytes),
]) }}
</p>
@endif
<x-ui.button variant="{{ $trafficMeter && $trafficMeter->state() !== 'ok' ? 'primary' : 'secondary' }}" size="sm" class="mt-4 w-full"
wire:click="purchase('traffic')" wire:target="purchase('traffic')" wire:loading.attr="disabled">
{{ __('billing.traffic_cta', ['gb' => $trafficAddon['gb']]) }}
</x-ui.button>
</div>
{{-- Add-ons --}}
@foreach ($addons as $key => $addon)
<div wire:key="addon-{{ $key }}" class="flex flex-col rounded-xl border border-line bg-surface p-5 shadow-xs">
<div class="flex items-center gap-2">
<x-ui.icon name="box" class="size-5 text-muted" />
<p class="font-semibold text-ink">{{ __('billing.addon.'.$key.'.name') }}</p>
</div>
<p class="mt-2 flex-1 text-sm text-muted">{{ __('billing.addon.'.$key.'.desc') }}</p>
<p class="mt-3 text-lg font-semibold text-ink">{{ $eur($addon['price_cents']) }}<span class="text-sm font-normal text-muted"> / {{ __('billing.month_short') }}</span></p>
<x-ui.button variant="secondary" size="sm" class="mt-3 w-full" wire:click="purchase('addon', '{{ $key }}')" wire:target="purchase('addon', '{{ $key }}')" wire:loading.attr="disabled">
{{ __('billing.addon_cta') }}
</x-ui.button>
</div>
@endforeach
</div>
<p class="text-xs text-faint">{{ __('billing.mock_note') }}</p>
</div>