"use client"; import { useState, useEffect } from "react"; type AuthModalProps = { open: "login" | "register" | null; onClose: () => void; onSwitch: (mode: "login" | "register") => void; }; export default function AuthModal({ open, onClose, onSwitch }: AuthModalProps) { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [firstName, setFirstName] = useState(""); const [lastName, setLastName] = useState(""); const [msg, setMsg] = useState(""); const [busy, setBusy] = useState(false); const [passwordStrength, setPasswordStrength] = useState<{ met: boolean; missing: string[]; }>({ met: false, missing: [] }); const [providers, setProviders] = useState<{ google?: boolean; github?: boolean; facebook?: boolean; discord?: boolean; }>({}); useEffect(() => { const handleEscape = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", handleEscape); return () => window.removeEventListener("keydown", handleEscape); }, [onClose]); useEffect(() => { setMsg(""); setEmail(""); setPassword(""); setConfirmPassword(""); setFirstName(""); setLastName(""); }, [open]); // Load OAuth provider configuration useEffect(() => { const loadProviders = async () => { try { const res = await fetch("/api/public/app-setup"); const data = await res.json(); if (data.setup?.data?.oauth) { setProviders({ google: data.setup.data.oauth.google?.enabled, github: data.setup.data.oauth.github?.enabled, facebook: data.setup.data.oauth.facebook?.enabled, discord: data.setup.data.oauth.discord?.enabled, }); } } catch (err) { console.error("Failed to load OAuth providers:", err); } }; loadProviders(); }, []); // Validate password strength useEffect(() => { const missing: string[] = []; if (password.length < 8 || password.length > 20) missing.push("8-20 characters"); if (!/[A-Z]/.test(password)) missing.push("uppercase letter"); if (!/\d/.test(password)) missing.push("number"); if (/\s/.test(password)) missing.push("no spaces"); setPasswordStrength({ met: missing.length === 0, missing }); }, [password]); const handleSignUp = async (e: React.FormEvent) => { e.preventDefault(); setBusy(true); setMsg(""); try { if (!firstName.trim() || !lastName.trim()) { setMsg("First and last name are required"); setBusy(false); return; } if (password !== confirmPassword) { setMsg("Passwords do not match"); setBusy(false); return; } if (!passwordStrength.met) { setMsg(`Password must contain: ${passwordStrength.missing.join(", ")}`); setBusy(false); return; } const res = await fetch("/api/auth/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ firstName, lastName, email, password, confirmPassword, }), }); const data = await res.json(); if (!data.ok) { setMsg(data.message || "Sign up failed"); setBusy(false); return; } setMsg("✅ Account created! Redirecting..."); setTimeout(() => { window.location.href = "/account/webinars"; }, 1500); } catch (err: any) { setMsg(err?.message || "Sign up failed. Please try again."); setBusy(false); } }; const handleSignIn = async (e: React.FormEvent) => { e.preventDefault(); setBusy(true); setMsg(""); try { const res = await fetch("/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }), }); const data = await res.json(); if (!data.ok) { setMsg(data.message || "Sign in failed"); setBusy(false); return; } // Redirect based on user role const userRole = data.user?.role; if (userRole === "ADMIN") { window.location.href = "/admin"; } else { window.location.href = "/account/webinars"; } } catch (err: any) { setMsg(err?.message || "Sign in failed. Please try again."); setBusy(false); } }; const handleOAuthSignIn = async (provider: "google" | "github" | "facebook" | "discord") => { try { setBusy(true); // Better Auth OAuth flow: Redirect to /api/auth/{provider} // BetterAuth will handle the redirect to the provider's OAuth endpoint const redirectUrl = `/api/auth/${provider}`; // Get the provider's OAuth authorization URL const res = await fetch(`${redirectUrl}?action=signin`, { method: "GET", }); if (!res.ok) { throw new Error(`OAuth redirect failed: ${res.statusText}`); } // BetterAuth returns a redirect, follow it window.location.href = redirectUrl; } catch (err: any) { setMsg(`${provider} sign in failed. Please try again.`); setBusy(false); } }; if (!open) return null; return (

{open === "login" ? "👤 Sign In" : "🚀 Sign Up"}

{open === "register" && ( <> setFirstName(e.target.value)} className="input-field w-full mb-4" disabled={busy} /> setLastName(e.target.value)} className="input-field w-full mb-4" disabled={busy} /> )} setEmail(e.target.value)} className="input-field w-full mb-4" disabled={busy} /> setPassword(e.target.value)} className="input-field w-full mb-2" disabled={busy} /> {open === "register" && ( <>
{password && (
{[ { label: "8-20 chars", check: password.length >= 8 && password.length <= 20 }, { label: "Uppercase", check: /[A-Z]/.test(password) }, { label: "Number", check: /\d/.test(password) }, { label: "No spaces", check: !/\s/.test(password) }, ].map(({ label, check }) => (
{check ? "✅" : "❌"} {label}
))}
)}
setConfirmPassword(e.target.value)} className="input-field w-full mb-4" disabled={busy} /> )} {msg && (
{msg}
)} {/* OAuth Buttons */} {Object.values(providers).some(p => p) && ( <>
Or continue with
{providers.google && ( )} {providers.github && ( )} {providers.facebook && ( )} {providers.discord && ( )}
)}
{open === "login" ? "Don't have an account? " : "Already have an account? "}
); }