diff --git a/app/components/Header.tsx b/app/components/Header.tsx index 7d902f6..4a3e092 100644 --- a/app/components/Header.tsx +++ b/app/components/Header.tsx @@ -85,7 +85,7 @@ const Header = ({ user, route }: Props) => { {user ? (
-
+
{user.icon ?? user.username[0]}
diff --git a/app/routes/login.tsx b/app/routes/login.tsx index f1af1ca..1a14021 100644 --- a/app/routes/login.tsx +++ b/app/routes/login.tsx @@ -1,6 +1,6 @@ import type { ActionFunction, LinksFunction, MetaFunction } from "remix"; import { useActionData, json, Link, useSearchParams, Form } from "remix"; -import { login, createUserSession, register } from "~/utils/session.server"; +import { login, createUserSession } from "~/utils/session.server"; import Header from "../components/Header"; export const links: LinksFunction = () => { @@ -104,7 +104,7 @@ export default function Login() { type="text" id="username-input" name="username" - className="input" + className="input input-bordered" defaultValue={actionData?.fields?.username} aria-invalid={Boolean(actionData?.fieldErrors?.username)} aria-describedby={ @@ -143,7 +143,7 @@ export default function Login() { { return []; @@ -9,8 +10,8 @@ export const links: LinksFunction = () => { export const meta: MetaFunction = () => { return { - title: "Explit | Login", - description: "Login to track and split your expenses!", + title: "Explit | Sign in", + description: "Sign in to track and split your expenses!", }; }; @@ -26,6 +27,18 @@ function validatePassword(password: unknown) { } } +function validateConfirmPassword(confirmPassword: unknown, password: string) { + if (typeof confirmPassword !== "string" || confirmPassword !== password) { + return `Passwords must match`; + } +} + +function validateIcon(icon: unknown) { + if (typeof icon !== "string" || icon.length > 2) { + return `Icons must be a single character, e.g. "A" or "😎"`; + } +} + function validateTeamId(teamId: unknown) { if (typeof teamId !== "string" || teamId.length < 1) { return "You must indicate an arbitrary team ID"; @@ -37,11 +50,14 @@ type ActionData = { fieldErrors?: { username: string | undefined; password: string | undefined; + teamId: string | undefined; + confirmPassword: string | undefined; + icon: string | undefined; }; fields?: { - loginType: string; username: string; password: string; + confirmPassword: string; teamId?: string; icon?: string; }; @@ -51,73 +67,55 @@ 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 confirmPassword = form.get("confirmPassword"); + const icon = + form.get("icon") ?? + (typeof username === "string" ? username[0] : undefined); 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")) + typeof confirmPassword !== "string" || + typeof teamId !== "string" || + typeof redirectTo !== "string" ) { return badRequest({ formError: `Form not submitted correctly.`, }); } - const fields = { loginType, username, password, teamId }; + const fields = { username, password, confirmPassword, teamId }; const fieldErrors = { username: validateUsername(username), password: validatePassword(password), - teamId: loginType === "register" && validateTeamId(teamId), + confirmPassword: validateConfirmPassword(confirmPassword, password), + icon: validateIcon(icon), + teamId: 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`, - }); - } + 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); }; export default function Login() { @@ -125,143 +123,294 @@ export default function Login() { const [searchParams] = useSearchParams(); return ( -
-
-

Login

-
- -
- Login or Register? -
-
- - - {actionData?.fieldErrors?.username ? ( - - ) : null} + type="hidden" + name="redirectTo" + value={searchParams.get("redirectTo") ?? undefined} + /> +
+ + + {actionData?.fieldErrors?.username && ( +
+
+ + + + +
+
+ )} +
+
+ + + + {actionData?.fieldErrors?.icon && ( +
+
+ + + + +
+
+ )} +
+
+ + + {actionData?.fieldErrors?.password && ( +
+
+ + + + +
+
+ )} +
+
+ + + {actionData?.fieldErrors?.confirmPassword && ( +
+
+ + + + +
+
+ )} +
+
+ + + {actionData?.fieldErrors?.teamId && ( +
+
+ + + + +
+
+ )} +
+ {actionData?.formError && ( +
+
+ + + + +
+
+ )} +
+ +
+
-
- - - {actionData?.fieldErrors?.teamId ? ( - - ) : null} -
-
- - -
-
- - - {actionData?.fieldErrors?.password ? ( - - ) : null} -
-
- {actionData?.formError ? ( -

- {actionData?.formError} -

- ) : null} -
- - +
-
-
    -
  • - Home -
  • -
-
-
+ + ); }