import type { ActionFunction, LinksFunction, MetaFunction } from "remix"; import { useActionData, json, Link, useSearchParams, Form } from "remix"; import { db } from "~/utils/db.server"; import { login, createUserSession, register } from "~/utils/session.server"; export const links: LinksFunction = () => { return []; }; export const meta: MetaFunction = () => { return { title: "Explit | Login", description: "Login to track and split your expenses!", }; }; function validateUsername(username: unknown) { if (typeof username !== "string" || username.length < 3) { return `Usernames must be at least 3 characters long`; } } function validatePassword(password: unknown) { if (typeof password !== "string" || password.length < 6) { return `Passwords must be at least 6 characters long`; } } function validateTeamId(teamId: unknown) { if (typeof teamId !== "string" || teamId.length < 1) { return "You must indicate an arbitrary team ID"; } } type ActionData = { formError?: string; fieldErrors?: { username: string | undefined; password: string | undefined; }; fields?: { loginType: string; username: string; password: string; teamId?: string; icon?: string; }; }; const badRequest = (data: ActionData) => json(data, { status: 400 }); export const action: ActionFunction = async ({ request }) => { const form = await request.formData(); const loginType = form.get("loginType"); const username = form.get("username"); const password = form.get("password"); const icon = form.get("icon"); const teamId = form.get("teamId"); const redirectTo = form.get("redirectTo") || "/expenses"; if ( typeof loginType !== "string" || typeof username !== "string" || typeof password !== "string" || (loginType === "register" && (typeof icon !== "string" || typeof teamId !== "string" || typeof redirectTo !== "string")) ) { return badRequest({ formError: `Form not submitted correctly.`, }); } const fields = { loginType, username, password, teamId }; const fieldErrors = { username: validateUsername(username), password: validatePassword(password), teamId: loginType === "register" && validateTeamId(teamId), }; if (Object.values(fieldErrors).some(Boolean)) return badRequest({ fieldErrors, fields }); switch (loginType) { case "login": { const user = await login({ username, password }); if (!user) { return badRequest({ fields, formError: `Username/Password combination is incorrect`, }); } return createUserSession(user.id, redirectTo); } case "register": { const userExists = await db.user.findFirst({ where: { username }, }); if (userExists) { console.error(userExists); return badRequest({ fields, formError: `User with username ${username} already exists`, }); } const user = await register({ username, password, icon, teamId }); if (!user) { return badRequest({ fields, formError: `Something went wrong trying to create a new user.`, }); } return createUserSession(user.id, redirectTo); } default: { return badRequest({ fields, formError: `Login type invalid`, }); } } }; export default function Login() { const actionData = useActionData(); const [searchParams] = useSearchParams(); return (

Login

Login or Register?
{actionData?.fieldErrors?.username ? ( ) : null}
{actionData?.fieldErrors?.teamId ? ( ) : null}
{actionData?.fieldErrors?.password ? ( ) : null}
{actionData?.formError ? (

{actionData?.formError}

) : null}
  • Home
); }