Skip to main content
Glama
Login.tsx7.1 kB
import React, { useState } from 'react'; import { Link, useNavigate } from 'react-router-dom'; import { Eye, EyeOff, Users, Video, ArrowRight } from 'lucide-react'; import { useAuth } from '../contexts/AuthContext'; const Login: React.FC = () => { const [formData, setFormData] = useState({ email: '', password: '', type: 'mentee' as 'mentor' | 'mentee' }); const [showPassword, setShowPassword] = useState(false); const [loading, setLoading] = useState(false); const [errors, setErrors] = useState<Record<string, string>>({}); const { login } = useAuth(); const navigate = useNavigate(); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!formData.email || !formData.password) { setErrors({ general: 'Please fill in all fields' }); return; } setLoading(true); setErrors({}); try { await login(formData.email, formData.password, formData.type); navigate('/dashboard'); } catch (error) { setErrors({ general: 'Invalid credentials. Please try again.' }); } finally { setLoading(false); } }; const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); if (errors[name] || errors.general) { setErrors({}); } }; return ( <div className="min-h-screen flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8 bg-gradient-to-br from-primary-50 via-white to-secondary-50"> <div className="max-w-md w-full space-y-8"> <div className="text-center"> <h2 className="text-3xl font-bold text-gray-900 mb-2"> Welcome Back </h2> <p className="text-gray-600"> Sign in to continue your journey </p> </div> <div className="bg-white p-6 rounded-xl shadow-lg border border-gray-200"> {/* Account Type Selection */} <div className="grid grid-cols-2 gap-4 mb-6"> <button type="button" onClick={() => setFormData(prev => ({ ...prev, type: 'mentee' }))} className={`p-4 rounded-lg border-2 transition-all duration-200 ${ formData.type === 'mentee' ? 'border-primary-500 bg-primary-50 text-primary-700' : 'border-gray-200 hover:border-gray-300' }`} > <Users className="h-6 w-6 mx-auto mb-1" /> <div className="font-semibold text-sm">Mentee</div> </button> <button type="button" onClick={() => setFormData(prev => ({ ...prev, type: 'mentor' }))} className={`p-4 rounded-lg border-2 transition-all duration-200 ${ formData.type === 'mentor' ? 'border-secondary-500 bg-secondary-50 text-secondary-700' : 'border-gray-200 hover:border-gray-300' }`} > <Video className="h-6 w-6 mx-auto mb-1" /> <div className="font-semibold text-sm">Mentor</div> </button> </div> <form onSubmit={handleSubmit} className="space-y-4"> {errors.general && ( <div className="bg-error-50 border border-error-200 text-error-600 px-4 py-3 rounded-lg"> {errors.general} </div> )} <div> <label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-1"> Email Address </label> <input id="email" name="email" type="email" value={formData.email} onChange={handleInputChange} className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all duration-200" placeholder="Enter your email" /> </div> <div> <label htmlFor="password" className="block text-sm font-medium text-gray-700 mb-1"> Password </label> <div className="relative"> <input id="password" name="password" type={showPassword ? 'text' : 'password'} value={formData.password} onChange={handleInputChange} className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all duration-200 pr-10" placeholder="Enter your password" /> <button type="button" onClick={() => setShowPassword(!showPassword)} className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-gray-600" > {showPassword ? <EyeOff className="h-5 w-5" /> : <Eye className="h-5 w-5" />} </button> </div> </div> <div className="flex items-center justify-between"> <div className="flex items-center"> <input id="remember-me" name="remember-me" type="checkbox" className="h-4 w-4 text-primary-600 focus:ring-primary-500 border-gray-300 rounded" /> <label htmlFor="remember-me" className="ml-2 block text-sm text-gray-700"> Remember me </label> </div> <div className="text-sm"> <a href="#" className="text-primary-600 hover:text-primary-700"> Forgot password? </a> </div> </div> <button type="submit" disabled={loading} className="w-full bg-gradient-to-r from-primary-500 to-secondary-500 text-white py-3 px-4 rounded-lg font-semibold hover:from-primary-600 hover:to-secondary-600 focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center space-x-2" > {loading ? ( <div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div> ) : ( <> <span>Sign In</span> <ArrowRight className="h-5 w-5" /> </> )} </button> </form> <div className="mt-6 text-center"> <p className="text-gray-600"> Don't have an account?{' '} <Link to="/register" className="text-primary-600 hover:text-primary-700 font-medium"> Sign up here </Link> </p> </div> </div> </div> </div> ); }; export default Login;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ChiragPatankar/MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server