Files
ArtSplash/app/(pages)/register/page.tsx
2026-02-21 20:05:04 +05:30

396 lines
16 KiB
TypeScript

"use client";
import { useState } from "react";
import { motion } from "framer-motion";
import {
Mail,
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 [isRegistered, setIsRegistered] = useState(false);
const [isEmailValid, setIsEmailValid] = useState<boolean | null>(null);
const [isPhoneValid, setIsPhoneValid] = useState<boolean | null>(null);
const validateEmail = (email: string) => {
const sjecEmailRegex = /^[a-zA-Z0-9._%+-]+@sjec\.ac\.in$/;
return sjecEmailRegex.test(email);
};
const validatePhone = (phone: string) => {
const phoneRegex = /^(\+91[\s-]?)?[6-9]\d{9}$/;
return phoneRegex.test(phone.replace(/\s/g, ""));
};
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 handlePhoneChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const phone = e.target.value;
setFormData({ ...formData, phone });
if (phone.length > 0) {
setIsPhoneValid(validatePhone(phone));
} else {
setIsPhoneValid(null);
}
};
const isFormValid =
formData.name.trim().length > 0 &&
isEmailValid === true &&
isPhoneValid !== false &&
formData.phone.trim().length > 0 &&
formData.department.length > 0 &&
formData.year.length > 0 &&
formData.agreeToRules;
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!isFormValid) return;
setIsSubmitting(true);
// TODO: Implement actual registration logic
await new Promise(resolve => setTimeout(resolve, 2000));
setIsSubmitting(false);
setIsRegistered(true);
};
return (
<main className="min-h-screen bg-black pt-32 pb-20">
{isRegistered ? (
<div className="max-w-xl mx-auto px-4 sm:px-6 lg:px-8 text-center pt-20">
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ duration: 0.5 }}
>
<div className="w-20 h-20 rounded-full bg-lime-400 flex items-center justify-center mx-auto mb-6">
<CheckCircle className="w-10 h-10 text-black" />
</div>
<h1 className="text-3xl sm:text-4xl font-black text-white mb-4">
Registration Successful!
</h1>
<p className="text-zinc-400 text-lg mb-8">
Welcome to ArtSplash 2026! You can now submit your artwork.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link
href="/submit"
className="inline-flex items-center justify-center gap-2 bg-lime-400 text-black px-8 py-4 rounded-full font-bold hover:bg-lime-300 transition-all"
>
Submit Artwork
<ArrowRight className="w-5 h-5" />
</Link>
<Link
href="/"
className="inline-flex items-center justify-center gap-2 bg-transparent text-white px-8 py-4 rounded-full font-bold border border-zinc-700 hover:border-zinc-500 transition-all"
>
Back to Home
</Link>
</div>
</motion.div>
</div>
) : (
<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={handlePhoneChange}
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 ${
isPhoneValid === null
? "border-zinc-700 focus:border-lime-400"
: isPhoneValid
? "border-lime-400"
: "border-red-500"
}`}
placeholder="+91 XXXXX XXXXX"
/>
{isPhoneValid !== null && (
<div className="absolute right-4 top-1/2 -translate-y-1/2">
{isPhoneValid ? (
<CheckCircle className="w-5 h-5 text-lime-400" />
) : (
<AlertCircle className="w-5 h-5 text-red-500" />
)}
</div>
)}
</div>
{isPhoneValid === false && (
<p className="text-red-500 text-sm mt-2">
Please enter a valid Indian phone number
</p>
)}
</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 || !isFormValid}
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>
);
}