110 lines
3.7 KiB
TypeScript
110 lines
3.7 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import Link from 'next/link';
|
|
|
|
export default function Home() {
|
|
const [loggedIn, setLoggedIn] = useState(false);
|
|
const [password, setPassword] = useState('');
|
|
const [error, setError] = useState('');
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
useEffect(() => {
|
|
if (localStorage.getItem('auth')) {
|
|
window.location.href = '/domains';
|
|
}
|
|
}, []);
|
|
|
|
const handleLogin = async () => {
|
|
setError('');
|
|
setLoading(true);
|
|
|
|
try {
|
|
const response = await fetch('/api/auth', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ password }),
|
|
});
|
|
|
|
if (response.ok) {
|
|
const auth = btoa(`admin:${password}`);
|
|
localStorage.setItem('auth', auth);
|
|
window.location.href = '/domains';
|
|
} else {
|
|
setError('Falsches Passwort');
|
|
}
|
|
} catch (err) {
|
|
setError('Verbindungsfehler. Bitte erneut versuchen.');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleKeyPress = (e: React.KeyboardEvent) => {
|
|
if (e.key === 'Enter' && !loading) {
|
|
handleLogin();
|
|
}
|
|
};
|
|
|
|
if (!loggedIn) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center bg-gradient-to-b from-blue-50 to-gray-100">
|
|
<div className="bg-white p-10 rounded-xl shadow-lg w-96 fade-in">
|
|
<h1 id="login-heading" className="text-3xl font-bold mb-8 text-center text-gray-800">
|
|
Login to Mail S3 Admin
|
|
</h1>
|
|
<form onSubmit={(e) => { e.preventDefault(); handleLogin(); }} aria-labelledby="login-heading">
|
|
<div className="mb-6">
|
|
<label htmlFor="password" className="sr-only">
|
|
Password
|
|
</label>
|
|
<input
|
|
id="password"
|
|
type="password"
|
|
value={password}
|
|
onChange={e => { setPassword(e.target.value); setError(''); }}
|
|
onKeyPress={handleKeyPress}
|
|
className={`border ${error ? 'border-red-500' : 'border-gray-300'} p-4 w-full rounded-lg focus:outline-none focus:ring-2 ${error ? 'focus:ring-red-500' : 'focus:ring-blue-500'} transition-colors`}
|
|
placeholder="Enter password"
|
|
aria-invalid={!!error}
|
|
aria-describedby={error ? "password-error" : undefined}
|
|
disabled={loading}
|
|
autoFocus
|
|
/>
|
|
{error && (
|
|
<p id="password-error" role="alert" className="text-red-600 text-sm mt-2 fade-in">
|
|
{error}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<button
|
|
type="submit"
|
|
onClick={handleLogin}
|
|
disabled={loading}
|
|
className="bg-blue-600 text-white px-6 py-4 rounded-lg w-full hover:bg-blue-700 transition-all font-medium disabled:opacity-50 disabled:cursor-not-allowed button-hover-lift focus-ring"
|
|
aria-label="Log in to admin panel"
|
|
>
|
|
{loading ? 'Logging in...' : 'Login'}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gradient-to-b from-blue-50 to-gray-100 p-8">
|
|
<main id="main-content" className="fade-in">
|
|
<h1 className="text-4xl font-bold mb-8 text-center text-gray-800">Mail S3 Admin</h1>
|
|
<div className="flex justify-center">
|
|
<Link
|
|
href="/domains"
|
|
className="bg-blue-600 text-white px-8 py-4 rounded-lg hover:bg-blue-700 transition-all shadow-md font-medium button-hover-lift focus-ring"
|
|
>
|
|
Go to Domains
|
|
</Link>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
);
|
|
} |