118 lines
3.1 KiB
TypeScript
118 lines
3.1 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { useRouter } from 'next/navigation';
|
|
|
|
export default function LoginPage() {
|
|
const [password, setPassword] = useState('');
|
|
const [error, setError] = useState('');
|
|
const [loading, setLoading] = useState(false);
|
|
const router = useRouter();
|
|
|
|
async function handleLogin() {
|
|
if (!password || loading) return;
|
|
setLoading(true);
|
|
setError('');
|
|
try {
|
|
const res = await fetch('/api/auth/login', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
credentials: 'include',
|
|
body: JSON.stringify({ password }),
|
|
});
|
|
if (!res.ok) throw new Error('Invalid password');
|
|
router.push('/');
|
|
router.refresh();
|
|
} catch {
|
|
setError('Invalid password');
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
function handleKeyDown(e: React.KeyboardEvent) {
|
|
if (e.key === 'Enter') handleLogin();
|
|
}
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
minHeight: '100dvh',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
padding: '16px',
|
|
background: '#faf9f6',
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
width: '100%',
|
|
maxWidth: '360px',
|
|
background: '#f0ede6',
|
|
border: '1px solid #dddad2',
|
|
borderRadius: '16px',
|
|
padding: '32px',
|
|
}}
|
|
>
|
|
<div style={{ textAlign: 'center', marginBottom: '32px' }}>
|
|
<div style={{ fontSize: '22px', fontWeight: 500, color: '#1a1a18', marginBottom: '4px' }}>
|
|
Aaron AI
|
|
</div>
|
|
<div style={{ fontSize: '13px', color: '#999990' }}>
|
|
personal knowledge assistant
|
|
</div>
|
|
</div>
|
|
|
|
<input
|
|
type="password"
|
|
value={password}
|
|
onChange={e => setPassword(e.target.value)}
|
|
onKeyDown={handleKeyDown}
|
|
placeholder="Password"
|
|
autoFocus
|
|
autoComplete="current-password"
|
|
style={{
|
|
width: '100%',
|
|
background: '#faf9f6',
|
|
border: `1px solid ${error ? '#a32d2d' : '#ccc9c0'}`,
|
|
borderRadius: '10px',
|
|
padding: '12px 16px',
|
|
fontSize: '16px',
|
|
color: '#1a1a18',
|
|
outline: 'none',
|
|
marginBottom: error ? '6px' : '16px',
|
|
display: 'block',
|
|
boxSizing: 'border-box',
|
|
}}
|
|
/>
|
|
|
|
{error && (
|
|
<div style={{ fontSize: '12px', color: '#a32d2d', marginBottom: '16px' }}>
|
|
{error}
|
|
</div>
|
|
)}
|
|
|
|
<button
|
|
onClick={handleLogin}
|
|
disabled={loading}
|
|
style={{
|
|
width: '100%',
|
|
background: '#2d5a3d',
|
|
color: '#e8f5ed',
|
|
border: 'none',
|
|
borderRadius: '10px',
|
|
padding: '12px',
|
|
fontSize: '15px',
|
|
cursor: loading ? 'not-allowed' : 'pointer',
|
|
opacity: loading ? 0.5 : 1,
|
|
display: 'block',
|
|
boxSizing: 'border-box',
|
|
}}
|
|
>
|
|
{loading ? 'Signing in...' : 'Sign in'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|