Skip to content

Commit

Permalink
core functionality done!
Browse files Browse the repository at this point in the history
  • Loading branch information
swizzard committed May 9, 2020
1 parent b622b2e commit 88a69a4
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 96 deletions.
15 changes: 10 additions & 5 deletions app/src/App.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import SignIn from './SignIn';
import DashboardPicker from './Dashboard';
import { retrieveUser, storeUser } from './store-user';
import React, { useState } from "react";
import SignIn from "./SignIn";
import DashboardPicker from "./Dashboard";
import { retrieveUser, storeUser } from "./store-user";

function App() {
const [user, setUser] = useState(retrieveUser());
Expand All @@ -10,7 +10,12 @@ function App() {
storeUser(u);
setUser(u);
}
return user ? <DashboardPicker user={user} /> : <SignIn setUser={su} />;
function signOut() {
storeUser(null);
setUser(null);
}

return user ? <DashboardPicker user={user} signOut={signOut} /> : <SignIn setUser={su} />;
}

export default App;
63 changes: 28 additions & 35 deletions app/src/Dashboard.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
import React, { useState } from 'react';
import React, { useState } from "react";

import DraftDash from './DraftDash';
import HostDash from './HostDash';
import PlayDash from './PlayDash';
import DraftDash from "./DraftDash";
import HostDash from "./HostDash";
import PlayDash from "./PlayDash";
import { retrieveDashState, storeDashState } from "./store-user";

const PLAY = 'play';
const HOST = 'host';
const DRAFT = 'draft';
const PLAY = "play";
const HOST = "host";
const DRAFT = "draft";

export default function DashboardPicker({ user }) {
const [dashState, setDashState] = useState(null);
export default function DashboardPicker({ signOut, user }) {
const [dashState, setDashState] = useState(retrieveDashState());

function setState(st) {
storeDashState(st);
setDashState(st);
}

function radioChange(e) {
setDashState(e.target.value);
setState(e.target.value);
}

function displayDash() {
switch (dashState) {
case PLAY:
return <PlayDash user={user} setDashState={setDashState} />;
return <PlayDash user={user} setDashState={setState} />;
case HOST:
return <HostDash user={user} setDashState={setDashState} />;
return <HostDash user={user} setDashState={setState} />;
case DRAFT:
return <DraftDash user={user} setDashState={setDashState} />;
return <DraftDash user={user} setDashState={setState} />;
default:
return null;
}
Expand All @@ -35,31 +41,18 @@ export default function DashboardPicker({ user }) {
</div>
<div>
<label>Play a Game</label>
<input
type="radio"
name="stateSelector"
value={PLAY}
checked={dashState === PLAY}
onChange={radioChange}
/>
<input type="radio" name="stateSelector" value={PLAY} checked={dashState === PLAY} onChange={radioChange} />
<label>Host a Game</label>
<input
type="radio"
name="stateSelector"
value={HOST}
checked={dashState === HOST}
onChange={radioChange}
/>
<label>Draft a Game</label>
<input
type="radio"
name="stateSelector"
value={DRAFT}
checked={dashState === DRAFT}
onChange={radioChange}
/>
<input type="radio" name="stateSelector" value={HOST} checked={dashState === HOST} onChange={radioChange} />
<label>Create or Edit a Game</label>
<input type="radio" name="stateSelector" value={DRAFT} checked={dashState === DRAFT} onChange={radioChange} />
</div>
{displayDash()}
<div>
<button type="button" onClick={() => signOut()}>
Sign Out
</button>
</div>
</div>
);
}
40 changes: 34 additions & 6 deletions app/src/HostGame.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,51 @@ export default function HostGame({ game, user }) {
return (
<div>
<h5>Round: {roundNo + 1}</h5>
{questions.map(({ question }) => (
<HostQuestion question={question} />
{questions.map(({ question }, ix) => (
<HostQuestion key={`question-${roundNo}-${ix}`} question={question} ix={ix} />
))}
</div>
);
}

function HostQuestion({ question }) {
function HostQuestion({ question, ix }) {
return (
<div>
<h5>{question}</h5>
<p>
<b>{`${ix + 1}.`}</b>
{`${question}`}
</p>
</div>
);
}

function CopyCodeButton({ code }) {
const [copied, setCopied] = useState(false);
const [err, setErr] = useState(false);
const copyCode = () =>
navigator.clipboard
.writeText(code)
.then(() => setCopied(true))
.catch(() => setErr(true));
return (
<div>
<h4>Code: {code}</h4>
<p>Send this code to your players so they can join the game!</p>
{!copied && !err ? (
<button type="button" onClick={copyCode}>
Copy
</button>
) : copied ? (
<span class="small">Copied!</span>
) : (
<span>An error occurred&mdash;please copy the code manually.</span>
)}
</div>
);
}

if (score) {
return <ScoreGame game={game} user={user} />;
return <ScoreGame code={game.code} />;
} else if (!game) {
return (
<div>
Expand All @@ -76,7 +104,7 @@ export default function HostGame({ game, user }) {
{error ? <div>{error}</div> : null}
<div>
<h3>{game.quizName}</h3>
<h4>Code: {game.code}</h4>
<CopyCodeButton code={game.code} />
</div>
<div>
<h4>Participants</h4>
Expand Down
2 changes: 1 addition & 1 deletion app/src/PlayerGame.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function PlayerAnswer({ answers, answerId, setAnswer }) {
function PlayerQuestion({ question: { answers: anss }, questionNo, setAnswer, answers }) {
return (
<div>
<h3>{questionNo + 1}</h3>
<h3>Question {questionNo + 1}</h3>
{anss.map(({ answerId }) => (
<PlayerAnswer key={`${answerId}-answer`} answers={answers} answerId={answerId} setAnswer={setAnswer} />
))}
Expand Down
89 changes: 50 additions & 39 deletions app/src/ScoreGame.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
import React, { useEffect, useState } from "react";
import { getParticipantAnswers, submitScore } from "./db/game";
import _ from "lodash";
import { getParticipants, getParticipantAnswers, submitScore } from "./db/game";

export default function ScoreGame({ game }) {
export default function ScoreGame({ code }) {
const [error, setError] = useState(null);
const [answers, setAnswers] = useState(null);
const [currentParticipant, setCurrentParticipant] = useState(0);
const [participantScores, setParticipantScores] = useState([]);

function getResponses() {
getParticipantAnswers(game.code)
let playerIds;
getParticipants(code)
.then((resp) => {
if (resp.ok) {
return resp.json();
} else {
throw new Error(resp.statusText);
}
})
.then(({ participants }) => participants.map((p) => p.playerId))
.then((pids) => {
playerIds = pids;
return getParticipantAnswers(pids);
})
.then((resp) => {
if (resp.ok) {
return resp.json();
} else {
throw new Error("There was a problem retrieving participants' answers.");
}
})
.then(([{ participants }]) => {
setAnswers(fmtAnswers(participants));
});
// .catch((e) => setError(e.message));
.then((participants) => setAnswers(fmtAnswers(playerIds, participants)))
.catch((e) => setError(e.message));
}

useEffect(getResponses, [answers]);
useEffect(getResponses, [code]);

function submitParticipantScore(participantId, displayName, score) {
submitScore(participantId, score)
Expand All @@ -41,7 +53,7 @@ export default function ScoreGame({ game }) {
return <Loading error={error} />;
}
if (currentParticipant < answers.length) {
return <Scoring answers={answers} currentParticipant={currentParticipant} error={error} submitParticpantScore={submitParticipantScore} />;
return <Scoring answers={answers} currentParticipant={currentParticipant} error={error} submitParticipantScore={submitParticipantScore} />;
}
return <Results participantScores={participantScores} />;
}
Expand All @@ -62,8 +74,8 @@ function Results({ participantScores }) {
{doSort(participantScores).map(({ rank, score, displayName }) => (
<tr>
<td>{rank}</td>
<td>{score}</td>
<td>{displayName}</td>
<td>{score}</td>
</tr>
))}
</tbody>
Expand All @@ -73,10 +85,10 @@ function Results({ participantScores }) {
}

function Scoring({ answers, currentParticipant, error, submitParticipantScore }) {
const [currentRound, setCurrentRound] = useState(1);
const [currentRound, setCurrentRound] = useState(0);
const [currentScore, setCurrentScore] = useState({});
function updateScore(answerId, val) {
setCurrentScore({ ...currentScore, [answerId]: val });
setCurrentScore({ ...currentScore, [answerId]: parseInt(val) });
}
return (
<div>
Expand All @@ -86,13 +98,13 @@ function Scoring({ answers, currentParticipant, error, submitParticipantScore })
<h2>Team: {answers[currentParticipant].displayName}</h2>
<h3>Round {currentRound}</h3>
<div>
{answers[currentParticipant].responses[currentRound].map(({ question: { question, questionId }, answers: responses }) => {
return <ScoringQuestion key={questionId} question={question} responses={responses} updateScore={updateScore} />;
})}
{answers[currentParticipant].rounds[currentRound].questions.map(({ question, answers }, ix) => (
<ScoringQuestion key={`${currentRound}-${ix}`} question={question} responses={answers} updateScore={updateScore} currentScore={currentScore} />
))}
</div>
</div>
<div>
{currentRound < answers[currentParticipant].responses.length - 1 ? (
{currentRound < answers[currentParticipant].rounds.length - 1 ? (
<button type="button" onClick={() => setCurrentRound(currentRound + 1)}>
Next Round
</button>
Expand All @@ -102,7 +114,7 @@ function Scoring({ answers, currentParticipant, error, submitParticipantScore })
Previous Round
</button>
) : null}
{currentRound === answers[currentParticipant].responses.length - 1 && currentParticipant < answers.length - 1 ? (
{currentRound === answers[currentParticipant].rounds.length - 1 && currentParticipant <= answers.length - 1 ? (
<button
type="button"
onClick={() => {
Expand All @@ -127,18 +139,19 @@ function Loading({ error }) {
);
}

function ScoringQuestion({ question, responses, updateScore }) {
function ScoringQuestion({ question, responses, updateScore, currentScore }) {
return (
<div>
<h4>{question}</h4>
{Object.values(responses).map(({ answer, answerId, points, response }) => (
<ScoringAnswer answer={answer} answerId={answerId} points={points} response={response} setCurrentScore={updateScore} key={answerId} />
{responses.map(({ answer, answerId, points, response }) => (
<ScoringAnswer answer={answer} answerId={answerId} points={points} response={response} updateScore={updateScore} currentScore={currentScore[answerId]} key={answerId} />
))}
</div>
);
}

function ScoringAnswer({ answer, answerId, points, response, updateScore }) {
function ScoringAnswer({ answer, answerId, points, response, updateScore, currentScore }) {
const [score, setScore] = useState(currentScore || 0);
return (
<div>
<div>
Expand All @@ -153,10 +166,12 @@ function ScoringAnswer({ answer, answerId, points, response, updateScore }) {
<label htmlFor={`points-${answerId}`}>Points:</label>
<input
type="number"
placeholder="0"
placeholder={score}
id={`points-${answerId}`}
onChange={(e) => {
updateScore(answerId, e.target.value);
const v = e.target.value;
setScore(v);
updateScore(answerId, v);
}}
/>
<label htmlFor={`answerPoints-${answerId}`}>Points for a correct answer:</label>
Expand All @@ -166,22 +181,18 @@ function ScoringAnswer({ answer, answerId, points, response, updateScore }) {
);
}

function fmtAnswers(ps) {
const resps = ps.reduce((acc, { id, responses: resps }) => {
acc.push({
id,
responses: resps.reduce((acc, { answer: { answer, answerId, points, question: { questionId, questionNo, question, round: { roundNo } } }, response }) => {
const currRound = acc[roundNo] || [];
const currQ = currRound[questionNo] || { questionId, question, answers: {} };
currQ.answers[answerId] = { answerId, answer, response, points };
currRound[questionNo] = currQ;
acc[roundNo] = currRound;
return acc;
}, {})
});
return acc;
}, []);
return resps;
function fmtAnswers(playerIds, responses) {
return _.zip(playerIds, responses).map(([pid, { game: { quiz: { quizRound } }, player: { displayName }, responses }]) => ({
participantId: pid,
displayName,
rounds: quizRound.map(({ questions, roundNo }) => ({
roundNo,
questions: questions.map(({ question, answers }) => ({
question,
answers: answers.map(({ answer, answerId, points }) => ({ answer, answerId, points, response: _.find(responses, (r) => r.answerId).response }))
}))
}))
}));
}

function doSort(ps) {
Expand Down
4 changes: 2 additions & 2 deletions app/src/db/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ export async function del(endpoint, params) {

export async function patch(endpoint, params, data) {
const req = {
method: "patch",
method: "PATCH",
body: JSON.stringify(data),
headers: {
"Contenty-Type": "application/json"
"Content-Type": "application/json"
}
};
return fetch(buildEndpoint(endpoint, params), req);
Expand Down
Loading

0 comments on commit 88a69a4

Please sign in to comment.