"use client"; import React, { useState } from "react"; import { useRouter } from "next/navigation"; import Link from "next/link"; import { signInWithGoogle, sendVerificationLink, registerUserWithInvite } from "@/lib/auth"; import { GradientText } from "@/components/ui/gradient-text"; import { GoogleLoginButton } from "@/components/ui/google-login-button"; import { Eye, EyeOff, Mail, PartyPopper } from "lucide-react"; import { isGoogleLoginEnabled } from "@/lib/server-config"; import { fetchSettingByCode } from "@/api/serversetting"; import { useDeviceType } from "@/hooks/useDeviceType"; export default function SignupPage() { const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [inviteCode, setInviteCode] = useState(""); const [isSubmitting, setIsSubmitting] = useState(false); const [formError, setFormError] = useState(""); const [passwordError, setPasswordError] = useState(""); const [showPassword, setShowPassword] = useState(false); const [agreeToTerms, setAgreeToTerms] = useState(true); const [showActivationModal, setShowActivationModal] = useState(false); const [resendCooldown, setResendCooldown] = useState(60); const [resendLoading, setResendLoading] = useState(false); const [resendMessage, setResendMessage] = useState(""); const [resendError, setResendError] = useState(""); const [googleLoading, setGoogleLoading] = useState(false); const [emailFocused, setEmailFocused] = useState(false); const [passwordFocused, setPasswordFocused] = useState(false); const [showGoogleLogin, setShowGoogleLogin] = useState(false); const [showRedirectModal, setShowRedirectModal] = useState(false); const router = useRouter(); const { isMobile } = useDeviceType(); // Handle scroll indicator for small screens and load SSO config React.useEffect(() => { try { const url = new URL(window.location.href); const codeFromUrl = url.searchParams.get("inviteCode"); const codeFromSession = sessionStorage.getItem("inviteCode"); const code = codeFromUrl || codeFromSession || ""; if (code) { setInviteCode(code); sessionStorage.setItem("inviteCode", code); } } catch (err) {} // 检查是否启用Google登录 const checkGoogleLoginStatus = async () => { try { const enabled = await isGoogleLoginEnabled(); setShowGoogleLogin(enabled); } catch (error) { console.error("Failed to check Google login status:", error); setShowGoogleLogin(false); } }; checkGoogleLoginStatus(); const handleScroll = () => { const scrollableElement = document.querySelector('.signup-form > div:nth-child(2)'); const formElement = document.querySelector('.signup-form'); if (scrollableElement && formElement) { const hasScroll = scrollableElement.scrollHeight > scrollableElement.clientHeight; const isScrolledToBottom = scrollableElement.scrollTop + scrollableElement.clientHeight >= scrollableElement.scrollHeight - 10; if (hasScroll && !isScrolledToBottom) { formElement.classList.add('has-scroll'); } else { formElement.classList.remove('has-scroll'); } } }; const scrollableElement = document.querySelector('.signup-form > div:nth-child(2)'); if (scrollableElement) { scrollableElement.addEventListener('scroll', handleScroll); // Check initially handleScroll(); return () => { scrollableElement.removeEventListener('scroll', handleScroll); }; } }, []); /** Password validation function with English prompts */ const validatePassword = (password: string): string => { if (password.length < 8) { return "Password must be at least 8 characters"; } if (password.length > 18) { return "Password cannot exceed 18 characters"; } if (!/^(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z\d!@#$%^*&\.]{8,18}$/.test(password)) { return "Password must contain both letters and numbers"; } return ""; }; /** Get quick link to email provider by domain */ const getEmailProviderLink = (addr: string): string | undefined => { const domain = addr.split("@")[1]?.toLowerCase(); if (!domain) return undefined; const map: Record = { "gmail.com": "https://mail.google.com", "outlook.com": "https://outlook.live.com/mail", "hotmail.com": "https://outlook.live.com/mail", "live.com": "https://outlook.live.com/mail", "yahoo.com": "https://mail.yahoo.com", "icloud.com": "https://www.icloud.com/mail", "qq.com": "https://mail.qq.com", "163.com": "https://mail.163.com", "126.com": "https://mail.126.com", "yeah.net": "https://mail.yeah.net", }; return map[domain]; }; /** Handle resend activation email */ const handleResend = async () => { if (resendCooldown > 0 || resendLoading) return; try { setResendLoading(true); setResendMessage(""); setResendError(""); await sendVerificationLink(email); setResendMessage("Resent. Please check your email."); setResendCooldown(60); } catch (err: any) { setResendError(err?.message || "Sending failed, please try again later"); } finally { setResendLoading(false); } }; /** Countdown for resend button */ React.useEffect(() => { if (!showActivationModal) return; if (resendCooldown <= 0) return; const timer = setInterval(() => { setResendCooldown((s) => (s > 0 ? s - 1 : 0)); }, 1000); return () => clearInterval(timer); }, [showActivationModal, resendCooldown]); /** Handle Terms of Service click */ const handleTermsClick = () => { window.open("/Terms", "_blank"); }; /** Handle Privacy Policy click */ const handlePrivacyClick = () => { window.open("/Privacy", "_blank"); }; /** 处理密码输入变化 */ const handlePasswordChange = (e: React.ChangeEvent) => { const newPassword = e.target.value; setPassword(newPassword); if (newPassword) { const error = validatePassword(newPassword); setPasswordError(error); } else { setPasswordError(""); } }; const handleGoogleSignIn = async () => { try { setGoogleLoading(true); setFormError(""); // signInWithGoogle now returns a promise and may throw errors await signInWithGoogle(); } catch (error: any) { console.error("Google sign-in error:", error); setFormError(error.message || "Google sign-in failed, please try again"); setGoogleLoading(false); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); // 验证密码 const passwordValidationError = validatePassword(password); if (passwordValidationError) { setPasswordError(passwordValidationError); return; } // 验证是否同意条款 if (!agreeToTerms) { setFormError("Please agree to the Terms of Service and Privacy Policy"); return; } setIsSubmitting(true); setFormError(""); try { // Use new registration API const response = await registerUserWithInvite({ email, password, invite_code: inviteCode || undefined, }); // Clear inviteCode after successful registration try { sessionStorage.removeItem("inviteCode"); } catch {} // 根据服务端配置是否展示激活弹窗 try { const showActivation = await fetchSettingByCode<{show: boolean}>("showActivation", {show: true}); if (showActivation?.show === true) { setShowActivationModal(true); setResendCooldown(60); } else { setShowRedirectModal(true); setTimeout(() => { router.push("/login"); }, 1500); } } catch {} } catch (error: any) { console.error("Signup error:", error); setFormError(error.message || "Registration failed, please try again"); } finally { setIsSubmitting(false); } }; return ( <>
{/* Height-responsive container styles */} {/* 背景视频 */} {/* 视频遮罩层 */}
{/* Logo */}
router.push("/")} > {/* beta标签 */} Beta
{/* 注册框 - 响应式高度显示 */}
{/* Fixed Header */}

