diff --git a/.env.example b/.env.example index 3f37be1..7706e7f 100644 --- a/.env.example +++ b/.env.example @@ -1,12 +1,12 @@ # Firebase Configuration -REACT_APP_FIREBASE_API_KEY=your_firebase_api_key_here -REACT_APP_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com -REACT_APP_FIREBASE_PROJECT_ID=your_project_id -REACT_APP_FIREBASE_STORAGE_BUCKET=your_project.firebasestorage.app -REACT_APP_FIREBASE_MESSAGING_SENDER_ID=your_messaging_sender_id -REACT_APP_FIREBASE_APP_ID=your_app_id -REACT_APP_FIREBASE_MEASUREMENT_ID=your_measurement_id +REACT_APP_FIREBASE_API_KEY="AIzaSyD7g330-A1CGgYElN4s88CS2RMR5pRyJnw" +REACT_APP_FIREBASE_AUTH_DOMAIN="nexus-657c3.firebaseapp.com" +REACT_APP_FIREBASE_PROJECT_ID="nexus-657c3" +REACT_APP_FIREBASE_STORAGE_BUCKET="nexus-657c3.firebasestorage.app" +REACT_APP_FIREBASE_MESSAGING_SENDER_ID="875080966871" +REACT_APP_FIREBASE_APP_ID="1:875080966871:web:f51ef8679e56b5a86a8692" +REACT_APP_FIREBASE_MEASUREMENT_ID="G-6XMGFFC9NL" -# TMDB API Configuration -REACT_APP_TMDB_API_KEY=your_tmdb_api_key_here -REACT_APP_TMDB_ACCESS_TOKEN=your_tmdb_access_token_here +# Optional: TMDB API (for real data) +REACT_APP_TMDB_API_KEY=your_tmdb_api_key +REACT_APP_TMDB_ACCESS_TOKEN=your_tmdb_access_token \ No newline at end of file diff --git a/src/components/Login.js b/src/components/Login.js index d555aa6..0a26055 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -1,4 +1,4 @@ -import React, { useRef, useState } from "react"; +import React, { useRef, useState, useEffect } from "react"; import { useDispatch } from "react-redux"; import { addUser } from "../utils/userSlice"; import { checkValidatedata } from "../utils/validate"; @@ -9,12 +9,15 @@ import { updateProfile, } from "firebase/auth"; import { useNavigate, useLocation } from "react-router-dom"; +import { Mail, Lock, User, LogIn, UserPlus, Sparkles, Shield, Zap, CheckCircle2 } from 'lucide-react'; -// Enhanced Login component with better responsiveness and animations const Login = () => { const [isSignInForm, setIsSignInForm] = useState(true); const [errorMessage, setErrorMessage] = useState(null); + const [successMessage, setSuccessMessage] = useState(null); const [isLoading, setIsLoading] = useState(false); + const [focusedField, setFocusedField] = useState(null); + const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); const nameRef = useRef(null); const emailRef = useRef(null); const passwordRef = useRef(null); @@ -22,13 +25,22 @@ const Login = () => { const location = useLocation(); const dispatch = useDispatch(); - // Get the intended destination from location state, default to /browse const from = location.state?.from || '/browse'; + // Track mouse position for interactive effects + useEffect(() => { + const handleMouseMove = (e) => { + setMousePosition({ x: e.clientX, y: e.clientY }); + }; + window.addEventListener('mousemove', handleMouseMove); + return () => window.removeEventListener('mousemove', handleMouseMove); + }, []); + const handleButtonClick = async () => { setIsLoading(true); + setErrorMessage(null); + setSuccessMessage(null); - // Validate the user credentials const email = emailRef.current.value; const password = passwordRef.current.value; const name = !isSignInForm && nameRef.current ? nameRef.current.value : ""; @@ -38,42 +50,30 @@ const Login = () => { if (message) { setIsLoading(false); - return; // Stop if validation fails + return; } - // Sign in and sign up logic if (!isSignInForm) { - // Sign up logic try { - const userCredential = await createUserWithEmailAndPassword( - auth, - email, - password - ); - // Signed up successfully + const userCredential = await createUserWithEmailAndPassword(auth, email, password); const user = userCredential.user; - await updateProfile(auth.currentUser, { - displayName: name, - }); - // Update Redux user state + await updateProfile(auth.currentUser, { displayName: name }); + dispatch(addUser({ uid: user.uid, email: user.email, displayName: name, })); - setErrorMessage(null); - navigate(from, { replace: true }); + + setSuccessMessage("Account created successfully! Redirecting..."); + setTimeout(() => navigate(from, { replace: true }), 1500); } catch (error) { const errorCode = error.code; - const errorMessage = error.message; - console.error("Sign up error:", errorCode, errorMessage); - - // Provide user-friendly error messages let friendlyMessage = ""; + switch (errorCode) { case 'auth/email-already-in-use': - friendlyMessage = "This email is already registered. Please sign in instead or use a different email."; - // Auto-switch to sign-in mode for better UX + friendlyMessage = "This email is already registered. Please sign in instead."; setTimeout(() => { setIsSignInForm(true); setErrorMessage("Switched to Sign In - this email is already registered."); @@ -85,36 +85,29 @@ const Login = () => { case 'auth/invalid-email': friendlyMessage = "Please enter a valid email address."; break; - case 'auth/operation-not-allowed': - friendlyMessage = "Email/password accounts are not enabled. Please contact support."; - break; default: - friendlyMessage = `Sign Up Failed: ${errorMessage}`; + friendlyMessage = `Sign Up Failed: ${error.message}`; } setErrorMessage(friendlyMessage); } } else { - // Sign in logic signInWithEmailAndPassword(auth, email, password) .then((userCredential) => { const user = userCredential.user; - // Update Redux user state dispatch(addUser({ uid: user.uid, email: user.email, displayName: user.displayName, })); - setErrorMessage(null); - navigate(from, { replace: true }); + + setSuccessMessage("Signed in successfully! Redirecting..."); + setTimeout(() => navigate(from, { replace: true }), 1500); }) .catch((error) => { const errorCode = error.code; - const errorMessage = error.message; - console.error("Sign In error:", errorCode, errorMessage); - - // Provide user-friendly error messages let friendlyMessage = ""; + switch (errorCode) { case 'auth/user-not-found': friendlyMessage = "No account found with this email. Please sign up first."; @@ -128,14 +121,11 @@ const Login = () => { case 'auth/too-many-requests': friendlyMessage = "Too many failed attempts. Please try again later."; break; - case 'auth/user-disabled': - friendlyMessage = "This account has been disabled. Please contact support."; - break; case 'auth/invalid-credential': friendlyMessage = "Invalid email or password. Please check your credentials."; break; default: - friendlyMessage = `Sign In Failed: ${errorMessage}`; + friendlyMessage = `Sign In Failed: ${error.message}`; } setErrorMessage(friendlyMessage); @@ -147,12 +137,13 @@ const Login = () => { const toggleSignInForm = () => { setIsSignInForm(!isSignInForm); - setErrorMessage(null); // Clear error message when toggling form + setErrorMessage(null); + setSuccessMessage(null); }; return (
- {/* Enhanced Background with Parallax Effect */} + {/* Enhanced Background */}
{ backgroundSize: '30px 30px', animation: 'gridMove 20s linear infinite' }} /> + {/* Floating orbs */} +
+
- {/* Enhanced Gradient Overlays */} + {/* Gradient Overlays */}
+ + {/* Interactive cursor glow */} +
- {/* Ultra Responsive Main Content Area - Account for header height */} + {/* Main Content */}
- {/* Left Side - Ultra Responsive Hero Content */} + {/* Left Side - Hero Content */}
- {/* Ultra Responsive Main Headline */} + {/* Main Headline */}

