adding base project
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Link, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { Shield, Mail, Lock, Sparkles, ArrowRight, Server } from 'lucide-react';
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
import { Button } from '../components/common/Button';
|
||||
import { Input } from '../components/common/Input';
|
||||
import { Toast } from '../components/common/Toast';
|
||||
import { ThemeToggle } from '../components/layout/ThemeToggle';
|
||||
import { DEMO_USER } from '../services/mockData';
|
||||
import '../styles/auth.css';
|
||||
|
||||
export function Login() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const { login } = useAuth();
|
||||
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [rememberMe, setRememberMe] = useState(true);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
// If redirected with registered email
|
||||
React.useEffect(() => {
|
||||
if (location.state?.registeredEmail) {
|
||||
setEmail(location.state.registeredEmail);
|
||||
}
|
||||
}, [location.state]);
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
if (!email.trim() || !password.trim()) {
|
||||
setError('Please provide both email and password.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
await login(email, password);
|
||||
navigate('/dashboard');
|
||||
} catch (err) {
|
||||
console.error('Login error:', err);
|
||||
setError(err.message || 'Failed to authenticate. Please check your credentials.');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleQuickDemo = async () => {
|
||||
setEmail(DEMO_USER.email);
|
||||
setPassword('admin123');
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
await login(DEMO_USER.email, 'admin123', true);
|
||||
navigate('/dashboard');
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="auth-container">
|
||||
{/* Background Orbs */}
|
||||
<div className="auth-bg-decorations">
|
||||
<div className="auth-orb auth-orb-1" />
|
||||
<div className="auth-orb auth-orb-2" />
|
||||
<div className="auth-orb auth-orb-3" />
|
||||
</div>
|
||||
|
||||
<div className="auth-card animate-fade-in">
|
||||
{/* Top bar with Brand and Theme Toggle */}
|
||||
<div className="auth-top-bar">
|
||||
<div className="auth-brand">
|
||||
<div className="auth-brand-icon">
|
||||
<Shield size={22} />
|
||||
</div>
|
||||
<span className="auth-brand-name">AuthSec</span>
|
||||
</div>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
|
||||
{/* Header */}
|
||||
<div className="auth-header">
|
||||
<h1 className="auth-title">Welcome back</h1>
|
||||
<p className="auth-subtitle">Sign in to your enterprise security console</p>
|
||||
</div>
|
||||
|
||||
{/* Demo Credentials Quick-Fill Banner */}
|
||||
<div className="demo-quick-bar">
|
||||
<div className="demo-quick-info">
|
||||
<Sparkles size={16} />
|
||||
<span>Demo: <strong>{DEMO_USER.email}</strong></span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="demo-quick-btn"
|
||||
onClick={handleQuickDemo}
|
||||
disabled={loading}
|
||||
>
|
||||
One-Click Login
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Error Toast */}
|
||||
{error && <Toast type="error" message={error} onClose={() => setError(null)} />}
|
||||
|
||||
{/* Login Form */}
|
||||
<form onSubmit={handleSubmit} className="auth-form" noValidate>
|
||||
<Input
|
||||
label="Email Address"
|
||||
type="email"
|
||||
placeholder="admin@authsec.com"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
icon={Mail}
|
||||
required
|
||||
autoComplete="email"
|
||||
/>
|
||||
|
||||
<Input
|
||||
label="Password"
|
||||
type="password"
|
||||
placeholder="••••••••"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
icon={Lock}
|
||||
required
|
||||
autoComplete="current-password"
|
||||
/>
|
||||
|
||||
<div className="auth-options">
|
||||
<label className="auth-remember">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="auth-checkbox"
|
||||
checked={rememberMe}
|
||||
onChange={(e) => setRememberMe(e.target.checked)}
|
||||
/>
|
||||
<span>Remember this session</span>
|
||||
</label>
|
||||
<a href="#trouble" className="auth-link" onClick={(e) => { e.preventDefault(); setError('Contact security administrator to reset credential tokens.'); }}>
|
||||
Forgot password?
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
size="lg"
|
||||
fullWidth
|
||||
isLoading={loading}
|
||||
icon={ArrowRight}
|
||||
>
|
||||
Sign In to AuthSec
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
{/* Bottom Switch to Register */}
|
||||
<div className="auth-footer">
|
||||
Don't have an enterprise account?{' '}
|
||||
<Link to="/register" className="auth-link">
|
||||
Register here
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user