315 lines
13 KiB
TypeScript
315 lines
13 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
import { motion } from "framer-motion";
|
|
import {
|
|
Mail,
|
|
Lock,
|
|
User,
|
|
Phone,
|
|
GraduationCap,
|
|
CheckCircle,
|
|
AlertCircle,
|
|
ArrowRight,
|
|
Chrome
|
|
} from "lucide-react";
|
|
import Link from "next/link";
|
|
|
|
const departments = [
|
|
"Computer Science & Engineering",
|
|
"Information Science & Engineering",
|
|
"Electronics & Communication Engineering",
|
|
"Electrical & Electronics Engineering",
|
|
"Mechanical Engineering",
|
|
"Civil Engineering",
|
|
"Artificial Intelligence & Machine Learning",
|
|
"Data Science",
|
|
];
|
|
|
|
const years = ["1st Year", "2nd Year", "3rd Year", "4th Year"];
|
|
|
|
export default function RegisterPage() {
|
|
const [formData, setFormData] = useState({
|
|
name: "",
|
|
email: "",
|
|
phone: "",
|
|
department: "",
|
|
year: "",
|
|
agreeToRules: false,
|
|
});
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
const [isEmailValid, setIsEmailValid] = useState<boolean | null>(null);
|
|
|
|
const validateEmail = (email: string) => {
|
|
const sjecEmailRegex = /^[a-zA-Z0-9._%+-]+@sjec\.ac\.in$/;
|
|
return sjecEmailRegex.test(email);
|
|
};
|
|
|
|
const handleEmailChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const email = e.target.value;
|
|
setFormData({ ...formData, email });
|
|
if (email.length > 0) {
|
|
setIsEmailValid(validateEmail(email));
|
|
} else {
|
|
setIsEmailValid(null);
|
|
}
|
|
};
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
if (!isEmailValid) return;
|
|
|
|
setIsSubmitting(true);
|
|
// TODO: Implement actual registration logic
|
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
setIsSubmitting(false);
|
|
};
|
|
|
|
return (
|
|
<main className="min-h-screen bg-black pt-32 pb-20">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="grid lg:grid-cols-2 gap-12 items-start">
|
|
{/* Left Column - Info */}
|
|
<motion.div
|
|
initial={{ opacity: 0, x: -30 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.6 }}
|
|
>
|
|
<span className="inline-block bg-lime-400 text-black px-4 py-1.5 text-xs font-bold tracking-wider rounded-full mb-6">
|
|
JOIN ARTSPLASH
|
|
</span>
|
|
<h1 className="text-4xl sm:text-5xl font-black tracking-tight text-white mb-6">
|
|
Register to
|
|
<span className="text-lime-400"> Compete</span>
|
|
</h1>
|
|
<p className="text-zinc-400 text-lg mb-8 leading-relaxed">
|
|
Create your account to participate in ArtSplash 2026.
|
|
Only SJEC students with valid college email addresses can register to submit artwork.
|
|
</p>
|
|
|
|
{/* Benefits */}
|
|
<div className="space-y-4 mb-8">
|
|
{[
|
|
"Submit artwork in up to 3 categories",
|
|
"Get your art seen by hundreds of voters",
|
|
"Compete for exciting prizes",
|
|
"Receive feedback from moderators",
|
|
].map((benefit, index) => (
|
|
<div key={index} className="flex items-center gap-3">
|
|
<CheckCircle className="w-5 h-5 text-lime-400" />
|
|
<span className="text-zinc-300">{benefit}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Important Notice */}
|
|
<div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-6">
|
|
<div className="flex items-start gap-3">
|
|
<AlertCircle className="w-5 h-5 text-lime-400 flex-shrink-0 mt-0.5" />
|
|
<div>
|
|
<h3 className="text-white font-semibold mb-2">Important</h3>
|
|
<p className="text-zinc-400 text-sm">
|
|
You must use your official SJEC email address (@sjec.ac.in) to register
|
|
and submit artwork. Public voters can use any email address.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Right Column - Form */}
|
|
<motion.div
|
|
initial={{ opacity: 0, x: 30 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.2 }}
|
|
>
|
|
<div className="bg-zinc-900 border border-zinc-800 rounded-3xl p-8">
|
|
{/* OAuth Button */}
|
|
<button
|
|
type="button"
|
|
className="w-full flex items-center justify-center gap-3 bg-white text-black px-6 py-4 rounded-xl font-semibold hover:bg-zinc-100 transition-colors mb-6"
|
|
>
|
|
<Chrome className="w-5 h-5" />
|
|
Continue with Google
|
|
</button>
|
|
|
|
<div className="relative mb-6">
|
|
<div className="absolute inset-0 flex items-center">
|
|
<div className="w-full border-t border-zinc-700" />
|
|
</div>
|
|
<div className="relative flex justify-center text-sm">
|
|
<span className="px-4 bg-zinc-900 text-zinc-500">or register with email</span>
|
|
</div>
|
|
</div>
|
|
|
|
<form onSubmit={handleSubmit} className="space-y-5">
|
|
{/* Name Field */}
|
|
<div>
|
|
<label className="block text-white text-sm font-medium mb-2">
|
|
Full Name
|
|
</label>
|
|
<div className="relative">
|
|
<User className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-zinc-500" />
|
|
<input
|
|
type="text"
|
|
required
|
|
value={formData.name}
|
|
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
className="w-full bg-zinc-800 border border-zinc-700 rounded-xl pl-12 pr-4 py-3 text-white placeholder-zinc-500 focus:outline-none focus:border-lime-400 transition-colors"
|
|
placeholder="Enter your full name"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Email Field */}
|
|
<div>
|
|
<label className="block text-white text-sm font-medium mb-2">
|
|
SJEC Email Address
|
|
</label>
|
|
<div className="relative">
|
|
<Mail className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-zinc-500" />
|
|
<input
|
|
type="email"
|
|
required
|
|
value={formData.email}
|
|
onChange={handleEmailChange}
|
|
className={`w-full bg-zinc-800 border rounded-xl pl-12 pr-12 py-3 text-white placeholder-zinc-500 focus:outline-none transition-colors ${
|
|
isEmailValid === null
|
|
? "border-zinc-700 focus:border-lime-400"
|
|
: isEmailValid
|
|
? "border-lime-400"
|
|
: "border-red-500"
|
|
}`}
|
|
placeholder="yourname@sjec.ac.in"
|
|
/>
|
|
{isEmailValid !== null && (
|
|
<div className="absolute right-4 top-1/2 -translate-y-1/2">
|
|
{isEmailValid ? (
|
|
<CheckCircle className="w-5 h-5 text-lime-400" />
|
|
) : (
|
|
<AlertCircle className="w-5 h-5 text-red-500" />
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
{isEmailValid === false && (
|
|
<p className="text-red-500 text-sm mt-2">
|
|
Please use your SJEC email address (@sjec.ac.in)
|
|
</p>
|
|
)}
|
|
</div>
|
|
|
|
{/* Phone Field */}
|
|
<div>
|
|
<label className="block text-white text-sm font-medium mb-2">
|
|
Phone Number
|
|
</label>
|
|
<div className="relative">
|
|
<Phone className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-zinc-500" />
|
|
<input
|
|
type="tel"
|
|
required
|
|
value={formData.phone}
|
|
onChange={(e) => setFormData({ ...formData, phone: e.target.value })}
|
|
className="w-full bg-zinc-800 border border-zinc-700 rounded-xl pl-12 pr-4 py-3 text-white placeholder-zinc-500 focus:outline-none focus:border-lime-400 transition-colors"
|
|
placeholder="+91 XXXXX XXXXX"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Department & Year */}
|
|
<div className="grid sm:grid-cols-2 gap-4">
|
|
<div>
|
|
<label className="block text-white text-sm font-medium mb-2">
|
|
Department
|
|
</label>
|
|
<div className="relative">
|
|
<GraduationCap className="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-zinc-500" />
|
|
<select
|
|
required
|
|
value={formData.department}
|
|
onChange={(e) => setFormData({ ...formData, department: e.target.value })}
|
|
className="w-full bg-zinc-800 border border-zinc-700 rounded-xl pl-12 pr-4 py-3 text-white appearance-none focus:outline-none focus:border-lime-400 transition-colors"
|
|
>
|
|
<option value="">Select</option>
|
|
{departments.map((dept) => (
|
|
<option key={dept} value={dept}>
|
|
{dept}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<label className="block text-white text-sm font-medium mb-2">
|
|
Year
|
|
</label>
|
|
<select
|
|
required
|
|
value={formData.year}
|
|
onChange={(e) => setFormData({ ...formData, year: e.target.value })}
|
|
className="w-full bg-zinc-800 border border-zinc-700 rounded-xl px-4 py-3 text-white appearance-none focus:outline-none focus:border-lime-400 transition-colors"
|
|
>
|
|
<option value="">Select Year</option>
|
|
{years.map((year) => (
|
|
<option key={year} value={year}>
|
|
{year}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Terms Checkbox */}
|
|
<div className="flex items-start gap-3">
|
|
<input
|
|
type="checkbox"
|
|
id="agreeToRules"
|
|
required
|
|
checked={formData.agreeToRules}
|
|
onChange={(e) => setFormData({ ...formData, agreeToRules: e.target.checked })}
|
|
className="mt-1 w-4 h-4 rounded border-zinc-700 bg-zinc-800 text-lime-400 focus:ring-lime-400"
|
|
/>
|
|
<label htmlFor="agreeToRules" className="text-zinc-400 text-sm">
|
|
I have read and agree to the{" "}
|
|
<Link href="/rules" className="text-lime-400 hover:underline">
|
|
rules and guidelines
|
|
</Link>{" "}
|
|
of ArtSplash 2026
|
|
</label>
|
|
</div>
|
|
|
|
{/* Submit Button */}
|
|
<button
|
|
type="submit"
|
|
disabled={isSubmitting || !isEmailValid}
|
|
className="w-full flex items-center justify-center gap-2 bg-lime-400 text-black px-6 py-4 rounded-xl font-bold tracking-wider hover:bg-lime-300 transition-all disabled:opacity-50 disabled:cursor-not-allowed"
|
|
>
|
|
{isSubmitting ? (
|
|
<>
|
|
<div className="w-5 h-5 border-2 border-black/30 border-t-black rounded-full animate-spin" />
|
|
REGISTERING...
|
|
</>
|
|
) : (
|
|
<>
|
|
CREATE ACCOUNT
|
|
<ArrowRight className="w-5 h-5" />
|
|
</>
|
|
)}
|
|
</button>
|
|
</form>
|
|
|
|
<p className="text-center text-zinc-500 text-sm mt-6">
|
|
Already have an account?{" "}
|
|
<Link href="/login" className="text-lime-400 hover:underline">
|
|
Sign in
|
|
</Link>
|
|
</p>
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|