Skip to content

Commit

Permalink
WIP major refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
vnglst committed Feb 2, 2020
1 parent f1af367 commit f74fb11
Show file tree
Hide file tree
Showing 27 changed files with 515 additions and 1,432 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@fortawesome/react-fontawesome": "^0.1.8",
"classnames": "^2.2.6",
"howler": "^2.1.3",
"immer": "^5.3.2",
"minimal-analytics": "^0.1.15",
"prevent-double-tap-zoom": "^2.0.4",
"react": "^16.12.0",
Expand Down
108 changes: 57 additions & 51 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { faCog, faInfoCircle, faRedo } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import * as React from "react";
import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";

import Grid from "./components/Grid";
import AboutPage from "./pages/About";
Expand All @@ -11,59 +12,60 @@ import BackgroundImage from "./components/BackgroundImage";
import BottomBar from "./components/BottomBar";
import Button from "./components/Button";
import Overlay from "./components/Overlay";
import { IGridItem, StatusEnum } from "./types";
import { IGameState } from "./redux/reducers";

import "./App.css";
import { GridType, IGameState, IGridItem, StatusEnum } from "./types";
import { filterPossibleSolutions } from "model/puzzle";

const festenUrl =
"https://res.cloudinary.com/vnglst/image/upload/f_auto/v1537882150/festen.jpg";

