{isSignup ? "Create your account" : "Welcome back"}
{isSignup ? "Start asking questions grounded in your own documents." : "Sign in to continue to your workspace."}
{isSignup ? "Already have an account? " : "New to FinanceFlow? "}
import { useEffect, useRef, useState } from "react"; import { IconCheck, IconEye, IconEyeOff, IconQuote, IconShield, IconSpark, } from "../../lib/icons"; import Button from "../ui/Button"; import { ErrorState } from "../ui/States"; const emailRe = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; // Renders the official Google Identity Services button when a client id is set; // on success it hands the Google ID token to onCredential. Hidden otherwise. function GoogleButton({ clientId, onCredential }) { const ref = useRef(null); const cbRef = useRef(onCredential); cbRef.current = onCredential; useEffect(() => { if (!clientId) return undefined; let cancelled = false; function render() { const gid = window.google?.accounts?.id; if (cancelled || !gid || !ref.current) return; gid.initialize({ client_id: clientId, callback: (resp) => cbRef.current?.(resp.credential), }); ref.current.innerHTML = ""; gid.renderButton(ref.current, { type: "standard", theme: "outline", size: "large", text: "continue_with", width: 320, }); } if (window.google?.accounts?.id) { render(); return () => { cancelled = true; }; } let script = document.getElementById("gis-script"); if (!script) { script = document.createElement("script"); script.id = "gis-script"; script.src = "https://accounts.google.com/gsi/client"; script.async = true; document.body.appendChild(script); } script.addEventListener("load", render); return () => { cancelled = true; script.removeEventListener("load", render); }; }, [clientId]); if (!clientId) return null; return
; } export default function AuthScreen({ onSignIn, onSignUp, onGoogle, onDemo, googleClientId, loading = false, serverError = "", }) { const [mode, setMode] = useState("signin"); // 'signin' | 'signup' const [show, setShow] = useState(false); const [values, setValues] = useState({ email: "", password: "", confirm: "" }); const [errors, setErrors] = useState({}); const [touched, setTouched] = useState({}); const isSignup = mode === "signup"; function validate(v = values) { const e = {}; if (!v.email) e.email = "Email is required."; else if (!emailRe.test(v.email)) e.email = "Enter a valid email address."; if (!v.password) e.password = "Password is required."; else if (isSignup && v.password.length < 8) e.password = "Use at least 8 characters."; if (isSignup && v.confirm !== v.password) e.confirm = "Passwords don’t match."; return e; } function setField(name, val) { const next = { ...values, [name]: val }; setValues(next); if (touched[name]) setErrors(validate(next)); } function switchMode(next) { setMode(next); setErrors({}); setTouched({}); } async function onSubmit(ev) { ev.preventDefault(); const e = validate(); setErrors(e); setTouched({ email: true, password: true, confirm: true }); if (Object.keys(e).length) return; const payload = { email: values.email.trim(), password: values.password }; if (isSignup) await onSignUp?.(payload); else await onSignIn?.(payload); } const eid = (n) => `auth-${n}`; const errId = (n) => (errors[n] ? `${eid(n)}-err` : undefined); return ({isSignup ? "Start asking questions grounded in your own documents." : "Sign in to continue to your workspace."}
{isSignup ? "Already have an account? " : "New to FinanceFlow? "}