Convert backends to Firebase and combine projects
This commit is contained in:
405
RIT-EVENT-MANAGEMENT--main/components/LoginForm.tsx
Normal file
405
RIT-EVENT-MANAGEMENT--main/components/LoginForm.tsx
Normal file
@@ -0,0 +1,405 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { UserRole } from '../types';
|
||||
import { supabase } from '../supabase';
|
||||
|
||||
const DEPARTMENTS = ['AIDS', 'CSBS', 'CSE', 'CCE', 'MECH', 'VLSI', 'BIO-TECH', 'AIML', 'ECE', 'H&S'];
|
||||
const EXTERNAL_DEPARTMENTS = [
|
||||
...DEPARTMENTS,
|
||||
'Information Technology (IT)',
|
||||
'Electrical & Electronics Engineering (EEE)',
|
||||
'Civil Engineering',
|
||||
'Biomedical Engineering',
|
||||
'Chemical Engineering',
|
||||
'Aeronautical / Aerospace Engineering',
|
||||
'Mechatronics Engineering',
|
||||
'Others'
|
||||
];
|
||||
const SECTIONS = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
|
||||
const YEARS = ['1st Year', '2nd Year', '3rd Year', '4th Year', '5th Year'];
|
||||
|
||||
interface LoginFormProps {
|
||||
role: UserRole;
|
||||
onSuccess: () => void;
|
||||
onBack: () => void;
|
||||
}
|
||||
|
||||
const LoginForm: React.FC<LoginFormProps> = ({ role, onSuccess, onBack }) => {
|
||||
const [isSignUp, setIsSignUp] = useState(false);
|
||||
const [signUpType, setSignUpType] = useState<'INTERNAL' | 'EXTERNAL' | null>(null);
|
||||
const [coordinatorLoginType, setCoordinatorLoginType] = useState<'Faculty' | 'HOD' | null>(null);
|
||||
const [formData, setFormData] = useState({
|
||||
email: '',
|
||||
phone: '',
|
||||
regNo: '',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
name: '',
|
||||
collegeName: 'Rajalakshmi Institute of Technology',
|
||||
department: '',
|
||||
section: '',
|
||||
year: '',
|
||||
gender: '',
|
||||
collegeLocation: '',
|
||||
captchaInput: '',
|
||||
});
|
||||
|
||||
// Auto-set internal for non-student roles
|
||||
useEffect(() => {
|
||||
if (role !== 'STUDENT') {
|
||||
setSignUpType('INTERNAL');
|
||||
} else if (!isSignUp) {
|
||||
setSignUpType(null);
|
||||
}
|
||||
}, [role, isSignUp]);
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [errorMessage, setErrorMessage] = useState<string | null>(null);
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({ ...prev, [name]: value }));
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setErrorMessage(null);
|
||||
setIsSubmitting(true);
|
||||
|
||||
try {
|
||||
if (!isSignUp) {
|
||||
// Login Logic
|
||||
const { data: loginData, error } = await supabase.auth.signInWithPassword({
|
||||
email: formData.email,
|
||||
password: formData.password
|
||||
});
|
||||
if (error) throw error;
|
||||
|
||||
if (role === 'COORDINATOR' && coordinatorLoginType && loginData.user) {
|
||||
const { data: faculty } = await supabase.from('Facultyusers').select('role').eq('id', loginData.user.id).single();
|
||||
if (!faculty || (faculty.role !== coordinatorLoginType && faculty.role !== 'System Admin')) {
|
||||
await supabase.auth.signOut();
|
||||
throw new Error(`Access Denied: You are not provisioned as ${coordinatorLoginType}.`);
|
||||
}
|
||||
}
|
||||
|
||||
// For students, ensure they have a profile in Studentusers
|
||||
if (role === 'STUDENT' && signUpType === 'INTERNAL' && loginData.user) {
|
||||
const { data: existing } = await supabase.from('Studentusers').select('id').eq('id', loginData.user.id).single();
|
||||
if (!existing) {
|
||||
const { error: profileError } = await supabase.from('Studentusers').insert({
|
||||
id: loginData.user.id,
|
||||
name: formData.name,
|
||||
email: formData.email,
|
||||
reg_no: formData.regNo,
|
||||
phone: formData.phone,
|
||||
department: formData.department,
|
||||
year: formData.year,
|
||||
section: formData.section,
|
||||
college_name: 'RAJALAKSHMI INSTITUTE OF TECHNOLOGY'
|
||||
});
|
||||
if (profileError) console.error("Profile creation error:", profileError);
|
||||
}
|
||||
}
|
||||
|
||||
onSuccess();
|
||||
} else {
|
||||
// Sign-Up Logic
|
||||
const { data: signUpData, error } = await supabase.auth.signUp({
|
||||
email: formData.email,
|
||||
password: formData.password,
|
||||
options: {
|
||||
data: {
|
||||
name: formData.name,
|
||||
role: signUpType === 'EXTERNAL' ? 'EXTERNAL_STUDENT' : role,
|
||||
regNo: formData.regNo,
|
||||
phone: formData.phone,
|
||||
gender: formData.gender,
|
||||
college: formData.collegeName,
|
||||
collegeLocation: formData.collegeLocation,
|
||||
department: formData.department,
|
||||
year: formData.year,
|
||||
section: formData.section
|
||||
}
|
||||
}
|
||||
});
|
||||
if (error) throw error;
|
||||
|
||||
if (signUpData.user) {
|
||||
if (signUpType === 'EXTERNAL') {
|
||||
await supabase.from('externalusers').insert({
|
||||
id: signUpData.user.id,
|
||||
name: formData.name,
|
||||
email: formData.email,
|
||||
reg_no: formData.regNo,
|
||||
phone: formData.phone,
|
||||
department: formData.department,
|
||||
year: formData.year,
|
||||
section: formData.section,
|
||||
college: formData.collegeName,
|
||||
college_location: formData.collegeLocation,
|
||||
gender: formData.gender
|
||||
});
|
||||
} else if (role === 'STUDENT') {
|
||||
await supabase.from('Studentusers').insert({
|
||||
id: signUpData.user.id,
|
||||
name: formData.name,
|
||||
email: formData.email,
|
||||
reg_no: formData.regNo,
|
||||
phone: formData.phone,
|
||||
department: formData.department,
|
||||
year: formData.year,
|
||||
section: formData.section,
|
||||
college_name: 'RAJALAKSHMI INSTITUTE OF TECHNOLOGY'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
alert("Verification link sent to your email. Please verify to continue.");
|
||||
setIsSignUp(false);
|
||||
if (role === 'STUDENT') setSignUpType(null);
|
||||
}
|
||||
} catch (err: any) {
|
||||
setErrorMessage(err.message || "An error occurred.");
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
const RIT_BLUE = 'bg-[#004a99]';
|
||||
const RIT_BLUE_TEXT = 'text-[#004a99]';
|
||||
const RIT_BLUE_HOVER = 'hover:bg-[#003366]';
|
||||
const RIT_BLUE_BORDER = 'border-[#004a99]';
|
||||
|
||||
return (
|
||||
<div className="min-h-screen w-full bg-slate-50 flex items-center justify-center p-4 md:p-10 font-inter">
|
||||
{/* Main Container */}
|
||||
<div className="relative w-full max-w-5xl h-[700px] bg-white rounded-[3rem] shadow-[0_50px_100px_-20px_rgba(0,0,0,0.15)] overflow-hidden flex flex-col md:flex-row border border-slate-100">
|
||||
|
||||
{/* Back Button */}
|
||||
<button
|
||||
onClick={onBack}
|
||||
className="absolute top-8 left-8 z-[60] w-12 h-12 bg-white/10 backdrop-blur-md border border-white/20 rounded-full flex items-center justify-center text-white hover:bg-white/20 transition-all"
|
||||
>
|
||||
<i className="fas fa-arrow-left"></i>
|
||||
</button>
|
||||
|
||||
{/* Forms Container */}
|
||||
<div className="relative flex-1 flex">
|
||||
|
||||
{/* Sign Up Form (Left Side) */}
|
||||
<div className={`absolute inset-0 w-full md:w-1/2 h-full flex flex-col justify-center p-12 transition-all duration-700 ease-in-out z-10 ${isSignUp ? 'opacity-100 translate-x-0 visible' : 'opacity-0 -translate-x-full invisible pointer-events-none'}`}>
|
||||
<img
|
||||
src="https://www.facultyplus.com/wp-content/uploads/2020/11/Rit-logo.png"
|
||||
alt="RIT Logo"
|
||||
className="h-12 w-auto mb-6 object-contain"
|
||||
/>
|
||||
{!signUpType && role === 'STUDENT' ? (
|
||||
<div className="space-y-6 text-center animate-in fade-in zoom-in-95 duration-500">
|
||||
<h2 className="text-3xl font-black text-slate-900 uppercase tracking-tighter mb-8">Choose <span className="text-orange-500">Portal</span></h2>
|
||||
<div className="grid gap-4">
|
||||
<button
|
||||
onClick={() => setSignUpType('INTERNAL')}
|
||||
className={`w-full py-6 ${RIT_BLUE} text-white rounded-2xl font-black uppercase text-xs tracking-[0.2em] shadow-lg transition-all hover:scale-[1.02] active:scale-95`}
|
||||
>
|
||||
RIT Student (Internal)
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSignUpType('EXTERNAL')}
|
||||
className="w-full py-6 bg-white border-2 border-slate-200 text-slate-700 rounded-2xl font-black uppercase text-xs tracking-[0.2em] transition-all hover:border-orange-500 hover:text-orange-500 hover:scale-[1.02] active:scale-95"
|
||||
>
|
||||
Other College (External)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit} className="space-y-4 overflow-y-auto no-scrollbar py-4">
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-3xl font-black text-slate-900 uppercase tracking-tighter">
|
||||
{role === 'STUDENT' ? (signUpType === 'INTERNAL' ? 'Internal' : 'External') : (role === 'COORDINATOR' ? 'Event Coordinator' : 'Admin')} <span className="text-orange-500">Sign Up</span>
|
||||
</h2>
|
||||
{role === 'STUDENT' && <button type="button" onClick={() => setSignUpType(null)} className="text-[10px] font-black text-slate-400 uppercase hover:text-orange-500">Change</button>}
|
||||
</div>
|
||||
<p className="text-slate-400 text-[10px] font-bold uppercase tracking-widest mt-2">Join the RIT Excellence Hub</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<input required name="name" placeholder="FULL NAME" className="bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.name} onChange={handleInputChange} />
|
||||
<input required type="email" name="email" placeholder="EMAIL" className="bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.email} onChange={handleInputChange} />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<input required name="regNo" placeholder="REG NO" className="bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.regNo} onChange={handleInputChange} />
|
||||
<input required name="phone" placeholder="PHONE NUMBER" className="bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.phone} onChange={handleInputChange} />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<input required type="password" name="password" placeholder="PASSWORD" className="bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.password} onChange={handleInputChange} />
|
||||
<input required type="password" name="confirmPassword" placeholder="CONFIRM" className="bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.confirmPassword} onChange={handleInputChange} />
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<select required name="gender" className="bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.gender} onChange={handleInputChange}>
|
||||
<option value="">SELECT GENDER</option>
|
||||
<option value="Male">MALE</option>
|
||||
<option value="Female">FEMALE</option>
|
||||
<option value="Other">OTHER</option>
|
||||
</select>
|
||||
<input required name="collegeLocation" placeholder="COLLEGE LOCATION" className="bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.collegeLocation} onChange={handleInputChange} />
|
||||
</div>
|
||||
|
||||
{(role === 'STUDENT' || signUpType === 'EXTERNAL') && (
|
||||
<>
|
||||
<input
|
||||
required
|
||||
name="collegeName"
|
||||
placeholder="COLLEGE NAME"
|
||||
disabled={signUpType === 'INTERNAL'}
|
||||
className="w-full bg-slate-50 border-none rounded-2xl px-6 py-4 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all disabled:opacity-60"
|
||||
value={formData.collegeName}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<select required name="department" className="bg-slate-50 border-none rounded-2xl px-4 py-4 text-[10px] font-black outline-none" value={formData.department} onChange={handleInputChange}>
|
||||
<option value="">DEPT</option>
|
||||
{(signUpType === 'EXTERNAL' ? EXTERNAL_DEPARTMENTS : DEPARTMENTS).map(d => <option key={d} value={d}>{d}</option>)}
|
||||
</select>
|
||||
<select required name="year" className="bg-slate-50 border-none rounded-2xl px-4 py-4 text-[10px] font-black outline-none" value={formData.year} onChange={handleInputChange}>
|
||||
<option value="">YEAR</option>
|
||||
{YEARS.map(y => <option key={y} value={y}>{y}</option>)}
|
||||
</select>
|
||||
<select required name="section" className="bg-slate-50 border-none rounded-2xl px-4 py-4 text-[10px] font-black outline-none" value={formData.section} onChange={handleInputChange}>
|
||||
<option value="">SEC</option>
|
||||
{SECTIONS.map(s => <option key={s} value={s}>{s}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{errorMessage && <p className="text-rose-500 text-[10px] font-bold uppercase">{errorMessage}</p>}
|
||||
|
||||
<button type="submit" disabled={isSubmitting} className="w-full py-5 bg-orange-500 text-white text-[10px] font-black uppercase tracking-[0.3em] rounded-2xl hover:bg-orange-600 transition-all shadow-lg shadow-orange-500/20 active:scale-95">
|
||||
{isSubmitting ? 'Initializing...' : 'Sign Up Now'}
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Sign In Form (Right Side) */}
|
||||
<div className={`absolute inset-0 w-full md:w-1/2 h-full flex flex-col justify-center p-12 transition-all duration-700 ease-in-out z-10 ml-auto ${!isSignUp ? 'opacity-100 translate-x-0 visible' : 'opacity-0 translate-x-full invisible pointer-events-none'}`}>
|
||||
{role === 'COORDINATOR' && !coordinatorLoginType ? (
|
||||
<div className="space-y-6 text-center animate-in fade-in zoom-in-95 duration-500">
|
||||
<img
|
||||
src="https://www.facultyplus.com/wp-content/uploads/2020/11/Rit-logo.png"
|
||||
alt="RIT Logo"
|
||||
className="h-12 w-auto mb-6 object-contain mx-auto"
|
||||
/>
|
||||
<h2 className="text-3xl font-black text-slate-900 uppercase tracking-tighter mb-8">Choose <span className="text-orange-500">Access Level</span></h2>
|
||||
<div className="grid gap-4">
|
||||
<button
|
||||
onClick={() => setCoordinatorLoginType('Faculty')}
|
||||
type="button"
|
||||
className={`w-full py-6 ${RIT_BLUE} text-white rounded-2xl font-black uppercase text-xs tracking-[0.2em] shadow-lg transition-all hover:scale-[1.02] active:scale-95`}
|
||||
>
|
||||
Faculty Member
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setCoordinatorLoginType('HOD')}
|
||||
type="button"
|
||||
className="w-full py-6 bg-orange-500 text-white rounded-2xl font-black uppercase text-xs tracking-[0.2em] shadow-lg transition-all hover:scale-[1.02] active:scale-95"
|
||||
>
|
||||
Head of Department
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div className="mb-8">
|
||||
<img
|
||||
src="https://www.facultyplus.com/wp-content/uploads/2020/11/Rit-logo.png"
|
||||
alt="RIT Logo"
|
||||
className="h-12 w-auto mb-6 object-contain"
|
||||
/>
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-4xl font-black text-slate-900 uppercase tracking-tighter">Welcome <span className={RIT_BLUE_TEXT}>Back</span></h2>
|
||||
{role === 'COORDINATOR' && (
|
||||
<button type="button" onClick={() => setCoordinatorLoginType(null)} className="text-[10px] font-black text-slate-400 uppercase hover:text-orange-500">Change</button>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-slate-400 text-xs font-bold uppercase tracking-widest mt-2">
|
||||
Access your {role === 'ADMIN' ? 'Admin' : (role === 'COORDINATOR' ? `${coordinatorLoginType} Event` : 'Student')} portal
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="relative">
|
||||
<i className="fas fa-envelope absolute left-6 top-1/2 -translate-y-1/2 text-slate-300"></i>
|
||||
<input required type="email" name="email" placeholder="EMAIL ADDRESS" className="w-full bg-slate-50 border-none rounded-2xl pl-14 pr-6 py-5 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.email} onChange={handleInputChange} />
|
||||
</div>
|
||||
<div className="relative">
|
||||
<i className="fas fa-lock absolute left-6 top-1/2 -translate-y-1/2 text-slate-300"></i>
|
||||
<input required type={showPassword ? 'text' : 'password'} name="password" placeholder="PASSWORD" className="w-full bg-slate-50 border-none rounded-2xl pl-14 pr-14 py-5 text-xs font-bold outline-none focus:ring-2 focus:ring-[#004a99] transition-all" value={formData.password} onChange={handleInputChange} />
|
||||
<button type="button" onClick={() => setShowPassword(!showPassword)} className={`absolute right-6 top-1/2 -translate-y-1/2 text-slate-300 hover:${RIT_BLUE_TEXT} transition-colors`}>
|
||||
<i className={`fas ${showPassword ? 'fa-eye-slash' : 'fa-eye'}`}></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<button type="button" className="text-[10px] font-black text-slate-400 uppercase tracking-widest hover:text-orange-500 transition-colors">Forgot Password?</button>
|
||||
</div>
|
||||
|
||||
{errorMessage && <p className="text-rose-500 text-[10px] font-bold uppercase">{errorMessage}</p>}
|
||||
|
||||
<button type="submit" disabled={isSubmitting} className={`w-full py-5 ${RIT_BLUE} text-white text-[10px] font-black uppercase tracking-[0.3em] rounded-2xl ${RIT_BLUE_HOVER} transition-all shadow-lg shadow-blue-900/20 active:scale-95`}>
|
||||
{isSubmitting ? 'Verifying...' : 'Sign In Now'}
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Sliding Overlay Panel */}
|
||||
<div className={`absolute top-0 left-0 w-full md:w-1/2 h-full ${RIT_BLUE} z-50 transition-all duration-700 ease-[cubic-bezier(0.7,0,0.3,1)] flex flex-col items-center justify-center text-center p-12 overflow-hidden ${isSignUp ? 'md:translate-x-full' : 'translate-x-0'}`}>
|
||||
{/* Background Pattern */}
|
||||
<div className="absolute inset-0 opacity-10 pointer-events-none">
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-[radial-gradient(circle_at_center,_white_1px,_transparent_1px)] bg-[size:30px_30px]"></div>
|
||||
</div>
|
||||
|
||||
<div className={`absolute inset-0 flex flex-col items-center justify-center p-12 transition-all duration-700 delay-100 ${isSignUp ? 'opacity-0 -translate-y-10 pointer-events-none invisible' : 'opacity-100 translate-y-0 pointer-events-auto visible'}`}>
|
||||
<h2 className="text-4xl font-black text-white uppercase tracking-tighter mb-4">{role === 'STUDENT' ? 'New Here?' : 'Restricted Access'}</h2>
|
||||
<p className="text-white/80 text-sm font-medium leading-relaxed mb-10 max-w-xs mx-auto">
|
||||
{role === 'STUDENT'
|
||||
? 'Sign up and discover a world of possibilities at RIT Events Hub.'
|
||||
: 'Sign up is restricted for this portal. Please contact the administrator to provision an account.'}
|
||||
</p>
|
||||
{role === 'STUDENT' && (
|
||||
<button
|
||||
onClick={() => setIsSignUp(true)}
|
||||
className="px-12 py-4 border-2 border-white text-white text-[10px] font-black uppercase tracking-[0.3em] rounded-full hover:bg-white hover:text-[#004a99] transition-all active:scale-95"
|
||||
>
|
||||
Sign Up
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={`absolute inset-0 flex flex-col items-center justify-center p-12 transition-all duration-700 delay-100 ${(!isSignUp || role !== 'STUDENT') ? 'opacity-0 translate-y-10 pointer-events-none invisible' : 'opacity-100 translate-y-0 pointer-events-auto visible'}`}>
|
||||
<h2 className="text-4xl font-black text-white uppercase tracking-tighter mb-4">Welcome <span className="text-white/70">Back!</span></h2>
|
||||
<p className="text-white/80 text-sm font-medium leading-relaxed mb-10 max-w-xs mx-auto">
|
||||
To keep connected with us please login with your personal info.
|
||||
</p>
|
||||
<button
|
||||
onClick={() => setIsSignUp(false)}
|
||||
className="px-12 py-4 border-2 border-white text-white text-[10px] font-black uppercase tracking-[0.3em] rounded-full hover:bg-white hover:text-[#004a99] transition-all active:scale-95"
|
||||
>
|
||||
Sign In
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginForm;
|
||||
Reference in New Issue
Block a user