| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- import { useState } from 'react';
- import { Link, useNavigate } from 'react-router-dom';
- import { useAuth } from '@/hooks/useAuth';
- import { Eye, EyeOff, Shield } from 'lucide-react';
- export default function Login() {
- const [email, setEmail] = useState('');
- const [password, setPassword] = useState('');
- const [showPassword, setShowPassword] = useState(false);
- const { login, loginLoading } = useAuth();
- const navigate = useNavigate();
- const handleSubmit = async (e: React.FormEvent) => {
- e.preventDefault();
- try {
- await login({ email, password });
- } catch (error) {
- // Error is handled by useAuth hook
- }
- };
- return (
- <div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
- <div className="max-w-md w-full space-y-8">
- {/* Header */}
- <div className="text-center">
- <div className="mx-auto h-16 w-16 rounded-full bg-primary-100 flex items-center justify-center">
- <Shield className="h-8 w-8 text-primary-600" />
- </div>
- <h2 className="mt-6 text-3xl font-extrabold text-gray-900">
- SaaS Platform
- </h2>
- <p className="mt-2 text-sm text-gray-600">
- Sign in to manage your platform
- </p>
- </div>
- {/* Login Form */}
- <div className="bg-white py-8 px-6 shadow-xl rounded-xl">
- <form className="space-y-6" onSubmit={handleSubmit}>
- {/* Email */}
- <div>
- <label htmlFor="email" className="block text-sm font-medium text-gray-700">
- Email address
- </label>
- <input
- id="email"
- name="email"
- type="email"
- autoComplete="email"
- required
- value={email}
- onChange={(e) => setEmail(e.target.value)}
- className="mt-1 input-field"
- placeholder="Enter your email"
- />
- </div>
- {/* Password */}
- <div>
- <label htmlFor="password" className="block text-sm font-medium text-gray-700">
- Password
- </label>
- <div className="mt-1 relative">
- <input
- id="password"
- name="password"
- type={showPassword ? 'text' : 'password'}
- autoComplete="current-password"
- required
- value={password}
- onChange={(e) => setPassword(e.target.value)}
- className="input-field pr-10"
- placeholder="Enter your password"
- />
- <button
- type="button"
- className="absolute inset-y-0 right-0 pr-3 flex items-center"
- onClick={() => setShowPassword(!showPassword)}
- >
- {showPassword ? (
- <EyeOff className="h-5 w-5 text-gray-400" />
- ) : (
- <Eye className="h-5 w-5 text-gray-400" />
- )}
- </button>
- </div>
- </div>
- {/* Submit Button */}
- <div>
- <button
- type="submit"
- disabled={loginLoading}
- className="w-full btn-primary flex items-center justify-center"
- >
- {loginLoading ? (
- <div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div>
- ) : (
- 'Sign in'
- )}
- </button>
- </div>
- </form>
- {/* Demo Credentials */}
- <div className="mt-6 border-t border-gray-200 pt-6">
- <p className="text-center text-sm text-gray-600">
- Demo Credentials:
- </p>
- <div className="mt-2 text-xs text-gray-500 text-center">
- <p>Email: admin@example.com</p>
- <p>Password: demo_password</p>
- </div>
- </div>
- </div>
- {/* Footer */}
- <div className="text-center">
- <p className="text-sm text-gray-500">
- Don't have an account?{' '}
- <Link
- to="/register"
- className="font-medium text-primary-600 hover:text-primary-500"
- >
- Contact administrator
- </Link>
- </p>
- </div>
- </div>
- </div>
- );
- }
|