initial find & create game functionality
and restructure homepage components
This commit is contained in:
@@ -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() {
|
||||
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">
|
||||
<h2 className="mb-4 text-xl font-bold leading-tight">Join from invite</h2>
|
||||
<div className="form-control">
|
||||
<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>
|
||||
<JoinGame />
|
||||
</div>
|
||||
|
||||
<div className="divider divider-vertical">or</div>
|
||||
|
||||
<div className="flex flex-col items-center">
|
||||
<h2 className="mb-4 text-xl font-bold leading-tight">Create game</h2>
|
||||
<div className="form-control">
|
||||
<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>
|
||||
<CreateGame />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
59
client/src/components/home/CreateGame.tsx
Normal file
59
client/src/components/home/CreateGame.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
52
client/src/components/home/JoinGame.tsx
Normal file
52
client/src/components/home/JoinGame.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user