Files
HaBit/components/sign-up-form.tsx
Harkamal Randhawa f20c053db3 Harden production auth for hackathon demo.
Configure Supabase redirect URLs, disable email confirmation on the remote
project, create profile and avatar rows on signup, and route new users to
/protected when a session is returned immediately.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-23 18:13:52 -06:00

125 lines
3.8 KiB
TypeScript

"use client";
import { cn } from "@/lib/utils";
import { createClient } from "@/lib/supabase/client";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState } from "react";
export function SignUpForm({
className,
...props
}: React.ComponentPropsWithoutRef<"div">) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [repeatPassword, setRepeatPassword] = useState("");
const [error, setError] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(false);
const router = useRouter();
const handleSignUp = async (e: React.FormEvent) => {
e.preventDefault();
const supabase = createClient();
setIsLoading(true);
setError(null);
if (password !== repeatPassword) {
setError("Passwords do not match");
setIsLoading(false);
return;
}
try {
const { data, error } = await supabase.auth.signUp({
email,
password,
options: {
emailRedirectTo: `${window.location.origin}/auth/confirm?next=/protected`,
},
});
if (error) throw error;
if (data.session) {
router.push("/protected");
return;
}
router.push("/auth/sign-up-success");
} catch (error: unknown) {
setError(error instanceof Error ? error.message : "An error occurred");
} finally {
setIsLoading(false);
}
};
return (
<div className={cn("flex flex-col gap-6", className)} {...props}>
<Card>
<CardHeader>
<CardTitle className="text-2xl">Sign up</CardTitle>
<CardDescription>Create a new account</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSignUp}>
<div className="flex flex-col gap-6">
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="m@example.com"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="grid gap-2">
<div className="flex items-center">
<Label htmlFor="password">Password</Label>
</div>
<Input
id="password"
type="password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div className="grid gap-2">
<div className="flex items-center">
<Label htmlFor="repeat-password">Repeat Password</Label>
</div>
<Input
id="repeat-password"
type="password"
required
value={repeatPassword}
onChange={(e) => setRepeatPassword(e.target.value)}
/>
</div>
{error && <p className="text-sm text-red-500">{error}</p>}
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? "Creating an account..." : "Sign up"}
</Button>
</div>
<div className="mt-4 text-center text-sm">
Already have an account?{" "}
<Link href="/auth/login" className="underline underline-offset-4">
Login
</Link>
</div>
</form>
</CardContent>
</Card>
</div>
);
}