initial find & create game functionality

and restructure homepage components
This commit is contained in:
Nathaniel Tampus
2023-03-04 18:43:32 +08:00
parent 6de9943dca
commit dd0a097a48
4 changed files with 116 additions and 28 deletions

View File

@@ -0,0 +1,59 @@
"use client";
import type { FormEvent } from "react";
import { useState, useContext } from "react";
import { SessionContext } from "@/context/session";
import { createGame } from "@/lib/game";
import { useRouter } from "next/navigation";
export default function CreateGame() {
const session = useContext(SessionContext);
const [buttonLoading, setButtonLoading] = useState(false);
const router = useRouter();
async function submitCreateGame(e: FormEvent<HTMLFormElement>) {
e.preventDefault();
if (!session?.user?.id) return;
setButtonLoading(true);
const target = e.target as HTMLFormElement;
const unlisted = target.elements.namedItem("createUnlisted") as HTMLInputElement;
const startingSide = (target.elements.namedItem("createStartingSide") as HTMLSelectElement)
.value;
const game = await createGame(startingSide, unlisted.checked);
if (game) {
router.push(`/game/${game.code}`);
} else {
setButtonLoading(false);
// TODO: Show error message
}
}
return (
<form className="form-control" onSubmit={submitCreateGame}>
<label className="label cursor-pointer">
<span className="label-text">Unlisted/invite-only</span>
<input type="checkbox" className="checkbox" name="createUnlisted" id="createUnlisted" />
</label>
<label className="label" htmlFor="createStartingSide">
<span className="label-text">Select your side</span>
</label>
<div className="input-group">
<select
className="select select-bordered"
name="createStartingSide"
id="createStartingSide"
>
<option value="random">Random</option>
<option value="white">White</option>
<option value="black">Black</option>
</select>
<button className={"btn" + (buttonLoading ? " loading" : "")} type="submit">
Create
</button>
</div>
</form>
);
}

View File

@@ -0,0 +1,52 @@
"use client";
import type { FormEvent } from "react";
import { useState, useContext } from "react";
import { SessionContext } from "@/context/session";
import { findGame } from "@/lib/game";
import { useRouter } from "next/navigation";
export default function JoinGame() {
const session = useContext(SessionContext);
const [buttonLoading, setButtonLoading] = useState(false);
const router = useRouter();
async function submitJoinGame(e: FormEvent<HTMLFormElement>) {
e.preventDefault();
if (!session?.user?.id) return;
setButtonLoading(true);
const target = e.target as HTMLFormElement;
const codeEl = target.elements.namedItem("joinGameCode") as HTMLInputElement;
let code = codeEl.value;
if (code.startsWith("http") || code.startsWith("ches.su")) {
code = new URL(code).pathname.split("/")[2];
}
const game = await findGame(code);
if (game) {
router.push(`/game/${game.code}`);
} else {
setButtonLoading(false);
codeEl.value = "";
// TODO: Show error message
}
}
return (
<form className="input-group" onSubmit={submitJoinGame}>
<input
type="text"
placeholder="Invite link or code"
className="input input-bordered"
name="joinGameCode"
id="joinGameCode"
/>
<button className={"btn btn-square" + (buttonLoading ? " loading" : "")} type="submit">
Join
</button>
</form>
);
}

View File

@@ -0,0 +1,51 @@
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>
);
}