feat: optimize web ui
This commit is contained in:
@@ -6,32 +6,76 @@ export default function Login() {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { login } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setError('');
|
||||
setLoading(true);
|
||||
try {
|
||||
await login(email, password);
|
||||
navigate('/');
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Login failed');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50">
|
||||
<div className="w-full max-w-md p-8 bg-white rounded-lg shadow">
|
||||
<h1 className="text-2xl font-bold text-center mb-6">Sign In to Agent Fox</h1>
|
||||
{error && <p className="text-red-500 text-sm mb-4">{error}</p>}
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<input type="email" placeholder="Email" value={email} onChange={(e) => setEmail(e.target.value)} className="w-full px-3 py-2 border rounded-md" required />
|
||||
<input type="password" placeholder="Password" value={password} onChange={(e) => setPassword(e.target.value)} className="w-full px-3 py-2 border rounded-md" required />
|
||||
<button type="submit" className="w-full py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">Sign In</button>
|
||||
</form>
|
||||
<p className="text-center text-sm mt-4">
|
||||
Don't have an account? <Link to="/register" className="text-blue-600 hover:underline">Sign Up</Link>
|
||||
<div className="min-h-screen flex items-center justify-center bg-bg-primary relative overflow-hidden">
|
||||
{/* Subtle grid background */}
|
||||
<div className="absolute inset-0" style={{
|
||||
backgroundImage: `linear-gradient(var(--border-muted) 1px, transparent 1px), linear-gradient(90deg, var(--border-muted) 1px, transparent 1px)`,
|
||||
backgroundSize: '48px 48px',
|
||||
}} />
|
||||
{/* Radial fade */}
|
||||
<div className="absolute inset-0" style={{
|
||||
background: `radial-gradient(ellipse at center, transparent 0%, var(--bg-primary) 70%)`,
|
||||
}} />
|
||||
|
||||
<div className="w-full max-w-[360px] mx-4 relative animate-slide-up">
|
||||
{/* Brand */}
|
||||
<div className="text-center mb-8">
|
||||
<div className="w-11 h-11 rounded-xl bg-accent mx-auto flex items-center justify-center mb-4 shadow-md">
|
||||
<svg className="w-5 h-5 text-white" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<h1 className="text-xl font-semibold text-text-primary tracking-[-0.01em]">Sign in to Agent Fox</h1>
|
||||
<p className="text-[13px] text-text-muted mt-1">API documentation for LLMs</p>
|
||||
</div>
|
||||
|
||||
{/* Card */}
|
||||
<div className="card p-6 shadow-md">
|
||||
{error && (
|
||||
<div className="mb-4 p-3 rounded-lg bg-danger-muted flex items-center gap-2">
|
||||
<svg className="w-4 h-4 text-danger shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}><circle cx="12" cy="12" r="10" /><path d="M15 9l-6 6m0-6l6 6" /></svg>
|
||||
<span className="text-danger text-[13px]">{error}</span>
|
||||
</div>
|
||||
)}
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div>
|
||||
<label className="block text-[13px] font-medium text-text-secondary mb-1.5">Email</label>
|
||||
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} className="input-base" placeholder="you@example.com" required />
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[13px] font-medium text-text-secondary mb-1.5">Password</label>
|
||||
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} className="input-base" placeholder="Enter your password" required />
|
||||
</div>
|
||||
<button type="submit" disabled={loading} className="btn-primary w-full">
|
||||
{loading ? (
|
||||
<><svg className="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" /><path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" /></svg> Signing in...</>
|
||||
) : 'Sign In'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<p className="text-center text-[13px] text-text-muted mt-6">
|
||||
Don't have an account?{' '}
|
||||
<Link to="/register" className="text-accent hover:underline font-medium">Sign Up</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user