import { useState, useEffect } from "react"; import type { FormEvent } from "react"; import { useNavigate, useLocation } from "react-router-dom"; import { useAuthStore } from "../../stores/authStore"; import { Loader2, Mail, Lock, Target, Clock, BarChart2 } from "lucide-react"; interface LocationState { from?: { pathname: string }; } 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; } .lg-root { min-height: 100vh; display: flex; font-family: 'Nunito', sans-serif; background: #fffbf4; } /* ─── LEFT PANEL ─── */ .lg-left { position: relative; width: 50%; min-height: 100vh; background: linear-gradient(160deg, #060d1f 0%, #0f2044 40%, #0e3476 75%, #1a56c4 100%); display: flex; flex-direction: column; align-items: flex-start; justify-content: center; padding: 3rem 3.5rem; overflow: hidden; flex-shrink: 0; } /* Animated grid */ .lg-grid { position: absolute; inset: 0; pointer-events: none; background-image: linear-gradient(rgba(99,179,255,0.06) 1px, transparent 1px), linear-gradient(90deg, rgba(99,179,255,0.06) 1px, transparent 1px); background-size: 52px 52px; animation: gridScroll 25s linear infinite; } @keyframes gridScroll { from { background-position: 0 0; } to { background-position: 52px 52px; } } /* Radial glow spots */ .lg-glow { position: absolute; pointer-events: none; border-radius: 50%; filter: blur(60px); } .lg-glow-1 { width: 380px; height: 380px; background: #1d4ed8; opacity: 0.35; top: -120px; right: -80px; animation: glowPulse 8s ease-in-out infinite; } .lg-glow-2 { width: 280px; height: 280px; background: #0ea5e9; opacity: 0.2; bottom: -60px; left: -60px; animation: glowPulse 10s ease-in-out infinite 2s; } .lg-glow-3 { width: 200px; height: 200px; background: #f97316; opacity: 0.12; top: 55%; left: 55%; animation: glowPulse 12s ease-in-out infinite 1s; } @keyframes glowPulse { 0%,100% { transform: scale(1); opacity: 0.2; } 50% { transform: scale(1.2); opacity: 0.35; } } /* ── Floating score card ── */ .lg-score-card { position: absolute; top: 9%; right: 6%; width: 162px; background: linear-gradient(135deg, rgba(255,255,255,0.11), rgba(255,255,255,0.05)); border: 1px solid rgba(255,255,255,0.18); border-radius: 20px; padding: 1.1rem 1.2rem 1rem; backdrop-filter: blur(16px); box-shadow: 0 8px 32px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.15); animation: floatA 6s ease-in-out infinite; z-index: 2; } @keyframes floatA { 0%,100% { transform: translateY(0) rotate(-1.5deg); } 50% { transform: translateY(-14px) rotate(0.5deg); } } .lg-score-tag { font-size: 0.58rem; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: #7dd3fc; margin-bottom: 0.5rem; display: flex; align-items: center; gap: 0.3rem; } .lg-score-tag::before { content:''; width:6px;height:6px;border-radius:50%;background:#34d399;display:inline-block;box-shadow:0 0 6px #34d399; } .lg-score-num { font-size: 2.2rem; font-weight: 900; color: white; line-height: 1; margin-bottom: 0.2rem; text-shadow: 0 2px 12px rgba(99,179,255,0.4); } .lg-score-delta { font-family: 'Nunito Sans', sans-serif; font-size: 0.7rem; font-weight: 700; color: #4ade80; display: flex; align-items: center; gap: 0.2rem; margin-bottom: 0.75rem; } .lg-bars { display: flex; align-items: flex-end; gap: 3px; height: 40px; } .lg-bar { flex: 1; border-radius: 3px 3px 0 0; animation: barGrow 1s cubic-bezier(0.34,1.56,0.64,1) both; transform-origin: bottom; } @keyframes barGrow { from { transform: scaleY(0); } to { transform: scaleY(1); } } /* ── Streak pill ── */ .lg-streak { position: absolute; bottom: 12%; left: 5%; background: linear-gradient(135deg, rgba(249,115,22,0.18), rgba(239,68,68,0.1)); border: 1px solid rgba(249,115,22,0.4); border-radius: 100px; padding: 0.65rem 1.2rem; backdrop-filter: blur(14px); box-shadow: 0 4px 20px rgba(249,115,22,0.2), inset 0 1px 0 rgba(255,255,255,0.1); display: flex; align-items: center; gap: 0.65rem; animation: floatB 7s ease-in-out infinite 1s; z-index: 2; } @keyframes floatB { 0%,100% { transform: translateY(0) rotate(1deg); } 50% { transform: translateY(-10px) rotate(-0.5deg); } } .lg-streak-fire { font-size: 1.5rem; filter: drop-shadow(0 0 8px #f97316); } .lg-streak-text strong { display:block; font-size:0.85rem; font-weight:900; color:white; } .lg-streak-text span { font-family:'Nunito Sans',sans-serif; font-size:0.68rem; font-weight:600; color:#fed7aa; } /* ── Questions badge ── */ .lg-q-badge { position: absolute; bottom: 28%; right: 5%; background: linear-gradient(135deg, rgba(139,92,246,0.18), rgba(99,102,241,0.1)); border: 1px solid rgba(139,92,246,0.4); border-radius: 16px; padding: 0.7rem 1.05rem; backdrop-filter: blur(14px); box-shadow: 0 4px 20px rgba(139,92,246,0.2), inset 0 1px 0 rgba(255,255,255,0.1); animation: floatA 9s ease-in-out infinite 0.5s; z-index: 2; } .lg-q-badge p { font-family:'Nunito Sans',sans-serif; font-size:0.68rem; font-weight:700; color:#c4b5fd; margin-bottom:0.15rem; } .lg-q-badge strong { font-size:1.35rem; font-weight:900; color:white; display:block; text-shadow:0 0 20px rgba(167,139,250,0.5); } /* ── Accuracy ring ── */ .lg-ring-wrap { position: absolute; top: 52%; left: 6%; width: 80px; height: 80px; animation: floatB 10s ease-in-out infinite 0.8s; z-index: 2; } .lg-ring-svg { width: 80px; height: 80px; transform: rotate(-90deg); } .lg-ring-bg { fill: none; stroke: rgba(255,255,255,0.08); stroke-width: 5; } .lg-ring-fill { fill: none; stroke: #34d399; stroke-width: 5; stroke-linecap: round; stroke-dasharray: 188; stroke-dashoffset: 18; animation: ringFill 1.8s ease both 0.3s; } @keyframes ringFill { from { stroke-dashoffset: 188; } to { stroke-dashoffset: 18; } } .lg-ring-label { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; } .lg-ring-label strong { font-size: 0.95rem; font-weight: 900; color: white; line-height: 1; } .lg-ring-label span { font-family:'Nunito Sans',sans-serif; font-size: 0.52rem; font-weight: 700; color: #7dd3fc; text-transform: uppercase; letter-spacing: 0.05em; } /* Scattered glitter dots */ .lg-glitter { position: absolute; border-radius: 50%; pointer-events: none; animation: glitterFloat 8s ease-in-out infinite; } @keyframes glitterFloat { 0%,100% { transform: translateY(0) scale(1); opacity: 0.5; } 50% { transform: translateY(-16px) scale(1.3); opacity: 0.9; } } /* Stars */ .lg-star { position: absolute; pointer-events: none; animation: starTwinkle 2.5s ease-in-out infinite; color: #fde68a; } @keyframes starTwinkle { 0%,100% { opacity: 0.4; transform: scale(0.9) rotate(0deg); } 50% { opacity: 1; transform: scale(1.4) rotate(20deg); } } /* Thin decorative rings */ .lg-deco-ring { position: absolute; border-radius: 50%; pointer-events: none; border: 1.5px solid rgba(255,255,255,0.07); animation: decoSpin 40s linear infinite; } @keyframes decoSpin { to { transform: rotate(360deg); } } /* Panel content */ .lg-panel-content { position: relative; z-index: 3; display: flex; flex-direction: column; align-items: flex-start; gap: 2rem; width: 100%; } .lg-panel-logo { display: flex; align-items: center; gap: 0.75rem; } .lg-panel-logo-badge { width: 46px; height: 46px; border-radius: 13px; background: linear-gradient(135deg, #f97316, #ef4444); display: flex; align-items: center; justify-content: center; box-shadow: 0 5px 0 rgba(0,0,0,0.3), 0 8px 20px rgba(249,115,22,0.45); font-size: 1.3rem; } .lg-panel-logo-text { font-size: 1.35rem; font-weight: 900; color: white; letter-spacing: -0.02em; } .lg-panel-headline { display: flex; flex-direction: column; gap: 0.6rem; } .lg-panel-headline h2 { font-size: 2.6rem; font-weight: 900; line-height: 1.1; color: white; letter-spacing: -0.035em; text-shadow: 0 4px 24px rgba(0,0,0,0.3); } .lg-panel-headline h2 span { background: linear-gradient(90deg, #fbbf24 0%, #f97316 60%, #ef4444 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; filter: drop-shadow(0 0 16px rgba(249,115,22,0.4)); } .lg-panel-headline p { font-family: 'Nunito Sans', sans-serif; font-size: 0.92rem; font-weight: 600; color: #93c5fd; line-height: 1.65; } /* Stats row */ .lg-stats { display: flex; gap: 0.75rem; width: 100%; } .lg-stat { flex: 1; background: linear-gradient(135deg, rgba(255,255,255,0.09), rgba(255,255,255,0.04)); border: 1px solid rgba(255,255,255,0.13); border-radius: 18px; padding: 0.9rem 0.85rem; backdrop-filter: blur(12px); box-shadow: 0 4px 16px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.12); display: flex; flex-direction: column; gap: 0.2rem; animation: statSlide 0.5s ease both; } .lg-stat:nth-child(1) { animation-delay: 0.1s; } .lg-stat:nth-child(2) { animation-delay: 0.2s; } .lg-stat:nth-child(3) { animation-delay: 0.3s; } @keyframes statSlide { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } } .lg-stat-icon { width: 28px; height: 28px; border-radius: 8px; display:flex;align-items:center;justify-content:center; margin-bottom:0.3rem; } .lg-stat strong { font-size: 1.3rem; font-weight: 900; color: white; line-height: 1; } .lg-stat span { font-family:'Nunito Sans',sans-serif; font-size:0.64rem; font-weight:600; color:#93c5fd; } /* Social proof */ .lg-social { display: flex; align-items: center; gap: 0.75rem; } .lg-avs { display: flex; } .lg-av { width: 30px; height: 30px; border-radius: 50%; border: 2px solid #0f2044; margin-left: -8px; display: flex; align-items: center; justify-content: center; font-size: 0.6rem; font-weight: 800; color: white; box-shadow: 0 2px 8px rgba(0,0,0,0.3); } .lg-av:first-child { margin-left: 0; } .lg-social p { font-family:'Nunito Sans',sans-serif; font-size:0.75rem; font-weight:700; color:#93c5fd; } .lg-social p strong { color:#fbbf24; } /* ─── RIGHT PANEL ─── */ .lg-right { flex: 1; display: flex; align-items: center; justify-content: center; padding: 3rem 4rem; position: relative; overflow: hidden; } .lg-bg-dot { position:absolute;border-radius:50%;pointer-events:none;opacity:0.09;animation:bgFloat 10s ease-in-out infinite; } @keyframes bgFloat { 0%,100%{transform:translateY(0);} 50%{transform:translateY(-14px);} } .lg-form-wrap { position: relative; z-index: 1; width: 100%; max-width: 400px; display: flex; flex-direction: column; gap: 2rem; animation: formPop 0.55s cubic-bezier(0.34,1.56,0.64,1) both; } @keyframes formPop { from { opacity:0; transform:translateY(22px) scale(0.97); } to { opacity:1; transform:translateY(0) scale(1); } } .lg-form-header { display:flex;flex-direction:column;gap:0.4rem; } .lg-form-header h1 { font-size:2rem;font-weight:900;color:#1e1b4b;letter-spacing:-0.03em;line-height:1.2; } .lg-form-header p { font-family:'Nunito Sans',sans-serif;font-size:0.88rem;font-weight:600;color:#9ca3af; } .lg-fields { display:flex;flex-direction:column;gap:1.1rem; } .lg-field { display:flex;flex-direction:column;gap:0.4rem; } .lg-label { font-size:0.7rem;font-weight:800;letter-spacing:0.1em;text-transform:uppercase;color:#6b7280;padding-left:0.2rem; } .lg-input-wrap { position:relative; } .lg-input-icon { position:absolute;left:0.9rem;top:50%;transform:translateY(-50%);pointer-events:none;color:#9ca3af;transition:color 0.2s; } .lg-input { width:100%;padding:0.9rem 1rem 0.9rem 2.65rem; background:#f9fafb;border:2.5px solid #f3f4f6;border-radius:14px; font-family:'Nunito Sans',sans-serif;font-size:0.9rem;font-weight:600;color:#1e1b4b; outline:none;transition:all 0.2s;box-sizing:border-box; } .lg-input:focus { background:white;border-color:#93c5fd;box-shadow:0 0 0 3.5px rgba(59,130,246,0.1); } .lg-input:disabled { opacity:0.5;cursor:not-allowed; } .lg-input::placeholder { color:#d1d5db; } .lg-remember { display:flex;align-items:center;gap:0.5rem;padding:0 0.1rem; } .lg-checkbox { width:17px;height:17px;border-radius:5px;accent-color:#3b82f6;cursor:pointer;flex-shrink:0; } .lg-remember-label { font-family:'Nunito Sans',sans-serif;font-size:0.8rem;font-weight:600;color:#6b7280;cursor:pointer; } .lg-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; } .lg-success { background:#f0fdf4;border:2px solid #bbf7d0;border-radius:14px;padding:0.8rem 1rem; font-family:'Nunito Sans',sans-serif;font-size:0.82rem;font-weight:700;color:#15803d; display:flex;align-items:center;gap:0.5rem; animation: formPop 0.4s cubic-bezier(0.34,1.56,0.64,1) both; } .lg-btn { width:100%;padding:1rem;background:#f97316;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 #c2560e,0 10px 24px rgba(249,115,22,0.28); transition:transform 0.1s,box-shadow 0.1s; } .lg-btn:hover { transform:translateY(-2px);box-shadow:0 8px 0 #c2560e,0 14px 28px rgba(249,115,22,0.32); } .lg-btn:active { transform:translateY(3px);box-shadow:0 3px 0 #c2560e; } .lg-btn:disabled { background:#e5e7eb;color:#9ca3af;cursor:not-allowed;box-shadow:0 4px 0 #d1d5db; } .lg-btn:disabled:hover { transform:none;box-shadow:0 4px 0 #d1d5db; } .lg-spinner { animation:spin 0.8s linear infinite; } @keyframes spin { to { transform:rotate(360deg); } } .lg-footer { text-align:center;font-family:'Nunito Sans',sans-serif;font-size:0.75rem;font-weight:600;color:#9ca3af; } .lg-signup-footer { text-align:center;font-family:'Nunito Sans',sans-serif;font-size:0.8rem;font-weight:600;color:#9ca3af; } .lg-link { color:#f97316;font-weight:800;text-decoration:none;cursor:pointer; } .lg-link:hover { color:#ea6c00; } @media (max-width: 860px) { .lg-left { display:none; } .lg-right { padding:2rem 1.5rem; } } `; const BAR_HEIGHTS = [30, 50, 42, 75, 55, 88, 65]; const BAR_COLORS = [ "#60a5fa", "#60a5fa", "#7dd3fc", "#38bdf8", "#60a5fa", "#7dd3fc", "#38bdf8", ]; const AV_COLORS = [ "linear-gradient(135deg,#3b82f6,#1d4ed8)", "linear-gradient(135deg,#f97316,#ef4444)", "linear-gradient(135deg,#22c55e,#15803d)", "linear-gradient(135deg,#a855f7,#7c3aed)", "linear-gradient(135deg,#eab308,#ca8a04)", ]; const AV_INITIALS = ["SK", "NR", "TM", "AB", "PL"]; export const Login = () => { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const navigate = useNavigate(); const location = useLocation(); const { login, isAuthenticated, isLoading, error, clearError, registrationMessage, } = useAuthStore(); const from = (location.state as LocationState)?.from?.pathname || "/student/home"; useEffect(() => { if (isAuthenticated) navigate("/student/home", { replace: true }); }, [isAuthenticated, navigate]); useEffect(() => { return () => clearError(); }, [clearError]); const handleSubmit = async (e: FormEvent) => { e.preventDefault(); clearError(); const success = await login({ email, password }); if (success) navigate(from, { replace: true }); }; if (isAuthenticated) return null; return (
{/* ── LEFT PANEL ── */}
{/* Background layers */}
{/* Decorative spinning rings */} {[ { s: 260, t: "38%", l: "58%", mt: -130, ml: -130 }, { s: 380, t: "42%", l: "54%", mt: -190, ml: -190, dir: "reverse" as const, }, ].map((r, i) => (
))} {/* Floating score card */}

SAT Score

1480

▲ +120 pts this month

{BAR_HEIGHTS.map((h, i) => (
))}
{/* Accuracy ring */}
94% Accuracy
{/* Streak pill */}
🔥
14-day streak! Keep it going
{/* Questions badge */}

Questions solved

2,847
{/* Glitter dots */} {[ { s: 10, c: "#60a5fa", t: "13%", l: "58%", d: "0s", dur: "9s" }, { s: 7, c: "#fbbf24", t: "70%", l: "70%", d: "1s", dur: "11s" }, { s: 12, c: "#34d399", t: "38%", l: "7%", d: "0.4s", dur: "8s" }, { s: 5, c: "#f472b6", t: "82%", l: "35%", d: "1.8s", dur: "13s" }, { s: 8, c: "#a78bfa", t: "20%", l: "36%", d: "0.9s", dur: "10s" }, { s: 6, c: "#fb923c", t: "62%", l: "80%", d: "1.3s", dur: "7s" }, ].map((d, i) => (
))} {/* Stars */} {[ { t: "8%", l: "16%", s: "1.1rem", d: "0s" }, { t: "22%", l: "74%", s: "0.85rem", d: "0.7s" }, { t: "55%", l: "20%", s: "0.95rem", d: "1.4s" }, { t: "86%", l: "58%", s: "0.75rem", d: "0.3s" }, { t: "44%", l: "88%", s: "1rem", d: "1.0s" }, ].map((s, i) => ( ))} {/* Panel content */}
📚
EdBridge

Welcome
back,
champion.

Your SAT goals are waiting.
Pick up right where you left off.

{[ { icon: , bg: "linear-gradient(135deg,#3b82f6,#1d4ed8)", val: "94%", label: "Accuracy", }, { icon: , bg: "linear-gradient(135deg,#f97316,#ef4444)", val: "47m", label: "Daily study", }, { icon: , bg: "linear-gradient(135deg,#22c55e,#15803d)", val: "+180", label: "Score gain", }, ].map((s, i) => (
{s.icon}
{s.val} {s.label}
))}
{AV_INITIALS.map((init, i) => (
{init}
))}

2,400+ students improved their scores

{/* ── RIGHT PANEL ── */}
{[ { s: 200, c: "#f97316", t: "4%", r: "4%", d: "0s", dur: "12s" }, { s: 120, c: "#3b82f6", b: "8%", l: "2%", d: "1.5s", dur: "10s" }, { s: 70, c: "#22c55e", t: "52%", r: "2%", d: "0.8s", dur: "8s" }, ].map((d, i) => (
))}

Welcome back 👋

Sign in to continue your SAT prep

setEmail(e.target.value)} disabled={isLoading} />
setPassword(e.target.value)} disabled={isLoading} />
{registrationMessage && (
{registrationMessage}
)} {error && (
⚠️ {error}
)}

By signing in you agree to EdBridge's Terms & Privacy Policy.

Don't have an account?{" "} navigate("/register")}> Sign up

); };