|
@@ -1,17 +1,12 @@
|
|
|
-import React, { useRef } from 'react';
|
|
|
+import React, { useState } from 'react';
|
|
|
import styled from "styled-components";
|
|
|
import Loading from '../../util/Loading';
|
|
|
-import Button from "../../util/Button";
|
|
|
-import PlayerScoreTile from "./PlayerScoreTile";
|
|
|
import useGameInfo from '../../../hooks/useGameInfo';
|
|
|
import ClickToCopy from '../../util/ClickToCopy';
|
|
|
-import { dispatch } from '../../../domain/gameStore';
|
|
|
-import { linkGame } from '../../../domain/apiMethods';
|
|
|
-import GameCreationForm from '../../util/GameCreationForm';
|
|
|
-import useMap from '../../../hooks/useMap';
|
|
|
-import useMarkersFromGuesses from '../../../hooks/useMarkersFromGuesses';
|
|
|
-import { useState } from 'react';
|
|
|
-import { useEffect } from 'react';
|
|
|
+import SummaryMap from './SummaryMap';
|
|
|
+import LinkedGame from './LinkedGame';
|
|
|
+import RoundSelect from './RoundSelect';
|
|
|
+import ScoreBoard from './ScoreBoard';
|
|
|
|
|
|
const Container = styled.div`
|
|
|
display: flex;
|
|
@@ -21,129 +16,11 @@ const Container = styled.div`
|
|
|
height: 100%;
|
|
|
`
|
|
|
|
|
|
-const ScoreBoardContainer = styled.div`
|
|
|
- flex: 2;
|
|
|
- display: flex;
|
|
|
- flex-flow: row wrap;
|
|
|
- justify-content: space-evenly;
|
|
|
- align-items: flex-start;
|
|
|
- align-content: space-around;
|
|
|
- max-width: 80%;
|
|
|
- margin-top: 2em;
|
|
|
-`
|
|
|
-
|
|
|
-const LinkedGameContainer = styled.div`
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- width: 100%;
|
|
|
- margin-top: 1em;
|
|
|
- margin-bottom: 10em;
|
|
|
-`
|
|
|
-
|
|
|
const Label = styled.span`
|
|
|
padding: 0.2em;
|
|
|
margin-bottom: 0.5em;
|
|
|
`
|
|
|
|
|
|
-const StyledButton = styled(Button)`
|
|
|
- margin-top: 0.5em;
|
|
|
-`
|
|
|
-
|
|
|
-const MapDiv = styled.div`
|
|
|
- position: absolute;
|
|
|
- height: 30%;
|
|
|
- width: 90%;
|
|
|
-`;
|
|
|
-
|
|
|
-const MapContainer = styled.div`
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
-`;
|
|
|
-
|
|
|
-const RoundSelectContainer = styled.div`
|
|
|
- display: flex;
|
|
|
- flex-flow: row nowrap;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- width: 50%;
|
|
|
- margin-bottom: 0.5em;
|
|
|
-`;
|
|
|
-
|
|
|
-const RoundSelectButton = styled.div`
|
|
|
- background-color: ${({active}) => active ? "#777" : "#555"};
|
|
|
- width: 2em;
|
|
|
- height: 2em;
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
-`;
|
|
|
-
|
|
|
-const getUrl = gameId => {
|
|
|
- const u = new URL(window.location.href);
|
|
|
- u.searchParams.append("summary", gameId);
|
|
|
- return u.href;
|
|
|
-}
|
|
|
-
|
|
|
-const SummaryMap = ({ players, coords, roundActive }) => {
|
|
|
- // create the map
|
|
|
- const mapDivRef = useRef(null);
|
|
|
- const mapRef = useMap(mapDivRef, 0, 0, 1);
|
|
|
-
|
|
|
- // get the target point
|
|
|
- const targetPoint = coords?.[roundActive] ?? null;
|
|
|
-
|
|
|
- // put the markers on the map
|
|
|
- useMarkersFromGuesses(mapRef, players, roundActive, targetPoint);
|
|
|
-
|
|
|
- // scroll the map to the target point
|
|
|
- useEffect(() => {
|
|
|
- if (targetPoint && mapRef.current) {
|
|
|
- mapRef.current.panTo(targetPoint);
|
|
|
- }
|
|
|
- }, [mapRef, targetPoint]);
|
|
|
-
|
|
|
- return (
|
|
|
- <MapContainer>
|
|
|
- <MapDiv ref={mapDivRef}/>
|
|
|
- </MapContainer>
|
|
|
- );
|
|
|
-}
|
|
|
-
|
|
|
-const RoundSelect = ({ rounds, roundNum, setRoundNum }) => (
|
|
|
- <RoundSelectContainer>
|
|
|
- {
|
|
|
- // fun fact: es6 doesn't have a range(x) function
|
|
|
- Array.from(Array(rounds).keys())
|
|
|
- .map(r => (r + 1).toString())
|
|
|
- .map(r => <RoundSelectButton active={r === roundNum} key={r} onClick={() => setRoundNum(r)}>{r}</RoundSelectButton>)
|
|
|
- }
|
|
|
- </RoundSelectContainer>
|
|
|
-);
|
|
|
-
|
|
|
-const ScoreBoard = ({ players }) => (
|
|
|
- <ScoreBoardContainer>
|
|
|
- {
|
|
|
- players
|
|
|
- .filter(({ currentRound }) => currentRound === null)
|
|
|
- .sort((p1, p2) => p1.totalScore > p2.totalScore ? -1 : (p1.totalScore < p2.totalScore ? 1 : 0))
|
|
|
- .map((data) => <PlayerScoreTile key={data.name} {...data} />)
|
|
|
- }
|
|
|
- </ScoreBoardContainer>
|
|
|
-)
|
|
|
-
|
|
|
-const LinkedGame = React.memo(({ linkedGame, gameId }) => (
|
|
|
- <LinkedGameContainer>
|
|
|
- {
|
|
|
- linkedGame
|
|
|
- ? <StyledButton onClick={() => dispatch.goToLobby(linkedGame)}>
|
|
|
- Continue to Linked Game Lobby
|
|
|
- </StyledButton>
|
|
|
- : <GameCreationForm afterCreate={linkId => linkGame(gameId, linkId)}/>
|
|
|
- }
|
|
|
- </LinkedGameContainer>
|
|
|
-));
|
|
|
-
|
|
|
export default () => {
|
|
|
// poll the game state
|
|
|
const { gameId, players, coords, rounds, linkedGame } = useGameInfo();
|
|
@@ -152,6 +29,10 @@ export default () => {
|
|
|
const [roundNum, setRoundNum] = useState("0");
|
|
|
const roundActive = rounds > 1 ? roundNum : "1";
|
|
|
|
|
|
+ // set up the summary URL
|
|
|
+ const summaryURL = new URL(window.location.href);
|
|
|
+ summaryURL.searchParams.append("summary", gameId);
|
|
|
+
|
|
|
if (!players) {
|
|
|
return <Loading/>
|
|
|
}
|
|
@@ -162,7 +43,7 @@ export default () => {
|
|
|
<SummaryMap {...{ players, coords, roundActive }}/>
|
|
|
<ScoreBoard {...{ players }} />
|
|
|
<LinkedGame {...{ linkedGame, gameId }} />
|
|
|
- <Label><ClickToCopy text={getUrl(gameId)}>Click here to copy a link to this summary!</ClickToCopy></Label>
|
|
|
+ <Label><ClickToCopy text={summaryURL.href}>Click here to copy a link to this summary!</ClickToCopy></Label>
|
|
|
</Container>
|
|
|
);
|
|
|
}
|