Created a homepage, started on a debug menu

This commit is contained in:
martin 2023-08-05 19:52:47 +02:00
parent 296025fd4c
commit 697a4ddd6d
10 changed files with 88 additions and 47 deletions

View File

@ -23,6 +23,7 @@ export const App: FC = () => (
* @param secured Whether or not the page is secured.
* @constructor The Secured component.
*/
// TODO only works on first render after refresh
const Secured: FC<{ secured: boolean } & ChildProps> = ({children, secured}) => {
const player = useAtomValue(thisPlayerAtom);
const navigate = useNavigate();

View File

@ -1,13 +1,14 @@
import React from "react";
import {Counter} from "./pages/counter";
import Game from "./pages/game";
import GamePage from "./pages/game";
import LobbyPage from "./pages/lobby";
import Login from "./pages/login";
import LoginPage from "./pages/login";
import HomePage from "./pages/home";
const AppRoutes = [
{
index: true,
element: <LobbyPage/> // TODO change to home page
element: <HomePage/>
},
{
path: "/counter",
@ -15,7 +16,7 @@ const AppRoutes = [
},
{
path: "/game/:id",
element: <Game/>,
element: <GamePage/>,
secured: true
},
{
@ -25,7 +26,7 @@ const AppRoutes = [
},
{
path: "/login",
element: <Login/>
element: <LoginPage/>
}
];

View File

@ -0,0 +1,47 @@
import React, {FC} from "react";
import useToggle from "../hooks/useToggle";
import {BugAntIcon} from "@heroicons/react/20/solid";
import {selectedMapAtom} from "../utils/state";
import {useAtom} from "jotai";
const DebugMenu: FC = () => {
const [open, toggleOpen] = useToggle();
if (import.meta.env.DEV) {
return (
<div>
{open && <DebugOptions/>}
<button className={"fixed bottom-2 right-2 bg-gray-800 text-white p-2 z-50 rounded-full"}
title={"Debug menu"}
onClick={() => toggleOpen()}>
<BugAntIcon className={"w-8 m-1"}/>
</button>
</div>
);
}
}
export default DebugMenu;
const DebugOptions: FC = () => {
const [map, setMap] = useAtom(selectedMapAtom);
function clearSessionStorage(): void {
sessionStorage.clear();
}
function resetMap() {
// TODO
}
return (
<div className={"fixed w-max right-2 bottom-16 border-2 z-50 bg-white rounded-xl p-2"}>
<button onClick={clearSessionStorage}>Clear sessionstorage</button>
<br/>
<button onClick={resetMap}>Reset map</button>
</div>
)
}

View File

@ -18,7 +18,11 @@ const wsService = new WebSocketService(import.meta.env.VITE_API_WS);
// TODO bug, first player can sometimes roll dice twice
// TODO bug, when refreshing page, some data is missing until other clients make a move
// TODO bug, stolen pellets are only updated on the client that stole them
// TODO bug, when navigating to lobby from the navbar while not logged in, the page is blank instead of redirecting to login
// TODO spawns should be the same color as the player
// TODO better front page
// TODO smaller map to fit button and dice on screen
// TODO guest users
// TODO store map in backend and save it in state on each client
// TODO add debug menu on dev, for testing and cheating

View File

@ -5,6 +5,7 @@ import {App} from './App';
// @ts-ignore
import reportWebVitals from './reportWebVitals';
import {DevTools} from "jotai-devtools";
import DebugMenu from "./components/debugMenu";
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
const rootElement = document.getElementById('root');
@ -14,6 +15,7 @@ const root = createRoot(rootElement);
root.render(
<BrowserRouter basename={baseUrl ?? undefined}>
<DevTools/>
<DebugMenu/>
<App/>
</BrowserRouter>);

View File

@ -3,7 +3,7 @@ import {GameComponent} from "../components/gameComponent";
import {useAtomValue} from "jotai";
import {selectedMapAtom, thisPlayerAtom} from "../utils/state";
const Game: FC = () => {
const GamePage: FC = () => {
const player = useAtomValue(thisPlayerAtom);
const map = useAtomValue(selectedMapAtom);
@ -14,4 +14,4 @@ const Game: FC = () => {
}
};
export default Game;
export default GamePage;

View File

@ -1,42 +1,27 @@
import React, {FC, useRef} from "react";
import Player from "../game/player";
import Input from "../components/input";
import Dropdown from "../components/dropdown";
import {Colour, getColours} from "../game/colour";
import {useNavigate} from "react-router-dom";
import {useSetAtom} from "jotai";
import React, {FC} from "react";
import {Link} from "react-router-dom";
import {useAtomValue} from "jotai";
import {thisPlayerAtom} from "../utils/state";
const Home: FC = () => {
const input = useRef<HTMLInputElement>(null);
const dropdown = useRef<HTMLSelectElement>(null);
const setPlayer = useSetAtom(thisPlayerAtom);
const navigate = useNavigate();
function formHandler(): void {
if (!input.current || !dropdown.current) return;
const player = new Player({
username: input.current.value,
colour: dropdown.current.value as Colour,
});
setPlayer(player);
navigate("/game");
}
const HomePage: FC = () => {
const player = useAtomValue(thisPlayerAtom);
return (
<>
<h1 className={"w-fit mx-auto"}>Pac-Man The Board Game</h1>
<form className={"flex flex-col items-center"} onSubmit={formHandler}>
<p>Enter your name:</p>
<Input ref={input} required/>
<p>Choose a colour:</p>
<Dropdown ref={dropdown} options={getColours()}/>
<br/>
<button type={"submit"}>Find game</button>
</form>
</>
<div className={"container max-w-[800px] mx-auto px-2"}>
<h1 className={"w-fit mx-auto"}>Hello {player?.username ?? "Player"}. Do you want to play a game?</h1>
<p className={"text-center mt-5"}>
{!player ?
<>Start by {" "}
<Link to={"/login"} className={"text-blue-600"}>logging in</Link>.
</>
:
<>Go to the {" "}
<Link to={"/lobby"} className={"text-blue-600"}>lobby</Link> to select a game.
</>
}
</p>
</div>
);
};
export default Home;
export default HomePage;

View File

@ -7,7 +7,7 @@ import Player from "../game/player";
import {useNavigate} from "react-router-dom";
import {postData} from "../utils/api";
const Login: FC = () => {
const LoginPage: FC = () => {
const setThisPlayer = useSetAtom(thisPlayerAtom);
const navigate = useNavigate();
@ -57,4 +57,4 @@ const Login: FC = () => {
);
}
export default Login;
export default LoginPage;

View File

@ -9,10 +9,11 @@ import {Colour} from "../game/colour";
export enum GameAction {
rollDice,
moveCharacter,
playerInfo,
playerInfo, // TODO rename to joinGame
ready,
nextPlayer,
disconnect,
// TODO add updatePellets
}
const store = getDefaultStore();

View File

@ -26,7 +26,7 @@ export const allCharactersAtom = atom(get => [...get(playerCharactersAtom), ...g
const playerAtom = atom<Player | undefined>(undefined);
/**
* Gets a getter and setter to get or set the player that is currently logged in.
* @returns A tuple containing a getter and setter to get or set the player that is currently logged in.
* Returns A tuple containing a getter and setter to get or set the player that is currently logged in.
*/
export const thisPlayerAtom = atom(get => {
const atomValue = get(playerAtom);
@ -38,7 +38,7 @@ export const thisPlayerAtom = atom(get => {
}
}
return atomValue;
}, (get, set, player: Player | undefined) => {
}, (_get, set, player: Player | undefined) => {
if (player)
sessionStorage.setItem(playerStorage, JSON.stringify(player));
else