import { redirect, Form } from "react-router"; import { auth } from "~/lib/auth.server"; import { findUserById, findUserByUsername, updateUser } from "~/models/user"; import type { Route } from "./+types/onboarding"; import { Button } from "~/components/ui/button"; import { Input } from "~/components/ui/input"; import { Label } from "~/components/ui/label"; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "~/components/ui/card"; export function meta(): Route.MetaDescriptors { return [{ title: "Choose a Username - Brackt" }]; } function suggestUsername(displayName: string | null): string { if (!displayName) return ""; return displayName .toLowerCase() .replace(/[^a-z0-9_-]/g, "") .slice(0, 20); } const USERNAME_RE = /^[a-zA-Z0-9_-]{3,30}$/; export async function loader({ request }: Route.LoaderArgs) { const session = await auth.api.getSession({ headers: request.headers }); if (!session) return redirect("/login"); const user = await findUserById(session.user.id); if (!user) return redirect("/login"); if (user.username) return redirect("/"); return { suggestion: suggestUsername(user.displayName) }; } export async function action({ request }: Route.ActionArgs) { const session = await auth.api.getSession({ headers: request.headers }); if (!session) return redirect("/login"); const formData = await request.formData(); const username = (formData.get("username") as string | null)?.trim() ?? ""; if (!USERNAME_RE.test(username)) { return { error: "Username must be 3–30 characters and contain only letters, numbers, underscores, or hyphens.", }; } const existing = await findUserByUsername(username); if (existing && existing.id !== session.user.id) { return { error: "That username is already taken." }; } await updateUser(session.user.id, { username }); return redirect("/"); } export default function OnboardingPage({ loaderData, actionData }: Route.ComponentProps) { return (