{

- {/* Ultra Responsive Feature Cards - Compact 2x2 Grid */} + {/* Feature Cards */}
{[ { - icon: ( - - - - ), + Icon: Sparkles, title: "Premium Content", - desc: "Latest blockbusters and trending series" + desc: "Latest blockbusters and trending series", + color: "from-red-500 to-orange-500" }, { - icon: ( - - - - ), + Icon: Zap, title: "4K Streaming", - desc: "Ultra-high definition quality" + desc: "Ultra-high definition quality", + color: "from-purple-500 to-pink-500" }, { - icon: ( - - - - ), + Icon: Shield, title: "No Ads", - desc: "Uninterrupted viewing experience" + desc: "Uninterrupted viewing experience", + color: "from-green-500 to-emerald-500" }, { - icon: ( - - - - ), + Icon: Sparkles, title: "Multi-Device", - desc: "Watch anywhere, anytime" + desc: "Watch anywhere, anytime", + color: "from-blue-500 to-cyan-500" } - ].map((feature, index) => ( -
-
-
- {feature.icon} + ].map((feature, index) => { + const { Icon, title, desc, color } = feature; + return ( +
+
+ +
+
+
+ +
+

{title}

+
+

+ {desc} +

-

{feature.title}

-

- {feature.desc} -

-
- ))} + ); + })}
- {/* Simplified Call to Action */} + {/* Call to Action */}
@@ -266,136 +264,183 @@ const Login = () => {
- {/* Right Side - Ultra Responsive Login Form */} + {/* Right Side - Login Form */}
-
- {/* Ultra Responsive Animated Background Elements */} -
+
+ {/* Animated Background Glow */} +
e.preventDefault()} - className="relative bg-black/70 sm:bg-black/80 backdrop-blur-2xl p-3 sm:p-4 md:p-5 lg:p-6 rounded-xl shadow-2xl border border-red-900/30 hover:border-red-500/50 transition-all duration-500 animate-fade-in-delayed-2" + className="relative bg-gradient-to-br from-black/80 via-gray-900/80 to-black/80 backdrop-blur-3xl p-4 sm:p-5 md:p-6 lg:p-8 rounded-2xl shadow-2xl border border-white/10 hover:border-white/20 transition-all duration-500" > - {/* Ultra Responsive Header */} -
-
-
- - - + {/* Shine effect */} +
+
+
+ + {/* Header */} +
+
+
+
+
+ {isSignInForm ? ( + + ) : ( + + )} +
-