Sign Up, for free

Start Turning Your Ideas Into Incredible Videos

{/* Scrollable Middle Content */}
setEmail(e.target.value)} onFocus={() => setEmailFocused(true)} onBlur={() => setEmailFocused(false)} required className={`w-full px-4 py-3 rounded-lg bg-black/30 border border-white/20 text-white placeholder-gray-400 focus:outline-none focus:ring-1 focus:border-custom-blue/80 ${isMobile ? 'mobile-input' : ''}`} />
setPasswordFocused(true)} onBlur={() => setPasswordFocused(false)} required className={`w-full px-4 py-3 pr-12 rounded-lg bg-black/30 border border-white/20 text-white placeholder-gray-400 focus:outline-none focus:ring-1 focus:border-custom-blue/80 ${ passwordError ? "border-red-500/50" : "border-white/20" } ${isMobile ? 'mobile-input' : ''}`} />
{passwordError && (

{passwordError}

)}
{formError && (
{formError}
)}
Back to login
{/* Fixed Footer */}
{/* Google登录按钮 - 根据服务端配置显示/隐藏 */} {showGoogleLogin && ( <>
or
)}

Already have an account?{" "} Sign in

{' '}
{showActivationModal && (

Please verify your email to activate your account

We have sent an activation email to {email || "your email"}; if you don't receive it, please check your spam folder or try again later

{(() => { const provider = getEmailProviderLink(email); if (!provider) return null; const domain = email.split("@")[1] || "email"; return ( Open {domain} ); })()}
{(resendMessage || resendError) && (
{resendError || resendMessage}
)}
)} {showRedirectModal && (

Sign up successful

Please wait a moment, redirecting to login...

)} ); }