aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend/app/routes
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/app/routes')
-rw-r--r--frontend/app/routes/_index.tsx36
-rw-r--r--frontend/app/routes/admin.dashboard.tsx38
-rw-r--r--frontend/app/routes/admin.games.tsx52
-rw-r--r--frontend/app/routes/admin.games_.$gameId.tsx172
-rw-r--r--frontend/app/routes/admin.users.tsx50
-rw-r--r--frontend/app/routes/dashboard.tsx122
-rw-r--r--frontend/app/routes/golf.$gameId.play.tsx54
-rw-r--r--frontend/app/routes/golf.$gameId.watch.tsx54
-rw-r--r--frontend/app/routes/login.tsx116
-rw-r--r--frontend/app/routes/logout.tsx4
10 files changed, 349 insertions, 349 deletions
diff --git a/frontend/app/routes/_index.tsx b/frontend/app/routes/_index.tsx
index b5951ab..c56d4b2 100644
--- a/frontend/app/routes/_index.tsx
+++ b/frontend/app/routes/_index.tsx
@@ -2,25 +2,25 @@ import type { MetaFunction } from "@remix-run/node";
import { Link } from "@remix-run/react";
export const meta: MetaFunction = () => {
- return [{ title: "iOSDC Japan 2024 Albatross.swift" }];
+ return [{ title: "iOSDC Japan 2024 Albatross.swift" }];
};
export default function Index() {
- return (
- <div className="min-h-screen bg-gray-100 flex items-center justify-center">
- <div className="text-center">
- <h1 className="text-4xl font-bold text-blue-600 mb-4">
- iOSDC Japan 2024 Albatross.swift
- </h1>
- <p>
- <Link
- to="/login"
- className="text-lg text-white bg-blue-500 px-4 py-2 rounded hover:bg-blue-600 transition duration-300"
- >
- Login
- </Link>
- </p>
- </div>
- </div>
- );
+ return (
+ <div className="min-h-screen bg-gray-100 flex items-center justify-center">
+ <div className="text-center">
+ <h1 className="text-4xl font-bold text-blue-600 mb-4">
+ iOSDC Japan 2024 Albatross.swift
+ </h1>
+ <p>
+ <Link
+ to="/login"
+ className="text-lg text-white bg-blue-500 px-4 py-2 rounded hover:bg-blue-600 transition duration-300"
+ >
+ Login
+ </Link>
+ </p>
+ </div>
+ </div>
+ );
}
diff --git a/frontend/app/routes/admin.dashboard.tsx b/frontend/app/routes/admin.dashboard.tsx
index 1d172af..ce3e910 100644
--- a/frontend/app/routes/admin.dashboard.tsx
+++ b/frontend/app/routes/admin.dashboard.tsx
@@ -3,29 +3,29 @@ import { Link } from "@remix-run/react";
import { isAuthenticated } from "../.server/auth";
export const meta: MetaFunction = () => {
- return [{ title: "[Admin] Dashboard | iOSDC Japan 2024 Albatross.swift" }];
+ return [{ title: "[Admin] Dashboard | iOSDC Japan 2024 Albatross.swift" }];
};
export async function loader({ request }: LoaderFunctionArgs) {
- const { user } = await isAuthenticated(request, {
- failureRedirect: "/login",
- });
- if (!user.is_admin) {
- throw new Error("Unauthorized");
- }
- return null;
+ const { user } = await isAuthenticated(request, {
+ failureRedirect: "/login",
+ });
+ if (!user.is_admin) {
+ throw new Error("Unauthorized");
+ }
+ return null;
}
export default function AdminDashboard() {
- return (
- <div>
- <h1>[Admin] Dashboard</h1>
- <p>
- <Link to="/admin/users">Users</Link>
- </p>
- <p>
- <Link to="/admin/games">Games</Link>
- </p>
- </div>
- );
+ return (
+ <div>
+ <h1>[Admin] Dashboard</h1>
+ <p>
+ <Link to="/admin/users">Users</Link>
+ </p>
+ <p>
+ <Link to="/admin/games">Games</Link>
+ </p>
+ </div>
+ );
}
diff --git a/frontend/app/routes/admin.games.tsx b/frontend/app/routes/admin.games.tsx
index adba7f5..af3554e 100644
--- a/frontend/app/routes/admin.games.tsx
+++ b/frontend/app/routes/admin.games.tsx
@@ -4,37 +4,37 @@ import { adminApiGetGames } from "../.server/api/client";
import { isAuthenticated } from "../.server/auth";
export const meta: MetaFunction = () => {
- return [{ title: "[Admin] Games | iOSDC Japan 2024 Albatross.swift" }];
+ return [{ title: "[Admin] Games | iOSDC Japan 2024 Albatross.swift" }];
};
export async function loader({ request }: LoaderFunctionArgs) {
- const { user, token } = await isAuthenticated(request, {
- failureRedirect: "/login",
- });
- if (!user.is_admin) {
- throw new Error("Unauthorized");
- }
- const { games } = await adminApiGetGames(token);
- return { games };
+ const { user, token } = await isAuthenticated(request, {
+ failureRedirect: "/login",
+ });
+ if (!user.is_admin) {
+ throw new Error("Unauthorized");
+ }
+ const { games } = await adminApiGetGames(token);
+ return { games };
}
export default function AdminGames() {
- const { games } = useLoaderData<typeof loader>()!;
+ const { games } = useLoaderData<typeof loader>()!;
- return (
- <div>
- <div>
- <h1>[Admin] Games</h1>
- <ul>
- {games.map((game) => (
- <li key={game.game_id}>
- <Link to={`/admin/games/${game.game_id}`}>
- {game.display_name} (id={game.game_id})
- </Link>
- </li>
- ))}
- </ul>
- </div>
- </div>
- );
+ return (
+ <div>
+ <div>
+ <h1>[Admin] Games</h1>
+ <ul>
+ {games.map((game) => (
+ <li key={game.game_id}>
+ <Link to={`/admin/games/${game.game_id}`}>
+ {game.display_name} (id={game.game_id})
+ </Link>
+ </li>
+ ))}
+ </ul>
+ </div>
+ </div>
+ );
}
diff --git a/frontend/app/routes/admin.games_.$gameId.tsx b/frontend/app/routes/admin.games_.$gameId.tsx
index a7bd651..34860ab 100644
--- a/frontend/app/routes/admin.games_.$gameId.tsx
+++ b/frontend/app/routes/admin.games_.$gameId.tsx
@@ -1,107 +1,107 @@
import type {
- ActionFunctionArgs,
- LoaderFunctionArgs,
- MetaFunction,
+ ActionFunctionArgs,
+ LoaderFunctionArgs,
+ MetaFunction,
} from "@remix-run/node";
import { Form, useLoaderData } from "@remix-run/react";
import { adminApiGetGame, adminApiPutGame } from "../.server/api/client";
import { isAuthenticated } from "../.server/auth";
export const meta: MetaFunction<typeof loader> = ({ data }) => {
- return [
- {
- title: data
- ? `[Admin] Game Edit ${data.game.display_name} | iOSDC Japan 2024 Albatross.swift`
- : "[Admin] Game Edit | iOSDC Japan 2024 Albatross.swift",
- },
- ];
+ return [
+ {
+ title: data
+ ? `[Admin] Game Edit ${data.game.display_name} | iOSDC Japan 2024 Albatross.swift`
+ : "[Admin] Game Edit | iOSDC Japan 2024 Albatross.swift",
+ },
+ ];
};
export async function loader({ request, params }: LoaderFunctionArgs) {
- const { user, token } = await isAuthenticated(request, {
- failureRedirect: "/login",
- });
- if (!user.is_admin) {
- throw new Error("Unauthorized");
- }
- const { gameId } = params;
- const { game } = await adminApiGetGame(token, Number(gameId));
- return { game };
+ const { user, token } = await isAuthenticated(request, {
+ failureRedirect: "/login",
+ });
+ if (!user.is_admin) {
+ throw new Error("Unauthorized");
+ }
+ const { gameId } = params;
+ const { game } = await adminApiGetGame(token, Number(gameId));
+ return { game };
}
export async function action({ request, params }: ActionFunctionArgs) {
- const { user, token } = await isAuthenticated(request, {
- failureRedirect: "/login",
- });
- if (!user.is_admin) {
- throw new Error("Unauthorized");
- }
- const { gameId } = params;
+ const { user, token } = await isAuthenticated(request, {
+ failureRedirect: "/login",
+ });
+ if (!user.is_admin) {
+ throw new Error("Unauthorized");
+ }
+ const { gameId } = params;
- const formData = await request.formData();
- const action = formData.get("action");
+ const formData = await request.formData();
+ const action = formData.get("action");
- const nextState =
- action === "open"
- ? "waiting_entries"
- : action === "start"
- ? "prepare"
- : null;
- if (!nextState) {
- throw new Error("Invalid action");
- }
+ const nextState =
+ action === "open"
+ ? "waiting_entries"
+ : action === "start"
+ ? "prepare"
+ : null;
+ if (!nextState) {
+ throw new Error("Invalid action");
+ }
- await adminApiPutGame(token, Number(gameId), {
- state: nextState,
- });
- return null;
+ await adminApiPutGame(token, Number(gameId), {
+ state: nextState,
+ });
+ return null;
}
export default function AdminGameEdit() {
- const { game } = useLoaderData<typeof loader>()!;
+ const { game } = useLoaderData<typeof loader>()!;
- return (
- <div>
- <div>
- <h1>[Admin] Game Edit {game.display_name}</h1>
- <ul>
- <li>ID: {game.game_id}</li>
- <li>State: {game.state}</li>
- <li>Display Name: {game.display_name}</li>
- <li>Duration Seconds: {game.duration_seconds}</li>
- <li>
- Started At:{" "}
- {game.started_at
- ? new Date(game.started_at * 1000).toString()
- : "-"}
- </li>
- <li>Problem ID: {game.problem ? game.problem.problem_id : "-"}</li>
- </ul>
- <div>
- <Form method="post">
- <div>
- <button
- type="submit"
- name="action"
- value="open"
- disabled={game.state !== "closed"}
- >
- Open
- </button>
- </div>
- <div>
- <button
- type="submit"
- name="action"
- value="start"
- disabled={game.state !== "waiting_start"}
- >
- Start
- </button>
- </div>
- </Form>
- </div>
- </div>
- </div>
- );
+ return (
+ <div>
+ <div>
+ <h1>[Admin] Game Edit {game.display_name}</h1>
+ <ul>
+ <li>ID: {game.game_id}</li>
+ <li>State: {game.state}</li>
+ <li>Display Name: {game.display_name}</li>
+ <li>Duration Seconds: {game.duration_seconds}</li>
+ <li>
+ Started At:{" "}
+ {game.started_at
+ ? new Date(game.started_at * 1000).toString()
+ : "-"}
+ </li>
+ <li>Problem ID: {game.problem ? game.problem.problem_id : "-"}</li>
+ </ul>
+ <div>
+ <Form method="post">
+ <div>
+ <button
+ type="submit"
+ name="action"
+ value="open"
+ disabled={game.state !== "closed"}
+ >
+ Open
+ </button>
+ </div>
+ <div>
+ <button
+ type="submit"
+ name="action"
+ value="start"
+ disabled={game.state !== "waiting_start"}
+ >
+ Start
+ </button>
+ </div>
+ </Form>
+ </div>
+ </div>
+ </div>
+ );
}
diff --git a/frontend/app/routes/admin.users.tsx b/frontend/app/routes/admin.users.tsx
index 8d9a8f2..9eed263 100644
--- a/frontend/app/routes/admin.users.tsx
+++ b/frontend/app/routes/admin.users.tsx
@@ -4,36 +4,36 @@ import { adminApiGetUsers } from "../.server/api/client";
import { isAuthenticated } from "../.server/auth";
export const meta: MetaFunction = () => {
- return [{ title: "[Admin] Users | iOSDC Japan 2024 Albatross.swift" }];
+ return [{ title: "[Admin] Users | iOSDC Japan 2024 Albatross.swift" }];
};
export async function loader({ request }: LoaderFunctionArgs) {
- const { user, token } = await isAuthenticated(request, {
- failureRedirect: "/login",
- });
- if (!user.is_admin) {
- throw new Error("Unauthorized");
- }
- const { users } = await adminApiGetUsers(token);
- return { users };
+ const { user, token } = await isAuthenticated(request, {
+ failureRedirect: "/login",
+ });
+ if (!user.is_admin) {
+ throw new Error("Unauthorized");
+ }
+ const { users } = await adminApiGetUsers(token);
+ return { users };
}
export default function AdminUsers() {
- const { users } = useLoaderData<typeof loader>()!;
+ const { users } = useLoaderData<typeof loader>()!;
- return (
- <div>
- <div>
- <h1>[Admin] Users</h1>
- <ul>
- {users.map((user) => (
- <li key={user.user_id}>
- {user.display_name} (id={user.user_id} username={user.username})
- {user.is_admin && <span> admin</span>}
- </li>
- ))}
- </ul>
- </div>
- </div>
- );
+ return (
+ <div>
+ <div>
+ <h1>[Admin] Users</h1>
+ <ul>
+ {users.map((user) => (
+ <li key={user.user_id}>
+ {user.display_name} (id={user.user_id} username={user.username})
+ {user.is_admin && <span> admin</span>}
+ </li>
+ ))}
+ </ul>
+ </div>
+ </div>
+ );
}
diff --git a/frontend/app/routes/dashboard.tsx b/frontend/app/routes/dashboard.tsx
index 1f80634..1c2137d 100644
--- a/frontend/app/routes/dashboard.tsx
+++ b/frontend/app/routes/dashboard.tsx
@@ -5,72 +5,72 @@ import { apiGetGames } from "../.server/api/client";
import { isAuthenticated } from "../.server/auth";
export const meta: MetaFunction = () => {
- return [{ title: "Dashboard | iOSDC Japan 2024 Albatross.swift" }];
+ return [{ title: "Dashboard | iOSDC Japan 2024 Albatross.swift" }];
};
export async function loader({ request }: LoaderFunctionArgs) {
- const { user, token } = await isAuthenticated(request, {
- failureRedirect: "/login",
- });
- if (user.is_admin) {
- return redirect("/admin/dashboard");
- }
- const { games } = await apiGetGames(token);
- return {
- user,
- games,
- };
+ const { user, token } = await isAuthenticated(request, {
+ failureRedirect: "/login",
+ });
+ if (user.is_admin) {
+ return redirect("/admin/dashboard");
+ }
+ const { games } = await apiGetGames(token);
+ return {
+ user,
+ games,
+ };
}
export default function Dashboard() {
- const { user, games } = useLoaderData<typeof loader>()!;
+ const { user, games } = useLoaderData<typeof loader>()!;
- return (
- <div className="min-h-screen p-8">
- <div className="p-6 rounded shadow-md max-w-4xl mx-auto">
- <h1 className="text-3xl font-bold mb-4">
- {user.username}{" "}
- {user.is_admin && <span className="text-red-500 text-lg">admin</span>}
- </h1>
- <h2 className="text-2xl font-semibold mb-2">User</h2>
- <div className="mb-6">
- <ul className="list-disc list-inside">
- <li>Name: {user.display_name}</li>
- </ul>
- </div>
- <h2 className="text-2xl font-semibold mb-2">Games</h2>
- <div>
- <ul className="list-disc list-inside">
- {games.map((game) => (
- <li key={game.game_id}>
- {game.display_name}{" "}
- {game.state === "closed" || game.state === "finished" ? (
- <span className="inline-block px-6 py-2 text-gray-400 bg-gray-200 cursor-not-allowed rounded">
- Entry
- </span>
- ) : (
- <Link
- to={`/golf/${game.game_id}/play`}
- className="inline-block px-6 py-2 text-white bg-blue-500 hover:bg-blue-700 rounded"
- >
- Entry
- </Link>
- )}
- </li>
- ))}
- </ul>
- </div>
- <div>
- <Form method="post" action="/logout">
- <button
- className="mt-6 px-6 py-2 text-white bg-red-500 hover:bg-red-700 rounded"
- type="submit"
- >
- Logout
- </button>
- </Form>
- </div>
- </div>
- </div>
- );
+ return (
+ <div className="min-h-screen p-8">
+ <div className="p-6 rounded shadow-md max-w-4xl mx-auto">
+ <h1 className="text-3xl font-bold mb-4">
+ {user.username}{" "}
+ {user.is_admin && <span className="text-red-500 text-lg">admin</span>}
+ </h1>
+ <h2 className="text-2xl font-semibold mb-2">User</h2>
+ <div className="mb-6">
+ <ul className="list-disc list-inside">
+ <li>Name: {user.display_name}</li>
+ </ul>
+ </div>
+ <h2 className="text-2xl font-semibold mb-2">Games</h2>
+ <div>
+ <ul className="list-disc list-inside">
+ {games.map((game) => (
+ <li key={game.game_id}>
+ {game.display_name}{" "}
+ {game.state === "closed" || game.state === "finished" ? (
+ <span className="inline-block px-6 py-2 text-gray-400 bg-gray-200 cursor-not-allowed rounded">
+ Entry
+ </span>
+ ) : (
+ <Link
+ to={`/golf/${game.game_id}/play`}
+ className="inline-block px-6 py-2 text-white bg-blue-500 hover:bg-blue-700 rounded"
+ >
+ Entry
+ </Link>
+ )}
+ </li>
+ ))}
+ </ul>
+ </div>
+ <div>
+ <Form method="post" action="/logout">
+ <button
+ className="mt-6 px-6 py-2 text-white bg-red-500 hover:bg-red-700 rounded"
+ type="submit"
+ >
+ Logout
+ </button>
+ </Form>
+ </div>
+ </div>
+ </div>
+ );
}
diff --git a/frontend/app/routes/golf.$gameId.play.tsx b/frontend/app/routes/golf.$gameId.play.tsx
index 0ce3353..d498200 100644
--- a/frontend/app/routes/golf.$gameId.play.tsx
+++ b/frontend/app/routes/golf.$gameId.play.tsx
@@ -7,40 +7,40 @@ import GolfPlayApp from "../components/GolfPlayApp.client";
import GolfPlayAppConnecting from "../components/GolfPlayApps/GolfPlayAppConnecting";
export const meta: MetaFunction<typeof loader> = ({ data }) => {
- return [
- {
- title: data
- ? `Golf Playing ${data.game.display_name} | iOSDC Japan 2024 Albatross.swift`
- : "Golf Playing | iOSDC Japan 2024 Albatross.swift",
- },
- ];
+ return [
+ {
+ title: data
+ ? `Golf Playing ${data.game.display_name} | iOSDC Japan 2024 Albatross.swift`
+ : "Golf Playing | iOSDC Japan 2024 Albatross.swift",
+ },
+ ];
};
export async function loader({ params, request }: LoaderFunctionArgs) {
- const { token } = await isAuthenticated(request, {
- failureRedirect: "/login",
- });
+ const { token } = await isAuthenticated(request, {
+ failureRedirect: "/login",
+ });
- const fetchGame = async () => {
- return (await apiGetGame(token, Number(params.gameId))).game;
- };
- const fetchSockToken = async () => {
- return (await apiGetToken(token)).token;
- };
+ const fetchGame = async () => {
+ return (await apiGetGame(token, Number(params.gameId))).game;
+ };
+ const fetchSockToken = async () => {
+ return (await apiGetToken(token)).token;
+ };
- const [game, sockToken] = await Promise.all([fetchGame(), fetchSockToken()]);
- return {
- game,
- sockToken,
- };
+ const [game, sockToken] = await Promise.all([fetchGame(), fetchSockToken()]);
+ return {
+ game,
+ sockToken,
+ };
}
export default function GolfPlay() {
- const { game, sockToken } = useLoaderData<typeof loader>();
+ const { game, sockToken } = useLoaderData<typeof loader>();
- return (
- <ClientOnly fallback={<GolfPlayAppConnecting />}>
- {() => <GolfPlayApp game={game} sockToken={sockToken} />}
- </ClientOnly>
- );
+ return (
+ <ClientOnly fallback={<GolfPlayAppConnecting />}>
+ {() => <GolfPlayApp game={game} sockToken={sockToken} />}
+ </ClientOnly>
+ );
}
diff --git a/frontend/app/routes/golf.$gameId.watch.tsx b/frontend/app/routes/golf.$gameId.watch.tsx
index 0f0e085..0203e27 100644
--- a/frontend/app/routes/golf.$gameId.watch.tsx
+++ b/frontend/app/routes/golf.$gameId.watch.tsx
@@ -7,40 +7,40 @@ import GolfWatchApp from "../components/GolfWatchApp.client";
import GolfWatchAppConnecting from "../components/GolfWatchApps/GolfWatchAppConnecting";
export const meta: MetaFunction<typeof loader> = ({ data }) => {
- return [
- {
- title: data
- ? `Golf Watching ${data.game.display_name} | iOSDC Japan 2024 Albatross.swift`
- : "Golf Watching | iOSDC Japan 2024 Albatross.swift",
- },
- ];
+ return [
+ {
+ title: data
+ ? `Golf Watching ${data.game.display_name} | iOSDC Japan 2024 Albatross.swift`
+ : "Golf Watching | iOSDC Japan 2024 Albatross.swift",
+ },
+ ];
};
export async function loader({ params, request }: LoaderFunctionArgs) {
- const { token } = await isAuthenticated(request, {
- failureRedirect: "/login",
- });
+ const { token } = await isAuthenticated(request, {
+ failureRedirect: "/login",
+ });
- const fetchGame = async () => {
- return (await apiGetGame(token, Number(params.gameId))).game;
- };
- const fetchSockToken = async () => {
- return (await apiGetToken(token)).token;
- };
+ const fetchGame = async () => {
+ return (await apiGetGame(token, Number(params.gameId))).game;
+ };
+ const fetchSockToken = async () => {
+ return (await apiGetToken(token)).token;
+ };
- const [game, sockToken] = await Promise.all([fetchGame(), fetchSockToken()]);
- return {
- game,
- sockToken,
- };
+ const [game, sockToken] = await Promise.all([fetchGame(), fetchSockToken()]);
+ return {
+ game,
+ sockToken,
+ };
}
export default function GolfWatch() {
- const { game, sockToken } = useLoaderData<typeof loader>();
+ const { game, sockToken } = useLoaderData<typeof loader>();
- return (
- <ClientOnly fallback={<GolfWatchAppConnecting />}>
- {() => <GolfWatchApp game={game} sockToken={sockToken} />}
- </ClientOnly>
- );
+ return (
+ <ClientOnly fallback={<GolfWatchAppConnecting />}>
+ {() => <GolfWatchApp game={game} sockToken={sockToken} />}
+ </ClientOnly>
+ );
}
diff --git a/frontend/app/routes/login.tsx b/frontend/app/routes/login.tsx
index f63df08..95effaa 100644
--- a/frontend/app/routes/login.tsx
+++ b/frontend/app/routes/login.tsx
@@ -1,74 +1,74 @@
import type {
- ActionFunctionArgs,
- LoaderFunctionArgs,
- MetaFunction,
+ ActionFunctionArgs,
+ LoaderFunctionArgs,
+ MetaFunction,
} from "@remix-run/node";
import { Form } from "@remix-run/react";
import { authenticator } from "../.server/auth";
export const meta: MetaFunction = () => {
- return [{ title: "Login | iOSDC Japan 2024 Albatross.swift" }];
+ return [{ title: "Login | iOSDC Japan 2024 Albatross.swift" }];
};
export async function loader({ request }: LoaderFunctionArgs) {
- return await authenticator.isAuthenticated(request, {
- successRedirect: "/dashboard",
- });
+ return await authenticator.isAuthenticated(request, {
+ successRedirect: "/dashboard",
+ });
}
export async function action({ request }: ActionFunctionArgs) {
- return await authenticator.authenticate("default", request, {
- successRedirect: "/dashboard",
- failureRedirect: "/login",
- });
+ return await authenticator.authenticate("default", request, {
+ successRedirect: "/dashboard",
+ failureRedirect: "/login",
+ });
}
export default function Login() {
- 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>
- <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>
- );
+ 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>
+ <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>
+ );
}
diff --git a/frontend/app/routes/logout.tsx b/frontend/app/routes/logout.tsx
index 030bde0..012d9e9 100644
--- a/frontend/app/routes/logout.tsx
+++ b/frontend/app/routes/logout.tsx
@@ -2,6 +2,6 @@ import type { ActionFunctionArgs } from "@remix-run/node";
import { authenticator } from "../.server/auth";
export async function action({ request }: ActionFunctionArgs) {
- await authenticator.logout(request, { redirectTo: "/" });
- return null;
+ await authenticator.logout(request, { redirectTo: "/" });
+ return null;
}