diff options
Diffstat (limited to 'frontend/app/routes/login.tsx')
| -rw-r--r-- | frontend/app/routes/login.tsx | 150 |
1 files changed, 100 insertions, 50 deletions
diff --git a/frontend/app/routes/login.tsx b/frontend/app/routes/login.tsx index d6414f7..b1249e0 100644 --- a/frontend/app/routes/login.tsx +++ b/frontend/app/routes/login.tsx @@ -3,8 +3,11 @@ import type { LoaderFunctionArgs, MetaFunction, } from "@remix-run/node"; -import { Form, useLocation } from "@remix-run/react"; +import { Form, json, useActionData, useLocation } from "@remix-run/react"; import { ensureUserNotLoggedIn, login } from "../.server/auth"; +import BorderedContainer from "../components/BorderedContainer"; +import InputText from "../components/InputText"; +import SubmitButton from "../components/SubmitButton"; export const meta: MetaFunction = () => [ { title: "Login | iOSDC Japan 2024 Albatross.swift" }, @@ -15,7 +18,42 @@ export async function loader({ request }: LoaderFunctionArgs) { } export async function action({ request }: ActionFunctionArgs) { - await login(request); + const formData = await request.clone().formData(); + const username = String(formData.get("username")); + const password = String(formData.get("password")); + if (username === "" || password === "") { + return json( + { + message: "ユーザー名またはパスワードが誤っています", + errors: { + username: + username === "" ? "ユーザー名を入力してください" : undefined, + password: + password === "" ? "パスワードを入力してください" : undefined, + }, + }, + { status: 400 }, + ); + } + + try { + await login(request); + } catch (error) { + if (error instanceof Error) { + return json( + { + message: error.message, + errors: { + username: undefined, + password: undefined, + }, + }, + { status: 400 }, + ); + } else { + throw error; + } + } return null; } @@ -24,56 +62,68 @@ export default function Login() { const searchParams = new URLSearchParams(location.search); const registrationToken = searchParams.get("registration_token"); + const loginErrors = useActionData<typeof action>(); + return ( <div className="min-h-screen bg-gray-100 flex items-center justify-center"> - <Form - method="post" - className="bg-white p-8 rounded shadow-md w-full max-w-sm" - > - <h2 className="text-2xl font-bold mb-6 text-center">Login</h2> - <div className="mb-4"> - <label - htmlFor="username" - className="block text-sm font-medium text-gray-700" - > - Username - </label> - <input - type="text" - name="username" - id="username" - required - className="mt-1 p-2 block w-full border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500" - /> - </div> - <div className="mb-6"> - <label - htmlFor="password" - className="block text-sm font-medium text-gray-700" - > - Password - </label> - <input - type="password" - name="password" - id="password" - autoComplete="current-password" - required - className="mt-1 p-2 block w-full border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500" - /> - </div> - <input - type="hidden" - name="registration_token" - value={registrationToken ?? ""} - /> - <button - type="submit" - className="w-full bg-blue-500 text-white py-2 rounded hover:bg-blue-600 transition duration-300" - > - Log In - </button> - </Form> + <div className="mx-2"> + <BorderedContainer> + <Form method="post" className="w-full max-w-sm p-2"> + <h2 className="text-2xl mb-6 text-center"> + fortee アカウントでログイン + </h2> + <p className="text-sm mb-4"> + fortee + のアカウントをお持ちでない場合は、イベントスタッフにお声がけください。 + </p> + {loginErrors?.message && ( + <p className="text-red-500 text-sm mb-4">{loginErrors.message}</p> + )} + <div className="mb-4 flex flex-col gap-1"> + <label + htmlFor="username" + className="block text-sm font-medium text-gray-700" + > + ユーザー名 + </label> + <InputText type="text" name="username" id="username" required /> + {loginErrors?.errors?.username && ( + <p className="text-red-500 text-sm"> + {loginErrors.errors.username} + </p> + )} + </div> + <div className="mb-6 flex flex-col gap-1"> + <label + htmlFor="password" + className="block text-sm font-medium text-gray-700" + > + パスワード + </label> + <InputText + type="password" + name="password" + id="password" + autoComplete="current-password" + required + /> + {loginErrors?.errors?.password && ( + <p className="text-red-500 text-sm"> + {loginErrors.errors.password} + </p> + )} + </div> + <input + type="hidden" + name="registration_token" + value={registrationToken ?? ""} + /> + <div className="flex justify-center"> + <SubmitButton type="submit">ログイン</SubmitButton> + </div> + </Form> + </BorderedContainer> + </div> </div> ); } |
