import { type FormEvent, useEffect, useState } from "react"; import { Link, useLocation, useNavigate } from "react-router-dom"; import { useQueryClient } from "@tanstack/react-query"; import { http } from "../api/http"; import { useAuthSession } from "../hooks/useAuthSession"; function useNextPath() { const location = useLocation(); const params = new URLSearchParams(location.search); return params.get("next") || "/"; } export default function RegisterPage() { const navigate = useNavigate(); const next = useNextPath(); const qc = useQueryClient(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [error, setError] = useState(null); const [pending, setPending] = useState(false); const [touched, setTouched] = useState({ email: false, password: false, confirmPassword: false, }); const [submitted, setSubmitted] = useState(false); const session = useAuthSession({ retry: false }); const isEmailValid = (value: string) => /\S+@\S+\.\S+/.test(value); const emailError = (touched.email || submitted) && !email.trim() ? "Email is required." : (touched.email || submitted) && !isEmailValid(email) ? "Enter a valid email address." : ""; const passwordError = (touched.password || submitted) && !password ? "Password is required." : (touched.password || submitted) && password.length < 8 ? "Password must be at least 8 characters." : ""; const confirmError = (touched.confirmPassword || submitted) && !confirmPassword ? "Please confirm your password." : (touched.confirmPassword || submitted) && password && confirmPassword !== password ? "Passwords do not match." : ""; useEffect(() => { if (session.data?.userId) { navigate(next || "/", { replace: true }); } }, [session.data, navigate, next]); async function handleSubmit(e: FormEvent) { e.preventDefault(); setError(null); setPending(true); setSubmitted(true); if (emailError || passwordError || confirmError) { setPending(false); return; } try { await http<{ ok: true }>("/auth/register", { method: "POST", body: { email, password }, skipAuthRedirect: true, }); qc.clear(); navigate(next || "/", { replace: true }); } catch (err) { const status = (err as { status?: number })?.status; const message = status === 409 ? "That email is already registered. Try signing in." : status === 400 ? "Enter a valid email and password." : err instanceof Error ? err.message : "Unable to register. Try again."; setError(message); } finally { setPending(false); } } return (

Register

Create an account to track your money buckets.

{error &&
{error}
} {/* Session errors are expected on registration page, so don't show them */}

Already have an account?{" "} Sign in

); }