makearmy-app/app/auth/sign-up/page.tsx
2025-09-26 15:59:15 -04:00

131 lines
4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { Suspense, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
function SignUpInner() {
const router = useRouter();
const sp = useSearchParams();
const [username, setUsername] = useState("");
const [email, setEmail] = useState(""); // optional
const [password, setPassword] = useState("");
const [submitting, setSubmitting] = useState(false);
const [err, setErr] = useState<string | null>(null);
const next = sp.get("next") || "/my/rigs";
async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setErr(null);
setSubmitting(true);
try {
const res = await fetch("/api/auth/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
username,
email: email || undefined,
password,
}),
});
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(data?.error || "Registration failed");
router.replace(next);
} catch (e: any) {
setErr(e?.message || "Registration failed");
} finally {
setSubmitting(false);
}
}
return (
<div className="min-h-[60vh] flex items-center justify-center px-4">
<div className="w-full max-w-md space-y-6">
<div className="text-center space-y-2">
<h1 className="text-2xl font-bold">Create account</h1>
<p className="text-sm text-muted-foreground">
Pick a username and password. Email is optional (recommended for password reset).
</p>
</div>
<form onSubmit={onSubmit} className="space-y-4">
{err && (
<div className="text-sm rounded border border-destructive/30 bg-destructive/10 px-3 py-2 text-destructive">
{err}
</div>
)}
<div className="space-y-2">
<label className="text-sm font-medium">Username</label>
<Input
autoFocus
autoComplete="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium">
Email <span className="text-muted-foreground font-normal">(optional)</span>
</label>
<Input
type="email"
autoComplete="email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<p className="text-xs text-muted-foreground">
Without an email, we cant reset your password if you lose it.
</p>
</div>
<div className="space-y-2">
<label className="text-sm font-medium">Password</label>
<Input
type="password"
autoComplete="new-password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
<Button type="submit" disabled={submitting} className="w-full">
{submitting ? "Creating…" : "Create account"}
</Button>
<input type="hidden" name="next" value={next} />
</form>
<p className="text-sm text-center text-muted-foreground">
Already have an account?{" "}
<Link href="/auth/sign-in" className="underline underline-offset-4 hover:opacity-80">
Sign in
</Link>
</p>
</div>
</div>
);
}
export default function SignUpPage() {
return (
<Suspense
fallback={
<div className="min-h-[60vh] flex items-center justify-center px-4">
<div className="text-sm text-muted-foreground">Loading</div>
</div>
}
>
<SignUpInner />
</Suspense>
);
}