import React, { useState, useEffect } from 'react' import { useAuth } from '../contexts/AuthContext' import { useLanguage } from '../contexts/LanguageContext' import { t } from '../i18n/translations' import { getSystemConfig } from '../lib/config' import HeaderBar from './landing/HeaderBar' export function RegisterPage() { const { language } = useLanguage() const { register, completeRegistration } = useAuth() const [step, setStep] = useState<'register' | 'setup-otp' | 'verify-otp'>( 'register' ) const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [confirmPassword, setConfirmPassword] = useState('') const [betaCode, setBetaCode] = useState('') const [betaMode, setBetaMode] = useState(false) const [otpCode, setOtpCode] = useState('') const [userID, setUserID] = useState('') const [otpSecret, setOtpSecret] = useState('') const [qrCodeURL, setQrCodeURL] = useState('') const [error, setError] = useState('') const [loading, setLoading] = useState(false) useEffect(() => { // 获取系统配置,检查是否开启内测模式 getSystemConfig() .then((config) => { setBetaMode(config.beta_mode || false) }) .catch((err) => { console.error('Failed to fetch system config:', err) }) }, []) const handleRegister = async (e: React.FormEvent) => { e.preventDefault() setError('') if (password !== confirmPassword) { setError(t('passwordMismatch', language)) return } if (password.length < 6) { setError(t('passwordTooShort', language)) return } if (betaMode && !betaCode.trim()) { setError('内测期间,注册需要提供内测码') return } setLoading(true) const result = await register(email, password, betaCode.trim() || undefined) if (result.success && result.userID) { setUserID(result.userID) setOtpSecret(result.otpSecret || '') setQrCodeURL(result.qrCodeURL || '') setStep('setup-otp') } else { setError(result.message || t('registrationFailed', language)) } setLoading(false) } const handleSetupComplete = () => { setStep('verify-otp') } const handleOTPVerify = async (e: React.FormEvent) => { e.preventDefault() setError('') setLoading(true) const result = await completeRegistration(userID, otpCode) if (!result.success) { setError(result.message || t('registrationFailed', language)) } // 成功的话AuthContext会自动处理登录状态 setLoading(false) } const copyToClipboard = (text: string) => { navigator.clipboard.writeText(text) } return (
{}} onPageChange={(page) => { console.log('RegisterPage onPageChange called with:', page) if (page === 'competition') { window.location.href = '/competition' } }} />
{/* Logo */}
NoFx Logo

{t('appTitle', language)}

{step === 'register' && t('registerTitle', language)} {step === 'setup-otp' && t('setupTwoFactor', language)} {step === 'verify-otp' && t('verifyOTP', language)}

{/* Registration Form */}
{step === 'register' && (
setEmail(e.target.value)} className="w-full px-3 py-2 rounded" style={{ background: 'var(--brand-black)', border: '1px solid var(--panel-border)', color: 'var(--brand-light-gray)', }} placeholder={t('emailPlaceholder', language)} required />
setPassword(e.target.value)} className="w-full px-3 py-2 rounded" style={{ background: 'var(--brand-black)', border: '1px solid var(--panel-border)', color: 'var(--brand-light-gray)', }} placeholder={t('passwordPlaceholder', language)} required />
setConfirmPassword(e.target.value)} className="w-full px-3 py-2 rounded" style={{ background: 'var(--brand-black)', border: '1px solid var(--panel-border)', color: 'var(--brand-light-gray)', }} placeholder={t('confirmPasswordPlaceholder', language)} required />
{betaMode && (
setBetaCode( e.target.value .replace(/[^a-z0-9]/gi, '') .toLowerCase() ) } className="w-full px-3 py-2 rounded font-mono" style={{ background: '#0B0E11', border: '1px solid #2B3139', color: '#EAECEF', }} placeholder="请输入6位内测码" maxLength={6} required={betaMode} />

内测码由6位字母数字组成,区分大小写

)} {error && (
{error}
)}
)} {step === 'setup-otp' && (
📱

{t('setupTwoFactor', language)}

{t('setupTwoFactorDesc', language)}

{t('authStep1Title', language)}

{t('authStep1Desc', language)}

{t('authStep2Title', language)}

{t('authStep2Desc', language)}

{qrCodeURL && (

{t('qrCodeHint', language)}

QR Code
)}

{t('otpSecret', language)}

{otpSecret}

{t('authStep3Title', language)}

{t('authStep3Desc', language)}

)} {step === 'verify-otp' && (
🔐

{t('enterOTPCode', language)}
{t('completeRegistrationSubtitle', language)}

setOtpCode(e.target.value.replace(/\D/g, '').slice(0, 6)) } className="w-full px-3 py-2 rounded text-center text-2xl font-mono" style={{ background: 'var(--brand-black)', border: '1px solid var(--panel-border)', color: 'var(--brand-light-gray)', }} placeholder={t('otpPlaceholder', language)} maxLength={6} required />
{error && (
{error}
)}
)}
{/* Login Link */} {step === 'register' && (

已有账户?{' '}

)}
) }