Skip to content

Commit

Permalink
merge dev
Browse files Browse the repository at this point in the history
  • Loading branch information
perennialAutodidact committed Nov 2, 2024
2 parents c58a590 + 5b41ebc commit 4c6b355
Show file tree
Hide file tree
Showing 40 changed files with 607 additions and 120 deletions.
11 changes: 7 additions & 4 deletions apps/backend/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@
},
"extends": ["@memory-snap/eslint-config/frontend"],
"rules": {
"prettier/prettier": ["error", { "endOfLine": "auto" }],
"no-console": ["error", { "allow": ["warn", "error"] }],
"no-unused-vars": "off",
"react/prop-types": "error",
"prettier/prettier": ["error", { "endOfLine": "auto", "arrowParens": "avoid" }],
"no-console": ["error", { "allow": ["warn"] }],
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"no-unused-vars": "error",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
"error",
{
"vars": "all",
"varsIgnorePattern": "^_",
Expand Down
3 changes: 2 additions & 1 deletion apps/frontend/.prettierrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"trailingComma": "es5",
"semi": true,
"singleQuote": true,
"endOfLine": "auto"
"endOfLine": "auto",
"arrowParens": "avoid"
}
2 changes: 1 addition & 1 deletion apps/frontend/lint-staged.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const lintStagedConfig = {
'*.{js,jsx}': 'yarn lint',
'*.{js,jsx}': 'yarn lint --max-warnings=0',
'*.scss': 'npx stylelint',
};

Expand Down
3 changes: 2 additions & 1 deletion apps/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"proxy": "http://localhost:8080",
"homepage": ".",
"dependencies": {
"@hookform/resolvers": "^3.3.4",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.4.3",
Expand All @@ -16,7 +17,7 @@
"pexels": "^1.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.51.1",
"react-hook-form": "^7.51.4",
"react-router-dom": "^6.15.0",
"react-scripts": "5.0.1",
"turbo": "^1.12.5-canary.0",
Expand Down
17 changes: 11 additions & 6 deletions apps/frontend/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
import React, { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import './styles/App.scss';
import { Routes, Route, useNavigate } from 'react-router-dom';
import { routes } from './utils';
import useGameContext from 'hooks/useGameContext';

const App = () => {
const navigate = useNavigate();
const location = useLocation();

const {
state: { stage },
} = useGameContext();

useEffect(() => {
const { path } = routes[stage];
navigate(path);
}, [stage]);
if (location.pathname.split('/')[1] !== path.split('/')[1]) {
navigate(path);
}
}, [stage, navigate, location.pathname]);

return (
<div className="App bg-dark text-light vh-100 container-fluid p-0">
<Routes>
{Object.keys(routes).map((key) => (
{routes.map((route, index) => (
<Route
key={key}
path={routes[key].path}
element={routes[key].component}
path={route.path}
element={<route.Element parent={route} index={index} key={index} />}
key={index}
/>
))}
</Routes>
Expand Down
6 changes: 3 additions & 3 deletions apps/frontend/src/App.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { produce } from 'immer';
import { GAME_STAGES } from 'utils/stages';

describe('App', () => {
it('it renders that game component at /play', () => {
it('it renders the game component at /play', () => {
const setupTests = createSetupTestsForRoute('/play');

const { screen } = setupTests(App);
Expand All @@ -16,7 +16,7 @@ describe('App', () => {
it('it renders the setup component at /setup', () => {
const setupTests = createSetupTestsForRoute('/setup');

const setupGameState = produce(baseState.game, (draft) => {
const setupGameState = produce(baseState.game, draft => {
draft.stage = GAME_STAGES.SETUP;
});

Expand All @@ -32,7 +32,7 @@ describe('App', () => {
it('it renders the result display component at /game-over', () => {
const setupTests = createSetupTestsForRoute('/game-over');

const gameOverState = produce(baseState.game, (draft) => {
const gameOverState = produce(baseState.game, draft => {
draft.stage = GAME_STAGES.GAME_OVER;
draft.winner = baseState.game.players[0];
});
Expand Down
67 changes: 52 additions & 15 deletions apps/frontend/src/components/Game/GameBoard/ResultDisplay/index.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,65 @@
import React from 'react';
import useGameContext from 'hooks/useGameContext';
import useFormContext from 'hooks/useFormContext';
import usePhotosContext from 'hooks/usePhotosContext';
import Button from 'components/Button';
import { resetGame, updateStage } from '../../../../contexts/game/actions/';
import { resetForm } from 'contexts/form/actions';
import { resetPhotos } from 'contexts/photos/actions';

const ResultDisplay = () => {
const {
state: { winner },
state: { winner, stage },
dispatch: gameDispatch,
} = useGameContext();

const { dispatch: formDispatch } = useFormContext();
const { dispatch: photoDispatch } = usePhotosContext();

const handleReset = () => {
photoDispatch(resetPhotos());
gameDispatch(resetGame());
formDispatch(resetForm());
};

const handlePlayAgain = () => {
gameDispatch(resetGame());
gameDispatch(updateStage(1));
};

return (
<div
data-testid="result-display"
className="container d-flex justify-content-center pt-5"
>
<div className="d-flex-column text-center">
<h1 className="mb-5">GAME OVER!</h1>
stage === 2 && (
<div
data-testid="result-display"
className="container d-flex justify-content-center pt-5"
>
<div className="d-flex-column text-center">
<h1 className="mb-5">GAME OVER!</h1>

{winner === null ? (
<h2 className="lh-lg">Its a tie!</h2>
) : (
<h2 className={`text-${winner.color.className}`}>
{`${winner.name} wins!`}
</h2>
)}
{winner === null ? (
<h2 className="lh-lg">Its a tie!</h2>
) : (
<h2 className={`text-${winner.color.className}`}>
{`${winner.name} wins!`}
</h2>
)}
<div className="container d-flex flex-column pt-3">
<Button
onClick={handlePlayAgain}
text={'play again'}
color={'primary-dark'}
textColor={'primary'}
/>
<Button
onClick={handleReset}
text={'reset game'}
color={'primary-dark'}
textColor={'secondary'}
/>
</div>
</div>
</div>
</div>
)
);
};

Expand Down
11 changes: 10 additions & 1 deletion apps/frontend/src/components/Game/GameBoard/index.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import useGameContext from 'hooks/useGameContext';
import useFormContext from 'hooks/useFormContext';
import ScoreBoard from '../ScoreBoard';
import TileGrid from './TileGrid';

Expand All @@ -8,9 +9,17 @@ const GameBoard = () => {
state: { players, currentPlayer, tiles },
} = useGameContext();

const {
state: { formValues },
} = useFormContext();

return (
<>
<ScoreBoard players={players} currentPlayer={currentPlayer} />
<ScoreBoard
players={players}
names={formValues}
currentPlayer={currentPlayer}
/>
<TileGrid tiles={tiles} />
</>
);
Expand Down
7 changes: 4 additions & 3 deletions apps/frontend/src/components/Game/PlayerHUD/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Player } from 'proptypes';
import './style.scss';
import useGameContext from 'hooks/useGameContext';

const PlayerHUD = ({ player, isActive }) => {
const PlayerHUD = ({ player, isActive, name }) => {
const { state } = useGameContext();

const bgClasses = {
Expand Down Expand Up @@ -37,7 +37,7 @@ const PlayerHUD = ({ player, isActive }) => {
role="note"
aria-label={`turn-indicator-${state.currentPlayer.name}`}
>
name: {player.name}
name: {name}
</span>
) : null}
<div
Expand All @@ -50,7 +50,7 @@ const PlayerHUD = ({ player, isActive }) => {
data-testid={`player-name-${player.number}`}
className={`${classes.playerName}`}
>
{player.name}
{name}
</div>
</div>
);
Expand All @@ -59,6 +59,7 @@ const PlayerHUD = ({ player, isActive }) => {
PlayerHUD.propTypes = {
player: Player,
isActive: PropTypes.bool,
name: PropTypes.string,
};

export default PlayerHUD;
6 changes: 4 additions & 2 deletions apps/frontend/src/components/Game/ScoreBoard/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import PropTypes from 'prop-types';
import { Player } from 'proptypes';
import PlayerHUD from '../PlayerHUD';

const ScoreBoard = ({ players, currentPlayer }) => {
const ScoreBoard = ({ players, currentPlayer, names }) => {
if (!players) return null;
return (
<div className="d-flex">
{players.map((player) => (
{players.map((player, index) => (
<PlayerHUD
key={player.number}
player={player}
name={index === 0 ? names.player1Name : names.player2Name}
isActive={player.number === currentPlayer.number}
/>
))}
Expand All @@ -21,6 +22,7 @@ const ScoreBoard = ({ players, currentPlayer }) => {
ScoreBoard.propTypes = {
players: PropTypes.arrayOf(Player),
currentPlayer: Player,
names: PropTypes.object,
};

export default ScoreBoard;
34 changes: 31 additions & 3 deletions apps/frontend/src/components/Setup/Form/index.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,40 @@
import React from 'react';
import Header from '../Header';
import { Outlet, Routes, Route } from 'react-router-dom';
import PropTypes from 'prop-types';

const SetupForm = () => {
const SetupForm = ({ parent }) => {
return (
<form className="container p-0 bg-light rounded text-dark">
<div className="container p-0 bg-light rounded text-dark">
<Header headerText={'Game setup'} />
</form>
<Routes>
{parent.children.map((child, index) => (
<Route
path={child.path}
index={child.index}
key={index}
element={
<child.Element
label={child.elementProps.label}
btnText={child.elementProps.buttonText}
btnColor={child.elementProps.buttonColorClass}
FormElement={child.elementProps.FormElement}
id={child.elementProps.id}
name={child.name}
schema={child.schema}
{...child}
/>
}
/>
))}
</Routes>
<Outlet />
</div>
);
};

SetupForm.propTypes = {
parent: PropTypes.object,
};

export default SetupForm;
52 changes: 52 additions & 0 deletions apps/frontend/src/components/Setup/Form/index.test.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { setupTests } from 'helpers/tests';
import { createSetupTestsForRoute } from 'helpers/tests';
import SetupForm from '.';
import { routes } from 'utils';

describe('SetupForm component', () => {
it('renders form header component', () => {
Expand All @@ -8,4 +10,54 @@ describe('SetupForm component', () => {
} = setupTests(SetupForm);
expect(getByTestId('setupFormHeader')).toBeInTheDocument();
});

it('it renders the correct form component at /setup/step-1', () => {
const setupTests = createSetupTestsForRoute('/step-1');

const parent = routes[0];

const { screen } = setupTests(SetupForm, { props: { parent } });

const stepOneComponent = screen.getByText("Enter the first player's name");

expect(stepOneComponent).toBeInTheDocument();
});

it('it renders the correct form component at /setup/step-2', () => {
const setupTests = createSetupTestsForRoute('/step-2');

const parent = routes[0];

const { screen } = setupTests(SetupForm, { props: { parent } });

const stepTwoComponent = screen.getByText("Enter the second player's name");

expect(stepTwoComponent).toBeInTheDocument();
});

it('it renders the correct form component at /setup/step-3', () => {
const setupTests = createSetupTestsForRoute('/step-3');

const parent = routes[0];

const { screen } = setupTests(SetupForm, { props: { parent } });

const stepThreeComponent = screen.getByText('How many tiles?');

expect(stepThreeComponent).toBeInTheDocument();
});

it('it renders the correct form component at /setup/step-4', () => {
const setupTests = createSetupTestsForRoute('/step-4');

const parent = routes[0];

const { screen } = setupTests(SetupForm, { props: { parent } });

const stepFourComponent = screen.getByText(
'What kind of photos on the tiles?'
);

expect(stepFourComponent).toBeInTheDocument();
});
});
Loading

0 comments on commit 4c6b355

Please sign in to comment.