// screens-public.jsx — Landing + Signup const API_BASE = ""; // ── LANDING — single page, hero + how-it-works + pricing ────────────── const Landing = ({ goto, selectPath }) => { const [stats, setStats] = React.useState({ total_claims: null }); React.useEffect(() => { fetch("/api/public/stats").then(r => r.ok ? r.json() : null) .then(d => { if (d) setStats(d); }).catch(() => {}); document.documentElement.classList.add("pattern-loud"); return () => document.documentElement.classList.remove("pattern-loud"); }, []); const tiers = [ { id: "house_cut", name: "House Cut", price: 10, blurb: "Regular drops" }, { id: "prime_cut", name: "Prime Cut", price: 15, blurb: "+ highroller", featured: true }, { id: "grand_feast", name: "Grand Feast", price: 30, blurb: "Every code" }, ]; const steps = [ { icon: "tg", label: "Link Telegram" }, { icon: "key", label: "Add API key" }, { icon: "bolt", label: "We claim" }, ]; const go = () => { selectPath("api"); goto("signup"); }; return (
); }; // ── SIGNUP — Telegram first ──────────────────────────────────────── const Signup = ({ goto, signIn }) => { const [mode, setMode] = React.useState("telegram"); // telegram | email const [isSignIn, setIsSignIn] = React.useState(false); const [busy, setBusy] = React.useState(false); const [error, setError] = React.useState(""); // Telegram state const [tgUser, setTgUser] = React.useState(""); const [tgCode, setTgCode] = React.useState(null); const [tgPolling, setTgPolling] = React.useState(false); const [tgToken, setTgToken] = React.useState(null); const pollRef = React.useRef(null); // Email state const [email, setEmail] = React.useState(""); const [pw, setPw] = React.useState(""); // Credentials-set step (after Telegram, if no email yet) const [settingCreds, setSettingCreds] = React.useState(false); const [credEmail, setCredEmail] = React.useState(""); const [credPw, setCredPw] = React.useState(""); const [credError, setCredError] = React.useState(""); const [credBusy, setCredBusy] = React.useState(false); const tgValid = tgUser.replace("@", "").length > 2; const emailValid = /\S+@\S+\.\S+/.test(email) && pw.length >= 6; const stopPoll = () => { if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null; } }; const startPoll = (code) => { stopPoll(); setTgPolling(true); pollRef.current = setInterval(async () => { try { const r = await fetch(`${API_BASE}/api/auth/telegram/poll`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ code }), }); const d = await r.json(); if (d.verified) { stopPoll(); setTgPolling(false); if (d.needs_credentials) { setTgToken(d.token); setSettingCreds(true); } else { localStorage.setItem("cc_token", d.token); signIn(d.user); goto(d.user?.plan && d.user.plan !== "free" ? "dashboard" : "subscription"); } } } catch (_) {} }, 2000); }; const submitTg = async (e) => { e?.preventDefault(); if (!tgValid) return; setError(""); setBusy(true); try { const r = await fetch(`${API_BASE}/api/auth/telegram/request`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ username: tgUser.replace("@", "") }), }); const d = await r.json(); if (d.error) { setError(d.error); setBusy(false); return; } setTgCode(d.code); setBusy(false); startPoll(d.code); } catch { setError("Network error"); setBusy(false); } }; const submitEmail = async (e) => { e?.preventDefault(); if (!emailValid) return; setError(""); setBusy(true); const endpoint = isSignIn ? "/api/signin" : "/api/signup"; try { const r = await fetch(`${API_BASE}${endpoint}`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ email, password: pw }), }); const d = await r.json(); if (d.error) { setError(d.error); setBusy(false); return; } localStorage.setItem("cc_token", d.token); signIn(d.user); goto(d.user?.plan && d.user.plan !== "free" ? "dashboard" : "subscription"); } catch { setError("Network error"); setBusy(false); } }; const submitCreds = async (e) => { e?.preventDefault(); if (!/\S+@\S+\.\S+/.test(credEmail) || credPw.length < 6) return; setCredError(""); setCredBusy(true); try { const r = await fetch(`${API_BASE}/api/me/set-credentials`, { method: "POST", headers: { "content-type": "application/json", "Authorization": `Bearer ${tgToken}` }, body: JSON.stringify({ email: credEmail, password: credPw }), }); const d = await r.json(); if (d.error) { setCredError(d.error); setCredBusy(false); return; } localStorage.setItem("cc_token", d.token); signIn(d.user); goto(d.user?.plan && d.user.plan !== "free" ? "dashboard" : "subscription"); } catch { setCredError("Network error"); setCredBusy(false); } }; // Credential-set screen (after Telegram verify, no email yet) if (settingCreds) { const credValid = /\S+@\S+\.\S+/.test(credEmail) && credPw.length >= 6; return (
one more thing

Set a password

setCredEmail(e.target.value)} /> setCredPw(e.target.value)} /> {credError &&

{credError}

} {credBusy ? "Saving…" : <>Continue }
); } // Telegram code screen if (tgCode) { return (
{ stopPoll(); setTgCode(null); }}> Back

Send to @CCUclaimerbot

Open Telegram. Paste this code to the bot.

{tgCode}

{tgPolling ? "⏳ waiting…" : ""}

); } // Main signup screen — Telegram primary, email collapsed return (
goto("landing")}> Back

{isSignIn ? "Sign in" : "Sign up"}

{mode === "telegram" ? (
setTgUser(e.target.value)} /> {error &&

{error}

} {busy ? "…" : <> Continue with Telegram}
) : (
setEmail(e.target.value)} /> setPw(e.target.value)} /> {error &&

{error}

} {busy ? "…" : isSignIn ? <>Sign in : <>Create account }
)}

{isSignIn ? "New here?" : "Already have an account?"} {" "}

); }; Object.assign(window, { Landing, Signup });