- {isSignInForm ? "SIGN IN" : "CREATE ACCOUNT"} +

+ {isSignInForm ? "Welcome Back" : "Get Started"}

-
-

+

+
+
+
+

{isSignInForm ? "Enter your credentials to continue" : "Join the streaming revolution"}

- {/* Ultra Responsive Form Fields */} -
+ {/* Form Fields */} +
{!isSignInForm && (
+
+ +
setFocusedField('name')} + onBlur={() => setFocusedField(null)} + className="w-full pl-10 sm:pl-12 pr-4 py-3 sm:py-4 bg-white/5 backdrop-blur-sm rounded-xl text-white placeholder-gray-500 focus:outline-none border border-white/10 focus:border-red-500/50 hover:border-white/20 transition-all duration-300 text-sm sm:text-base" /> -
+
)}
+
+ +
setFocusedField('email')} + onBlur={() => setFocusedField(null)} + className="w-full pl-10 sm:pl-12 pr-4 py-3 sm:py-4 bg-white/5 backdrop-blur-sm rounded-xl text-white placeholder-gray-500 focus:outline-none border border-white/10 focus:border-red-500/50 hover:border-white/20 transition-all duration-300 text-sm sm:text-base" /> -
+
+
+ +
setFocusedField('password')} + onBlur={() => setFocusedField(null)} + className="w-full pl-10 sm:pl-12 pr-4 py-3 sm:py-4 bg-white/5 backdrop-blur-sm rounded-xl text-white placeholder-gray-500 focus:outline-none border border-white/10 focus:border-red-500/50 hover:border-white/20 transition-all duration-300 text-sm sm:text-base" /> -
+
- {/* Password Requirements for Sign Up - Updated validation display */} + {/* Password Requirements for Sign Up */} {!isSignInForm && ( -
-

Password Requirements:

-
-
-
- 8-32 characters -
-
-
- One number (0-9) -
-
-
- One lowercase (a-z) -
-
-
- One uppercase (A-Z) -
+
+

Password Requirements:

+
+ {[ + "8-32 characters", + "One number (0-9)", + "One lowercase (a-z)", + "One uppercase (A-Z)" + ].map((req, idx) => ( +
+
+ {req} +
+ ))} +
+
+ )} + + {/* Success Message */} + {successMessage && ( +
+
+ +

+ {successMessage} +

)} + {/* Error Message */} {errorMessage && ( -
+
- + -

+

{errorMessage}

)} - {/* Ultra Responsive Action Button */} -
+ {/* Action Button */} +
- {/* Ultra Responsive Footer Options */} -
+ {/* Footer Options */} +
- {/* Sign Up Instructions */} + {/* Sign Up Info */} {!isSignInForm && ( -
+
- +
@@ -426,10 +471,10 @@ const Login = () => {
)} - {/* Ultra Responsive Toggle Section */} -
-
-

+ {/* Toggle Section */} +

+
+

{isSignInForm ? "Don't have an account?" : "Already have an account?"}{" "}

- {/* Ultra Responsive Bottom Footer */} + {/* Bottom Footer */}
diff --git a/src/components/LoginOld.js b/src/components/LoginOld.js new file mode 100644 index 0000000..9690391 --- /dev/null +++ b/src/components/LoginOld.js @@ -0,0 +1,482 @@ +import React, { useRef, useState, useEffect } from "react"; +import { useDispatch } from "react-redux"; +import { addUser } from "../utils/userSlice"; +import { checkValidatedata } from "../utils/validate"; +import { auth } from "../utils/firebase"; +import { + createUserWithEmailAndPassword, + signInWithEmailAndPassword, + updateProfile, +} from "firebase/auth"; +import { useNavigate, useLocation } from "react-router-dom"; +import { Mail, Lock, User, LogIn, UserPlus, Sparkles, Shield, Zap } from 'lucide-react'; + +// Enhanced Login component with better responsiveness and animations +const Login = () => { + const [isSignInForm, setIsSignInForm] = useState(true); + const [errorMessage, setErrorMessage] = useState(null); + const [successMessage, setSuccessMessage] = useState(null); + const [isLoading, setIsLoading] = useState(false); + const [focusedField, setFocusedField] = useState(null); + const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); + const nameRef = useRef(null); + const emailRef = useRef(null); + const passwordRef = useRef(null); + const navigate = useNavigate(); + const location = useLocation(); + const dispatch = useDispatch(); + + // Get the intended destination from location state, default to /browse + const from = location.state?.from || '/browse'; + + // Track mouse position for interactive effects + useEffect(() => { + const handleMouseMove = (e) => { + setMousePosition({ x: e.clientX, y: e.clientY }); + }; + window.addEventListener('mousemove', handleMouseMove); + return () => window.removeEventListener('mousemove', handleMouseMove); + }, []); + + const handleButtonClick = async () => { + setIsLoading(true); + + // Validate the user credentials + const email = emailRef.current.value; + const password = passwordRef.current.value; + const name = !isSignInForm && nameRef.current ? nameRef.current.value : ""; + + const message = checkValidatedata(email, password); + setErrorMessage(message); + + if (message) { + setIsLoading(false); + return; // Stop if validation fails + } + + // Sign in and sign up logic + if (!isSignInForm) { + // Sign up logic + try { + const userCredential = await createUserWithEmailAndPassword( + auth, + email, + password + ); + // Signed up successfully + const user = userCredential.user; + await updateProfile(auth.currentUser, { + displayName: name, + }); + // Update Redux user state + dispatch(addUser({ + uid: user.uid, + email: user.email, + displayName: name, + })); + setErrorMessage(null); + navigate(from, { replace: true }); + } catch (error) { + const errorCode = error.code; + const errorMessage = error.message; + console.error("Sign up error:", errorCode, errorMessage); + + // Provide user-friendly error messages + let friendlyMessage = ""; + switch (errorCode) { + case 'auth/email-already-in-use': + friendlyMessage = "This email is already registered. Please sign in instead or use a different email."; + // Auto-switch to sign-in mode for better UX + setTimeout(() => { + setIsSignInForm(true); + setErrorMessage("Switched to Sign In - this email is already registered."); + }, 2000); + break; + case 'auth/weak-password': + friendlyMessage = "Password should be at least 6 characters long."; + break; + case 'auth/invalid-email': + friendlyMessage = "Please enter a valid email address."; + break; + case 'auth/operation-not-allowed': + friendlyMessage = "Email/password accounts are not enabled. Please contact support."; + break; + default: + friendlyMessage = `Sign Up Failed: ${errorMessage}`; + } + + setErrorMessage(friendlyMessage); + } + } else { + // Sign in logic + signInWithEmailAndPassword(auth, email, password) + .then((userCredential) => { + const user = userCredential.user; + // Update Redux user state + dispatch(addUser({ + uid: user.uid, + email: user.email, + displayName: user.displayName, + })); + setErrorMessage(null); + navigate(from, { replace: true }); + }) + .catch((error) => { + const errorCode = error.code; + const errorMessage = error.message; + console.error("Sign In error:", errorCode, errorMessage); + + // Provide user-friendly error messages + let friendlyMessage = ""; + switch (errorCode) { + case 'auth/user-not-found': + friendlyMessage = "No account found with this email. Please sign up first."; + break; + case 'auth/wrong-password': + friendlyMessage = "Incorrect password. Please try again."; + break; + case 'auth/invalid-email': + friendlyMessage = "Please enter a valid email address."; + break; + case 'auth/too-many-requests': + friendlyMessage = "Too many failed attempts. Please try again later."; + break; + case 'auth/user-disabled': + friendlyMessage = "This account has been disabled. Please contact support."; + break; + case 'auth/invalid-credential': + friendlyMessage = "Invalid email or password. Please check your credentials."; + break; + default: + friendlyMessage = `Sign In Failed: ${errorMessage}`; + } + + setErrorMessage(friendlyMessage); + }); + } + + setIsLoading(false); + }; + + const toggleSignInForm = () => { + setIsSignInForm(!isSignInForm); + setErrorMessage(null); // Clear error message when toggling form + }; + + return ( +
+ {/* Enhanced Background with Parallax Effect */} +
+
+ {/* Animated Grid Overlay */} +
+
+ + {/* Enhanced Gradient Overlays */} +
+
+ + {/* Ultra Responsive Main Content Area - Account for header height */} +
+ {/* Left Side - Ultra Responsive Hero Content */} +
+
+ {/* Ultra Responsive Main Headline */} +
+

+ STREAM THE + FUTURE +

+

+ Access unlimited movies and TV shows on demand +

+
+ + {/* Ultra Responsive Feature Cards - Compact 2x2 Grid */} +
+ {[ + { + icon: ( + + + + ), + title: "Premium Content", + desc: "Latest blockbusters and trending series" + }, + { + icon: ( + + + + ), + title: "4K Streaming", + desc: "Ultra-high definition quality" + }, + { + icon: ( + + + + ), + title: "No Ads", + desc: "Uninterrupted viewing experience" + }, + { + icon: ( + + + + ), + title: "Multi-Device", + desc: "Watch anywhere, anytime" + } + ].map((feature, index) => ( +
+
+
+ {feature.icon} +
+

{feature.title}

+
+

+ {feature.desc} +

+
+ ))} +
+ + {/* Simplified Call to Action */} +
+
+
+ Streaming servers online • Platform ready +
+
+
+
+ + {/* Right Side - Ultra Responsive Login Form */} +
+
+ {/* Ultra Responsive Animated Background Elements */} +
+ + e.preventDefault()} + className="relative bg-black/70 sm:bg-black/80 backdrop-blur-2xl p-3 sm:p-4 md:p-5 lg:p-6 rounded-xl shadow-2xl border border-red-900/30 hover:border-red-500/50 transition-all duration-500 animate-fade-in-delayed-2" + > + {/* Ultra Responsive Header */} +
+
+
+ + + +
+

