import type { ActionArgs, LoaderArgs, V2_MetaFunction } from "@remix-run/node"; import { json, redirect } from "@remix-run/node"; import { Form, Link, useActionData, useSearchParams } from "@remix-run/react"; import { useEffect, useRef } from "react"; import { verifyLogin } from "~/models/user.server"; import { createUserSession, getUserId } from "~/session.server"; import { safeRedirect, validateEmail } from "~/utils"; export const loader = async ({ request }: LoaderArgs) => { const userId = await getUserId(request); if (userId) return redirect("/"); return json({}); }; export const action = async ({ request }: ActionArgs) => { const formData = await request.formData(); const email = formData.get("email"); const password = formData.get("password"); const redirectTo = safeRedirect(formData.get("redirectTo"), "/"); const remember = formData.get("remember"); if (!validateEmail(email)) { return json( { errors: { email: "Email is invalid", password: null } }, { status: 400 } ); } if (typeof password !== "string" || password.length === 0) { return json( { errors: { email: null, password: "Password is required" } }, { status: 400 } ); } if (password.length < 8) { return json( { errors: { email: null, password: "Password is too short" } }, { status: 400 } ); } const user = await verifyLogin(email, password); if (!user) { return json( { errors: { email: "Invalid email or password", password: null } }, { status: 400 } ); } return createUserSession({ redirectTo, remember: remember === "on", request, userId: user.id }); }; export const meta: V2_MetaFunction = () => [{ title: "Login" }]; export default function LoginPage() { const [searchParams] = useSearchParams(); const redirectTo = searchParams.get("redirectTo") || "/listen"; const actionData = useActionData(); const emailRef = useRef(null); const passwordRef = useRef(null); useEffect(() => { if (actionData?.errors?.email) { emailRef.current?.focus(); } else if (actionData?.errors?.password) { passwordRef.current?.focus(); } }, [actionData]); return (
{actionData?.errors?.email ? (
{actionData.errors.email}
) : null}
{actionData?.errors?.password ? (
{actionData.errors.password}
) : null}
Don't have an account?{" "} Sign up
); }