5.5: <x-password-input> + 6 Auth-Passwortfelder umgestellt
Self-contained Alpine-Toggle (Anzeigen/Verbergen) pro Feld; Props name/label/
autocomplete/placeholder/required/autofocus/show-error, id default auth-<name>,
Slot :labelAction fuer den 'Passwort vergessen?'-Link (login). Ersetzt die
field-pw-wrap-Bloecke in login, register (2), reset-password (2), confirm-
password (1). Die nun ungenutzten form-level x-data={showPassword...} entfernt.
Nebeneffekt/Bugfix: register+reset nutzten :placeholder="__(...)" auf rohem
<input> -> wurde als Alpine-Bind woertlich ausgegeben und schlug fehl (leerer
Platzhalter). Als Component-Prop wird __() korrekt in PHP aufgeloest, der
Hinweistext (z. B. 'Mindestens 8 Zeichen') erscheint jetzt.
Bestaetigungsfelder ohne Fehleranzeige (show-error=false, wie zuvor).
116 Auth-Tests gruen, alle Views kompilieren.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1729e35943
commit
9fadfe6458
5 changed files with 112 additions and 143 deletions
72
resources/views/components/password-input.blade.php
Normal file
72
resources/views/components/password-input.blade.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
@props([
|
||||
/** Feldname: wire:model-Ziel + @error-Key (z. B. 'password', 'password_confirmation') */
|
||||
'name',
|
||||
|
||||
/** Label-Text (bereits übersetzt) */
|
||||
'label',
|
||||
|
||||
/** DOM-id; Standard: auth-<name mit Bindestrichen> */
|
||||
'id' => null,
|
||||
|
||||
/** autocomplete-Hinweis (current-password | new-password) */
|
||||
'autocomplete' => 'current-password',
|
||||
|
||||
/** Platzhalter im Feld */
|
||||
'placeholder' => '••••••••••',
|
||||
|
||||
/** Pflichtfeld */
|
||||
'required' => true,
|
||||
|
||||
/** Autofokus setzen (z. B. Passwort-Bestätigungsseite) */
|
||||
'autofocus' => false,
|
||||
|
||||
/** aria-invalid + Fehlermeldung anzeigen (bei Bestätigungsfeldern aus) */
|
||||
'showError' => true,
|
||||
])
|
||||
|
||||
@php
|
||||
$id ??= 'auth-'.str_replace('_', '-', $name);
|
||||
@endphp
|
||||
|
||||
{{--
|
||||
Passwort-Feld mit Anzeigen/Verbergen-Umschalter (self-contained Alpine).
|
||||
Optionaler Slot :labelAction für Zusatzlink in der Label-Zeile (z. B.
|
||||
„Passwort vergessen?"). Ersetzt die kopierten field-pw-wrap-Blöcke der
|
||||
Auth-Seiten.
|
||||
--}}
|
||||
<div x-data="{ show: false }">
|
||||
@isset($labelAction)
|
||||
<div class="flex items-baseline justify-between mb-1.5">
|
||||
<label class="field-label !mb-0" for="{{ $id }}">{{ $label }}</label>
|
||||
{{ $labelAction }}
|
||||
</div>
|
||||
@else
|
||||
<label class="field-label" for="{{ $id }}">{{ $label }}</label>
|
||||
@endisset
|
||||
|
||||
<div class="field-pw-wrap">
|
||||
<input
|
||||
id="{{ $id }}"
|
||||
wire:model="{{ $name }}"
|
||||
:type="show ? 'text' : 'password'"
|
||||
autocomplete="{{ $autocomplete }}"
|
||||
@if ($required) required @endif
|
||||
@if ($autofocus) autofocus @endif
|
||||
class="field-input pr-[72px]"
|
||||
placeholder="{{ $placeholder }}"
|
||||
@if ($showError) @error($name) aria-invalid="true" @enderror @endif
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="field-affix"
|
||||
@click="show = !show"
|
||||
x-text="show ? '{{ __('Verbergen') }}' : '{{ __('Anzeigen') }}'"
|
||||
>{{ __('Anzeigen') }}</button>
|
||||
</div>
|
||||
|
||||
@if ($showError)
|
||||
@error($name)
|
||||
<p class="field-error">{{ $message }}</p>
|
||||
@enderror
|
||||
@endif
|
||||
</div>
|
||||
|
|
@ -37,33 +37,14 @@ new #[Layout('components.layouts.auth.pressekonto', ['heading' => 'Passwort best
|
|||
{{ __('Dieser Bereich des Publisher-Hubs ist besonders geschützt. Bitte bestätigen Sie zur Sicherheit erneut Ihr Passwort, bevor Sie fortfahren.') }}
|
||||
</p>
|
||||
|
||||
<form wire:submit="confirmPassword" class="space-y-[18px]" x-data="{ showPassword: false }" novalidate>
|
||||
<form wire:submit="confirmPassword" class="space-y-[18px]" novalidate>
|
||||
|
||||
<div>
|
||||
<label class="field-label" for="auth-password">{{ __('Passwort') }}</label>
|
||||
<div class="field-pw-wrap">
|
||||
<input
|
||||
id="auth-password"
|
||||
wire:model="password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
required
|
||||
autofocus
|
||||
autocomplete="current-password"
|
||||
class="field-input pr-[72px]"
|
||||
placeholder="••••••••••"
|
||||
@error('password') aria-invalid="true" @enderror
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="field-affix"
|
||||
@click="showPassword = !showPassword"
|
||||
x-text="showPassword ? '{{ __('Verbergen') }}' : '{{ __('Anzeigen') }}'"
|
||||
>{{ __('Anzeigen') }}</button>
|
||||
</div>
|
||||
@error('password')
|
||||
<p class="field-error">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
<x-password-input
|
||||
name="password"
|
||||
:label="__('Passwort')"
|
||||
autocomplete="current-password"
|
||||
:autofocus="true"
|
||||
/>
|
||||
|
||||
<button type="submit" class="auth-btn-primary !mt-[22px]" wire:loading.attr="disabled" wire:target="confirmPassword">
|
||||
<span wire:loading.remove wire:target="confirmPassword">{{ __('Bestätigen') }}</span>
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ new #[Layout('components.layouts.auth.pressekonto', ['heading' => 'Willkommen zu
|
|||
<div>
|
||||
<x-session-status class="mb-4" />
|
||||
|
||||
<form wire:submit="login" class="space-y-[18px]" x-data="{ showPassword: false }" novalidate>
|
||||
<form wire:submit="login" class="space-y-[18px]" novalidate>
|
||||
|
||||
<div>
|
||||
<label class="field-label" for="auth-email">{{ __('E-Mail-Adresse') }}</label>
|
||||
|
|
@ -147,37 +147,15 @@ new #[Layout('components.layouts.auth.pressekonto', ['heading' => 'Willkommen zu
|
|||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex items-baseline justify-between mb-1.5">
|
||||
<label class="field-label !mb-0" for="auth-password">{{ __('Passwort') }}</label>
|
||||
<x-password-input name="password" :label="__('Passwort')" autocomplete="current-password">
|
||||
<x-slot:labelAction>
|
||||
@if (\Illuminate\Support\Facades\Route::has('password.request'))
|
||||
<a href="{{ route('password.request') }}" class="link-hub text-[12px]" wire:navigate>
|
||||
{{ __('Passwort vergessen?') }}
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
<div class="field-pw-wrap">
|
||||
<input
|
||||
id="auth-password"
|
||||
wire:model="password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
autocomplete="current-password"
|
||||
required
|
||||
class="field-input pr-[72px]"
|
||||
placeholder="••••••••••"
|
||||
@error('password') aria-invalid="true" @enderror
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="field-affix"
|
||||
@click="showPassword = !showPassword"
|
||||
x-text="showPassword ? '{{ __('Verbergen') }}' : '{{ __('Anzeigen') }}'"
|
||||
>{{ __('Anzeigen') }}</button>
|
||||
</div>
|
||||
@error('password')
|
||||
<p class="field-error">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
</x-slot:labelAction>
|
||||
</x-password-input>
|
||||
|
||||
<label class="flex items-center gap-2.5 text-[12.5px] text-ink-2 cursor-pointer select-none">
|
||||
<input type="checkbox" wire:model="remember" class="auth-check" />
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ new #[Layout('components.layouts.auth.pressekonto', ['heading' => 'Konto erstell
|
|||
<div>
|
||||
<x-session-status class="mb-4" />
|
||||
|
||||
<form wire:submit="register" class="space-y-[18px]" x-data="{ showPassword: false, showPasswordConfirmation: false }" novalidate>
|
||||
<form wire:submit="register" class="space-y-[18px]" novalidate>
|
||||
|
||||
<div>
|
||||
<label class="field-label" for="auth-name">{{ __('Name') }}</label>
|
||||
|
|
@ -93,51 +93,20 @@ new #[Layout('components.layouts.auth.pressekonto', ['heading' => 'Konto erstell
|
|||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="field-label" for="auth-password">{{ __('Passwort') }}</label>
|
||||
<div class="field-pw-wrap">
|
||||
<input
|
||||
id="auth-password"
|
||||
wire:model="password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
class="field-input pr-[72px]"
|
||||
:placeholder="__('Mindestens 8 Zeichen')"
|
||||
@error('password') aria-invalid="true" @enderror
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="field-affix"
|
||||
@click="showPassword = !showPassword"
|
||||
x-text="showPassword ? '{{ __('Verbergen') }}' : '{{ __('Anzeigen') }}'"
|
||||
>{{ __('Anzeigen') }}</button>
|
||||
</div>
|
||||
@error('password')
|
||||
<p class="field-error">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
<x-password-input
|
||||
name="password"
|
||||
:label="__('Passwort')"
|
||||
autocomplete="new-password"
|
||||
:placeholder="__('Mindestens 8 Zeichen')"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<label class="field-label" for="auth-password-confirmation">{{ __('Passwort bestätigen') }}</label>
|
||||
<div class="field-pw-wrap">
|
||||
<input
|
||||
id="auth-password-confirmation"
|
||||
wire:model="password_confirmation"
|
||||
:type="showPasswordConfirmation ? 'text' : 'password'"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
class="field-input pr-[72px]"
|
||||
:placeholder="__('Passwort wiederholen')"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="field-affix"
|
||||
@click="showPasswordConfirmation = !showPasswordConfirmation"
|
||||
x-text="showPasswordConfirmation ? '{{ __('Verbergen') }}' : '{{ __('Anzeigen') }}'"
|
||||
>{{ __('Anzeigen') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<x-password-input
|
||||
name="password_confirmation"
|
||||
:label="__('Passwort bestätigen')"
|
||||
autocomplete="new-password"
|
||||
:placeholder="__('Passwort wiederholen')"
|
||||
:show-error="false"
|
||||
/>
|
||||
|
||||
<div class="!mt-5">
|
||||
<label for="auth-terms" class="flex items-start gap-3 cursor-pointer select-none">
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ new #[Layout('components.layouts.auth.pressekonto', ['heading' => 'Neues Passwor
|
|||
{{ __('Vergeben Sie ein neues Passwort für Ihr Konto. Mindestens 8 Zeichen, idealerweise eine Kombination aus Buchstaben, Zahlen und Sonderzeichen.') }}
|
||||
</p>
|
||||
|
||||
<form wire:submit="resetPassword" class="space-y-[18px]" x-data="{ showPassword: false, showPasswordConfirmation: false }" novalidate>
|
||||
<form wire:submit="resetPassword" class="space-y-[18px]" novalidate>
|
||||
|
||||
<div>
|
||||
<label class="field-label" for="auth-email">{{ __('E-Mail-Adresse') }}</label>
|
||||
|
|
@ -88,51 +88,20 @@ new #[Layout('components.layouts.auth.pressekonto', ['heading' => 'Neues Passwor
|
|||
@enderror
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="field-label" for="auth-password">{{ __('Neues Passwort') }}</label>
|
||||
<div class="field-pw-wrap">
|
||||
<input
|
||||
id="auth-password"
|
||||
wire:model="password"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
class="field-input pr-[72px]"
|
||||
:placeholder="__('Mindestens 8 Zeichen')"
|
||||
@error('password') aria-invalid="true" @enderror
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="field-affix"
|
||||
@click="showPassword = !showPassword"
|
||||
x-text="showPassword ? '{{ __('Verbergen') }}' : '{{ __('Anzeigen') }}'"
|
||||
>{{ __('Anzeigen') }}</button>
|
||||
</div>
|
||||
@error('password')
|
||||
<p class="field-error">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
<x-password-input
|
||||
name="password"
|
||||
:label="__('Neues Passwort')"
|
||||
autocomplete="new-password"
|
||||
:placeholder="__('Mindestens 8 Zeichen')"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<label class="field-label" for="auth-password-confirmation">{{ __('Passwort bestätigen') }}</label>
|
||||
<div class="field-pw-wrap">
|
||||
<input
|
||||
id="auth-password-confirmation"
|
||||
wire:model="password_confirmation"
|
||||
:type="showPasswordConfirmation ? 'text' : 'password'"
|
||||
required
|
||||
autocomplete="new-password"
|
||||
class="field-input pr-[72px]"
|
||||
:placeholder="__('Neues Passwort wiederholen')"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="field-affix"
|
||||
@click="showPasswordConfirmation = !showPasswordConfirmation"
|
||||
x-text="showPasswordConfirmation ? '{{ __('Verbergen') }}' : '{{ __('Anzeigen') }}'"
|
||||
>{{ __('Anzeigen') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<x-password-input
|
||||
name="password_confirmation"
|
||||
:label="__('Passwort bestätigen')"
|
||||
autocomplete="new-password"
|
||||
:placeholder="__('Neues Passwort wiederholen')"
|
||||
:show-error="false"
|
||||
/>
|
||||
|
||||
<button type="submit" class="auth-btn-primary !mt-[22px]" wire:loading.attr="disabled" wire:target="resetPassword">
|
||||
<span wire:loading.remove wire:target="resetPassword">{{ __('Passwort zurücksetzen') }}</span>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue