From 72012983718a8d1f1d850e24e9af3a29fb20374a Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Thu, 1 Aug 2024 21:09:36 +0900
Subject: refactor: remove `player_id` parameter from `/api/games`

---
 frontend/app/routes/dashboard.tsx | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'frontend/app/routes/dashboard.tsx')

diff --git a/frontend/app/routes/dashboard.tsx b/frontend/app/routes/dashboard.tsx
index 3cc8e13..08780f9 100644
--- a/frontend/app/routes/dashboard.tsx
+++ b/frontend/app/routes/dashboard.tsx
@@ -17,9 +17,6 @@ export async function loader({ request }: LoaderFunctionArgs) {
   }
   const { data, error } = await apiClient.GET("/games", {
     params: {
-      query: {
-        player_id: user.user_id,
-      },
       header: {
         Authorization: `Bearer ${token}`,
       },
-- 
cgit v1.3.1


From 94d5d89aa59b6d1e53dab280c26e3a8fcb22b7e4 Mon Sep 17 00:00:00 2001
From: nsfisis <nsfisis@gmail.com>
Date: Thu, 1 Aug 2024 21:13:11 +0900
Subject: refactor(frontend): provide simpler API client

---
 frontend/app/.server/api/client.ts           | 90 +++++++++++++++++++++++++++-
 frontend/app/.server/auth.ts                 | 13 +---
 frontend/app/routes/admin.games.tsx          | 15 +----
 frontend/app/routes/admin.games_.$gameId.tsx | 35 ++---------
 frontend/app/routes/admin.users.tsx          | 15 +----
 frontend/app/routes/dashboard.tsx            | 15 +----
 frontend/app/routes/golf.$gameId.play.tsx    | 30 +---------
 frontend/app/routes/golf.$gameId.watch.tsx   | 30 +---------
 8 files changed, 110 insertions(+), 133 deletions(-)

(limited to 'frontend/app/routes/dashboard.tsx')

diff --git a/frontend/app/.server/api/client.ts b/frontend/app/.server/api/client.ts
index 8e50b7e..8f53b5b 100644
--- a/frontend/app/.server/api/client.ts
+++ b/frontend/app/.server/api/client.ts
@@ -1,9 +1,95 @@
 import createClient from "openapi-fetch";
-import type { paths } from "./schema";
+import type { paths, operations } from "./schema";
 
-export const apiClient = createClient<paths>({
+const apiClient = createClient<paths>({
   baseUrl:
     process.env.NODE_ENV === "development"
       ? "http://localhost:8002/api/"
       : "http://api-server/api/",
 });
+
+export async function apiPostLogin(username: string, password: string) {
+  const { data, error } = await apiClient.POST("/login", {
+    body: { username, password },
+  });
+  if (error) throw new Error(error.message);
+  return data;
+}
+
+export async function apiGetGames(token: string) {
+  const { data, error } = await apiClient.GET("/games", {
+    params: {
+      header: { Authorization: `Bearer ${token}` },
+    },
+  });
+  if (error) throw new Error(error.message);
+  return data;
+}
+
+export async function apiGetGame(token: string, gameId: number) {
+  const { data, error } = await apiClient.GET("/games/{game_id}", {
+    params: {
+      header: { Authorization: `Bearer ${token}` },
+      path: { game_id: gameId },
+    },
+  });
+  if (error) throw new Error(error.message);
+  return data;
+}
+
+export async function apiGetToken(token: string) {
+  const { data, error } = await apiClient.GET("/token", {
+    params: {
+      header: { Authorization: `Bearer ${token}` },
+    },
+  });
+  if (error) throw new Error(error.message);
+  return data;
+}
+
+export async function adminApiGetUsers(token: string) {
+  const { data, error } = await apiClient.GET("/admin/users", {
+    params: {
+      header: { Authorization: `Bearer ${token}` },
+    },
+  });
+  if (error) throw new Error(error.message);
+  return data;
+}
+
+export async function adminApiGetGames(token: string) {
+  const { data, error } = await apiClient.GET("/admin/games", {
+    params: {
+      header: { Authorization: `Bearer ${token}` },
+    },
+  });
+  if (error) throw new Error(error.message);
+  return data;
+}
+
+export async function adminApiGetGame(token: string, gameId: number) {
+  const { data, error } = await apiClient.GET("/admin/games/{game_id}", {
+    params: {
+      header: { Authorization: `Bearer ${token}` },
+      path: { game_id: gameId },
+    },
+  });
+  if (error) throw new Error(error.message);
+  return data;
+}
+
+export async function adminApiPutGame(
+  token: string,
+  gameId: number,
+  body: operations["adminPutGame"]["requestBody"]["content"]["application/json"],
+) {
+  const { data, error } = await apiClient.PUT("/admin/games/{game_id}", {
+    params: {
+      header: { Authorization: `Bearer ${token}` },
+      path: { game_id: gameId },
+    },
+    body,
+  });
+  if (error) throw new Error(error.message);
+  return data;
+}
diff --git a/frontend/app/.server/auth.ts b/frontend/app/.server/auth.ts
index b80166b..b7e1820 100644
--- a/frontend/app/.server/auth.ts
+++ b/frontend/app/.server/auth.ts
@@ -3,22 +3,13 @@ import { FormStrategy } from "remix-auth-form";
 import { jwtDecode } from "jwt-decode";
 import type { Session } from "@remix-run/server-runtime";
 import { sessionStorage } from "./session";
-import { apiClient } from "./api/client";
+import { apiPostLogin } from "./api/client";
 import { components } from "./api/schema";
 
 export const authenticator = new Authenticator<string>(sessionStorage);
 
 async function login(username: string, password: string): Promise<string> {
-  const { data, error } = await apiClient.POST("/login", {
-    body: {
-      username,
-      password,
-    },
-  });
-  if (error) {
-    throw new Error(error.message);
-  }
-  return data.token;
+  return (await apiPostLogin(username, password)).token;
 }
 
 authenticator.use(
diff --git a/frontend/app/routes/admin.games.tsx b/frontend/app/routes/admin.games.tsx
index 085a97e..00a56d6 100644
--- a/frontend/app/routes/admin.games.tsx
+++ b/frontend/app/routes/admin.games.tsx
@@ -1,7 +1,7 @@
 import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
 import { useLoaderData, Link } from "@remix-run/react";
 import { isAuthenticated } from "../.server/auth";
-import { apiClient } from "../.server/api/client";
+import { adminApiGetGames } from "../.server/api/client";
 
 export const meta: MetaFunction = () => {
   return [{ title: "[Admin] Games | iOSDC Japan 2024 Albatross.swift" }];
@@ -14,17 +14,8 @@ export async function loader({ request }: LoaderFunctionArgs) {
   if (!user.is_admin) {
     throw new Error("Unauthorized");
   }
-  const { data, error } = await apiClient.GET("/admin/games", {
-    params: {
-      header: {
-        Authorization: `Bearer ${token}`,
-      },
-    },
-  });
-  if (error) {
-    throw new Error(error.message);
-  }
-  return { games: data.games };
+  const { games } = await adminApiGetGames(token);
+  return { games };
 }
 
 export default function AdminGames() {
diff --git a/frontend/app/routes/admin.games_.$gameId.tsx b/frontend/app/routes/admin.games_.$gameId.tsx
index ff8f136..1ad8a2a 100644
--- a/frontend/app/routes/admin.games_.$gameId.tsx
+++ b/frontend/app/routes/admin.games_.$gameId.tsx
@@ -5,7 +5,7 @@ import type {
 } from "@remix-run/node";
 import { useLoaderData, Form } from "@remix-run/react";
 import { isAuthenticated } from "../.server/auth";
-import { apiClient } from "../.server/api/client";
+import { adminApiPutGame, adminApiGetGame } from "../.server/api/client";
 
 export const meta: MetaFunction<typeof loader> = ({ data }) => {
   return [
@@ -25,20 +25,8 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
     throw new Error("Unauthorized");
   }
   const { gameId } = params;
-  const { data, error } = await apiClient.GET("/admin/games/{game_id}", {
-    params: {
-      path: {
-        game_id: Number(gameId),
-      },
-      header: {
-        Authorization: `Bearer ${token}`,
-      },
-    },
-  });
-  if (error) {
-    throw new Error(error.message);
-  }
-  return { game: data.game };
+  const { game } = await adminApiGetGame(token, Number(gameId));
+  return { game };
 }
 
 export async function action({ request, params }: ActionFunctionArgs) {
@@ -63,22 +51,9 @@ export async function action({ request, params }: ActionFunctionArgs) {
     throw new Error("Invalid action");
   }
 
-  const { error } = await apiClient.PUT("/admin/games/{game_id}", {
-    params: {
-      path: {
-        game_id: Number(gameId),
-      },
-      header: {
-        Authorization: `Bearer ${token}`,
-      },
-    },
-    body: {
-      state: nextState,
-    },
+  await adminApiPutGame(token, Number(gameId), {
+    state: nextState,
   });
-  if (error) {
-    throw new Error(error.message);
-  }
   return null;
 }
 
diff --git a/frontend/app/routes/admin.users.tsx b/frontend/app/routes/admin.users.tsx
index 6c9b60d..c2e4cc7 100644
--- a/frontend/app/routes/admin.users.tsx
+++ b/frontend/app/routes/admin.users.tsx
@@ -1,7 +1,7 @@
 import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
 import { useLoaderData } from "@remix-run/react";
 import { isAuthenticated } from "../.server/auth";
-import { apiClient } from "../.server/api/client";
+import { adminApiGetUsers } from "../.server/api/client";
 
 export const meta: MetaFunction = () => {
   return [{ title: "[Admin] Users | iOSDC Japan 2024 Albatross.swift" }];
@@ -14,17 +14,8 @@ export async function loader({ request }: LoaderFunctionArgs) {
   if (!user.is_admin) {
     throw new Error("Unauthorized");
   }
-  const { data, error } = await apiClient.GET("/admin/users", {
-    params: {
-      header: {
-        Authorization: `Bearer ${token}`,
-      },
-    },
-  });
-  if (error) {
-    throw new Error(error.message);
-  }
-  return { users: data.users };
+  const { users } = await adminApiGetUsers(token);
+  return { users };
 }
 
 export default function AdminUsers() {
diff --git a/frontend/app/routes/dashboard.tsx b/frontend/app/routes/dashboard.tsx
index 08780f9..b93e5d1 100644
--- a/frontend/app/routes/dashboard.tsx
+++ b/frontend/app/routes/dashboard.tsx
@@ -2,7 +2,7 @@ import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
 import { redirect } from "@remix-run/node";
 import { Link, useLoaderData, Form } from "@remix-run/react";
 import { isAuthenticated } from "../.server/auth";
-import { apiClient } from "../.server/api/client";
+import { apiGetGames } from "../.server/api/client";
 
 export const meta: MetaFunction = () => {
   return [{ title: "Dashboard | iOSDC Japan 2024 Albatross.swift" }];
@@ -15,19 +15,10 @@ export async function loader({ request }: LoaderFunctionArgs) {
   if (user.is_admin) {
     return redirect("/admin/dashboard");
   }
-  const { data, error } = await apiClient.GET("/games", {
-    params: {
-      header: {
-        Authorization: `Bearer ${token}`,
-      },
-    },
-  });
-  if (error) {
-    throw new Error(error.message);
-  }
+  const { games } = await apiGetGames(token);
   return {
     user,
-    games: data.games,
+    games,
   };
 }
 
diff --git a/frontend/app/routes/golf.$gameId.play.tsx b/frontend/app/routes/golf.$gameId.play.tsx
index 919d8df..248c4e4 100644
--- a/frontend/app/routes/golf.$gameId.play.tsx
+++ b/frontend/app/routes/golf.$gameId.play.tsx
@@ -2,7 +2,7 @@ import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
 import { useLoaderData } from "@remix-run/react";
 import { ClientOnly } from "remix-utils/client-only";
 import { isAuthenticated } from "../.server/auth";
-import { apiClient } from "../.server/api/client";
+import { apiGetGame, apiGetToken } from "../.server/api/client";
 import GolfPlayApp from "../components/GolfPlayApp.client";
 import GolfPlayAppConnecting from "../components/GolfPlayApps/GolfPlayAppConnecting";
 
@@ -22,34 +22,10 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
   });
 
   const fetchGame = async () => {
-    const { data, error } = await apiClient.GET("/games/{game_id}", {
-      params: {
-        path: {
-          game_id: Number(params.gameId),
-        },
-        header: {
-          Authorization: `Bearer ${token}`,
-        },
-      },
-    });
-    if (error) {
-      throw new Error(error.message);
-    }
-    return data.game;
+    return (await apiGetGame(token, Number(params.gameId))).game;
   };
-
   const fetchSockToken = async () => {
-    const { data, error } = await apiClient.GET("/token", {
-      params: {
-        header: {
-          Authorization: `Bearer ${token}`,
-        },
-      },
-    });
-    if (error) {
-      throw new Error(error.message);
-    }
-    return data.token;
+    return (await apiGetToken(token)).token;
   };
 
   const [game, sockToken] = await Promise.all([fetchGame(), fetchSockToken()]);
diff --git a/frontend/app/routes/golf.$gameId.watch.tsx b/frontend/app/routes/golf.$gameId.watch.tsx
index c2e269e..1a14e78 100644
--- a/frontend/app/routes/golf.$gameId.watch.tsx
+++ b/frontend/app/routes/golf.$gameId.watch.tsx
@@ -2,7 +2,7 @@ import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
 import { useLoaderData } from "@remix-run/react";
 import { ClientOnly } from "remix-utils/client-only";
 import { isAuthenticated } from "../.server/auth";
-import { apiClient } from "../.server/api/client";
+import { apiGetGame, apiGetToken } from "../.server/api/client";
 import GolfWatchApp from "../components/GolfWatchApp.client";
 import GolfWatchAppConnecting from "../components/GolfWatchApps/GolfWatchAppConnecting";
 
@@ -22,34 +22,10 @@ export async function loader({ params, request }: LoaderFunctionArgs) {
   });
 
   const fetchGame = async () => {
-    const { data, error } = await apiClient.GET("/games/{game_id}", {
-      params: {
-        path: {
-          game_id: Number(params.gameId),
-        },
-        header: {
-          Authorization: `Bearer ${token}`,
-        },
-      },
-    });
-    if (error) {
-      throw new Error(error.message);
-    }
-    return data.game;
+    return (await apiGetGame(token, Number(params.gameId))).game;
   };
-
   const fetchSockToken = async () => {
-    const { data, error } = await apiClient.GET("/token", {
-      params: {
-        header: {
-          Authorization: `Bearer ${token}`,
-        },
-      },
-    });
-    if (error) {
-      throw new Error(error.message);
-    }
-    return data.token;
+    return (await apiGetToken(token)).token;
   };
 
   const [game, sockToken] = await Promise.all([fetchGame(), fetchSockToken()]);
-- 
cgit v1.3.1

