412 lines
20 KiB
PHP
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>
|
|
|