Skip to content

Commit 4de4439

Browse files
committed
Merge branch 'dev50' into kevin/david-filter
2 parents df8cb1a + 93187c9 commit 4de4439

27 files changed

+1782
-1207
lines changed

demo-app/.babelrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
{
3+
"presets": [
4+
"@babel/preset-env",
5+
"@babel/preset-react"
6+
]
7+
}

demo-app/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

demo-app/package.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "typescript-module",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"start": "webpack-dev-server",
8+
"test": "echo \"Error: no test specified\" && exit 1"
9+
},
10+
"devDependencies": {
11+
"@babel/core": "^7.16.7",
12+
"@babel/preset-env": "^7.16.7",
13+
"@babel/preset-react": "^7.16.7",
14+
"@types/express": "^4.17.13",
15+
"@types/node": "^17.0.8",
16+
"@types/react": "^17.0.38",
17+
"@types/react-dom": "^17.0.11",
18+
"babel-loader": "^8.2.3",
19+
"copy-webpack-plugin": "^10.2.0",
20+
"css-loader": "^6.5.1",
21+
"html-webpack-plugin": "^5.5.0",
22+
"nodemon": "^2.0.15",
23+
"ts-loader": "^9.2.6",
24+
"typescript": "^4.5.4",
25+
"webpack": "^5.65.0",
26+
"webpack-cli": "^4.9.1",
27+
"webpack-dev-server": "^4.7.2"
28+
},
29+
"dependencies": {
30+
"express": "^4.17.2",
31+
"react": "^18.1.0",
32+
"react-dom": "^18.1.0",
33+
"react-router-dom": "^6.3.0",
34+
"ts-node": "^10.4.0"
35+
}
36+
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import React, { Component } from 'react';
2+
import Row from './Row';
3+
import { BoardText, BoardContent, Scoreboard, Player } from './../../types';
4+
5+
type BoardState = {
6+
board: BoardContent;
7+
currentPlayer: Player;
8+
gameOver: boolean;
9+
message: string;
10+
scoreboard: Scoreboard;
11+
};
12+
13+
class Board extends Component<{}, BoardState> {
14+
constructor(props: any) {
15+
super(props);
16+
this.state = {
17+
board: this.newBoard(),
18+
currentPlayer: 'X',
19+
gameOver: false,
20+
message: '',
21+
scoreboard: { X: 0, O: 0 },
22+
};
23+
24+
this.resetBoard = this.resetBoard.bind(this);
25+
this.handleBoxClick = this.handleBoxClick.bind(this);
26+
}
27+
28+
componentDidUpdate() {
29+
this.checkForWinner();
30+
}
31+
32+
/**
33+
* @method newBoard
34+
* @description - returns a blank BoardContent array,
35+
* for the start of a new game
36+
*/
37+
newBoard(): BoardContent {
38+
return [
39+
['-', '-', '-'],
40+
['-', '-', '-'],
41+
['-', '-', '-'],
42+
];
43+
}
44+
45+
/**
46+
* @method resetBoard
47+
* @description - sets to board object to be all '-',
48+
* and sets gameOver and message to default state
49+
*/
50+
resetBoard(): void {
51+
this.setState({
52+
gameOver: false,
53+
board: this.newBoard(),
54+
message: '',
55+
});
56+
}
57+
58+
/**
59+
* @method checkForWinner
60+
* @description - checks to see if either player has filled a row
61+
* if so, ends the game and updates the message to declare winner
62+
*/
63+
checkForWinner(): void {
64+
const { board, gameOver, currentPlayer } = this.state;
65+
66+
const spacesLeft = (): boolean => {
67+
for (let i of board) {
68+
if (i.includes('-')) return true;
69+
}
70+
return false;
71+
};
72+
73+
if (!gameOver) {
74+
// win conditions: matching rows, columns, or diagonals, that are not empty('-')
75+
if (
76+
(board[0][0] === board[0][1] &&
77+
board[0][1] === board[0][2] &&
78+
board[0][2] !== '-') ||
79+
(board[1][0] === board[1][1] &&
80+
board[1][1] === board[1][2] &&
81+
board[1][2] !== '-') ||
82+
(board[2][0] === board[2][1] &&
83+
board[2][1] === board[2][2] &&
84+
board[2][2] !== '-') ||
85+
(board[0][0] === board[1][0] &&
86+
board[1][0] === board[2][0] &&
87+
board[2][0] !== '-') ||
88+
(board[0][1] === board[1][1] &&
89+
board[1][1] === board[2][1] &&
90+
board[2][1] !== '-') ||
91+
(board[0][2] === board[1][2] &&
92+
board[1][2] === board[2][2] &&
93+
board[2][2] !== '-') ||
94+
(board[0][0] === board[1][1] &&
95+
board[1][1] === board[2][2] &&
96+
board[2][2] !== '-') ||
97+
(board[2][0] === board[1][1] &&
98+
board[1][1] === board[0][2] &&
99+
board[0][2] !== '-')
100+
) {
101+
// winner is the person who's turn was previous
102+
const winner: Player = currentPlayer === 'X' ? 'O' : 'X';
103+
104+
this.setState({
105+
gameOver: true,
106+
message: `Player ${winner} wins!`,
107+
});
108+
109+
// draw condition: no '-' remaining in board without above win condition triggering
110+
} else if (!spacesLeft()) {
111+
this.setState({
112+
gameOver: true,
113+
message: 'Draw!',
114+
});
115+
}
116+
}
117+
}
118+
119+
handleBoxClick(row: number, column: number): void {
120+
const boardCopy: BoardContent = [
121+
[...this.state.board[0]],
122+
[...this.state.board[1]],
123+
[...this.state.board[2]],
124+
];
125+
boardCopy[row][column] = this.state.currentPlayer;
126+
const newPlayer: Player = this.state.currentPlayer === 'X' ? 'O' : 'X';
127+
this.setState({ board: boardCopy, currentPlayer: newPlayer });
128+
}
129+
130+
render() {
131+
const rows: Array<JSX.Element> = [];
132+
for (let i = 0; i < 3; i++) {
133+
rows.push(
134+
<Row
135+
key={i}
136+
row={i}
137+
handleBoxClick={this.handleBoxClick}
138+
values={this.state.board[i]}
139+
/>
140+
);
141+
}
142+
const { X, O }: Scoreboard = this.state.scoreboard;
143+
144+
return (
145+
<div className="board">
146+
<h1>Tic Tac Toe</h1>
147+
{this.state.gameOver && <h4>{this.state.message}</h4>}
148+
{rows}
149+
<button id="reset" onClick={this.resetBoard}>
150+
Reset
151+
</button>
152+
</div>
153+
);
154+
}
155+
}
156+
157+
export default Board;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from 'react';
2+
import { BoardText } from '../../types';
3+
4+
type BoxProps = {
5+
value: BoardText;
6+
row: number;
7+
column: number;
8+
handleBoxClick: (row: number, column: number) => void;
9+
};
10+
11+
const Box = (props: BoxProps) => {
12+
return (
13+
<button
14+
className="box"
15+
onClick={(e) => props.handleBoxClick(props.row, props.column)}
16+
>
17+
{props.value}
18+
</button>
19+
);
20+
};
21+
22+
export default Box;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from "react";
2+
import Increment from "./Increment";
3+
4+
function Buttons() {
5+
const buttons = [];
6+
for (let i = 0; i < 4; i++){
7+
buttons.push(<Increment />)
8+
}
9+
10+
return(
11+
<div className="buttons">
12+
<h1>Stateful Buttons</h1>
13+
<h4>These buttons are functional components that each manage their own state with the useState hook.</h4>
14+
{buttons}
15+
</div>
16+
)
17+
}
18+
19+
export default Buttons;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react';
2+
3+
function Home() {
4+
return (
5+
<div className="about">
6+
<h1>Lorem Ipsum</h1>
7+
<p>
8+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
9+
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
10+
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
11+
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
12+
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
13+
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
14+
mollit anim id est laborum."
15+
</p>
16+
<p>
17+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
18+
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
19+
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
20+
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
21+
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
22+
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
23+
mollit anim id est laborum."
24+
</p>
25+
</div>
26+
);
27+
}
28+
29+
export default Home;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React, { useState } from 'react';
2+
3+
function Increment() {
4+
const [count, setCount] = useState(0);
5+
6+
return (
7+
<button className="increment" onClick={() => setCount(count + 1)}>
8+
You clicked me {count} times.
9+
</button>
10+
);
11+
}
12+
13+
export default Increment;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from "react";
2+
import { Link } from "react-router-dom";
3+
4+
function Nav() {
5+
return(
6+
<div className="nav">
7+
<Link className="link" to="/">About</Link>
8+
<Link id="tictactoe" className="link" to="/tictactoe">Tic-Tac-Toe</Link>
9+
<Link className="link" to="/buttons">Counter</Link>
10+
</div>
11+
)
12+
}
13+
14+
export default Nav;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from 'react';
2+
import Box from './Box';
3+
import { BoardText } from '../../types';
4+
5+
type RowProps = {
6+
handleBoxClick: (row: number, column: number) => void;
7+
values: Array<BoardText>;
8+
row: number;
9+
};
10+
11+
const Row = (props: RowProps) => {
12+
const boxes: Array<JSX.Element> = [];
13+
for (let i = 0; i < 3; i++) {
14+
boxes.push(
15+
<Box
16+
key={i}
17+
row={props.row}
18+
column={i}
19+
handleBoxClick={props.handleBoxClick}
20+
value={props.values[i]}
21+
></Box>
22+
);
23+
}
24+
25+
return <div className="row">{boxes}</div>;
26+
};
27+
28+
export default Row;

0 commit comments

Comments
 (0)