'use client'; import { useState, FormEvent } from 'react'; import { Lock } from 'lucide-react'; import Card from '@/components/ui/Card'; import Button from '@/components/ui/Button'; export default function LoginPage() { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const [success, setSuccess] = useState(false); const handleSubmit = async (e: FormEvent) => { e.preventDefault(); setError(''); setLoading(true); try { const res = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), credentials: 'include', }); if (res.status === 429) { setError('Too many login attempts. Please wait a moment and try again.'); setLoading(false); return; } const data = await res.json(); if (!res.ok) { setError(data.error || 'Login failed'); setLoading(false); return; } setSuccess(true); setLoading(false); setTimeout(() => { window.location.replace('/'); }, 500); } catch (err) { const errorMsg = err instanceof Error ? err.message : 'Unknown error'; setError(`Network error: ${errorMsg}`); setLoading(false); } }; if (success) { return (

Login Successful!

Redirecting to dashboard...

Click here if not redirected
); } return (

NEXUS

VM Control Center

{error && (

{error}

)}
setUsername(e.target.value)} required autoComplete="username" disabled={loading} className="w-full px-4 py-3 bg-background border border-border rounded-xl text-foreground placeholder-foreground-subtle focus:outline-none focus:border-foreground focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-background transition-colors disabled:opacity-50" placeholder="Enter username" />
setPassword(e.target.value)} required autoComplete="current-password" disabled={loading} className="w-full px-4 py-3 bg-background border border-border rounded-xl text-foreground placeholder-foreground-subtle focus:outline-none focus:border-foreground focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-background transition-colors disabled:opacity-50" placeholder="Enter password" />

Secure access only

); }