PopcornPing / frontend /src /components /SignupModal.jsx
Yash Goyal
Correction
2070fe3
import React, { useState } from 'react';
import { useAuth } from '../context/AuthContext';
import { useNavigate } from 'react-router-dom';
// Icons
const CloseIcon = ({ className }) => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
);
const GoogleIcon = ({ className }) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className={className}>
<path d="M12.479,14.265v-3.279h11.049c0.108,0.571,0.164,1.247,0.164,1.979c0,2.46-0.672,5.502-2.84,7.669 C18.744,22.829,16.051,24,12.483,24C5.869,24,0.308,18.613,0.308,12S5.869,0,12.483,0c3.659,0,6.265,1.436,8.223,3.307L18.392,5.62 c-1.404-1.317-3.307-2.341-5.913-2.341C7.65,3.279,3.873,7.171,3.873,12s3.777,8.721,8.606,8.721c3.132,0,4.916-1.258,6.059-2.401 c0.927-0.927,1.537-2.251,1.777-4.059L12.479,14.265z" />
</svg>
);
const AtSignIcon = ({ className }) => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><circle cx="12" cy="12" r="4"/><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94"/></svg>
);
const UserIcon = ({ className }) => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
);
const LockIcon = ({ className }) => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
);
const SignupModal = ({ onClose, onLogin }) => {
const [formData, setFormData] = useState({
username: '',
email: '',
password: '',
});
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const { register, googleLogin } = useAuth();
const navigate = useNavigate();
const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value,
});
};
const handleSubmit = async (e) => {
e.preventDefault();
setError('');
if (formData.password.length < 6) {
setError('Password must be at least 6 characters');
return;
}
setLoading(true);
try {
await register(formData);
onClose();
navigate('/dashboard');
} catch (err) {
setError(err.response?.data?.message || 'Registration failed');
} finally {
setLoading(false);
}
};
const handleGoogleLogin = () => {
googleLogin();
};
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm p-4">
{/* Container echoing the AuthPage styling */}
<div className="relative w-full max-w-md bg-black border border-gray-800 rounded-xl overflow-hidden shadow-2xl">
{/* Background Gradients */}
<div className="absolute inset-0 pointer-events-none opacity-40">
<div className="absolute top-0 right-0 h-[300px] w-[300px] bg-purple-900/20 blur-[100px] rounded-full translate-x-1/3 -translate-y-1/3" />
<div className="absolute bottom-0 left-0 h-[300px] w-[300px] bg-blue-900/10 blur-[100px] rounded-full -translate-x-1/3 translate-y-1/3" />
</div>
{/* Close Button */}
<button onClick={onClose} className="absolute top-4 right-4 text-gray-400 hover:text-white transition z-20">
<CloseIcon className="w-5 h-5" />
</button>
<div className="relative z-10 p-8">
{/* Header */}
<div className="flex flex-col space-y-1 mb-6 text-center md:text-left">
<h1 className="text-2xl font-bold tracking-wide text-white">Create Account</h1>
<p className="text-gray-400 text-sm">
Sign up to start your journey.
</p>
</div>
{/* Google Button */}
<div className="space-y-2 mb-6">
<button
onClick={handleGoogleLogin}
type="button"
className="w-full flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium h-10 px-4 py-2 border border-gray-700 bg-gray-900 hover:bg-gray-800 hover:text-white text-gray-200 transition-colors"
>
<GoogleIcon className="w-4 h-4 mr-2" />
Continue with Google
</button>
</div>
{/* Separator */}
<div className="flex w-full items-center justify-center mb-6">
<div className="bg-gray-800 h-px w-full" />
<span className="text-gray-500 px-2 text-xs uppercase">OR</span>
<div className="bg-gray-800 h-px w-full" />
</div>
{/* Error Message */}
{error && (
<div className="mb-4 p-3 bg-red-500/10 border border-red-500/50 rounded-md text-red-500 text-sm">
{error}
</div>
)}
{/* Signup Form */}
<form onSubmit={handleSubmit} className="space-y-4">
{/* Username */}
<div className="space-y-2">
<div className="relative">
<input
type="text"
name="username"
placeholder="Username"
value={formData.username}
onChange={handleChange}
required
className="flex h-10 w-full rounded-md border border-gray-700 bg-black px-3 py-2 pl-9 text-sm text-white placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-transparent transition-all"
/>
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-gray-500">
<UserIcon className="w-4 h-4" />
</div>
</div>
</div>
{/* Email */}
<div className="space-y-2">
<div className="relative">
<input
type="email"
name="email"
placeholder="name@example.com"
value={formData.email}
onChange={handleChange}
required
className="flex h-10 w-full rounded-md border border-gray-700 bg-black px-3 py-2 pl-9 text-sm text-white placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-transparent transition-all"
/>
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-gray-500">
<AtSignIcon className="w-4 h-4" />
</div>
</div>
</div>
{/* Password */}
<div className="space-y-2">
<div className="relative">
<input
type="password"
name="password"
placeholder="Password (min 6 chars)"
value={formData.password}
onChange={handleChange}
required
className="flex h-10 w-full rounded-md border border-gray-700 bg-black px-3 py-2 pl-9 text-sm text-white placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-transparent transition-all"
/>
<div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-gray-500">
<LockIcon className="w-4 h-4" />
</div>
</div>
</div>
<button
type="submit"
disabled={loading}
className="w-full inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium h-10 px-4 py-2 bg-purple-600 text-white hover:bg-purple-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
{loading ? 'Creating account...' : 'Create Account'}
</button>
</form>
{/* Footer */}
<p className="mt-6 text-center text-sm text-gray-400">
Already have an account?{' '}
<button
onClick={onLogin}
className="text-purple-400 hover:text-purple-300 font-medium underline underline-offset-4"
>
Log In
</button>
</p>
</div>
</div>
</div>
);
};
export default SignupModal;