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