interface IAddAnswer {
answer: IGridItem;
solution: string[];
grid: GridType;
}
interface IAppProps {
didWin: boolean;
didLoose: boolean;
remainingSolution: string[];
solution: string[];
updateSolution: (solution: string[]) => void;
restart: () => void;
game: IGameState;
addAnswer: ({ answer, solution, grid }: IAddAnswer) => void;
}
export default function App() {
const [page, setPage] = useState("home");
const dispatch = useDispatch();
const grid = useSelector((state: IGameState) => state.grid);
const remaining = useSelector((state: IGameState) => state.remaining);
const solution = useSelector((state: IGameState) => state.solution);
const solutions = useSelector((state: IGameState) => state.solutions);
const didWin = useSelector(
(state: IGameState) => state.remaining.length === 0
);

function handleClick(answer: IGridItem) {
if (answer.status === StatusEnum.Correct) return;

const possibleSolutions = filterPossibleSolutions(solutions, answer);

if (possibleSolutions.length > 0) {
dispatch({ type: "CORRECT_ANSWER", payload: answer });
if (remaining.length <= 1) dispatch({ type: "YOU_WON" });
return;
}

export default function App({
didWin,
didLoose,
updateSolution,
restart,
solution,
remainingSolution,
game,
addAnswer
}: IAppProps) {
const [page, setPage] = React.useState("home");
const almostCorrect = solutions.find((solution) => {
return solution.find(
(s) => s.column === answer.column && s.row === answer.row
);
});

const handleClick = (item: IGridItem) => {
if (
item.status === StatusEnum.Correct ||
item.status === StatusEnum.Wrong
) {
return; // already answered
if (almostCorrect) {
dispatch({ type: "ALMOST_CORRECT_ANSWER", payload: answer });
return;
}
addAnswer({ answer: item, solution: game.solution, grid: game.grid });
};

dispatch({ type: "WRONG_ANSWER", payload: answer });
}

return (
<BackgroundImage imageSrc={festenUrl}>
<div className="app">
<h1>{remainingSolution}</h1>
<h1>{remaining}</h1>
<Grid>
{game.grid.map((row, rowIndex) =>
row.map((item, columnIndex) => (
{grid.map((_, row) =>
_.map((item, column) => (
<Grid.Item
key={`${rowIndex}-${columnIndex}`}
key={`${row}-${column}`}
onClick={() => handleClick(item)}
falldown={item.status === StatusEnum.Wrong}
red={item.status === StatusEnum.Wrong}
Expand Down Expand Up @@ -93,13 +95,18 @@ export default function App({
/>
</BottomBar>
{page === "new-game" && (
<NewGamePage onNavigate={setPage} restart={restart} />
<NewGamePage
onNavigate={setPage}
restart={() => dispatch({ type: "RESTART" })}
/>
)}
{page === "settings" && (
<SettingsPage
solution={solution}
updateSolution={updateSolution}
restart={restart}
updateSolution={(newSolution) =>
dispatch({ type: "UPDATE_SOLUTION", payload: newSolution })
}
restart={() => dispatch({ type: "RESTART" })}
onNavigate={setPage}
/>
)}
Expand All @@ -113,14 +120,13 @@ export default function App({
{didWin && page === "home" && (
<Overlay>
<p>YOU WON</p>
<Button onMouseDown={restart}>Play again?</Button>
</Overlay>
)}

{didLoose && page === "home" && (
<Overlay>
<p>YOU LOST</p>
<Button onMouseDown={restart}>Play again?</Button>
<Button
onMouseDown={() => {
dispatch({ type: "RESTART" });
}}
>
Play again?
</Button>
</Overlay>
)}
</div>
Expand Down
65 changes: 0 additions & 65 deletions src/AppContainer.tsx

This file was deleted.

29 changes: 17 additions & 12 deletions src/__tests__/App.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import "@testing-library/jest-dom/extend-expect";
import React from "react";
import {
cleanup,
fireEvent,
render,
waitForElement
} from "@testing-library/react";
import reducers from "../redux/reducers";
import { cleanup, fireEvent, render } from "@testing-library/react";
import { reducers } from "../redux/reducers";
import { Provider } from "react-redux";
import { createStore } from "redux";
import App from "../AppContainer";
import App from "../App";
import { mockMathRandom } from "../test-utils/mockMathRandom";

mockMathRandom();
Expand All @@ -28,6 +23,7 @@ function renderWithRedux(
};
}

// TODO: Skipping mock random not working
it.skip("should show NORA", async () => {
const { getByRole, getByText, queryByText, debug } = renderWithRedux(<App />);
const heading = getByRole("heading");
Expand Down Expand Up @@ -109,10 +105,19 @@ it("should be not possible to change to a wrong name", async () => {
expect(getByRole("heading")).toHaveTextContent("NORA");
});

it("should be possible to restart the game", async () => {
const { getByLabelText, getByText, queryByText } = renderWithRedux(<App />);
// TODO: skipping mock random not working
it.skip("should be possible to restart the game", async () => {
const {
getByLabelText,
getByText,
getAllByText,
queryByText,
debug
} = renderWithRedux(<App />);

const A = getByText("A");
debug();

const A = getAllByText("A")[0];
fireEvent.mouseDown(A);
expect(A).toHaveClass("orange");

Expand All @@ -125,5 +130,5 @@ it("should be possible to restart the game", async () => {
fireEvent.mouseDown(getByText("New game"));

expect(queryByText(/New game/)).not.toBeInTheDocument();
expect(getByText("A")).not.toHaveClass("orange");
expect(getAllByText("A")[0]).not.toHaveClass("orange");
});
9 changes: 4 additions & 5 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import * as React from "react";
import * as ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { applyMiddleware, compose, createStore } from "redux";
import App from "./AppContainer";
import { audioMiddleware } from "./redux/audio-middleware";
import { IGameState } from "./types";
import reducers from "./redux/reducers";
import App from "./App";
import { middleware } from "./redux/middleware";
import { IGameState, reducers } from "./redux/reducers";
import "./index.css";
import register from "./registerServiceWorker";
import { BugsnagErrorBoundary } from "./utils/bugsnag";
Expand All @@ -17,7 +16,7 @@ const composeEnhancers =

const store = createStore<IGameState, any, any, any>(
reducers,
composeEnhancers(applyMiddleware(audioMiddleware))
composeEnhancers(applyMiddleware(middleware))
);

ReactDOM.render(
Expand Down
Loading

0 comments on commit f74fb11

Please sign in to comment.