diff options
Diffstat (limited to 'frontend/app/routes')
| -rw-r--r-- | frontend/app/routes/_index.tsx | 25 | ||||
| -rw-r--r-- | frontend/app/routes/login.tsx | 150 |
2 files changed, 114 insertions, 61 deletions
diff --git a/frontend/app/routes/_index.tsx b/frontend/app/routes/_index.tsx index ec87e86..9f9c2bb 100644 --- a/frontend/app/routes/_index.tsx +++ b/frontend/app/routes/_index.tsx @@ -2,6 +2,7 @@ import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node"; import { Link } from "@remix-run/react"; import "@fortawesome/fontawesome-svg-core/styles.css"; import { ensureUserNotLoggedIn } from "../.server/auth"; +import BorderedContainer from "../components/BorderedContainer"; export const meta: MetaFunction = () => [ { title: "iOSDC Japan 2024 Albatross.swift" }, @@ -23,19 +24,21 @@ export default function Index() { <div className="text-center"> <div className="font-bold text-transparent bg-clip-text bg-gradient-to-r from-orange-400 via-pink-500 to-purple-400 flex flex-col gap-y-2"> <div className="text-3xl">iOSDC Japan 2024</div> - <div className="text-6xl"> - Swift <wbr /> - Code Battle - </div> + <div className="text-6xl">Swift Code Battle</div> </div> </div> - <p className="text-gray-900 max-w-prose bg-white p-4 rounded-xl border-2 border-pink-600 mx-2"> - Swift コードバトルは指示された動作をする Swift - コードをより短く書けた方が勝ち、という 1 対 1 - の対戦コンテンツです。8/22(木)day0 前夜祭では 8/12 - に実施された予選を勝ち抜いたプレイヤーによるトーナメント形式での Swift - コードバトルを実施します。ここでは短いコードが正義です!可読性も保守性も放り投げた、イベントならではのコードをお楽しみください! - </p> + <div className="mx-2"> + <BorderedContainer> + <p className="text-gray-900 max-w-prose"> + Swift コードバトルは指示された動作をする Swift + コードをより短く書けた方が勝ち、という 1 対 1 + の対戦コンテンツです。8/22(木)day0 前夜祭では 8/12 + に実施された予選を勝ち抜いたプレイヤーによるトーナメント形式での + Swift + コードバトルを実施します。ここでは短いコードが正義です!可読性も保守性も放り投げた、イベントならではのコードをお楽しみください! + </p> + </BorderedContainer> + </div> <div> <Link to="/login" 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> ); } |
