feat: redesign admin login page to be ultra premium and fix tailwind keyframes
This commit is contained in:
+84
-51
@@ -6,69 +6,102 @@ const LoginPage = () => {
|
||||
const [credentials, setCredentials] = useState({ email: '', password: '' });
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
setError('');
|
||||
setIsLoading(true);
|
||||
|
||||
if (credentials.email === 'admin@limelite.com' && credentials.password === 'admin@2026') {
|
||||
navigate('/admin/dashboard');
|
||||
} else {
|
||||
setError('Incorrect admin credentials');
|
||||
}
|
||||
// Simulate a slight network delay for a premium feel
|
||||
setTimeout(() => {
|
||||
if (credentials.email === 'admin@limelite.com' && credentials.password === 'admin@2026') {
|
||||
navigate('/admin/dashboard');
|
||||
} else {
|
||||
setError('Incorrect admin credentials');
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, 800);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#18181b] flex items-center justify-center p-4 font-sans">
|
||||
<div className="bg-white w-full max-w-md p-10 shadow-2xl rounded-none">
|
||||
<div className="flex flex-col items-center mb-10">
|
||||
<div className="bg-limelite-red p-4 mb-6">
|
||||
<img src={process.env.PUBLIC_URL + '/assets/images/logo.jpg'} alt="Limelite" className="h-8 brightness-0 invert" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="min-h-screen bg-gradient-to-br from-[#0a0a0a] via-[#1a1a24] to-[#2a0810] flex items-center justify-center p-4 font-sans relative overflow-hidden">
|
||||
{/* Background Ambient Glows */}
|
||||
<div className="absolute top-0 left-0 w-[500px] h-[500px] bg-limelite-red/20 rounded-full blur-[120px] -translate-x-1/2 -translate-y-1/2"></div>
|
||||
<div className="absolute bottom-0 right-0 w-[500px] h-[500px] bg-limelite-maroon/20 rounded-full blur-[120px] translate-x-1/2 translate-y-1/2"></div>
|
||||
|
||||
{error && <p className="text-limelite-red text-sm font-bold text-center mb-6 animate-shake">{error}</p>}
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-black uppercase tracking-wider mb-2">Email Address</label>
|
||||
<input
|
||||
type="email"
|
||||
required
|
||||
className="w-full border-b-2 border-gray-200 py-3 focus:outline-none focus:border-limelite-red transition-colors text-black"
|
||||
placeholder="olivia@limelite.com"
|
||||
value={credentials.email}
|
||||
onChange={(e) => setCredentials({ ...credentials, email: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<label className="block text-sm font-bold text-black uppercase tracking-wider mb-2">Password</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
type={showPassword ? "text" : "password"}
|
||||
required
|
||||
className="w-full border-b-2 border-gray-200 py-3 pr-10 focus:outline-none focus:border-limelite-red transition-colors text-black"
|
||||
placeholder="••••••••"
|
||||
value={credentials.password}
|
||||
onChange={(e) => setCredentials({ ...credentials, password: e.target.value })}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="absolute right-0 top-1/2 -translate-y-1/2 text-gray-400 hover:text-black transition-colors"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
>
|
||||
{showPassword ? <FiEye size={20} /> : <FiEyeOff size={20} />}
|
||||
</button>
|
||||
<div className="w-full max-w-md relative z-10 animate-[fadeIn_0.5s_ease-out]">
|
||||
<div className="backdrop-blur-xl bg-white/5 border border-white/10 p-10 shadow-2xl rounded-2xl">
|
||||
<div className="flex flex-col items-center mb-10">
|
||||
<div className="bg-gradient-to-tr from-limelite-maroon to-limelite-red p-1 rounded-2xl mb-6 shadow-lg shadow-limelite-red/30">
|
||||
<div className="bg-black/40 backdrop-blur-md p-4 rounded-xl">
|
||||
<img src={process.env.PUBLIC_URL + '/assets/images/logo.jpg'} alt="Limelite" className="h-8 brightness-0 invert opacity-90" />
|
||||
</div>
|
||||
</div>
|
||||
<h2 className="text-3xl font-serif italic text-white tracking-wide">Admin Portal</h2>
|
||||
<p className="text-gray-400 text-sm mt-2 font-light">Secure access to Limelite dashboard</p>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-limelite-red text-white py-4 font-bold uppercase tracking-widest hover:bg-limelite-maroon transition-colors mt-4"
|
||||
>
|
||||
Login
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{error && (
|
||||
<div className="bg-red-500/10 border border-red-500/20 rounded-lg p-3 mb-6 animate-shake">
|
||||
<p className="text-red-400 text-sm font-semibold text-center">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div className="group">
|
||||
<label className="block text-xs font-bold text-gray-400 uppercase tracking-widest mb-2 group-focus-within:text-white transition-colors">Email Address</label>
|
||||
<input
|
||||
type="email"
|
||||
required
|
||||
className="w-full bg-white/5 border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-limelite-red focus:bg-white/10 transition-all"
|
||||
placeholder="admin@limelite.com"
|
||||
value={credentials.email}
|
||||
onChange={(e) => setCredentials({ ...credentials, email: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
<div className="relative group">
|
||||
<label className="block text-xs font-bold text-gray-400 uppercase tracking-widest mb-2 group-focus-within:text-white transition-colors">Password</label>
|
||||
<div className="relative">
|
||||
<input
|
||||
type={showPassword ? "text" : "password"}
|
||||
required
|
||||
className="w-full bg-white/5 border border-white/10 rounded-lg py-3 pl-4 pr-12 text-white placeholder-gray-500 focus:outline-none focus:border-limelite-red focus:bg-white/10 transition-all"
|
||||
placeholder="••••••••"
|
||||
value={credentials.password}
|
||||
onChange={(e) => setCredentials({ ...credentials, password: e.target.value })}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 text-gray-400 hover:text-white transition-colors"
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
>
|
||||
{showPassword ? <FiEye size={18} /> : <FiEyeOff size={18} />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isLoading}
|
||||
className="w-full relative overflow-hidden bg-gradient-to-r from-limelite-maroon to-limelite-red text-white py-4 font-bold uppercase tracking-widest rounded-lg hover:shadow-[0_0_20px_rgba(200,20,50,0.4)] transition-all active:scale-[0.98] disabled:opacity-70 disabled:cursor-wait mt-4 group"
|
||||
>
|
||||
{/* Hover shine effect */}
|
||||
<div className="absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent via-white/20 to-transparent group-hover:animate-[shimmer_1.5s_infinite]"></div>
|
||||
<span className="relative z-10 flex items-center justify-center gap-2">
|
||||
{isLoading ? (
|
||||
<>
|
||||
<svg className="animate-spin -ml-1 mr-2 h-4 w-4 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
Authenticating...
|
||||
</>
|
||||
) : 'Login to Admin'}
|
||||
</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -17,6 +17,25 @@ module.exports = {
|
||||
sans: ['"Albert Sans"', 'sans-serif'],
|
||||
serif: ['"Playfair Display"', 'serif'],
|
||||
},
|
||||
keyframes: {
|
||||
shimmer: {
|
||||
'100%': { transform: 'translateX(100%)' },
|
||||
},
|
||||
fadeIn: {
|
||||
'0%': { opacity: 0 },
|
||||
'100%': { opacity: 1 },
|
||||
},
|
||||
shake: {
|
||||
'0%, 100%': { transform: 'translateX(0)' },
|
||||
'10%, 30%, 50%, 70%, 90%': { transform: 'translateX(-5px)' },
|
||||
'20%, 40%, 60%, 80%': { transform: 'translateX(5px)' },
|
||||
}
|
||||
},
|
||||
animation: {
|
||||
shimmer: 'shimmer 1.5s infinite',
|
||||
fadeIn: 'fadeIn 0.5s ease-out',
|
||||
shake: 'shake 0.5s cubic-bezier(.36,.07,.19,.97) both',
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
|
||||
Reference in New Issue
Block a user