Skip to content

Commit

Permalink
Merge pull request #18 from zourdyzou/finalize_game-area
Browse files Browse the repository at this point in the history
Create game section board area for preview
  • Loading branch information
zourdyzou authored Aug 5, 2022
2 parents 3a55666 + 2904c46 commit 02f093c
Show file tree
Hide file tree
Showing 16 changed files with 277 additions and 27 deletions.
4 changes: 2 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ module.exports = {
testMatch: ["<rootDir>/src/**/?(*.)+(spec|test).[jt]s?(x)"],
coverageThreshold: {
global: {
branches: 80,
branches: 60,
functions: 50,
lines: 50,
statements: 80,
statements: 60,
},
},
errorOnDeprecated: false,
Expand Down
31 changes: 31 additions & 0 deletions src/components/game-area/game-layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { FunctionComponent, PropsWithChildren } from "react";

import styles from "./game-section.module.scss";

export interface Props {
/**
* Top component prop
*/
top: React.ReactNode;
/**
* Children = Main game area
*/
children: React.ReactNode;
}

export const WrapperContainer: FunctionComponent<PropsWithChildren> = ({ children }) => (
<div className={styles.wrapperContainer}>{children}</div>
);

export const GameArea: FunctionComponent<PropsWithChildren> = ({ children }) => (
<div className={styles.gameArea}>{children}</div>
);

export const GameLayout: FunctionComponent<Props> = ({ top, children }) => {
return (
<WrapperContainer>
{top}
<GameArea>{children}</GameArea>
</WrapperContainer>
);
};
12 changes: 12 additions & 0 deletions src/components/game-area/game-over.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, { FunctionComponent, PropsWithChildren } from "react";

import styles from "./game-section.module.scss";

interface GameOverProps {
isWin: boolean;
onClick: () => void;
}

export const GameOver: FunctionComponent<GameOverProps> = ({ onClick, isWin }) => {
return <div className={styles.gameOverComponent}>{isWin ? "😎" : "🙁"}</div>;
};
28 changes: 28 additions & 0 deletions src/components/game-area/game-section-example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { GameArea, WrapperContainer } from "@components/game-area/game-layout";
import { GameOver } from "@components/game-area/game-over";
import { GridComponent } from "@components/grid";
import { ScoreBoard } from "@components/scoreboard";
import { Top } from "@components/top-section";
import { Field, fieldGenerator } from "@helpers/field";
import React, { FunctionComponent } from "react";

export const GameSectionExample: FunctionComponent = () => {
return (
<WrapperContainer>
<Top feature="Flag" firstAction="right click">
Minesweeper
</Top>
<GameArea>
<ScoreBoard
time="000"
mines="000"
levels={["beginner", "intermediate", "expert"]}
onReset={() => null}
onChange={() => null}
/>
<GameOver onClick={() => null} isWin={true} />
<GridComponent children={fieldGenerator(10, 0.5) as Field} onClick={() => null} onContextMenu={() => null} />
</GameArea>
</WrapperContainer>
);
};
35 changes: 35 additions & 0 deletions src/components/game-area/game-section.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.wrapperContainer {
position: relative;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}

.gameArea {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
border: 6px solid #e3e3e3;
background-color: #e3e3e3;
}

.gameOverComponent {
top: 60%;
left: 50%;
z-index: 11;
width: 8vw;
height: 8vw;
font-size: 4vw;
text-align: center;
user-select: none;
cursor: pointer;
line-height: 8vw;
position: absolute;
border-radius: 50%;
pointer-events: auto;
background-color: #d1d1d1;
transform: translate(-50%, -50%);
border: 1px solid rgba(51, 51, 51, 0.25);
}
16 changes: 16 additions & 0 deletions src/components/game-area/game-section.module.scss.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// autogenerated by typings-for-css-modules-loader.
// Please do not change this file!
declare namespace GameSectionModuleScssNamespace {
export interface IGameSectionModuleScss {
gameArea: string;
gameOverComponent: string;
wrapperContainer: string;
}
}

declare const GameSectionModuleScssModule: GameSectionModuleScssNamespace.IGameSectionModuleScss & {
/** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
locals: GameSectionModuleScssNamespace.IGameSectionModuleScss;
};

export = GameSectionModuleScssModule;
3 changes: 3 additions & 0 deletions src/components/game-area/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { WrapperContainer, GameArea, GameLayout } from "./game-layout";
export { GameOver } from "./game-over";
export { GameSectionExample } from "./game-section-example";
47 changes: 47 additions & 0 deletions src/components/scoreboard/__snapshots__/scoreboard.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Scoreboard test cases Scoreboard renders correctly 1`] = `
<DocumentFragment>
<div
class="wrapperScoreboard"
>
<div
class="parentCounter"
>
000
</div>
<div>
<select
class="selectLevel"
role="select-component"
>
<option
class="optionLevel"
>
beginner
</option>
<option
class="optionLevel"
>
intermediate
</option>
<option
class="optionLevel"
>
expert
</option>
</select>
<button
class="resetButton"
>
🙂
</button>
</div>
<div
class="parentCounter"
>
010
</div>
</div>
</DocumentFragment>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Level component test case should render level correctly 1`] = `
<DocumentFragment>
<select
class="selectLevel"
role="select-component"
>
<option
class="optionLevel"
>
beginner
</option>
<option
class="optionLevel"
>
intermediate
</option>
<option
class="optionLevel"
>
expert
</option>
</select>
</DocumentFragment>
`;
26 changes: 26 additions & 0 deletions src/components/scoreboard/components/level/level.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Level } from "@components/scoreboard/components";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";

describe("Level component test case", function () {
it("should render level correctly", function () {
const onChange = jest.fn();
const levelData = ["beginner", "intermediate", "expert"];
const { asFragment } = render(<Level levelData={levelData} onChange={onChange} />);

expect(asFragment()).toMatchSnapshot();
});

it("should Select level behaviour", async function () {
const onChange = jest.fn();
const levelData = ["beginner", "intermediate", "expert"];
render(<Level levelData={levelData} onChange={onChange} />);

await userEvent.selectOptions(screen.getByRole("select-component"), "intermediate");
expect(screen.getByRole("option", { name: "intermediate" })).toBeEnabled();

await Promise.resolve();
expect(onChange).toHaveBeenCalled();
});
});
9 changes: 6 additions & 3 deletions src/components/scoreboard/components/level/level.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import React, { FunctionComponent } from "react";
import React, { ChangeEvent, FunctionComponent } from "react";

import styles from "./level.module.scss";

export const Level: FunctionComponent<{ levelData: string[] }> = ({ levelData }) => (
<select className={styles.selectLevel}>
export const Level: FunctionComponent<{
levelData: string[];
onChange: (event: ChangeEvent<HTMLSelectElement>) => void;
}> = ({ levelData, onChange }) => (
<select onChange={onChange} className={styles.selectLevel} role="select-component">
{levelData.map((item: string) => {
return (
<option className={styles.optionLevel} key={item}>
Expand Down
3 changes: 2 additions & 1 deletion src/components/scoreboard/components/reset/reset.module.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.resetButton {
font-size: 1.5vw;
font-size: 1.1vw;
height: 100%;
cursor: pointer;
font-weight: 700;
border-width: 0.15vw;
Expand Down
3 changes: 1 addition & 2 deletions src/components/scoreboard/scoreboard.module.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.wrapperScoreboard {
display: flex;
width: max-content;
padding-bottom: 2vw;
width: 100%;
justify-content: space-between;
}
28 changes: 28 additions & 0 deletions src/components/scoreboard/scoreboard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ScoreBoard } from "@components/scoreboard/scoreboard";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";

describe("Scoreboard test cases", () => {
const levels = ["beginner", "intermediate", "expert"];

it("Scoreboard renders correctly", () => {
const { asFragment } = render(
<ScoreBoard time="000" levels={levels} onReset={() => null} mines="010" onChange={() => null} />
);

expect(asFragment()).toMatchSnapshot();
});
it("Scoreboard select level handler check", async () => {
const onChange = jest.fn();

render(<ScoreBoard time="000" levels={levels} onReset={() => null} mines="010" onChange={onChange} />);

await userEvent.selectOptions(screen.getByRole("select-component"), "expert");

expect(screen.getByRole("option", { name: "expert" })).toBeEnabled();

await Promise.resolve();
expect(onChange).toHaveBeenCalled();
});
});
14 changes: 10 additions & 4 deletions src/components/scoreboard/scoreboard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FunctionComponent } from "react";
import React, { ChangeEvent, FunctionComponent } from "react";

import { Counter, Level, ResetButton } from "./components";
import styles from "./scoreboard.module.scss";
Expand All @@ -20,14 +20,20 @@ export interface ScoreboardProps {
* Bombs in the field
*/
mines: string;
/**
* Action handler when select new lvl
*/
onChange: (event: ChangeEvent<HTMLSelectElement>) => void;
}

export const ScoreBoard: FunctionComponent<ScoreboardProps> = ({ time, mines, onReset, levels }) => {
export const ScoreBoard: FunctionComponent<ScoreboardProps> = ({ time, mines, onReset, levels, onChange }) => {
return (
<div className={styles.wrapperScoreboard}>
<Counter itemNumber={time} />
<Level levelData={levels} />
<ResetButton onReset={onReset} />
<div>
<Level onChange={onChange} levelData={levels} />
<ResetButton onReset={onReset} />
</div>
<Counter itemNumber={mines} />
</div>
);
Expand Down
19 changes: 4 additions & 15 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,22 @@
import "@styles/styles.scss";
import "normalize.css/normalize.css";

import { GridComponent } from "@components/grid";
import { MockFieldData } from "@helpers/mockData";
import { GameSectionExample } from "@components/game-area";
// import { GridComponent } from "@components/grid";
// import { MockFieldData } from "@helpers/mockData";
import React from "react";
import { createRoot } from "react-dom/client";

// import { CellComponent } from "@components/grid/cell/cell";
// import { ScoreBoard } from "@components/scoreboard";
// import { App } from "@components/app";
// import { Top } from "@components/top-section";

// import Segment from "react-segment-analytics";

const container = document.getElementById("root") as HTMLElement;
const root = createRoot(container);

root.render(
<React.StrictMode>
{/*<Segment writeKey={process.env.SEGMENT_WRITE_KEY as string}>*/}
{/*<App />*/}
<>
{/*<Top feature="Flag" firstAction="ctrl" secondAction="click">*/}
{/* Minesweeper*/}
{/*</Top>*/}
{/*<ScoreBoard time="000" onReset={() => null} levels={["beginner", "intermediate", "expert"]} mines="010" />*/}
{/*<CellComponent coords={[1, 1]} children={10} onContextMenu={() => null} onClick={() => null} />*/}
<GridComponent children={MockFieldData} onContextMenu={() => null} onClick={() => null} />
</>
<GameSectionExample />
{/*</Segment>*/}
</React.StrictMode>
);

1 comment on commit 02f093c

@vercel
Copy link

@vercel vercel bot commented on 02f093c Aug 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.