diff --git a/frontend/app/signup/page.tsx b/frontend/app/signup/page.tsx index 3613ee8..32e9368 100644 --- a/frontend/app/signup/page.tsx +++ b/frontend/app/signup/page.tsx @@ -1,28 +1,52 @@ "use client"; -import { Eye, EyeClosed, Moon, Sun ,StepBack} from "lucide-react"; +import { Eye, EyeClosed, Moon, Sun, StepBack } from "lucide-react"; import { signIn } from "next-auth/react"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; import { BackgroundGradientAnimation } from "../../components/ui/background-gradient-animation"; + export default function SignupPage() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const [isNavigating, setIsNavigating] = useState(false); - const [socialLoading, setSocialLoading] = useState<"github" | "google" | null>(null); + const [socialLoading, setSocialLoading] = useState< + "github" | "google" | null + >(null); const [isDark, setIsDark] = useState(false); const [showPassword, setShowPassword] = useState(false); const router = useRouter(); + // Password rules state + const [passwordRules, setPasswordRules] = useState({ + minLength: false, + uppercase: false, + lowercase: false, + number: false, + specialChar: false, + }); + // Detect initial theme on mount useEffect(() => { if (typeof window !== "undefined") { - const isDarkMode = window.document.documentElement.classList.contains("dark"); + const isDarkMode = + window.document.documentElement.classList.contains("dark"); setIsDark(isDarkMode); } }, []); + // Update password rules on change + useEffect(() => { + setPasswordRules({ + minLength: password.length >= 8, + uppercase: /[A-Z]/.test(password), + lowercase: /[a-z]/.test(password), + number: /[0-9]/.test(password), + specialChar: /[!@#$%^&*(),.?":{}|<>]/.test(password), + }); + }, [password]); + const toggleTheme = () => { setIsDark(!isDark); if (typeof window !== "undefined") { @@ -78,13 +102,13 @@ export default function SignupPage() { const handleSocialSignIn = async (provider: "github" | "google") => { setSocialLoading(provider); setError(""); - + try { - const result = await signIn(provider, { + const result = await signIn(provider, { redirect: false, - callbackUrl: "/dashboard" + callbackUrl: "/dashboard", }); - + if (result?.error) { setError(`Failed to sign up with ${provider}. Please try again.`); } else if (result?.url) { @@ -100,7 +124,6 @@ export default function SignupPage() { if (isNavigating) { return (
- {/* Background Gradient Animation */}
- {/* Exit to Landing Page Button */} - - +
@@ -135,9 +157,10 @@ export default function SignupPage() { ); } + const isPasswordValid = Object.values(passwordRules).every(Boolean); + return (
- {/* Background Gradient Animation */}
- {/* Exit to Landing Page Button */} + - {/* Theme Toggle Button */}
-
-
- setPassword(e.target.value)} - className="w-full px-2 py-2 md:px-4 md:py-3 pr-12 rounded-xl bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-400 dark:focus:border-blue-400 transition-all duration-200" - required - /> - + + {/* Password Policy Checklist */} +
    +
  • + At least 8 characters +
  • +
  • + Contains uppercase letter +
  • +
  • + Contains lowercase letter +
  • +
  • + Contains number +
  • +
  • + Contains special character +
  • +
+ + {error && ( +
+ {error}
-
- {error &&
{error}
} + )} -
+ + {/* Social sign-in buttons */} +
+
- Already have an account? + Already have an account?{" "} +