23-01-2026
This commit is contained in:
parent
07959c0ba2
commit
854ce02bf6
166 changed files with 32909 additions and 1262 deletions
291
resources/views/livewire/reg/landing.blade.php
Normal file
291
resources/views/livewire/reg/landing.blade.php
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
<?php
|
||||
|
||||
use App\Models\RegistrationCode;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Attributes\Title;
|
||||
use Livewire\Volt\Component;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
new #[Layout('web.layouts.web-master-slot'), Title('Registrierung')] class extends Component {
|
||||
public string $roleSlug;
|
||||
public string $roleKey;
|
||||
public string $codePrefix = '';
|
||||
public string $codePart1 = '';
|
||||
public string $codePart2 = '';
|
||||
public string $codePart3 = '';
|
||||
public string $codePart4 = '';
|
||||
public string $roleLabel = '';
|
||||
public string $roleDescription = '';
|
||||
|
||||
protected array $roleMap = [];
|
||||
|
||||
|
||||
public function mount(string $role): void
|
||||
{
|
||||
$this->loadRoleMap();
|
||||
|
||||
$slug = strtolower($role);
|
||||
if (!isset($this->roleMap[$slug])) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$this->roleSlug = $slug;
|
||||
$this->roleKey = $this->roleMap[$slug]['key'];
|
||||
$this->roleLabel = $this->roleMap[$slug]['label'];
|
||||
$this->roleDescription = $this->roleMap[$slug]['description'];
|
||||
$this->codePrefix = $this->roleMap[$slug]['prefix'] ?? '';
|
||||
}
|
||||
|
||||
protected function loadRoleMap(): void
|
||||
{
|
||||
if (!empty($this->roleMap)) {
|
||||
return;
|
||||
}
|
||||
$roles = Role::whereNotNull('reg_prefix')->where('can_be_invited', true)->get();
|
||||
foreach ($roles as $role) {
|
||||
$slug = strtolower(str_replace('-', '', $role->reg_prefix));
|
||||
$key = strtolower(str_replace('-', '', $role->name));
|
||||
$this->roleMap[$slug] = [
|
||||
'key' => $key,
|
||||
'label' => __('registration.roles.' . $key . '.label'),
|
||||
'description' => __('registration.roles.' . $key . '.description'),
|
||||
'prefix' => $role->reg_prefix,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function submitCode(): void
|
||||
{
|
||||
$this->validate([
|
||||
'codePrefix' => ['required', 'string', 'size:1'],
|
||||
'codePart1' => ['required', 'digits:2'],
|
||||
'codePart2' => ['required', 'digits:2'],
|
||||
'codePart3' => ['required', 'digits:2'],
|
||||
'codePart4' => ['required', 'digits:2'],
|
||||
]);
|
||||
|
||||
|
||||
$normalized = $this->normalizeCode(
|
||||
$this->codePrefix,
|
||||
$this->codePart1,
|
||||
$this->codePart2,
|
||||
$this->codePart3,
|
||||
$this->codePart4
|
||||
);
|
||||
/** @var RegistrationCode|null $registrationCode */
|
||||
$registrationCode = RegistrationCode::where('code', $normalized)
|
||||
->where('role', $this->roleKey)
|
||||
->first();
|
||||
if (!$registrationCode || !$registrationCode->isAvailable()) {
|
||||
$this->addError('code', __('registration.messages.code_invalid'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Merke Code in Session; Verbrauch/Markierung erfolgt nach erfolgreicher Registrierung.
|
||||
session([
|
||||
'registration_code_id' => $registrationCode->id,
|
||||
'registration_role' => $this->roleKey,
|
||||
'registration_slug' => $this->roleSlug,
|
||||
]);
|
||||
|
||||
session()->flash('message', __('registration.messages.code_accepted'));
|
||||
$this->redirect(route('partner.create.account'), navigate: true);
|
||||
}
|
||||
|
||||
protected function normalizeCode(string $prefix, string ...$parts): string
|
||||
{
|
||||
$prefix = strtoupper(trim($prefix));
|
||||
$segments = array_map(fn ($p) => str_pad(preg_replace('/\D+/', '', $p), 2, '0', STR_PAD_LEFT), $parts);
|
||||
return $prefix . implode('', $segments);
|
||||
}
|
||||
}; ?>
|
||||
|
||||
|
||||
<div class="bg-background">
|
||||
<livewire:web.components.ui.header />
|
||||
|
||||
<main class="variante-glass-flow">
|
||||
<div class="max-w-xl mx-auto px-6 space-y-8 pt-20 pb-40" id="code-form">
|
||||
{{-- Hero --}}
|
||||
<div class="text-center space-y-3">
|
||||
<p class="text-xs uppercase tracking-[0.2em] text-accent-500">{{ __('registration.titles.registration') }}</p>
|
||||
<h1 class="text-3xl md:text-4xl font-bold text-foreground">
|
||||
{{ __('registration.titles.access_for_role', ['role' => $roleLabel]) }}
|
||||
</h1>
|
||||
<p class="text-base text-muted-foreground">
|
||||
{{ $roleDescription }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="bg-card/80 backdrop-blur shadow-2xl border border-border rounded-3xl p-6 md:p-8 space-y-6">
|
||||
|
||||
|
||||
<form wire:submit="submitCode" class="space-y-4 mt-10">
|
||||
<flux:field>
|
||||
<div class="text-center text-lg font-medium text-foreground mb-4">{{ __('registration.titles.enter_code') }}</div>
|
||||
<div class="flex justify-center items-center gap-3 flex-nowrap mx-auto w-fit">
|
||||
<input
|
||||
wire:model.defer="codePrefix"
|
||||
placeholder="M"
|
||||
maxlength="1"
|
||||
autofocus
|
||||
class="w-12 text-center uppercase text-xl px-3 py-3 bg-gray-50 border border-border rounded-lg outline-1 -outline-offset-1 outline-gray-300 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-sky-600 text-foreground"
|
||||
/>
|
||||
<span class="text-muted-foreground">|</span>
|
||||
<input
|
||||
wire:model.defer="codePart1"
|
||||
placeholder="00"
|
||||
maxlength="2"
|
||||
class="w-16 text-center text-xl px-3 py-3 bg-gray-50 border border-border rounded-lg outline-1 -outline-offset-1 outline-gray-300 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-sky-600"
|
||||
/>
|
||||
<input
|
||||
wire:model.defer="codePart2"
|
||||
placeholder="00"
|
||||
maxlength="2"
|
||||
class="w-16 text-center text-xl px-3 py-3 bg-gray-50 border border-border rounded-lg outline-1 -outline-offset-1 outline-gray-300 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-sky-600"
|
||||
/>
|
||||
<input
|
||||
wire:model.defer="codePart3"
|
||||
placeholder="00"
|
||||
maxlength="2"
|
||||
class="w-16 text-center text-xl px-3 py-3 bg-gray-50 border border-border rounded-lg outline-1 -outline-offset-1 outline-gray-300 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-sky-600"
|
||||
/>
|
||||
<input
|
||||
wire:model.defer="codePart4"
|
||||
placeholder="00"
|
||||
maxlength="2"
|
||||
class="w-16 text-center text-xl px-3 py-3 bg-gray-50 border border-border rounded-lg outline-1 -outline-offset-1 outline-gray-300 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-sky-600"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<div class="flex flex-col gap-3 p-4 mt-10 rounded-2xl bg-accent-50 dark:bg-accent-900/15 border border-accent-100 dark:border-accent-900/30">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="h-10 w-10 rounded-xl bg-accent-100 dark:bg-accent-900/40 flex items-center justify-center">
|
||||
<flux:icon.key class="h-5 w-5 text-accent-600 dark:text-accent-300" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-base text-foreground">{{ __('registration.messages.code_unique') }}</div>
|
||||
<div class="text-sm text-muted-foreground">{{ __('registration.messages.code_format') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-xs text-center text-muted-foreground mt-2 mb-2">
|
||||
{{ __('') }}
|
||||
</div>
|
||||
<br />
|
||||
|
||||
</flux:field>
|
||||
|
||||
<x-error-alert-static light />
|
||||
|
||||
<div class="flex justify-between">
|
||||
<flux:button type="button" variant="primary" icon="arrow-down" href="#how-it-works" class="cursor-pointer">
|
||||
{{ __('registration.actions.how_it_works') }}
|
||||
</flux:button>
|
||||
<button type="submit" class="btn-secondary-accent small cursor-pointer" wire:target="submitCode">
|
||||
<span class="flex items-center gap-2"><flux:icon.arrow-right class="h-5 w-5" /> {{ __('registration.actions.check_code') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@if (session()->has('message'))
|
||||
<div class="p-3 rounded-lg border border-red-200 bg-red-50 text-red-800">
|
||||
{{ session('message') }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="text-center text-sm text-muted-foreground">
|
||||
{{ __('registration.messages.code_problems') }}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<section class="section-padding bg-accent" id="how-it-works">
|
||||
<div class="container-padding">
|
||||
<div class="text-center mb-16 slide-up delay-300">
|
||||
<h2 class="text-section-title text-foreground mb-6">
|
||||
{{ __('registration.titles.how_it_works') }}
|
||||
</h2>
|
||||
<p class="text-large text-muted-foreground max-w-3xl mx-auto">
|
||||
{{ __('registration.titles.how_it_works_description', ['role' => $roleLabel]) }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-3 gap-8 mb-16">
|
||||
<div class="card-elevated p-0 overflow-hidden group hover:shadow-elevated transition-all duration-300 slide-up delay-200">
|
||||
<div class="relative pt-12 pb-8">
|
||||
<div class="mx-auto w-20 h-20 icon-secondary-linear glow-soft group-hover:glow-medium rounded-2xl flex items-center justify-center transition-colors duration-300">
|
||||
@svg('heroicon-o-key', 'w-10 h-10 text-secondary-foreground')
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-8">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 rounded-lg bg-secondary/10 flex items-center justify-center">
|
||||
<span class="text-lg font-bold text-secondary">1</span>
|
||||
</div>
|
||||
<h3 class="text-2xl font-medium text-foreground">
|
||||
{{ __('registration.steps.code_entry.title') }}
|
||||
</h3>
|
||||
</div>
|
||||
<p class="text-muted-foreground leading-relaxed mb-0">
|
||||
{{ __('registration.steps.code_entry.description') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-elevated p-0 overflow-hidden group hover:shadow-elevated transition-all duration-300 slide-up delay-400">
|
||||
<div class="relative pt-12 pb-8">
|
||||
<div class="mx-auto w-20 h-20 icon-secondary-linear glow-soft group-hover:glow-medium rounded-2xl flex items-center justify-center transition-colors duration-300">
|
||||
@svg('heroicon-o-user-plus', 'w-10 h-10 text-secondary-foreground')
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-8">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 rounded-lg bg-secondary/10 flex items-center justify-center">
|
||||
<span class="text-lg font-bold text-secondary">2</span>
|
||||
</div>
|
||||
<h3 class="text-2xl font-medium text-foreground">
|
||||
{{ __('registration.steps.create_account.title') }}
|
||||
</h3>
|
||||
</div>
|
||||
<p class="text-muted-foreground leading-relaxed mb-0">
|
||||
{{ __('registration.steps.create_account.description', ['role' => $roleLabel]) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-elevated p-0 overflow-hidden group hover:shadow-elevated transition-all duration-300 slide-up delay-600">
|
||||
<div class="relative pt-12 pb-8">
|
||||
<div class="mx-auto w-20 h-20 icon-secondary-linear glow-soft group-hover:glow-medium rounded-2xl flex items-center justify-center transition-colors duration-300">
|
||||
@svg('heroicon-o-sparkles', 'w-10 h-10 text-secondary-foreground')
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-8">
|
||||
<div class="flex items-center gap-3 mb-4">
|
||||
<div class="w-10 h-10 rounded-lg bg-secondary/10 flex items-center justify-center">
|
||||
<span class="text-lg font-bold text-secondary">3</span>
|
||||
</div>
|
||||
<h3 class="text-2xl font-medium text-foreground">
|
||||
{{ __('registration.steps.complete_onboarding.title') }}
|
||||
</h3>
|
||||
</div>
|
||||
<p class="text-muted-foreground leading-relaxed mb-6">
|
||||
{{ __('registration.steps.complete_onboarding.description') }}
|
||||
</p>
|
||||
<a href="#code-form" class="block">
|
||||
<button class="btn-secondary-accent small w-full cursor-pointer">
|
||||
{{ __('registration.actions.start_now') }}
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
<livewire:web.components.ui.footer />
|
||||
</div>
|
||||
129
resources/views/livewire/reg/thank-you.blade.php
Normal file
129
resources/views/livewire/reg/thank-you.blade.php
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Attributes\Title;
|
||||
use Livewire\Volt\Component;
|
||||
|
||||
new #[Layout('web.layouts.web-master-slot'), Title('Registrierung erfolgreich')] class extends Component {
|
||||
public ?string $email = null;
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->email = request()->query('email');
|
||||
}
|
||||
}; ?>
|
||||
|
||||
<div class="bg-background">
|
||||
<livewire:web.components.ui.header />
|
||||
|
||||
<main class="variante-glass-flow">
|
||||
<div class="max-w-3xl mx-auto px-6 space-y-8 pt-20 pb-40">
|
||||
{{-- Header --}}
|
||||
<div class="text-center space-y-4">
|
||||
<div class="mx-auto w-20 h-20 rounded-full bg-green-100 flex items-center justify-center mb-6">
|
||||
@svg('heroicon-o-check-circle', 'h-12 w-12 text-green-600')
|
||||
</div>
|
||||
<p class="text-xs uppercase tracking-[0.2em] text-accent-500">{{ __('registration.thank_you.subtitle') }}</p>
|
||||
<h1 class="text-3xl md:text-4xl font-bold text-foreground">
|
||||
{{ __('registration.thank_you.title') }}
|
||||
</h1>
|
||||
<p class="text-lg text-muted-foreground">
|
||||
{{ __('registration.thank_you.description') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{{-- Info Card --}}
|
||||
<div class="bg-card/80 backdrop-blur shadow-2xl border border-border rounded-3xl p-6 md:p-8 space-y-6">
|
||||
|
||||
{{-- Email Verification Info --}}
|
||||
<div class="flex flex-col gap-3 p-4 rounded-2xl bg-lime-100 border border-lime-200 ">
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="h-10 w-10 rounded-xl bg-lime-200 flex items-center justify-center flex-shrink-0">
|
||||
@svg('heroicon-o-envelope', 'h-5 w-5 text-lime-600')
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-foreground">{{ __('registration.thank_you.email_sent_title') }}</div>
|
||||
<div class="text-sm text-muted-foreground">
|
||||
{{ __('registration.thank_you.email_sent_description', ['email' => $email]) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Next Steps --}}
|
||||
<div class="space-y-4">
|
||||
<h2 class="text-xl font-semibold text-foreground">{{ __('registration.thank_you.next_steps_title') }}</h2>
|
||||
|
||||
<div class="space-y-3">
|
||||
{{-- Step 1 --}}
|
||||
<div class="flex gap-4 p-4 rounded-xl bg-accent-50 border border-accent-100">
|
||||
<div class="flex-shrink-0 w-8 h-8 rounded-lg bg-secondary text-secondary-foreground flex items-center justify-center font-bold text-sm">
|
||||
1
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-foreground">{{ __('registration.thank_you.step1_title') }}</div>
|
||||
<div class="text-sm text-muted-foreground">{{ __('registration.thank_you.step1_description') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Step 2 --}}
|
||||
<div class="flex gap-4 p-4 rounded-xl bg-accent-50 border border-accent-100">
|
||||
<div class="flex-shrink-0 w-8 h-8 rounded-lg bg-secondary text-secondary-foreground flex items-center justify-center font-bold text-sm">
|
||||
2
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-foreground">{{ __('registration.thank_you.step2_title') }}</div>
|
||||
<div class="text-sm text-muted-foreground">{{ __('registration.thank_you.step2_description') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Step 3 --}}
|
||||
<div class="flex gap-4 p-4 rounded-xl bg-accent-50 border border-accent-100">
|
||||
<div class="flex-shrink-0 w-8 h-8 rounded-lg bg-secondary text-secondary-foreground flex items-center justify-center font-bold text-sm">
|
||||
3
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-foreground">{{ __('registration.thank_you.step3_title') }}</div>
|
||||
<div class="text-sm text-muted-foreground">{{ __('registration.thank_you.step3_description') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Important Note --}}
|
||||
<div class="flex flex-col gap-3 p-4 rounded-2xl bg-amber-50 border border-amber-100">
|
||||
<div class="flex items-start gap-3">
|
||||
<div class="h-10 w-10 rounded-xl bg-amber-100 flex items-center justify-center flex-shrink-0">
|
||||
@svg('heroicon-o-exclamation-triangle', 'h-5 w-5 text-amber-600')
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-foreground">{{ __('registration.thank_you.spam_check_title') }}</div>
|
||||
<div class="text-sm text-muted-foreground">{{ __('registration.thank_you.spam_check_description') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Login Link --}}
|
||||
<div class="text-center pt-6">
|
||||
<p class="text-sm text-muted-foreground mb-4">
|
||||
{{ __('registration.thank_you.already_verified') }}
|
||||
</p>
|
||||
<a href="{{ route('login') }}" class="btn-secondary-accent small cursor-pointer inline-flex items-center gap-2">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
@svg('heroicon-o-arrow-right', 'h-5 w-5')
|
||||
{{ __('registration.thank_you.login_button') }}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Support Contact --}}
|
||||
<div class="text-center text-sm text-muted-foreground">
|
||||
{{ __('registration.messages.code_problems') }}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<livewire:web.components.ui.footer />
|
||||
</div>
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue