109 lines
5.3 KiB
Vue
109 lines
5.3 KiB
Vue
<script setup lang="ts">
|
|
import { Form, Head } from '@inertiajs/vue3';
|
|
import { onMounted, nextTick } from 'vue';
|
|
import InputError from '@/components/InputError.vue';
|
|
import AuthLayout from '@/layouts/AuthLayout.vue';
|
|
import { store } from '@/routes/password/confirm';
|
|
|
|
onMounted(() => {
|
|
nextTick(() => { if ((window as any).lucide) (window as any).lucide.createIcons(); });
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<AuthLayout>
|
|
<Head title="Passwort bestätigen" />
|
|
|
|
<div class="wrap">
|
|
<div class="main-panel">
|
|
<header class="page-head">
|
|
<div class="head-flex">
|
|
<div class="title-group">
|
|
<div class="title">Bestätigung erforderlich</div>
|
|
<p class="subtitle">Bitte bestätige dein Passwort, um fortzufahren</p>
|
|
</div>
|
|
<div class="security-badge">
|
|
<i data-lucide="lock"></i>
|
|
<span>Secure</span>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<Form v-bind="store.form()" reset-on-success v-slot="{ errors, processing }">
|
|
<div class="form-body">
|
|
<label class="field" for="password">
|
|
<span class="lbl">Passwort</span>
|
|
<div class="input-wrapper">
|
|
<i data-lucide="key-round"></i>
|
|
<input
|
|
id="password"
|
|
name="password"
|
|
type="password"
|
|
class="inp"
|
|
required
|
|
autocomplete="current-password"
|
|
autofocus
|
|
placeholder="••••••••"
|
|
/>
|
|
</div>
|
|
<InputError :message="errors.password" />
|
|
</label>
|
|
|
|
<div class="actions">
|
|
<button class="btn" type="submit" :disabled="processing" data-test="confirm-password-button">
|
|
<span v-if="processing" class="spinner" />
|
|
<span>{{ processing ? 'Wird bestätigt…' : 'Passwort bestätigen' }}</span>
|
|
<i v-if="!processing" data-lucide="arrow-right" style="width:14px"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="muted hint">
|
|
<i data-lucide="shield-check"></i>
|
|
<span>Sicherer Bereich. Deine Eingabe ist verschlüsselt.</span>
|
|
</div>
|
|
</div>
|
|
</Form>
|
|
</div>
|
|
</div>
|
|
</AuthLayout>
|
|
</template>
|
|
|
|
<style scoped>
|
|
:global(:root) { --bg-card:#0a0a0a; --border:#151515; --cyan:#00f2ff; --magenta:#ff007a; --green:#00ff9d; }
|
|
.wrap { width: 100%; }
|
|
.main-panel { background: var(--bg-card); border: 1px solid var(--border); border-radius: 20px; overflow: hidden; box-shadow: 0 20px 50px rgba(0,0,0,0.6); animation: fade-in 0.6s cubic-bezier(0.2,0,0,1); }
|
|
|
|
.page-head { padding: 22px 26px; border-bottom: 1px solid var(--border); background: linear-gradient(to right, rgba(0,242,255,0.03), transparent); }
|
|
.head-flex { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
|
|
.title { font-size: 13px; font-weight: 900; color: #fff; letter-spacing: 2px; text-transform: uppercase; }
|
|
.subtitle { color: #555; font-size: 11px; margin-top: 4px; font-weight: 600; }
|
|
.security-badge { display:flex; align-items:center; gap:6px; color: var(--green); background: rgba(0,255,157,0.05); padding:5px 12px; border-radius:50px; border:1px solid rgba(0,255,157,0.1); font-size:9px; font-weight:900; text-transform:uppercase; letter-spacing:1px; }
|
|
.security-badge i { width: 12px; height: 12px; }
|
|
|
|
.form-body { padding: 24px 26px; display: grid; gap: 20px; }
|
|
.field { display: grid; gap: 8px; }
|
|
.lbl { display:block; font-size:10px; font-weight:900; color:#555; text-transform:uppercase; letter-spacing:1px; }
|
|
.input-wrapper { position: relative; display:flex; align-items:center; }
|
|
.input-wrapper i { position: absolute; left: 14px; width: 16px; color: #444; pointer-events: none; transition: .3s; }
|
|
.inp { width: 100%; background:#000; border:1px solid var(--border); color:#fff; padding:14px 14px 14px 44px; border-radius:12px; font-size:13px; transition:.3s cubic-bezier(0.2,0,0,1); }
|
|
.inp:focus { border-color: var(--cyan); outline: none; box-shadow: 0 0 15px rgba(0,242,255,0.1); background:#050505; }
|
|
.inp:focus + i { color: var(--cyan); }
|
|
|
|
.actions { display:flex; gap:10px; margin-top: 5px; }
|
|
.btn { width: 100%; background: var(--cyan); color:#000; border:none; border-radius:12px; padding:14px 16px; font-size:12px; font-weight:900; text-transform:uppercase; letter-spacing:1px; cursor:pointer; transition:.3s; box-shadow: 0 0 20px rgba(0,242,255,0.2); display:flex; align-items:center; justify-content:center; gap:10px; }
|
|
.btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 6px 22px rgba(0,242,255,0.35); }
|
|
.btn:disabled { opacity: .6; cursor: not-allowed; }
|
|
.spinner { width: 16px; height: 16px; border: 2px solid rgba(0,0,0,0.1); border-top-color:#000; border-radius: 50%; animation: spin .8s linear infinite; }
|
|
|
|
.muted { color:#9aa0a6; font-size:11px; display:flex; align-items:center; gap:8px; justify-content: center; opacity: 0.7; }
|
|
.hint i { width: 14px; color:#444; }
|
|
|
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
@keyframes fade-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
|
|
|
@media (max-width: 560px) {
|
|
.page-head { padding: 18px 20px; }
|
|
.form-body { padding: 18px 20px; }
|
|
}
|
|
</style>
|