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

@@ -1,4 +1,6 @@
import PublicGames from "@/components/PublicGames"; import PublicGames from "@/components/home/PublicGames";
import JoinGame from "@/components/home/JoinGame";
import CreateGame from "@/components/home/CreateGame";
export default function Home() { export default function Home() {
return ( return (
@@ -8,39 +10,14 @@ export default function Home() {
<div className="flex flex-col items-center gap-4"> <div className="flex flex-col items-center gap-4">
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
<h2 className="mb-4 text-xl font-bold leading-tight">Join from invite</h2> <h2 className="mb-4 text-xl font-bold leading-tight">Join from invite</h2>
<div className="form-control"> <JoinGame />
<div className="input-group">
<input
type="text"
placeholder="Invite link or code"
className="input input-bordered"
/>
<button className="btn btn-square">Join</button>
</div>
</div>
</div> </div>
<div className="divider divider-vertical">or</div> <div className="divider divider-vertical">or</div>
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
<h2 className="mb-4 text-xl font-bold leading-tight">Create game</h2> <h2 className="mb-4 text-xl font-bold leading-tight">Create game</h2>
<div className="form-control"> <CreateGame />
<label className="label cursor-pointer">
<span className="label-text">Unlisted/invite-only</span>
<input type="checkbox" className="checkbox" />
</label>
<label className="label">
<span className="label-text">Select your side</span>
</label>
<div className="input-group">
<select className="select select-bordered">
<option value="random">Random</option>
<option value="white">White</option>
<option value="black">Black</option>
</select>
<button className="btn">Create</button>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

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>
);
}