'use client' import Topnav from '@/components/topnav' import Footer from '@/components/footer' import { useEffect, useState } from 'react' import { useRouter } from 'next/navigation' import Link from 'next/link' import { safeNext } from '@/lib/next' import '../styles/signup.css' /* Signup — markup from signup.html, wired to real Payload registration (create + auto-login) instead of the simulated client-only flow. */ export default function SignupPage() { const router = useRouter() const [showPassword, setShowPassword] = useState(false) const [status, setStatus] = useState('') const [email, setEmail] = useState('') const [emailError, setEmailError] = useState(null) const [suggestion, setSuggestion] = useState(null) const [pwOk, setPwOk] = useState(false) const [busy, setBusy] = useState(false) const [nextPath, setNextPath] = useState(null) /* Common typos → canonical domain (step 16; on blur of the email input). */ const EMAIL_TYPOS: Record = { 'gmial.com': 'gmail.com', 'gmai.com': 'gmail.com', 'gmail.co': 'gmail.com', 'hotmial.com': 'hotmail.com', 'outlook.co': 'outlook.com', 'yahoo.co': 'yahoo.com', } function domainSuggestion(raw: string): string | null { const at = raw.lastIndexOf('@') if (at < 0) return null return EMAIL_TYPOS[raw.slice(at + 1).toLowerCase().trim()] ?? null } useEffect(() => { setNextPath(safeNext(new URLSearchParams(window.location.search).get('next'))) }, []) async function onSubmit(e: React.FormEvent) { e.preventDefault() const form = e.currentTarget const data = new FormData(form) setEmailError(null) if (!form.checkValidity()) { setStatus('تحقق من جميع الحقول المطلوبة.') form.reportValidity() return } setBusy(true) setStatus('') try { const res = await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: data.get('email'), password: data.get('password'), fullName: data.get('name'), termsVersion: '2026-10-03' }), }) if (!res.ok) { const err = await res.json().catch(() => null) as { error?: string; errors?: { message?: string; path?: string; field?: string }[] } | null // Middleware 429 shape: { error: 'محاولات كثيرة جدًا. حاول بعد قليل.' } // + Retry-After seconds → show verbatim, append «حاول بعد X دقيقة.» const retryAfterHeader = res.headers.get('Retry-After') if (typeof err?.error === 'string') { const retryAfterSec = Number(retryAfterHeader) setStatus( retryAfterHeader && Number.isFinite(retryAfterSec) ? `${err.error} حاول بعد ${Math.max(1, Math.ceil(retryAfterSec / 60))} دقيقة.` : err.error, ) setBusy(false) return } const first = err?.errors?.[0] const failedField = first?.path ?? first?.field if (failedField === 'email' && first?.message) { // Duplicate email (unique-constraint ValidationError) → inline under // the email input, not the global status line. setEmailError('هذا البريد مسجَّل لدينا.') } else { setStatus(first?.message || 'تعذّر إنشاء الحساب — قد يكون البريد مستخدماً بالفعل.') } setBusy(false) return } const login = await fetch('/api/users/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: data.get('email'), password: data.get('password') }), }) if (login.ok) { try { sessionStorage.setItem('anwarpi:signup-email', String(data.get('email'))) } catch { /* private mode */ } try { nextPath ? sessionStorage.setItem('anwarpi:signup-next', nextPath) : sessionStorage.removeItem('anwarpi:signup-next') } catch { /* private mode */ } router.refresh() router.push('/verify-email') return } setStatus('تم إنشاء الحساب — سجّل الدخول للمتابعة.') router.push(nextPath ? '/login?next=' + encodeURIComponent(nextPath) : '/login') } catch { setStatus('تعذّر الاتصال. حاول مرة أخرى بعد التحقق من اتصالك.') } finally { setBusy(false) } } return (
{/* eslint-disable-next-line @next/next/no-img-element */}

ابدأ بحساب مجاني.

الحساب المجاني يفتح كل الأدلة المجانية كاملة والتعليق عليها. يمكنك الاشتراك في العضوية لاحقاً إن احتجتها.

حساب جديد

إنشاء حساب

أدخل بياناتك الأساسية للبدء.

e.currentTarget.setCustomValidity('أدخل اسمك.')} onInput={e => e.currentTarget.setCustomValidity('')} />
setEmail(e.target.value)} onBlur={e => setSuggestion(domainSuggestion(e.target.value))} onInvalid={e => e.currentTarget.setCustomValidity('أدخل بريداً إلكترونياً صحيحاً.')} onInput={e => e.currentTarget.setCustomValidity('')} /> {emailError && (

هذا البريد مسجَّل لدينا. تسجيل الدخول

)} {!emailError && suggestion && ( )}
e.currentTarget.setCustomValidity('أدخل كلمة مرور من ثمانية أحرف على الأقل.')} onInput={e => { e.currentTarget.setCustomValidity(''); setPwOk(e.currentTarget.value.length >= 8) }} />
ثمانية أحرف على الأقل.

مجاناً — بلا بطاقة ائتمانية. لن نشارك بريدك أبداً.

{status}

لديك حساب بالفعل؟ سجّل الدخول

) }