+ {isSignInForm ? "SIGN IN" : "CREATE ACCOUNT"} +

+
+

+ {isSignInForm ? "Enter your credentials to continue" : "Join the streaming revolution"} +

+
+
+ + {/* Ultra Responsive Form Fields */} +
+ {!isSignInForm && ( +
+ +
+
+ )} + +
+ +
+
+ +
+ +
+
+ + {/* Password Requirements for Sign Up - Updated validation display */} + {!isSignInForm && ( +
+

Password Requirements:

+
+
+
+ 8-32 characters +
+
+
+ One number (0-9) +
+
+
+ One lowercase (a-z) +
+
+
+ One uppercase (A-Z) +
+
+
+ )} + + {errorMessage && ( +
+
+ + + +

+ {errorMessage} +

+
+
+ )} + + {/* Ultra Responsive Action Button */} +
+ +
+
+ + {/* Ultra Responsive Footer Options */} +
+ + +
+ + {/* Sign Up Instructions */} + {!isSignInForm && ( +
+
+ + + +
+

Demo Account Info:

+

+ You can use any random email and password for testing. No real verification required! +

+
+
+
+ )} + + {/* Ultra Responsive Toggle Section */} +
+
+

+ {isSignInForm ? "Don't have an account?" : "Already have an account?"}{" "} + +

+

+ Secure & encrypted.{" "} + +

+
+ +
+
+
+ + {/* Ultra Responsive Bottom Footer */} +
+
+
+ © 2025 NEXUS • Premium Streaming +
+
+
+
+ ); +}; + +export default Login;