components: move state up to App, prepare for new comp

This commit is contained in:
Artur Tamborski 2020-12-27 21:30:38 +01:00
parent db77874786
commit 1dc334f41b
3 changed files with 82 additions and 64 deletions

View File

@ -5,22 +5,64 @@ import Board from '../Board/Board';
import './App.scss'; import './App.scss';
export default function App(): JSX.Element { export type Point = {
return ( x: number;
<div className="App"> y: number;
<div /> }
<div>
<Logo /> export type Bar = {
start: Point;
end: Point;
}
export type Solution = {
bar: Bar;
answer: string;
}
type Game = {
title: string;
description: string;
catchword: string;
cells: Array<Array<string>>;
solutions: Array<Solution>;
}
export default class App extends React.Component {
private game: Game;
private readonly answers: Array<JSX.Element>;
constructor(props: object) {
super(props);
this.game = require(`../../constants/1.json`)
this.answers = this.game.solutions.map(s => s.answer).map(k => <p>{k}</p>);
}
render() {
return (
<div className="App">
<div />
<div> <div>
controls: 1231414214 <Logo />
<div>
<p>{this.game.title}</p>
<p>{this.game.description}</p>
</div>
</div>
<div />
<div />
<div>
<Board
cells={this.game.cells}
solutions={this.game.solutions}
cellSize={60}
/>
</div>
<div style={{paddingLeft: '30px'}}>
{this.answers}
</div> </div>
</div> </div>
<div /> );
<div /> }
<div>
<Board numBoard={1}/>
</div>
<div />
</div>
);
} }

View File

