aziros/src/resources/views/livewire/checkout/index.blade.php

376 lines
22 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<div class="max-w-5xl mx-auto space-y-6">
{{-- HEADER --}}
<div class="flex items-center gap-3">
<a href="{{ route('subscription.index') }}"
class="w-8 h-8 rounded-lg border border-gray-200 flex items-center justify-center text-gray-400 hover:text-gray-600 hover:bg-gray-50 transition-colors">
<x-heroicon-o-arrow-left class="w-4 h-4"/>
</a>
<div>
@if($this->checkoutType === 'cancel')
<h1 class="text-xl font-semibold text-gray-800">{{ t('checkout.switch_free') }}</h1>
<p class="text-sm text-gray-400">{{ t('checkout.cancel_immediately') }}</p>
@elseif($this->checkoutType === 'update')
<h1 class="text-xl font-semibold text-gray-800">{{ t('checkout.change_plan') }}</h1>
<p class="text-sm text-gray-400">{{ t('checkout.switch_to') }} <span class="font-medium text-gray-600">{{ $plan->name }}</span> {{ t('checkout.prorated') }}</p>
@else
<h1 class="text-xl font-semibold text-gray-800">{{ t('checkout.title') }}</h1>
<p class="text-sm text-gray-400">{{ t('checkout.switch_to') }} <span class="font-medium text-gray-600">{{ $plan->name }}</span></p>
@endif
</div>
</div>
<div class="grid lg:grid-cols-[1fr_380px] gap-6 items-start">
{{-- ============================================================
LEFT ORDER SUMMARY
============================================================ --}}
<div class="space-y-5">
{{-- BILLING TOGGLE (nur bei paid plans) --}}
@if($this->checkoutType !== 'cancel')
<div class="bg-white border border-gray-100 rounded-2xl shadow-sm p-5 space-y-4">
<div class="text-sm font-semibold text-gray-700">{{ t('checkout.billing_period') }}</div>
<div class="grid grid-cols-2 gap-3">
{{-- Monthly --}}
<button wire:click="$set('billing', 'monthly')"
class="relative flex flex-col p-4 rounded-xl border-2 text-left transition-all
{{ $billing === 'monthly'
? 'border-indigo-500 bg-indigo-50'
: 'border-gray-200 hover:border-gray-300 bg-white' }}">
<div class="text-sm font-semibold {{ $billing === 'monthly' ? 'text-indigo-700' : 'text-gray-700' }}">
{{ t('checkout.monthly') }}
</div>
<div class="text-lg font-bold mt-1 {{ $billing === 'monthly' ? 'text-indigo-600' : 'text-gray-900' }}">
{{ number_format($this->monthlyPrice() / 100, 2, ',', '.') }}
</div>
<div class="text-xs {{ $billing === 'monthly' ? 'text-indigo-400' : 'text-gray-400' }} mt-0.5">
{{ t('checkout.per_month') }}
</div>
@if($billing === 'monthly')
<div class="absolute top-3 right-3 w-5 h-5 rounded-full bg-indigo-500 flex items-center justify-center">
<x-heroicon-o-check class="w-3 h-3 text-white"/>
</div>
@endif
</button>
{{-- Yearly --}}
<button wire:click="$set('billing', 'yearly')"
class="relative flex flex-col p-4 rounded-xl border-2 text-left transition-all
{{ $billing === 'yearly'
? 'border-indigo-500 bg-indigo-50'
: 'border-gray-200 hover:border-gray-300 bg-white' }}">
@if($plan->yearly_discount_months > 0)
<div class="absolute top-3 right-3">
@if($billing !== 'yearly')
<span class="text-[10px] font-bold px-1.5 py-0.5 rounded-md bg-green-100 text-green-700">
{{ $plan->yearly_discount_months }} {{ t('checkout.months_free') }}
</span>
@else
<div class="w-5 h-5 rounded-full bg-indigo-500 flex items-center justify-center">
<x-heroicon-o-check class="w-3 h-3 text-white"/>
</div>
@endif
</div>
@endif
<div class="text-sm font-semibold {{ $billing === 'yearly' ? 'text-indigo-700' : 'text-gray-700' }}">
{{ t('checkout.yearly') }}
</div>
<div class="text-lg font-bold mt-1 {{ $billing === 'yearly' ? 'text-indigo-600' : 'text-gray-900' }}">
{{ number_format(($this->yearlyPrice() / 100) / 12, 2, ',', '.') }}
</div>
<div class="text-xs {{ $billing === 'yearly' ? 'text-indigo-400' : 'text-gray-400' }} mt-0.5">
{{ t('checkout.per_month_yearly') }}
</div>
</button>
</div>
@if($billing === 'yearly' && $this->savings() > 0)
<div class="flex items-center gap-2 bg-green-50 border border-green-100 rounded-xl px-3 py-2">
<x-heroicon-o-tag class="w-4 h-4 text-green-500 shrink-0"/>
<span class="text-sm text-green-700">
{{ t('checkout.save_comparison', ['amount' => number_format($this->savings() / 100, 2, ',', '.') . ' €']) }}
</span>
</div>
@endif
</div>
@endif {{-- end billing toggle --}}
{{-- FEATURES --}}
<div class="bg-white border border-gray-100 rounded-2xl shadow-sm p-5">
<div class="text-sm font-semibold text-gray-700 mb-4">{{ t('checkout.included', ['plan' => $plan->name]) }}</div>
@if($features->isEmpty())
<p class="text-sm text-gray-400">{{ t('checkout.all_features') }}</p>
@else
<div class="grid sm:grid-cols-2 gap-2">
@foreach($features as $feature)
<div class="flex items-center gap-2.5">
<div class="w-5 h-5 rounded-full bg-green-50 flex items-center justify-center shrink-0">
<x-heroicon-o-check class="w-3 h-3 text-green-500"/>
</div>
<span class="text-sm text-gray-600">{{ $feature->label }}</span>
</div>
@endforeach
</div>
@endif
@if($plan->credit_limit)
<div class="mt-4 pt-4 border-t border-gray-50 flex items-center gap-2">
<x-heroicon-o-bolt class="w-4 h-4 text-indigo-400"/>
<span class="text-sm text-gray-600">
<span class="font-semibold text-gray-800">{{ number_format($plan->credit_limit) }}</span>
{{ t('checkout.credits_month') }}
</span>
</div>
@endif
</div>
{{-- TRUST SIGNALS --}}
<div class="bg-white border border-gray-100 rounded-2xl shadow-sm p-5">
<div class="grid sm:grid-cols-3 gap-4">
@foreach([
['icon' => 'shield-check', 'title' => t('checkout.secure_payment'), 'desc' => t('checkout.ssl_stripe')],
['icon' => 'arrow-uturn-left', 'title' => t('checkout.cancel_anytime'), 'desc' => t('checkout.no_minimum')],
['icon' => 'lock-closed', 'title' => t('checkout.gdpr'), 'desc' => t('checkout.eu_data')],
] as $trust)
<div class="flex items-start gap-3">
<div class="w-8 h-8 rounded-lg bg-gray-50 border border-gray-100 flex items-center justify-center shrink-0">
@if($trust['icon'] === 'shield-check') <x-heroicon-o-shield-check class="w-4 h-4 text-gray-500"/>
@elseif($trust['icon'] === 'arrow-uturn-left') <x-heroicon-o-arrow-uturn-left class="w-4 h-4 text-gray-500"/>
@else <x-heroicon-o-lock-closed class="w-4 h-4 text-gray-500"/>
@endif
</div>
<div>
<p class="text-xs font-semibold text-gray-700">{{ $trust['title'] }}</p>
<p class="text-[11px] text-gray-400 mt-0.5">{{ $trust['desc'] }}</p>
</div>
</div>
@endforeach
</div>
{{-- Stripe badge --}}
<div class="mt-4 pt-4 border-t border-gray-50 flex items-center gap-2 text-xs text-gray-400">
<svg class="h-4" viewBox="0 0 60 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.45 10.22c0-.76.62-1.05 1.65-1.05 1.48 0 3.35.45 4.83 1.25V6.17a12.83 12.83 0 0 0-4.83-.88C3.26 5.29 1 7.16 1 10.4c0 5.02 6.91 4.22 6.91 6.39 0 .9-.78 1.19-1.87 1.19-1.62 0-3.69-.67-5.33-1.57v4.3c1.82.78 3.65 1.11 5.33 1.11 4.06 0 6.85-2 6.85-5.28-.01-5.42-6.94-4.46-6.94-6.32zM21.1 2.38l-4.42.94-.01 14.52c0 2.68 2.01 4.66 4.69 4.66 1.48 0 2.56-.27 3.16-.6v-3.58c-.58.23-3.43 1.06-3.43-1.6V9.76h3.43V6.02H21.1V2.38zm9.19 4.43-4.55.97v14.7h4.55V6.81zm-4.55 4.64v10.06h4.55V11.45h-4.55zM30.74 4.3a2.65 2.65 0 1 0 0-5.3 2.65 2.65 0 0 0 0 5.3zm9.4 11.8L37.6 6.02h-4.97l5.56 16.46h3.87l5.6-16.46h-4.86l-2.66 10.08zm17.12-10.5c-1.48 0-2.43.7-2.97 1.17l-.2-1h-4.05v21.06l4.6-.97.01-5.1c.55.4 1.36.97 2.7.97 2.73 0 5.22-2.2 5.22-7.05-.01-4.44-2.52-7.08-5.31-7.08zm-.93 10.9c-.9 0-1.43-.32-1.8-.72l-.02-5.67c.4-.45.94-.75 1.82-.75 1.4 0 2.36 1.57 2.36 3.55 0 2.03-.94 3.59-2.36 3.59z" fill="#6772E5"/>
</svg>
{{ t('checkout.stripe_note') }}
</div>
</div>
</div>
{{-- ============================================================
RIGHT PRICE SUMMARY + PAY BUTTON
============================================================ --}}
<div class="space-y-4 lg:sticky lg:top-24">
{{-- Summary Card --}}
<div class="bg-white border border-gray-100 rounded-2xl shadow-sm overflow-hidden">
<div class="bg-indigo-600 px-5 py-4">
<div class="flex items-center justify-between">
<div>
<p class="text-indigo-200 text-xs font-medium">Plan</p>
<p class="text-white font-bold text-lg">{{ $plan->name }}</p>
</div>
<div class="text-right">
<p class="text-indigo-200 text-xs font-medium">{{ t('checkout.total') }}</p>
<p class="text-white font-bold text-2xl tabular-nums">
{{ number_format($this->activePrice() / 100, 2, ',', '.') }}
</p>
<p class="text-indigo-200 text-[10px]">
/ {{ $billing === 'yearly' ? t('common.year') : t('common.month') }}
</p>
</div>
</div>
</div>
<div class="px-5 py-4 space-y-3">
{{-- Line items --}}
<div class="space-y-2 text-sm">
<div class="flex justify-between text-gray-600">
<span>{{ $plan->name }} {{ $billing === 'yearly' ? t('checkout.yearly') : t('checkout.monthly') }}</span>
<span class="font-medium text-gray-800 tabular-nums">
{{ number_format($this->activePrice() / 100, 2, ',', '.') }}
</span>
</div>
@if($billing === 'yearly' && $this->savings() > 0)
<div class="flex justify-between text-green-600">
<span>{{ t('checkout.yearly_discount') }}</span>
<span class="font-medium tabular-nums">
{{ number_format($this->savings() / 100, 2, ',', '.') }}
</span>
</div>
@endif
<div class="border-t border-gray-100 pt-2 flex justify-between font-semibold text-gray-800">
<span>{{ t('checkout.total_incl_vat') }}</span>
<span class="tabular-nums">{{ number_format($this->activePrice() / 100, 2, ',', '.') }} </span>
</div>
</div>
{{-- Renewal info --}}
<div class="bg-gray-50 rounded-xl px-3 py-2 text-xs text-gray-500">
<x-heroicon-o-arrow-path class="w-3.5 h-3.5 inline-block mr-1 text-gray-400"/>
{{ t('checkout.auto_renew', ['period' => $billing === 'yearly' ? t('checkout.period.12months') : t('checkout.period.30days')]) }}
{{ t('checkout.cancel_anytime') }}
</div>
{{-- Info-Hinweis je nach Typ --}}
@if($this->checkoutType === 'cancel')
<div class="bg-amber-50 border border-amber-100 rounded-xl px-3 py-2.5 text-xs text-amber-700 space-y-1">
<div class="font-semibold flex items-center gap-1.5">
<x-heroicon-o-exclamation-triangle class="w-3.5 h-3.5"/>
{{ t('checkout.cancel_immediate') }}
</div>
<p>{{ t('checkout.cancel_desc') }}</p>
</div>
@elseif($this->checkoutType === 'update')
<div class="bg-indigo-50 border border-indigo-100 rounded-xl px-3 py-2.5 text-xs text-indigo-700 space-y-1">
<div class="font-semibold flex items-center gap-1.5">
<x-heroicon-o-bolt class="w-3.5 h-3.5"/>
{{ t('checkout.switch_immediate') }}
</div>
<p>{{ t('checkout.switch_desc') }}</p>
</div>
@endif
{{-- Widerrufsrecht-Checkboxen (nur bei paid plans) --}}
@if($this->checkoutType !== 'cancel')
<div class="space-y-3 border border-amber-100 bg-amber-50 rounded-xl p-4">
<div class="flex items-start gap-2.5">
<x-heroicon-o-information-circle class="w-4 h-4 text-amber-500 shrink-0 mt-0.5"/>
<p class="text-[11px] text-amber-700 font-medium leading-relaxed">
{{ t('checkout.waiver_info') }}
</p>
</div>
<label class="flex items-start gap-3 cursor-pointer group">
<input
type="checkbox"
wire:model.live="rightAcknowledged"
class="mt-0.5 rounded border-amber-300 text-amber-500 focus:ring-amber-400 shrink-0"
/>
<span class="text-[11px] text-amber-800 leading-relaxed">
{{ t('checkout.waiver_right_acknowledged') }}
</span>
</label>
<label class="flex items-start gap-3 cursor-pointer group">
<input
type="checkbox"
wire:model.live="waiverConfirmed"
class="mt-0.5 rounded border-amber-300 text-amber-500 focus:ring-amber-400 shrink-0"
/>
<span class="text-[11px] text-amber-800 leading-relaxed">
{{ t('checkout.waiver_confirmed') }}
</span>
</label>
</div>
@endif
{{-- CTA --}}
@if($this->checkoutType === 'cancel')
<button
wire:click="startCheckout"
wire:loading.attr="disabled"
class="w-full flex items-center justify-center gap-2 px-5 py-3.5 rounded-xl bg-amber-500 text-white font-semibold hover:bg-amber-600 active:scale-95 transition-all shadow-sm disabled:opacity-60">
<span wire:loading.remove wire:target="startCheckout">
<x-heroicon-o-x-circle class="w-4 h-4 inline-block mr-1 opacity-70"/>
{{ t('checkout.cancel_btn') }}
</span>
<span wire:loading wire:target="startCheckout" class="flex items-center gap-2">
<svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
</svg>
{{ t('checkout.cancelling') }}
</span>
</button>
@elseif($this->checkoutType === 'update')
<button
wire:click="startCheckout"
wire:loading.attr="disabled"
:disabled="!$wire.rightAcknowledged || !$wire.waiverConfirmed"
class="w-full flex items-center justify-center gap-2 px-5 py-3.5 rounded-xl bg-indigo-600 text-white font-semibold hover:bg-indigo-700 active:scale-95 transition-all shadow-sm shadow-indigo-200 disabled:opacity-60">
<span wire:loading.remove wire:target="startCheckout">
<x-heroicon-o-arrow-path class="w-4 h-4 inline-block mr-1 opacity-70"/>
{{ t('checkout.switch_btn', ['plan' => $plan->name]) }}
</span>
<span wire:loading wire:target="startCheckout" class="flex items-center gap-2">
<svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
</svg>
{{ t('checkout.switching') }}
</span>
</button>
@else
<button
wire:click="startCheckout"
wire:loading.attr="disabled"
:disabled="!$wire.rightAcknowledged || !$wire.waiverConfirmed"
class="w-full flex items-center justify-center gap-2 px-5 py-3.5 rounded-xl bg-indigo-600 text-white font-semibold hover:bg-indigo-700 active:scale-95 transition-all shadow-sm shadow-indigo-200 disabled:opacity-60">
<span wire:loading.remove wire:target="startCheckout">
<x-heroicon-o-lock-closed class="w-4 h-4 inline-block mr-1 opacity-70"/>
{{ t('checkout.pay_now') }}
</span>
<span wire:loading wire:target="startCheckout" class="flex items-center gap-2">
<svg class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/>
</svg>
{{ t('checkout.redirecting') }}
</span>
</button>
@endif
<p class="text-[11px] text-center text-gray-400">
@if($this->checkoutType === 'new')
{{ t('checkout.redirect_stripe') }}
@elseif($this->checkoutType === 'update')
{{ t('checkout.no_checkout') }}
@else
{{ t('checkout.cancel_effective') }}
@endif
</p>
</div>
</div>
{{-- Current user info --}}
<div class="bg-white border border-gray-100 rounded-xl shadow-sm px-4 py-3 flex items-center gap-3">
<div class="w-8 h-8 rounded-full bg-indigo-100 flex items-center justify-center text-indigo-600 font-bold text-sm shrink-0">
{{ strtoupper(substr(auth()->user()->name, 0, 1)) }}
</div>
<div class="min-w-0">
<p class="text-sm font-medium text-gray-800 truncate">{{ auth()->user()->name }}</p>
<p class="text-xs text-gray-400 truncate">{{ auth()->user()->email }}</p>
</div>
</div>
</div>
</div>
</div>