Skip to content

Commit 611bf8c

Browse files
Merge pull request #9 from oslabs-beta/frontend2
next demo app added
2 parents 1c36c7d + a79da75 commit 611bf8c

39 files changed

+775
-1442
lines changed

demo-app-next/.gitignore

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# next.js
12+
/.next/
13+
/out/
14+
15+
# production
16+
/build
17+
18+
# misc
19+
.DS_Store
20+
21+
# debug
22+
npm-debug.log*
23+
yarn-debug.log*
24+
yarn-error.log*
25+
26+
# local env files
27+
.env.local
28+
.env.development.local
29+
.env.test.local
30+
.env.production.local

demo-app-next/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a starter template for [Learn Next.js](https://nextjs.org/learn).

demo-app-next/next-env.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// <reference types="next" />
2+
/// <reference types="next/image-types/global" />
3+
4+
// NOTE: This file should not be edited
5+
// see https://nextjs.org/docs/basic-features/typescript for more information.

demo-app-next/package.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"private": true,
3+
"scripts": {
4+
"dev": "next dev",
5+
"build": "next build",
6+
"start": "next start"
7+
},
8+
"dependencies": {
9+
"next": "latest",
10+
"react": "18.2.0",
11+
"react-dom": "18.2.0"
12+
},
13+
"devDependencies": {
14+
"@types/node": "18.15.0",
15+
"@types/react": "18.0.28",
16+
"typescript": "4.9.5"
17+
}
18+
}

demo-app-next/public/favicon.ico

14.7 KB
Binary file not shown.

demo-app-next/public/vercel.svg

Lines changed: 4 additions & 0 deletions
Loading
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/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;

demo-app-next/src/components/Box.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { BoardText } from "../types/types";
2+
3+
type BoxProps = {
4+
value: BoardText;
5+
row: number;
6+
column: number;
7+
handleBoxClick: (row: number, column: number) => void;
8+
};
9+
10+
const Box = (props: BoxProps) => {
11+
return (
12+
<button
13+
className="box"
14+
onClick={(e) => props.handleBoxClick(props.row, props.column)}
15+
>
16+
{props.value}
17+
</button>
18+
);
19+
};
20+
21+
export default Box;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import Increment from "./Increment";
2+
3+
export default function Buttons() {
4+
const buttons = [];
5+
for (let i = 0; i < 4; i++) {
6+
buttons.push(<Increment />);
7+
}
8+
9+
return (
10+
<div className="buttons">
11+
<h1>Stateful Buttons</h1>
12+
<h4>
13+
These buttons are functional components that each manage their own state
14+
with the useState hook.
15+
</h4>
16+
{buttons}
17+
</div>
18+
);
19+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React, { useState } from "react";
2+
3+
export default 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+
}

0 commit comments

Comments
 (0)