浏览代码

Very basic support for linking directly to scores and semi-directly to joining

Kirk Trombley 5 年之前
父节点
当前提交
f51b8d279c

+ 0 - 2
README.md

@@ -86,8 +86,6 @@ POST /game/{ID}/guesses/{round}
 - Genericize number of rounds
 - Track name via tokens
 - Error handling in UI
-- Navigate directly to summary page
-- Navigate directly to joining a game
 - Re-join a game you did not finish
 - Show current best on round summary
 - Optimize docker file or set up compose structure

+ 15 - 0
client/src/components/Game/Game.jsx

@@ -21,10 +21,24 @@ const initialState = {
   lastRound: null,
 }
 
+const extractAndRemoveSearchParam = param => {
+  const u = new URL(window.location.href);
+  const extracted = u.searchParams.get(param);
+  u.searchParams.delete(param);
+  window.history.replaceState({}, document.title, u.href);
+  return extracted;
+}
+
 const Game = () => {
   const [ state, rawSetState ] = useState(initialState);
   const setGameState = gameState => rawSetState({ ...state, gameState });
   const setGameStateAnd = (gameState, updates) => rawSetState({ ...state, gameState, ...updates });
+  
+  const joinCode = extractAndRemoveSearchParam("join");
+  const summaryCode = extractAndRemoveSearchParam("summary");
+  if (summaryCode) {
+    setGameStateAnd(POST_GAME, { gameId: summaryCode });
+  }
 
   switch (state.gameState) {
     case PRE_GAME:
@@ -32,6 +46,7 @@ const Game = () => {
         <HeaderAndFooter>
           <PreGame
             initPlayerName={state.playerName}
+            initGameId={joinCode}
             onGameJoined={({ gameId, playerName }) => setGameStateAnd(PRE_ROUND, { gameId, playerName })}
           />
         </HeaderAndFooter>

+ 13 - 0
client/src/components/screens/PlayerScores/PlayerScores.jsx

@@ -4,6 +4,7 @@ import Loading from '../../util/Loading';
 import Button from "../../util/Button";
 import PlayerScoreTile from "./PlayerScoreTile";
 import usePlayerScores from '../../../hooks/usePlayerScores';
+import ClickToCopy from '../../util/ClickToCopy';
 
 const Container = styled.div`
   display: flex;
@@ -20,6 +21,16 @@ const ScoreBoard = styled.div`
   align-content: space-around;
 `
 
+const Label = styled.span`
+  padding: 0.2em;
+`
+
+const getUrl = gameId => {
+  const u = new URL(window.location.href);
+  u.searchParams.append("summary", gameId);
+  return u.href;
+}
+
 export default ({ gameId, onReturnToStart }) => {
   const scores = usePlayerScores(gameId);
 
@@ -37,6 +48,8 @@ export default ({ gameId, onReturnToStart }) => {
             .map(({ name, guesses, totalScore }) => <PlayerScoreTile key={name} {...{ name, guesses, totalScore }} />)
         }
       </ScoreBoard>
+      <Label>This page can be directly linked with:</Label>
+      <Label><ClickToCopy text={getUrl(gameId)} /></Label>
       <Button onClick={onReturnToStart}>Return to Start</Button>
     </Container>
   );

+ 2 - 2
client/src/components/screens/PreGame/PreGame.jsx

@@ -30,9 +30,9 @@ const Divider = styled.hr`
   }
 `
 
-export default ({ initPlayerName, onGameJoined }) => {
+export default ({ initPlayerName, initGameId, onGameJoined }) => {
   const [loading, setLoading] = useState(false);
-  const [gameId, setGameId] = useState(null);
+  const [gameId, setGameId] = useState(initGameId);
   const [playerName, setPlayerName] = useState(initPlayerName);
   const [timer, setTimer] = useState(300);
 

+ 12 - 8
client/src/components/screens/PreRound.jsx

@@ -11,24 +11,28 @@ const Container = styled.div`
   align-items: center;
 `
 
-const NameLabel = styled.span`
+const Label = styled.span`
   padding: 0.2em;
 `
 
-const CodeLabel = styled.span`
-  padding: 0.2em;
-  margin-bottom: 0.3em;
-`
-
 const StartButton = styled(Button)`
   padding: 1em;
   margin: 0.2em;
+  margin-top: 0.3em;
 `
 
+const getUrl = gameId => {
+  const u = new URL(window.location.href);
+  u.searchParams.append("join", gameId);
+  return u.href;
+}
+
 const PreRound = ({ gameId, playerName, onStart }) => (
   <Container>
-    <NameLabel>Playing as {playerName}</NameLabel>
-    <CodeLabel>Game Code: <ClickToCopy text={gameId} /></CodeLabel>
+    <Label>Playing as {playerName}</Label>
+    <Label>Game Code: <ClickToCopy text={gameId} /></Label>
+    <Label>Or, send the following link:</Label>
+    <Label><ClickToCopy text={getUrl(gameId)} /></Label>
     <StartButton onClick={onStart}>Start Game</StartButton>
   </Container>
 );