@ -1,66 +1,44 @@
import React from 'react'; import React from 'react';
import Line from '../Line/Line'; import Line from '../Line/Line';
import {Point, Bar, Solution} from "../App/App";
import './Board.scss'; import './Board.scss';
type Point = { type Answer = {
x: number;
y: number;
}
export type Bar = {
start: Point,
end: Point,
}
type Solution = {
bar: Bar; bar: Bar;
key: string;
}
type Selection = {
bar: Bar,
isVisible: boolean;
isCorrect: boolean; isCorrect: boolean;
} }
interface IBoardProps { interface IBoardProps {
numBoard: number; cells: Array<Array<string>>;
solutions: Array<Solution>;
cellSize: number;
} }
interface IBoardState { interface IBoardState {
score: number; score: number;
wasValid: boolean; wasValidAnswer: boolean;
wasSelecting: boolean; wasSelecting: boolean;
selections: Array<Selection>; selections: Array<Answer>;
bar: Bar; bar: Bar;
} }
export default class Board extends React.Component<IBoardProps, IBoardState> { export default class Board extends React.Component<IBoardProps, IBoardState> {
private readonly cells: Array<Array<string>>;
private readonly solutions: Array<Solution>;
private readonly cellSize: number;
constructor(props: IBoardProps) { constructor(props: IBoardProps) {
super(props); super(props);
const crosski: any = require(`../../constants/${props.numBoard}.json`) const selections = [...new Array(props.solutions.length)].map(() =>
this.cells = crosski.cells;
this.solutions = crosski.solutions;
this.cellSize = 60;
const selections = [...new Array(this.solutions.length)].map(() =>
Object.assign({}, { Object.assign({}, {
bar: {start: {x: 0, y: 0}, end: {x: 0, y: 0}}, bar: {start: {x: 0, y: 0}, end: {x: 0, y: 0}},
isCorrect: false, isCorrect: false,
isVisible: true,
})); }));
this.state = { this.state = {
score: 0, score: 0,
selections, selections,
wasValid: false, wasValidAnswer: false,
wasSelecting: false, wasSelecting: false,
bar: {start: {x: 0, y: 0}, end: {x: 0, y: 0}}, bar: {start: {x: 0, y: 0}, end: {x: 0, y: 0}},
} }
@ -74,7 +52,7 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
const [parse, str] = [JSON.parse, JSON.stringify]; const [parse, str] = [JSON.parse, JSON.stringify];
let score = this.state.score; let score = this.state.score;
const selections: Array<Selection> = parse(str(this.state.selections)); const selections: Array<Answer> = parse(str(this.state.selections));
const s = selections.find(v => !v.isCorrect); const s = selections.find(v => !v.isCorrect);
// skip if there are no lines left or the mouse is moving but not selecting // skip if there are no lines left or the mouse is moving but not selecting
@ -86,32 +64,33 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
const isValidMove = x === 0 || y === 0 || x === y; const isValidMove = x === 0 || y === 0 || x === y;
const isMouseDown = isSelecting && !this.state.wasSelecting; const isMouseDown = isSelecting && !this.state.wasSelecting;
const isMouseUp = !isSelecting && this.state.wasSelecting && isValidMove; const isMouseUp = !isSelecting && this.state.wasSelecting && isValidMove;
const isValidSolution = this.solutions.some(v => str(v.bar) === str(s.bar));
const wasAlreadySelected = this.state.selections.some(v => str(v.bar) === str(s.bar));
const isValid = isValidSolution && !wasAlreadySelected;
const start: Point = isMouseDown ? pos : this.state.bar.start; const start: Point = isMouseDown ? pos : this.state.bar.start;
const bar: Bar = {start, end: pos}; const bar: Bar = {start, end: pos};
if (isValidMove) if (isValidMove)
s.bar = bar; s.bar = bar;
if (isMouseUp && this.state.wasValid) if (isMouseUp && this.state.wasValidAnswer)
[s.isCorrect, score] = [true, score + 1]; [s.isCorrect, score] = [true, score + 1];
const isValidSolution = this.props.solutions.some(v => str(v.bar) === str(s.bar));
const wasAlreadySelected = this.state.selections.some(v => str(v.bar) === str(s.bar));
const isValidAnswer = isValidSolution && !wasAlreadySelected;
this.setState({ this.setState({
...this.state, ...this.state,
score, bar, selections, score, bar, selections,
wasValid: isValid, wasValidAnswer: isValidAnswer,
wasSelecting: isSelecting wasSelecting: isSelecting,
}); });
if (score === this.solutions.length) if (score === this.props.solutions.length)
this.gameOver(); this.gameOver();
} }
renderCell(s: string, pos: Point): JSX.Element { renderCell(s: string, pos: Point): JSX.Element {
const size = `${this.cellSize}px`; const size = `${this.props.cellSize}px`;
const padding = `${this.cellSize / 4}px`; const padding = `${this.props.cellSize / 4}px`;
return ( return (
<button <button
@ -127,28 +106,27 @@ export default class Board extends React.Component<IBoardProps, IBoardState> {
); );
} }
renderLine(s: Selection, n: number): JSX.Element { renderLine(s: Answer, n: number): JSX.Element {
return ( return (
<Line <Line
key={`Line${n}`} key={`Line${n}`}
bar={s.bar} bar={s.bar}
isVisible={s.isVisible}
isCorrect={s.isCorrect} isCorrect={s.isCorrect}
cellSize={this.cellSize} cellSize={this.props.cellSize}
/> />
); );
} }
render(): JSX.Element { render(): JSX.Element {
let cells = let cells =
this.cells.map((oy, y) => this.props.cells.map((oy, y) =>
oy.map((s, x) => oy.map((s, x) =>
this.renderCell(s, {x, y}))); this.renderCell(s, {x, y})));
let lines = this.state.selections.map((s, n) => let lines = this.state.selections.map((s, n) =>
this.renderLine(s, n)); this.renderLine(s, n));
const gridTemplateColumns = `repeat(${this.cells.length}, ${this.cellSize}px)`; const gridTemplateColumns = `repeat(${this.props.cells.length}, ${this.props.cellSize}px)`;
return ( return (
<div className="Container"> <div className="Container">

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import {Bar} from '../Board/Board' import {Bar} from '../App/App'
import './Line.scss'; import './Line.scss';
@ -19,7 +19,6 @@ enum Dir {
interface ILineProps { interface ILineProps {
bar: Bar; bar: Bar;
cellSize: number; cellSize: number;
isVisible: boolean;
isCorrect: boolean; isCorrect: boolean;
} }
@ -51,7 +50,6 @@ export default function Line(props: ILineProps): JSX.Element {
return ( return (
<rect <rect
className={props.isCorrect ? 'CorrectLine' : 'Line'} className={props.isCorrect ? 'CorrectLine' : 'Line'}
visibility={props.isVisible ? 'visible' : 'hidden'}
transform={`rotate(${r}, ${x}, ${y})`} transform={`rotate(${r}, ${x}, ${y})`}
{...{x, y, width: w, height: h, rx: m4, ry: m4}} {...{x, y, width: w, height: h, rx: m4, ry: m4}}
/> />