diff --git a/tank-frontend/package.json b/tank-frontend/package.json index 17be3e5..ba60c09 100644 --- a/tank-frontend/package.json +++ b/tank-frontend/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --host 0.0.0.0 --port 8543", "build": "tsc && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" diff --git a/tank-frontend/src/JoinForm.css b/tank-frontend/src/JoinForm.css index 4e33b01..d7bef0d 100644 --- a/tank-frontend/src/JoinForm.css +++ b/tank-frontend/src/JoinForm.css @@ -1,4 +1,16 @@ +.TankWelcome { + display: flex; + flex-direction: column; +} + .JoinForm { display: flex; - flex-direction: row; + flex-direction: column; + border: 2px solid rgb(76, 76, 76); + border-radius: 4px; } + +.JoinElems { + padding: 8px 8px; + margin: 8px 8px; +} \ No newline at end of file diff --git a/tank-frontend/src/JoinForm.tsx b/tank-frontend/src/JoinForm.tsx index cd3aabc..a62533c 100644 --- a/tank-frontend/src/JoinForm.tsx +++ b/tank-frontend/src/JoinForm.tsx @@ -1,24 +1,8 @@ -import {useEffect, useState} from 'react'; +import { useEffect, useState } from 'react'; import './JoinForm.css'; +import { PlayerResponse, postPlayer } from './serverCalls'; -type PlayerResponse = { - readonly name: string; - readonly id: string; -}; - -export async function fetchPlayer(name: string, options: RequestInit) { - const url = new URL(import.meta.env.VITE_TANK_PLAYER_URL); - url.searchParams.set('name', name); - - const response = await fetch(url, options); - if (!response.ok) - return null; - - const json = await response.json() as PlayerResponse; - return json.id; -} - -export default function JoinForm({onDone}: { onDone: (id: string) => void }) { +export default function JoinForm({ onDone }: { onDone: (id: string) => void }) { const [name, setName] = useState(''); const [clicked, setClicked] = useState(false); const [data, setData] = useState(null); @@ -28,12 +12,13 @@ export default function JoinForm({onDone}: { onDone: (id: string) => void }) { return; try { - fetchPlayer(name, {}).then((value: string | null) => { - if (value) - onDone(value); - else - setClicked(false); - }); + postPlayer(name) + .then((value: PlayerResponse | null) => { + if (value) + onDone(value.id); + else + setClicked(false); + }); } catch (e) { console.log(e); alert(e); @@ -41,17 +26,27 @@ export default function JoinForm({onDone}: { onDone: (id: string) => void }) { }, [clicked, setData, data]); const disableButtons = clicked || name.trim() === ''; - return
- setName(e.target.value)} - /> - + return
+

+ Tanks +

+

Welcome and have fun!

+
+

+ Enter your name to join the game! +

+ setName(e.target.value)} + /> + +
; } diff --git a/tank-frontend/src/PlayerInfo.css b/tank-frontend/src/PlayerInfo.css new file mode 100644 index 0000000..c4b38f2 --- /dev/null +++ b/tank-frontend/src/PlayerInfo.css @@ -0,0 +1,21 @@ +.Player { + display: flex; + flex-direction: column; + border: 2px solid rgb(76, 76, 76); + border-radius: 4px; +} + +.ScoreForm { + display: flex; + flex-direction: column; +} + +.ElemGroup { + display: flex; + flex-direction: row; +} + +.Elems { + padding: 8px 8px; + margin: 8px 8px; +} \ No newline at end of file diff --git a/tank-frontend/src/PlayerInfo.tsx b/tank-frontend/src/PlayerInfo.tsx new file mode 100644 index 0000000..af7501c --- /dev/null +++ b/tank-frontend/src/PlayerInfo.tsx @@ -0,0 +1,38 @@ +import { useEffect, useState } from 'react'; +import './PlayerInfo.css' +import { PlayerResponse, getPlayer } from './serverCalls'; + +export default function PlayerInfo({ playerId }: { playerId: string }) { + const [player, setPlayer] = useState(); + + const refresh = () => { + getPlayer(playerId).then(setPlayer); + }; + + useEffect(() => { + const timer = setInterval(refresh, 5000); + return () => clearInterval(timer); + }); + + return
+

+ Tanks +

+
+
+

+ name +

+

+ {player?.name} +

+
+
+

+ {JSON.stringify(player)} +

+ + +
+
; +} diff --git a/tank-frontend/src/index.tsx b/tank-frontend/src/index.tsx index 1ca269c..d6b278e 100644 --- a/tank-frontend/src/index.tsx +++ b/tank-frontend/src/index.tsx @@ -1,22 +1,24 @@ -import React, {useState} from 'react'; +import React, { useState } from 'react'; import './index.css'; import ClientScreen from './ClientScreen'; import Controls from './Controls.tsx'; import JoinForm from './JoinForm.tsx'; -import {createRoot} from 'react-dom/client'; +import { createRoot } from 'react-dom/client'; +import PlayerInfo from './PlayerInfo.tsx'; function App() { const [id, setId] = useState(null); return <> - {id === null && setId(name)}/>} - - {id == null || } + {id === null && setId(name)} />} + {id == null || } + + {id == null || } ; } createRoot(document.getElementById('root')!).render( - + ); diff --git a/tank-frontend/src/serverCalls.tsx b/tank-frontend/src/serverCalls.tsx new file mode 100644 index 0000000..6640b47 --- /dev/null +++ b/tank-frontend/src/serverCalls.tsx @@ -0,0 +1,23 @@ +export type PlayerResponse = { + readonly name: string; + readonly id: string; +}; + +export async function fetchTyped({ url, method }: { url: URL; method: string; }) { + const response = await fetch(url, { method }); + if (!response.ok) + return null; + return await response.json() as T; +} + +export function postPlayer(name: string) { + const url = new URL(import.meta.env.VITE_TANK_PLAYER_URL); + url.searchParams.set('name', name); + return fetchTyped({ url, method: 'POST' }); +} + +export function getPlayer(id: string) { + const url = new URL(import.meta.env.VITE_TANK_PLAYER_URL); + url.searchParams.set('id', id); + return fetchTyped({ url, method: 'GET' }); +}