b2in/resources/views/livewire/admin/testing/registration-tester.blade.php
2026-01-23 17:33:10 +01:00

412 lines
20 KiB
PHP

<?php
use App\Models\RegistrationCode;
use Spatie\Permission\Models\Role;
use Livewire\Volt\Component;
use function Livewire\Volt\{layout, title};
layout('components.layouts.app');
title('Registrierung testen');
new class extends Component {
public array $roleOptions = [];
public string $selectedRole = 'broker';
public function mount(): void
{
$this->loadRoleOptions();
}
private function loadRoleOptions(): void
{
$roles = Role::whereNotNull('reg_prefix')->where('can_be_invited', true)->orderBy('id', 'asc')->get();
foreach ($roles as $role) {
$key = strtolower(str_replace('-', '', $role->name));
$slug = strtolower($role->reg_prefix);
$this->roleOptions[$key] = [
'label' => $role->display_name ?? $role->name,
'prefix' => $role->reg_prefix,
'slug' => $slug,
'color' => $role->color ?? 'zinc',
'icon' => $role->icon ?? 'key',
];
}
if (!empty($this->roleOptions)) {
$this->selectedRole = array_key_first($this->roleOptions);
}
}
public function with(): array
{
// Lade verfügbare Codes für ausgewählte Rolle
$availableCodes = RegistrationCode::where('role', $this->selectedRole)
->where('status', RegistrationCode::STATUS_AVAILABLE)
->orderBy('created_at', 'desc')
->take(10)
->get();
// Lade letzte verwendete Codes
$recentUsedCodes = RegistrationCode::where('status', RegistrationCode::STATUS_USED)
->with('usedBy')
->orderBy('used_at', 'desc')
->take(5)
->get();
return [
'roleOptions' => $this->roleOptions,
'availableCodes' => $availableCodes,
'recentUsedCodes' => $recentUsedCodes,
];
}
}; ?>
<div class="space-y-6 p-6">
{{-- Header --}}
<div class="flex items-center justify-between">
<div>
<flux:heading size="xl" class="mb-2">{{ __('Registrierung testen') }}</flux:heading>
<flux:subheading>{{ __('Teste den kompletten Registrierungsprozess mit echten Codes') }}</flux:subheading>
</div>
</div>
{{-- Info Box --}}
<flux:card class="bg-accent-50 dark:bg-accent-900/20 border-accent-200 dark:border-accent-800">
<div class="flex items-start gap-4">
<div class="flex-shrink-0">
<div class="h-12 w-12 rounded-lg bg-accent-100 dark:bg-accent-900/40 flex items-center justify-center">
@svg('heroicon-o-information-circle', 'h-6 w-6 text-accent-600 dark:text-accent-400')
</div>
</div>
<div>
<flux:heading size="md" class="mb-2">{{ __('Wie funktioniert das Testing?') }}</flux:heading>
<flux:subheading class="mb-3">
{{ __('Wähle eine Rolle aus, kopiere einen verfügbaren Code und teste den gesamten Prozess:') }}
</flux:subheading>
<ol class="list-decimal list-inside space-y-1 text-sm text-zinc-700 dark:text-zinc-300">
<li>{{ __('Code-Eingabe auf der Landing-Page') }}</li>
<li>{{ __('Account-Erstellung mit persönlichen Daten') }}</li>
<li>{{ __('Setup-Wizard für Partner-Profil') }}</li>
</ol>
</div>
</div>
</flux:card>
{{-- Rollen-Auswahl --}}
<flux:card class="shadow-elegant">
<div class="mb-6">
<flux:heading size="lg" class="mb-2">{{ __('Rolle wählen') }}</flux:heading>
<flux:subheading>{{ __('Wähle die Rolle, für die du den Registrierungsprozess testen möchtest') }}</flux:subheading>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
@foreach($roleOptions as $key => $meta)
<button
type="button"
wire:click="$set('selectedRole', '{{ $key }}')"
class="p-4 rounded-lg border-2 transition-all {{ $selectedRole === $key ? 'border-accent-500 bg-accent-50 dark:bg-accent-900/20' : 'border-zinc-200 dark:border-zinc-700 hover:border-zinc-300 dark:hover:border-zinc-600' }}"
>
<div class="flex flex-col items-center gap-2">
<div class="h-12 w-12 rounded-lg flex items-center justify-center {{ $selectedRole === $key ? 'bg-accent-100 dark:bg-accent-900/40' : 'bg-zinc-100 dark:bg-zinc-800' }}">
@svg('heroicon-o-'.$meta['icon'], 'h-6 w-6 ' . ($selectedRole === $key ? 'text-accent-600 dark:text-accent-400' : 'text-zinc-600 dark:text-zinc-400'))
</div>
<div class="text-center">
<div class="font-semibold text-sm">{{ $meta['label'] }}</div>
<div class="text-xs text-zinc-500">{{ __('Prefix:') }} {{ $meta['prefix'] }}</div>
</div>
</div>
</button>
@endforeach
</div>
</flux:card>
{{-- Landing Page Link --}}
@if($selectedRole && isset($roleOptions[$selectedRole]))
<flux:card class="shadow-elegant bg-gradient-to-r from-accent-50 to-blue-50 dark:from-accent-900/20 dark:to-blue-900/20">
<div class="flex items-center justify-between">
<div>
<flux:heading size="lg" class="mb-2">
@svg('heroicon-o-arrow-top-right-on-square', 'inline-block h-5 w-5')
{{ __('Landing-Page aufrufen') }}
</flux:heading>
<flux:subheading class="mb-4">
{{ __('Starte den Registrierungsprozess für :role', ['role' => $roleOptions[$selectedRole]['label']]) }}
</flux:subheading>
<div class="flex flex-wrap gap-3">
<flux:button
variant="primary"
icon="arrow-right"
href="{{ config('domains.domain_b2in_url') . route('registration.landing', ['role' => $roleOptions[$selectedRole]['slug']], false) }}"
target="_blank"
>
{{ __('B2In') }}
</flux:button>
@if($selectedRole === 'customer')
<flux:button
variant="primary"
icon="sparkles"
href="{{ config('domains.domain_style2own_url') . route('registration.landing', ['role' => $roleOptions[$selectedRole]['slug']], false) }}"
target="_blank"
>
{{ __('Style2Own') }}
</flux:button>
<flux:button
variant="primary"
icon="home-modern"
href="{{ config('domains.domain_stileigentum_url') . route('registration.landing', ['role' => $roleOptions[$selectedRole]['slug']], false) }}"
target="_blank"
>
{{ __('Stileigentum') }}
</flux:button>
@endif
</div>
@if($selectedRole === 'customer')
<div class="mt-3 text-xs text-zinc-600 dark:text-zinc-400">
<flux:icon.information-circle class="inline-block h-4 w-4" />
{{ __('Für Kunden stehen drei Landing-Page-Varianten zur Verfügung') }}
</div>
@endif
</div>
<div class="hidden md:block">
<div class="h-20 w-20 rounded-2xl bg-white dark:bg-zinc-800 flex items-center justify-center shadow-lg">
@svg('heroicon-o-'.$roleOptions[$selectedRole]['icon'], 'h-10 w-10 text-accent-600 dark:text-accent-400')
</div>
</div>
</div>
</flux:card>
@endif
{{-- Verfügbare Codes --}}
<flux:card class="shadow-elegant">
<div class="mb-6">
<flux:heading size="lg" class="mb-2">
@svg('heroicon-o-key', 'inline-block h-5 w-5')
{{ __('Verfügbare Codes für :role', ['role' => $roleOptions[$selectedRole]['label'] ?? 'diese Rolle']) }}
</flux:heading>
<flux:subheading>{{ __('Kopiere einen dieser Codes für deinen Test') }}</flux:subheading>
</div>
@if($availableCodes->isEmpty())
<div class="text-center py-8">
<flux:icon.exclamation-triangle class="mx-auto h-12 w-12 text-zinc-400" />
<flux:heading size="md" class="mt-4">{{ __('Keine verfügbaren Codes') }}</flux:heading>
<flux:subheading class="mt-2">
{{ __('Erstelle zuerst Codes in der Registrierungscode-Verwaltung') }}
</flux:subheading>
<div class="mt-4">
<flux:button
variant="primary"
icon="plus"
href="{{ route('admin.partners.registration-codes') }}"
wire:navigate
>
{{ __('Zur Code-Verwaltung') }}
</flux:button>
</div>
</div>
@else
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
@foreach($availableCodes as $code)
<div class="p-4 rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800/50 hover:shadow-md transition-shadow">
<div class="flex items-center justify-between mb-2">
<div class="font-mono text-xl font-bold text-zinc-900 dark:text-white">
{{ $code->code }}
</div>
<button
type="button"
onclick="navigator.clipboard.writeText('{{ $code->code }}');
alert('Code kopiert: {{ $code->code }}');"
class="p-2 rounded-lg bg-accent-100 dark:bg-accent-900/40 hover:bg-accent-200 dark:hover:bg-accent-900/60 transition-colors"
title="{{ __('Code kopieren') }}"
>
@svg('heroicon-o-clipboard-document', 'h-5 w-5 text-accent-600 dark:text-accent-400')
</button>
</div>
@if($code->name)
<div class="text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-1">
{{ $code->name }}
</div>
@endif
<div class="flex items-center gap-2 text-xs text-zinc-500 dark:text-zinc-400">
<flux:icon.calendar class="h-4 w-4" />
{{ __('Erstellt:') }} {{ $code->created_at->format('d.m.Y H:i') }}
</div>
@if($code->expires_at)
<div class="flex items-center gap-2 text-xs text-zinc-500 dark:text-zinc-400">
<flux:icon.clock class="h-4 w-4" />
{{ __('Gültig bis:') }} {{ $code->expires_at->format('d.m.Y') }}
</div>
@endif
</div>
@endforeach
</div>
@endif
</flux:card>
{{-- Test-Prozess Steps --}}
<flux:card class="shadow-elegant">
<div class="mb-6">
<flux:heading size="lg" class="mb-2">
@svg('heroicon-o-clipboard-document-check', 'inline-block h-5 w-5')
{{ __('Test-Prozess') }}
</flux:heading>
<flux:subheading>{{ __('Folge diesen Schritten für einen vollständigen Test') }}</flux:subheading>
</div>
<div class="space-y-4">
<div class="flex items-start gap-4 p-4 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800">
<div class="flex-shrink-0 h-8 w-8 rounded-full bg-blue-500 text-white flex items-center justify-center font-bold">
1
</div>
<div class="flex-1">
<div class="font-semibold text-zinc-900 dark:text-white mb-1">
{{ __('Code kopieren') }}
</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">
{{ __('Wähle einen verfügbaren Code aus der Liste oben und kopiere ihn') }}
</div>
</div>
</div>
<div class="flex items-start gap-4 p-4 rounded-lg bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800">
<div class="flex-shrink-0 h-8 w-8 rounded-full bg-green-500 text-white flex items-center justify-center font-bold">
2
</div>
<div class="flex-1">
<div class="font-semibold text-zinc-900 dark:text-white mb-1">
{{ __('Landing-Page öffnen') }}
</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400 mb-2">
{{ __('Öffne die Landing-Page in einem neuen Tab (Private/Inkognito-Modus empfohlen)') }}
</div>
<flux:button
size="sm"
variant="primary"
icon="arrow-top-right-on-square"
href="{{ route('registration.landing', ['role' => $roleOptions[$selectedRole]['slug'] ?? 'e']) }}"
target="_blank"
>
{{ __('Landing-Page öffnen') }}
</flux:button>
</div>
</div>
<div class="flex items-start gap-4 p-4 rounded-lg bg-purple-50 dark:bg-purple-900/20 border border-purple-200 dark:border-purple-800">
<div class="flex-shrink-0 h-8 w-8 rounded-full bg-purple-500 text-white flex items-center justify-center font-bold">
3
</div>
<div class="flex-1">
<div class="font-semibold text-zinc-900 dark:text-white mb-1">
{{ __('Code eingeben') }}
</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">
{{ __('Gib den kopierten Code auf der Landing-Page ein und klicke auf "Code prüfen"') }}
</div>
</div>
</div>
<div class="flex items-start gap-4 p-4 rounded-lg bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-800">
<div class="flex-shrink-0 h-8 w-8 rounded-full bg-orange-500 text-white flex items-center justify-center font-bold">
4
</div>
<div class="flex-1">
<div class="font-semibold text-zinc-900 dark:text-white mb-1">
{{ __('Account erstellen') }}
</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">
{{ __('Fülle das Registrierungsformular mit Test-Daten aus (verwende eine Test-Email)') }}
</div>
</div>
</div>
<div class="flex items-start gap-4 p-4 rounded-lg bg-teal-50 dark:bg-teal-900/20 border border-teal-200 dark:border-teal-800">
<div class="flex-shrink-0 h-8 w-8 rounded-full bg-teal-500 text-white flex items-center justify-center font-bold">
5
</div>
<div class="flex-1">
<div class="font-semibold text-zinc-900 dark:text-white mb-1">
{{ __('Setup-Wizard durchlaufen') }}
</div>
<div class="text-sm text-zinc-600 dark:text-zinc-400">
{{ __('Vervollständige das Partner-Profil im Setup-Wizard') }}
</div>
</div>
</div>
</div>
</flux:card>
{{-- Letzte verwendete Codes --}}
<flux:card class="shadow-elegant">
<div class="mb-6">
<flux:heading size="lg" class="mb-2">
@svg('heroicon-o-check-circle', 'inline-block h-5 w-5')
{{ __('Kürzlich getestete Codes') }}
</flux:heading>
<flux:subheading>{{ __('Diese Codes wurden bereits verwendet') }}</flux:subheading>
</div>
@if($recentUsedCodes->isEmpty())
<div class="text-center py-8 text-zinc-500 dark:text-zinc-400">
{{ __('Noch keine Codes verwendet') }}
</div>
@else
<div class="space-y-3">
@foreach($recentUsedCodes as $code)
<div class="flex items-center justify-between p-4 rounded-lg border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800/50">
<div class="flex items-center gap-4">
<div class="font-mono font-semibold text-zinc-900 dark:text-white">
{{ $code->code }}
</div>
<flux:badge size="sm" color="zinc">
{{ $roleOptions[$code->role]['label'] ?? $code->role }}
</flux:badge>
</div>
<div class="text-sm text-zinc-500 dark:text-zinc-400">
@if($code->usedBy)
<div class="flex items-center gap-2">
<flux:icon.user class="h-4 w-4" />
{{ $code->usedBy->name }}
@if($code->used_at)
<span class="text-xs">• {{ $code->used_at->diffForHumans() }}</span>
@endif
</div>
@endif
</div>
</div>
@endforeach
</div>
@endif
</flux:card>
{{-- Quick Actions --}}
<flux:card class="shadow-elegant bg-zinc-50 dark:bg-zinc-800/50">
<div class="flex items-center justify-between">
<div>
<flux:heading size="md" class="mb-2">{{ __('Weitere Aktionen') }}</flux:heading>
<flux:subheading>{{ __('Nützliche Links für das Testing') }}</flux:subheading>
</div>
<div class="flex gap-2">
<flux:button
variant="ghost"
icon="key"
href="{{ route('admin.partners.registration-codes') }}"
wire:navigate
>
{{ __('Code-Verwaltung') }}
</flux:button>
<flux:button
variant="ghost"
icon="users"
href="{{ route('admin.users') }}"
wire:navigate
>
{{ __('Benutzer-Verwaltung') }}
</flux:button>
</div>
</div>
</flux:card>
</div>