import { useState } from "react"; import type { FormEvent } from "react"; import { useNavigate } from "react-router-dom"; import { useAuthStore } from "../../stores/authStore"; import { Loader2, Mail, Lock, User, ImageIcon, BookOpen, Star, Zap, Trophy, } from "lucide-react"; const STYLES = ` @import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;700;800;900&family=Nunito+Sans:wght@400;600;700&display=swap'); *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } .rg-root { min-height: 100vh; display: flex; font-family: 'Nunito', sans-serif; background: #fffbf4; } /* ─── LEFT PANEL ─── */ .rg-left { position: relative; width: 50%; min-height: 100vh; background: linear-gradient(150deg, #1e1b4b 0%, #3b1d8a 50%, #6d28d9 100%); display: flex; flex-direction: column; align-items: flex-start; justify-content: center; padding: 3rem 3.5rem; overflow: hidden; flex-shrink: 0; } /* Blobs inside left panel */ .rg-panel-blob { position: absolute; pointer-events: none; border-radius: 50%; opacity: 0.18; } .rg-panel-blob-1 { width: 420px; height: 420px; background: #a855f7; top: -140px; right: -100px; animation: blobDrift1 16s ease-in-out infinite; } .rg-panel-blob-2 { width: 300px; height: 300px; background: #f97316; bottom: -100px; left: -80px; animation: blobDrift2 18s ease-in-out infinite; } .rg-panel-blob-3 { width: 200px; height: 200px; background: #22c55e; top: 50%; left: 50%; transform: translate(-50%, -50%); animation: blobDrift1 14s ease-in-out infinite reverse; } @keyframes blobDrift1 { 0%,100% { transform: translate(0,0) scale(1); } 50% { transform: translate(24px, 32px) scale(1.08); } } @keyframes blobDrift2 { 0%,100% { transform: translate(0,0) scale(1); } 50% { transform: translate(-20px, -28px) scale(1.06); } } /* Floating decorative shapes */ .rg-shape { position: absolute; pointer-events: none; animation: floatShape 8s ease-in-out infinite; } @keyframes floatShape { 0%,100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-16px) rotate(12deg); } } /* Stars scattered */ .rg-star { position: absolute; pointer-events: none; color: #fde68a; opacity: 0.55; animation: twinkle 3s ease-in-out infinite; } @keyframes twinkle { 0%,100% { opacity: 0.55; transform: scale(1); } 50% { opacity: 0.9; transform: scale(1.3); } } /* Left panel content */ .rg-panel-content { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: flex-start; gap: 2.5rem; width: 100%; } .rg-panel-logo { display: flex; align-items: center; gap: 0.75rem; } .rg-panel-logo-badge { width: 48px; height: 48px; border-radius: 14px; background: linear-gradient(135deg, #f97316, #ef4444); display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 0 rgba(0,0,0,0.25), 0 8px 20px rgba(249,115,22,0.4); font-size: 1.4rem; } .rg-panel-logo-text { font-size: 1.4rem; font-weight: 900; color: white; letter-spacing: -0.02em; } .rg-panel-headline { display: flex; flex-direction: column; gap: 0.75rem; } .rg-panel-headline h2 { font-size: 2.4rem; font-weight: 900; line-height: 1.15; color: white; letter-spacing: -0.03em; } .rg-panel-headline h2 span { background: linear-gradient(90deg, #fde68a, #f97316); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .rg-panel-headline p { font-family: 'Nunito Sans', sans-serif; font-size: 1rem; font-weight: 600; color: #c4b5fd; line-height: 1.6; } /* Feature pills */ .rg-features { display: flex; flex-direction: column; gap: 0.85rem; } .rg-feature { display: flex; align-items: center; gap: 0.85rem; background: rgba(255,255,255,0.07); border: 1.5px solid rgba(255,255,255,0.12); border-radius: 14px; padding: 0.85rem 1.1rem; backdrop-filter: blur(8px); animation: fadeSlideIn 0.5s ease both; } .rg-feature:nth-child(1) { animation-delay: 0.1s; } .rg-feature:nth-child(2) { animation-delay: 0.2s; } .rg-feature:nth-child(3) { animation-delay: 0.3s; } @keyframes fadeSlideIn { from { opacity: 0; transform: translateX(-16px); } to { opacity: 1; transform: translateX(0); } } .rg-feature-icon { width: 36px; height: 36px; border-radius: 10px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .rg-feature-text strong { display: block; font-size: 0.85rem; font-weight: 800; color: white; } .rg-feature-text span { font-family: 'Nunito Sans', sans-serif; font-size: 0.75rem; font-weight: 600; color: #a5b4fc; } /* Social proof */ .rg-social-proof { display: flex; align-items: center; gap: 0.75rem; padding: 0.1rem 0; } .rg-avatars { display: flex; } .rg-av { width: 30px; height: 30px; border-radius: 50%; border: 2px solid #3b1d8a; background: linear-gradient(135deg, #a855f7, #6d28d9); margin-left: -8px; display: flex; align-items: center; justify-content: center; font-size: 0.65rem; font-weight: 800; color: white; } .rg-av:first-child { margin-left: 0; } .rg-social-proof p { font-family: 'Nunito Sans', sans-serif; font-size: 0.78rem; font-weight: 700; color: #c4b5fd; } .rg-social-proof p strong { color: #fde68a; } /* ─── RIGHT PANEL (form) ─── */ .rg-right { flex: 1; display: flex; align-items: center; justify-content: center; padding: 3rem 4rem; position: relative; overflow: hidden; } /* Subtle bg dots on right */ .rg-bg-dot { position: absolute; border-radius: 50%; pointer-events: none; opacity: 0.10; animation: bgDotFloat 9s ease-in-out infinite; } @keyframes bgDotFloat { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-12px); } } .rg-form-wrap { position: relative; z-index: 1; width: 100%; max-width: 420px; display: flex; flex-direction: column; gap: 2rem; animation: formPopIn 0.55s cubic-bezier(0.34,1.56,0.64,1) both; } @keyframes formPopIn { from { opacity: 0; transform: translateY(24px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } } /* Form header */ .rg-form-header { display: flex; flex-direction: column; gap: 0.4rem; } .rg-form-header h1 { font-size: 2rem; font-weight: 900; color: #1e1b4b; letter-spacing: -0.03em; line-height: 1.2; } .rg-form-header p { font-family: 'Nunito Sans', sans-serif; font-size: 0.88rem; font-weight: 600; color: #9ca3af; } /* Avatar row */ .rg-avatar-row { display: flex; align-items: center; gap: 1.1rem; background: #f9fafb; border: 2.5px solid #f3f4f6; border-radius: 18px; padding: 0.9rem 1.1rem; transition: border-color 0.2s; } .rg-avatar-row:focus-within { border-color: #c4b5fd; background: white; } .rg-avatar-ring { width: 52px; height: 52px; border-radius: 50%; border: 2.5px dashed #e5e7eb; display: flex; align-items: center; justify-content: center; overflow: hidden; background: white; flex-shrink: 0; transition: border-color 0.25s, border-style 0.25s; } .rg-avatar-ring.filled { border-style: solid; border-color: #a855f7; } .rg-avatar-ring img { width: 100%; height: 100%; object-fit: cover; } .rg-avatar-input-col { flex: 1; display: flex; flex-direction: column; gap: 0.2rem; } .rg-avatar-label { font-size: 0.68rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: #6b7280; } .rg-avatar-input { background: transparent; border: none; outline: none; font-family: 'Nunito Sans', sans-serif; font-size: 0.85rem; font-weight: 600; color: #1e1b4b; width: 100%; } .rg-avatar-input::placeholder { color: #d1d5db; } .rg-avatar-hint { font-family: 'Nunito Sans', sans-serif; font-size: 0.7rem; font-weight: 600; color: #c4b5fd; } /* Fields grid */ .rg-fields { display: flex; flex-direction: column; gap: 1rem; } .rg-row { display: flex; gap: 1rem; } .rg-row .rg-field { flex: 1; } .rg-field { display: flex; flex-direction: column; gap: 0.4rem; } .rg-label { font-size: 0.7rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: #6b7280; padding-left: 0.2rem; } .rg-input-wrap { position: relative; } .rg-input-icon { position: absolute; left: 0.9rem; top: 50%; transform: translateY(-50%); pointer-events: none; color: #9ca3af; transition: color 0.2s; } .rg-input { width: 100%; padding: 0.85rem 1rem 0.85rem 2.6rem; background: #f9fafb; border: 2.5px solid #f3f4f6; border-radius: 14px; font-family: 'Nunito Sans', sans-serif; font-size: 0.88rem; font-weight: 600; color: #1e1b4b; outline: none; transition: all 0.2s; } .rg-input:focus { background: white; border-color: #c4b5fd; box-shadow: 0 0 0 3.5px rgba(168,85,247,0.1); } .rg-input:focus + .rg-input-icon { color: #a855f7; } .rg-input:disabled { opacity: 0.5; cursor: not-allowed; } .rg-input::placeholder { color: #d1d5db; } /* Strength */ .rg-strength-bar { display: flex; gap: 5px; margin-top: 0.4rem; } .rg-strength-seg { flex: 1; height: 4px; border-radius: 999px; background: #f3f4f6; transition: background 0.3s; } .rg-strength-seg.weak { background: #f43f5e; } .rg-strength-seg.medium { background: #eab308; } .rg-strength-seg.strong { background: #22c55e; } .rg-strength-hint { font-family: 'Nunito Sans', sans-serif; font-size: 0.7rem; font-weight: 700; margin-top: 0.2rem; padding-left: 0.1rem; color: #9ca3af; } .rg-strength-hint.weak { color: #f43f5e; } .rg-strength-hint.medium { color: #eab308; } .rg-strength-hint.strong { color: #22c55e; } /* Error */ .rg-error { background: #fff1f2; border: 2px solid #fecdd3; border-radius: 14px; padding: 0.8rem 1rem; font-family: 'Nunito Sans', sans-serif; font-size: 0.82rem; font-weight: 700; color: #e11d48; display: flex; align-items: center; gap: 0.5rem; } /* Submit */ .rg-btn { width: 100%; padding: 1rem; background: #a855f7; color: white; border: none; border-radius: 100px; cursor: pointer; font-family: 'Nunito', sans-serif; font-size: 1rem; font-weight: 900; display: flex; align-items: center; justify-content: center; gap: 0.5rem; box-shadow: 0 6px 0 #7c3aed, 0 10px 24px rgba(168,85,247,0.3); transition: transform 0.1s, box-shadow 0.1s; letter-spacing: 0.01em; } .rg-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 0 #7c3aed, 0 14px 28px rgba(168,85,247,0.35); } .rg-btn:active { transform: translateY(3px); box-shadow: 0 3px 0 #7c3aed; } .rg-btn:disabled { background: #e5e7eb; color: #9ca3af; cursor: not-allowed; box-shadow: 0 4px 0 #d1d5db; } .rg-btn:disabled:hover { transform: none; box-shadow: 0 4px 0 #d1d5db; } .rg-spinner { animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .rg-form-footer { text-align: center; font-family: 'Nunito Sans', sans-serif; font-size: 0.8rem; font-weight: 600; color: #9ca3af; } .rg-link { color: #a855f7; font-weight: 800; text-decoration: none; } .rg-link:hover { color: #7c3aed; } /* Responsive */ @media (max-width: 860px) { .rg-left { display: none; } .rg-right { padding: 2rem 1.5rem; } } `; function getStrength(p: string): 0 | 1 | 2 | 3 { if (!p) return 0; let s = 0; if (p.length >= 8) s++; if (/[A-Z]/.test(p) && /[a-z]/.test(p)) s++; if (/[0-9]/.test(p) || /[^A-Za-z0-9]/.test(p)) s++; return s as 0 | 1 | 2 | 3; } const S_LABEL = ["", "Weak", "Medium", "Strong"]; const S_CLASS = ["", "weak", "medium", "strong"]; const FEATURES = [ { icon: , bg: "#a855f7", title: "Adaptive Practice", sub: "Questions tailored to your skill level", }, { icon: , bg: "#f97316", title: "Instant Feedback", sub: "Know exactly where you went wrong", }, { icon: , bg: "#22c55e", title: "Score Tracking", sub: "Watch your SAT score climb over time", }, ]; const PANEL_DOTS = [ { size: 70, color: "#f97316", top: "15%", left: "65%", delay: "0s", dur: "9s", }, { size: 45, color: "#22c55e", top: "62%", left: "10%", delay: "1s", dur: "11s", }, { size: 30, color: "#fde68a", top: "35%", left: "75%", delay: "0.5s", dur: "7s", }, { size: 20, color: "#a855f7", top: "78%", left: "50%", delay: "2s", dur: "13s", }, ]; const BG_DOTS = [ { size: 180, color: "#a855f7", top: "5%", right: "5%", delay: "0s", dur: "12s", }, { size: 100, color: "#f97316", bottom: "10%", left: "2%", delay: "1.5s", dur: "10s", }, { size: 60, color: "#22c55e", top: "50%", right: "3%", delay: "0.8s", dur: "8s", }, ]; const INITIALS = ["JD", "AS", "MK", "RP", "LL"]; export const Register = () => { const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [avatarUrl, setAvatarUrl] = useState(""); const [password, setPassword] = useState(""); const [avatarError, setAvatarError] = useState(false); const navigate = useNavigate(); const { register, isLoading, error, clearError } = useAuthStore(); const strength = getStrength(password); const isValid = name.trim() && email.trim() && password.length >= 6; const handleSubmit = async (e: FormEvent) => { e.preventDefault(); clearError(); const success = await register({ email, name, avatar_url: avatarUrl, password, }); if (success) navigate("/student/home", { replace: true }); }; return (
{/* ── LEFT PANEL ── */}
{/* Decorative floating dots */} {PANEL_DOTS.map((d, i) => (
))} {/* Stars */} {[ { top: "14%", left: "20%", size: 14, delay: "0s" }, { top: "28%", left: "78%", size: 10, delay: "0.7s" }, { top: "52%", left: "30%", size: 12, delay: "1.3s" }, { top: "70%", left: "65%", size: 8, delay: "0.4s" }, { top: "88%", left: "22%", size: 10, delay: "1.8s" }, ].map((s, i) => ( ))} {/* Decorative ring shapes */} {[ { size: 90, top: "72%", left: "5%", delay: "0.2s", dur: "10s" }, { size: 60, top: "8%", left: "55%", delay: "1.1s", dur: "13s" }, ].map((r, i) => (
))}
{/* Logo */}
📚
EdBridge
{/* Headline */}

Ace the SAT.
Start for free.

Join thousands of students who improved their
SAT scores with personalized practice.

{/* Feature pills */}
{FEATURES.map((f, i) => (
{f.icon}
{f.title} {f.sub}
))}
{/* Social proof */}
{INITIALS.map((s, i) => (
{s}
))}

2,400+ students already enrolled

{/* ── RIGHT PANEL ── */}
{BG_DOTS.map((d, i) => (
))}
{/* Header */}

Create your account ✨

Fill in the details below to get started

{/* Avatar URL row */}
{avatarUrl && !avatarError ? ( Avatar setAvatarError(true)} /> ) : ( )}
Avatar URL{" "} (optional) { setAvatarUrl(e.target.value); setAvatarError(false); }} disabled={isLoading} /> Paste any image URL to set your profile photo
{/* Fields */}
{/* Name + Email row */}
setName(e.target.value)} disabled={isLoading} />
{/* Email */}
setEmail(e.target.value)} disabled={isLoading} />
{/* Password */}
setPassword(e.target.value)} disabled={isLoading} />
{password && ( <>
{[1, 2, 3].map((seg) => (
= seg ? S_CLASS[strength] : ""}`} /> ))}

{S_LABEL[strength]} password

)}
{/* Error */} {error && (
⚠️ {error}
)} {/* Submit */}

Already have an account?{" "} Sign in

); };