public games list functionality

This commit is contained in:
Nathaniel Tampus
2023-03-05 22:06:59 +08:00
parent fa94df1d06
commit a30331ccb1
6 changed files with 115 additions and 52 deletions

View File

@@ -1,10 +1,11 @@
import PublicGames from "@/components/home/PublicGames"; import PublicGames from "@/components/home/PublicGames/PublicGames";
import JoinGame from "@/components/home/JoinGame"; import JoinGame from "@/components/home/JoinGame";
import CreateGame from "@/components/home/CreateGame"; import CreateGame from "@/components/home/CreateGame";
export default function Home() { export default function Home() {
return ( return (
<div className="bg-base-200 flex w-full flex-wrap items-center justify-evenly gap-4 rounded-xl px-4 py-10 shadow-md lg:gap-0"> <div className="bg-base-200 flex w-full flex-wrap items-center justify-evenly gap-4 rounded-xl px-4 py-10 shadow-md lg:gap-0">
{/* @ts-expect-error Server Component */}
<PublicGames /> <PublicGames />
<div className="flex flex-col items-center gap-4"> <div className="flex flex-col items-center gap-4">

View File

@@ -1,51 +0,0 @@
import { IconRefresh } from "@tabler/icons-react";
export default function PublicGames() {
return (
<div className="flex flex-col items-center">
<h2 className="mb-2 text-2xl font-bold leading-tight">
Public games{" "}
<div className="btn btn-sm btn-ghost">
<IconRefresh size={16} className="" />
</div>
</h2>
<div className="bg-base-100 h-80 max-h-80 overflow-y-auto">
<table className="table-compact lg:table-normal table rounded-none">
<thead>
<tr>
<th className="w-48">Host</th>
<th className="w-48">Opponent</th>
<th className="w-24"></th>
</tr>
</thead>
<tbody>
<tr>
<td>(empty)</td>
<td></td>
<td></td>
</tr>
{/* <tr className="group">
<td>nize</td>
<td>nize</td>
<th>
<button className="btn btn-ghost btn-xs focus:opacity-100 lg:opacity-0 lg:group-hover:opacity-100">
Join
</button>
</th>
</tr> */}
{/* <tr className="group">
<td>WPlaceholder_Text</td>
<td>WPlaceholder_Text</td>
<th>
<button className="btn btn-ghost btn-xs focus:opacity-100 lg:opacity-0 lg:group-hover:opacity-100">
Join
</button>
</th>
</tr> */}
</tbody>
</table>
</div>
</div>
);
}

View File

@@ -0,0 +1,27 @@
"use client";
import { useRouter } from "next/navigation";
import { useTransition } from "react";
export default function JoinButton({ code }: { code: string }) {
const router = useRouter();
const [isLoading, startTransition] = useTransition();
function handleJoin() {
startTransition(() => {
router.push(`/game/${code}`);
});
}
return (
<button
className={
"btn btn-ghost btn-xs focus:opacity-100 lg:opacity-0 lg:group-hover:opacity-100" +
(isLoading ? " btn-disabled" : "")
}
onClick={handleJoin}
>
Join
</button>
);
}

View File

@@ -0,0 +1,48 @@
import { getPublicGames } from "@/lib/game";
import JoinButton from "./JoinButton";
import RefreshButton from "./RefreshButton";
export default async function PublicGames() {
const games = await getPublicGames();
return (
<div className="flex flex-col items-center">
<h2 className="mb-2 text-2xl font-bold leading-tight">
Public games <RefreshButton />
</h2>
<div className="bg-base-100 h-80 max-h-80 overflow-y-auto">
<table className="table-compact lg:table-normal table rounded-none">
<thead>
<tr>
<th className="w-48">Host</th>
<th className="w-48">Opponent</th>
<th className="w-24"></th>
</tr>
</thead>
<tbody>
{games && games.length > 0 ? (
games.map((game) => (
<tr key={game.code} className="group">
<td>{game.host?.name}</td>
<td>
{(game.host?.id === game.white?.id ? game.black?.name : game.white?.name) || ""}
</td>
<th>
<JoinButton code={game.code as string} />
</th>
</tr>
))
) : (
<tr>
<td>(empty)</td>
<td></td>
<td></td>
</tr>
)}
</tbody>
</table>
</div>
</div>
);
}

View File

@@ -0,0 +1,25 @@
"use client";
import { IconRefresh } from "@tabler/icons-react";
import { useRouter } from "next/navigation";
import { useTransition } from "react";
export default function RefreshButton() {
const router = useRouter();
const [isLoading, startTransition] = useTransition();
function handleRefresh() {
startTransition(() => {
router.refresh();
});
}
return (
<button
className={"btn btn-sm btn-ghost" + (isLoading ? " loading" : "")}
onClick={handleRefresh}
>
<IconRefresh size={16} />
</button>
);
}

View File

@@ -34,3 +34,16 @@ export const getGame = async (code: string) => {
console.error(err); console.error(err);
} }
}; };
export const getPublicGames = async () => {
try {
const res = await fetch(`${API_URL}/v1/games`, { cache: "no-store" });
if (res && res.status === 200) {
const games: Game[] = await res.json();
return games;
}
} catch (err) {
console.error(err);
}
};