import type { ActionArgs, LoaderArgs, MetaFunction } from '@remix-run/node' import { json, redirect } from '@remix-run/node' import { Form, Link, useActionData, useSearchParams } from '@remix-run/react' import * as React from 'react' import { verifyLogin } from '~/models/user.server' import { createUserSession, getUserId } from '~/session.server' import { safeRedirect, validateEmail } from '~/utils' export async function loader({ request }: LoaderArgs) { const userId = await getUserId(request) if (userId) return redirect('/') return json({}) } export async function action({ 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: { password: 'Password is required', email: null } }, { status: 400 }) } if (password.length < 8) { return json({ errors: { password: 'Password is too short', email: null } }, { status: 400 }) } const user = await verifyLogin(email, password) if (!user) { return json({ errors: { email: 'Invalid email or password', password: null } }, { status: 400 }) } return createUserSession({ request, userId: user.id, remember: remember === 'on' ? true : false, redirectTo }) } export const meta: MetaFunction = () => { return { title: 'Login' } } export default function LoginPage() { const [searchParams] = useSearchParams() const redirectTo = searchParams.get('redirectTo') || '/notes' const actionData = useActionData() 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}
)}
) }