Redesign: Login-Seite an Wizard-Design angepasst

Eigenes HTML-Layout ohne Sidebar, mw-* CSS-Klassen, gleiches Logo
und Karten-Design wie der Setup-Wizard. Icons als Inline-SVG da
app.js (Phosphor) auf der Login-Seite nicht geladen wird.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
boban 2026-04-24 14:11:53 +02:00
parent 3869f6e67f
commit 085f27d67c
2 changed files with 95 additions and 162 deletions

View File

@ -1,77 +1,17 @@
{{-- resources/views/auth/login.blade.php --}} <!DOCTYPE html>
@extends('layouts.blank') <html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Anmelden · Mailwolt</title>
@vite(['resources/css/app.css'])
@livewireStyles
</head>
<body style="margin:0;background:var(--mw-bg);color:var(--mw-t1);font-family:-apple-system,BlinkMacSystemFont,'Inter','Segoe UI',sans-serif;font-size:13.5px;-webkit-font-smoothing:antialiased;min-height:100vh;display:flex;align-items:center;justify-content:center;
background-image:radial-gradient(900px 600px at 15% 0%,rgba(99,102,241,.07),transparent),radial-gradient(700px 500px at 85% 100%,rgba(59,130,246,.05),transparent)">
@section('title', 'Login') <livewire:auth.login-form />
@section('content') @livewireScripts
<div class="flex items-center justify-center p-6 w-full"> </body>
<livewire:auth.login-form /> </html>
</div>
@endsection
{{-- resources/views/auth/login.blade.php --}}
{{--@extends('layouts.app')--}}
{{--@section('title', 'Login')--}}
{{--@section('content')--}}
{{-- <div class="min-h-[86vh] grid place-items-center px-4--}}
{{-- bg-[radial-gradient(1200px_600px_at_10%_-10%,rgba(59,130,246,.08),transparent),--}}
{{-- radial-gradient(900px_500px_at_90%_0%,rgba(99,102,241,.06),transparent)]">--}}
{{-- <div class="nx-card w-full max-w-[520px]">--}}
{{-- --}}{{-- Header-Chip + Icon --}}
{{-- <div class="flex items-center justify-between mb-5">--}}
{{-- <span class="nx-chip">Erster Login</span>--}}
{{-- <i class="ph ph-lock-simple text-white/60"></i>--}}
{{-- </div>--}}
{{-- <p class="nx-subtle mb-7">--}}
{{-- Melde dich mit dem einmaligen Bootstrap-Konto an, um den Setup-Wizard zu starten.--}}
{{-- </p>--}}
{{-- --}}{{-- Fehler (optional) --}}
{{-- @if(session('error'))--}}
{{-- <div class="nx-alert mb-6">--}}
{{-- <i class="ph ph-warning-circle text-rose-300"></i>--}}
{{-- <div>--}}
{{-- <p class="font-medium">Anmeldung fehlgeschlagen</p>--}}
{{-- <p class="text-sm/5 text-rose-200/90">{{ session('error') }}</p>--}}
{{-- </div>--}}
{{-- </div>--}}
{{-- @endif--}}
{{-- --}}{{-- Formular --}}
{{-- <form method="POST" action="{{ route('login') }}" class="Space-y-5">--}}
{{-- @csrf--}}
{{-- <label class="nx-label" for="email">E-Mail</label>--}}
{{-- <input id="email" name="email" type="email" autocomplete="username" autofocus--}}
{{-- class="nx-input" value="{{ old('email') }}"/>--}}
{{-- <label class="nx-label" for="password">Passwort</label>--}}
{{-- <div class="relative">--}}
{{-- <input id="password" name="password" type="password" autocomplete="current-password" class="nx-input pr-10"/>--}}
{{-- <button type="button" class="nx-eye" onclick="this.previousElementSibling.type = this.previousElementSibling.type==='password'?'text':'password'">--}}
{{-- <i class="ph ph-eye text-white/60"></i>--}}
{{-- </button>--}}
{{-- </div>--}}
{{-- <div class="flex items-center justify-between pt-1">--}}
{{-- <label class="inline-flex items-center gap-2 text-sm text-white/70">--}}
{{-- <input type="checkbox" name="remember" class="nx-check"> Session merken--}}
{{-- </label>--}}
{{-- <a class="nx-link" href="#">Zugang zurücksetzen</a>--}}
{{-- </div>--}}
{{-- <button type="submit" class="nx-btn w-full">Anmelden</button>--}}
{{-- </form>--}}
{{-- --}}{{-- Optional: Provider-Buttons --}}
{{-- --}}{{-- <div class="nx-divider">oder verbinden via</div>--}}
{{-- <div class="grid grid-cols-2 gap-3 mt-4">--}}
{{-- <button class="nx-btn-ghost"><i class="ph ph-google-logo mr-2"></i> Google</button>--}}
{{-- <button class="nx-btn-ghost"><i class="ph ph-github-logo mr-2"></i> GitHub</button>--}}
{{-- </div> --}}
{{-- </div>--}}
{{-- </div>--}}
{{--@endsection--}}

View File

@ -1,120 +1,113 @@
<div class="w-full #min-h-[86vh] grid place-items-center <div style="width:100%;max-width:420px;padding:24px 16px">
bg-[radial-gradient(1200px_600px_at_10%_-10%,rgba(59,130,246,.08),transparent),
radial-gradient(900px_500px_at_90%_0%,rgba(99,102,241,.06),transparent)]">
{{-- Banner (dismissbar) --}} {{-- Logo --}}
<div style="display:flex;align-items:center;gap:10px;margin-bottom:32px;justify-content:center">
<div style="width:32px;height:32px;background:linear-gradient(135deg,#6366f1,#4f46e5);border-radius:8px;display:flex;align-items:center;justify-content:center;box-shadow:0 0 16px rgba(99,102,241,.4)">
<svg width="16" height="16" viewBox="0 0 18 18" fill="none">
<path d="M9 2L15.5 5.5v7L9 16 2.5 12.5v-7L9 2Z" stroke="white" stroke-width="1.5" stroke-linejoin="round"/>
<path d="M9 6L12 7.5v3L9 12 6 10.5v-3L9 6Z" fill="white" opacity=".9"/>
</svg>
</div>
<div>
<div style="font-size:14px;font-weight:700;letter-spacing:.3px;color:var(--mw-t1)">MAILWOLT</div>
<div style="font-size:11px;color:var(--mw-t4);margin-top:-1px">Control Panel</div>
</div>
</div>
{{-- Setup-Done Banner --}}
@if($showBanner && $banner) @if($showBanner && $banner)
<div class="max-w-[520px] mb-5 rounded-2xl border border-emerald-400/30 text-emerald-300 bg-emerald-500/10 p-4 #md:p-5 shadow backdrop-blur" <div style="margin-bottom:14px;padding:12px 14px;border-radius:9px;border:1px solid rgba(34,197,94,.25);background:rgba(34,197,94,.07);display:flex;align-items:flex-start;gap:10px">
role="status" aria-live="polite"> <svg width="15" height="15" viewBox="0 0 14 14" fill="none" style="flex-shrink:0;margin-top:1px;color:#4ade80"><path d="M2 7.5l3 3 7-7" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
<div class="flex items-start gap-3"> <div>
<div class="shrink-0 mt-0.5"> <div style="font-size:12.5px;font-weight:600;color:rgba(134,239,172,.95)">{{ $banner['title'] ?? 'Einrichtung abgeschlossen' }}</div>
<i class="ph ph-check-circle text-emerald-100 text-xl"></i> @if(!empty($banner['message']))
</div> <div style="font-size:11.5px;color:rgba(134,239,172,.7);margin-top:2px">{{ $banner['message'] }}</div>
<div class="flex-1"> @endif
<div class="font-semibold text-emerald-100">
{{ $banner['title'] ?? 'Erfolgreich registriert' }}
</div>
<div class="mt-0.5 text-sm text-emerald-200">
{{ $banner['message'] ?? 'Dein Konto ist bereit. Melde dich jetzt an.' }}
</div>
</div>
</div> </div>
</div> </div>
@endif @endif
<div class="nx-card w-full max-w-[520px]"> {{-- Karte --}}
<div class="flex items-center justify-between mb-5"> <div style="background:var(--mw-bg2);border:1px solid var(--mw-b2);border-radius:14px;padding:28px 24px">
<span class="nx-chip">Erster Login</span>
<i class="ph ph-lock-simple text-white/60"></i> <div style="margin-bottom:20px">
<div style="font-size:15px;font-weight:600;color:var(--mw-t1)">Anmelden</div>
<div style="font-size:12px;color:var(--mw-t4);margin-top:3px">Melde dich mit deinem Account an</div>
</div> </div>
{{-- globale Fehlermeldung --}}
{{-- Fehler --}}
@if($error) @if($error)
<div class="nx-alert mb-6"> <div style="margin-bottom:16px;padding:10px 12px;border-radius:8px;border:1px solid rgba(239,68,68,.25);background:rgba(239,68,68,.07);display:flex;align-items:center;gap:8px">
<i class="ph ph-warning-circle text-rose-300"></i> <svg width="13" height="13" viewBox="0 0 14 14" fill="none" style="flex-shrink:0;color:#f87171"><circle cx="7" cy="7" r="5.5" stroke="currentColor" stroke-width="1.3"/><path d="M7 4.5v3" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/><circle cx="7" cy="9.5" r=".7" fill="currentColor"/></svg>
<div> <span style="font-size:12px;color:#f87171">{{ $error }}</span>
<p class="font-medium">Anmeldung fehlgeschlagen</p>
<p class="text-sm/5 text-rose-200/90">{{ $error }}</p>
</div>
</div> </div>
@endif @endif
<form wire:submit.prevent="login" class="space-y-5"> <form wire:submit.prevent="login" style="display:flex;flex-direction:column;gap:16px">
<div> <div>
<label class="nx-label" for="email">E-Mail / Benutzername</label> <label class="mw-modal-label">E-Mail / Benutzername</label>
<input id="name" type="name" <input type="text"
wire:model.defer="name" wire:model.defer="name"
autocomplete="username" autofocus autocomplete="username"
class="nx-input @error('name') input-error @enderror"> autofocus
@error('name') class="mw-modal-input @error('name') border-red-500/50 @enderror"
<p class="field-error #mt-1">{{ $message }}</p> placeholder="admin@example.com">
@enderror @error('name') <div class="mw-modal-error">{{ $message }}</div> @enderror
</div> </div>
<div> <div>
<label class="nx-label" for="password">Passwort</label> <label class="mw-modal-label">Passwort</label>
<div class="relative"> <div style="position:relative">
<input id="password" type="{{ $show ? 'text' : 'password' }}" <input id="lf-password"
type="password"
wire:model.defer="password" wire:model.defer="password"
autocomplete="current-password" autocomplete="current-password"
class="nx-input pr-10 @error('password') input-error @enderror"> class="mw-modal-input @error('password') border-red-500/50 @enderror"
<button type="button" class="nx-eye" style="padding-right:38px"
onclick="togglePassword('password', this)"> placeholder="••••••••••">
<i class="ph ph-eye text-white/60"></i> <button type="button"
onclick="(function(btn){var i=document.getElementById('lf-password'),s=btn.querySelector('.ico-show'),h=btn.querySelector('.ico-hide');i.type=i.type==='password'?'text':'password';s.style.display=i.type==='text'?'none':'block';h.style.display=i.type==='text'?'block':'none';})(this)"
style="position:absolute;right:0;top:0;height:100%;width:36px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;color:var(--mw-t4)">
<svg class="ico-show" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
<svg class="ico-hide" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" style="display:none"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
</button> </button>
</div> </div>
@error('password') @error('password') <div class="mw-modal-error">{{ $message }}</div> @enderror
<p class="field-error mt-1">{{ $message }}</p>
@enderror
</div> </div>
<div> <div style="display:flex;align-items:center;justify-content:space-between">
<div class="flex items-center justify-between pt-1"> <label style="display:flex;align-items:center;gap:8px;cursor:pointer">
<label class="flex items-center gap-2 cursor-pointer"> <input type="checkbox" wire:model.live="remember" style="display:none" id="lf-remember">
<input type="checkbox" wire:model.live="remember" class="peer hidden"> <span onclick="document.getElementById('lf-remember').click()"
<span style="width:16px;height:16px;border-radius:4px;border:1.5px solid var(--mw-b2);background:var(--mw-bg3);display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:all .15s;{{ $remember ? 'background:rgba(99,102,241,.2);border-color:rgba(99,102,241,.6)' : '' }}">
class="w-5 h-5 flex items-center justify-center rounded border border-white/30 bg-white/5 peer-checked:bg-emerald-500/20 peer-checked:border-emerald-400 transition"> @if($remember)
<i class="ph ph-check text-emerald-400 text-xs hidden peer-checked:inline nx-check"></i> <svg width="9" height="9" viewBox="0 0 9 9" fill="none"><path d="M1.5 4.5l2 2 4-4" stroke="#a5b4fc" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg>
</span> @endif
<span class="text-sm text-white/70">Merken</span> </span>
</label> <span style="font-size:12px;color:var(--mw-t4)">Merken</span>
</div> </label>
</div> </div>
<button type="submit"
<button type="submit" class="nx-btn w-full" wire:loading.attr="disabled"> wire:loading.attr="disabled"
<span wire:loading.remove>Anmelden</span> class="mbx-btn-primary"
<span wire:loading class="inline-flex items-center gap-2"> style="width:100%;justify-content:center;font-size:13px;padding:9px 16px">
<svg class="animate-spin h-4 w-4" viewBox="0 0 24 24" fill="none"> <span wire:loading.remove wire:target="login">Anmelden</span>
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/> <span wire:loading wire:target="login" style="display:inline-flex;align-items:center;gap:6px">
<path class="opacity-75" fill="currentColor" <svg width="12" height="12" viewBox="0 0 12 12" fill="none" style="animation:spin .7s linear infinite">
d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"/> <path d="M10 6A4 4 0 1 1 6 2" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
</svg> </svg>
wird geprüft… wird geprüft…
</span> </span>
</button> </button>
</form> </form>
</div> </div>
@if(\App\Models\Setting::signupAllowed()) @if(\App\Models\Setting::signupAllowed())
<div class="mt-6 text-sm text-white/70"> <div style="margin-top:16px;text-align:center;font-size:12px;color:var(--mw-t4)">
Noch keinen Account? <a wire:navigate href="{{ route('signup') }}" class="nx-link">Zur Registiereung</a> Noch keinen Account?
<a wire:navigate href="{{ route('signup') }}" style="color:#a5b4fc;text-decoration:none">Zur Registrierung</a>
</div> </div>
@endif @endif
</div> </div>
<script>
function togglePassword(id, btn) {
const input = document.getElementById(id);
const icon = btn.querySelector('i');
if (input.type === 'password') {
input.type = 'text';
icon.classList.remove('ph-eye');
icon.classList.add('ph-eye-slash');
} else {
input.type = 'password';
icon.classList.remove('ph-eye-slash');
icon.classList.add('ph-eye');
}
}
</script>