Run prettier
This commit is contained in:
parent
f417229526
commit
6ec72dd643
|
@ -2,3 +2,5 @@
|
|||
node_modules
|
||||
# don't lint build output (make sure it's set to your correct build folder name)
|
||||
dist
|
||||
# Ignore eslintrc
|
||||
.eslintrc.js
|
||||
|
|
11
.eslintrc.js
11
.eslintrc.js
|
@ -1,11 +1,6 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
],
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint"],
|
||||
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||
};
|
||||
|
|
|
@ -42,10 +42,10 @@ body {
|
|||
}
|
||||
|
||||
.chess-board tr:nth-child(2n) td.icon-cell:nth-child(2n),
|
||||
.chess-board tr:nth-child(2n+1) td.icon-cell:nth-child(2n+1) {
|
||||
.chess-board tr:nth-child(2n + 1) td.icon-cell:nth-child(2n + 1) {
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
.chess-board tr:nth-child(2n+1) td.icon-cell:nth-child(2n),
|
||||
.chess-board tr:nth-child(2n) td.icon-cell:nth-child(2n+1) {
|
||||
.chess-board tr:nth-child(2n + 1) td.icon-cell:nth-child(2n),
|
||||
.chess-board tr:nth-child(2n) td.icon-cell:nth-child(2n + 1) {
|
||||
background-color: #c49d9d;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
test('it works', () => {
|
||||
test("it works", () => {
|
||||
expect(2 + 2).toEqual(4);
|
||||
})
|
||||
});
|
||||
|
||||
export { }
|
||||
export {};
|
||||
|
|
29
src/App.tsx
29
src/App.tsx
|
@ -1,9 +1,9 @@
|
|||
import Board, { BoardState } from "./Board";
|
||||
import './App.css';
|
||||
import "./App.css";
|
||||
|
||||
const App = (): JSX.Element => {
|
||||
const boardState: BoardState = {
|
||||
"a": {
|
||||
a: {
|
||||
1: {
|
||||
kind: "king",
|
||||
color: "white",
|
||||
|
@ -11,9 +11,9 @@ const App = (): JSX.Element => {
|
|||
2: {
|
||||
kind: "pawn",
|
||||
color: "white",
|
||||
}
|
||||
},
|
||||
},
|
||||
"b": {
|
||||
b: {
|
||||
1: {
|
||||
kind: "rook",
|
||||
color: "white",
|
||||
|
@ -21,27 +21,32 @@ const App = (): JSX.Element => {
|
|||
2: {
|
||||
kind: "pawn",
|
||||
color: "white",
|
||||
}
|
||||
},
|
||||
},
|
||||
"c": {
|
||||
c: {
|
||||
2: {
|
||||
kind: "pawn",
|
||||
color: "white",
|
||||
}
|
||||
},
|
||||
},
|
||||
"h": {
|
||||
h: {
|
||||
4: {
|
||||
kind: "pawn",
|
||||
color: "black",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<Board playerColor="white" boardState={boardState} onSelectPiece={() => Promise.resolve()} onMovePiece={() => Promise.resolve()} />
|
||||
<Board
|
||||
playerColor="white"
|
||||
boardState={boardState}
|
||||
onSelectPiece={() => Promise.resolve()}
|
||||
onMovePiece={() => Promise.resolve()}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
|
|
@ -8,20 +8,23 @@ type RANK = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
|||
type Coordinates = {
|
||||
rank: RANK;
|
||||
file: FILE;
|
||||
}
|
||||
};
|
||||
|
||||
type PieceState = {
|
||||
kind: PIECE;
|
||||
color: COLOR;
|
||||
}
|
||||
};
|
||||
|
||||
type Selected = {
|
||||
piece: PieceState,
|
||||
location: Coordinates,
|
||||
}
|
||||
piece: PieceState;
|
||||
location: Coordinates;
|
||||
};
|
||||
|
||||
type OnSelectPiece = (selected: Selected) => Promise<void>;
|
||||
type OnMovePiece = (selected: Selected, destination: Coordinates) => Promise<void>;
|
||||
type OnMovePiece = (
|
||||
selected: Selected,
|
||||
destination: Coordinates
|
||||
) => Promise<void>;
|
||||
type OnSelectDestination = (destination: Coordinates) => Promise<void>;
|
||||
|
||||
interface BoardProps {
|
||||
|
@ -36,34 +39,26 @@ interface CellProps {
|
|||
playerColor: COLOR;
|
||||
rank: RANK;
|
||||
file: FILE;
|
||||
selected: Selected | null,
|
||||
selected: Selected | null;
|
||||
onSelectPiece: OnSelectPiece;
|
||||
onSelectDestination: OnSelectDestination;
|
||||
}
|
||||
|
||||
type FileState = {
|
||||
[key in RANK]?: PieceState;
|
||||
}
|
||||
};
|
||||
|
||||
export type BoardState = {
|
||||
[key in FILE]?: FileState;
|
||||
}
|
||||
};
|
||||
|
||||
const RANKS: RANK[] = [
|
||||
1, 2, 3, 4, 5, 6, 7, 8,
|
||||
];
|
||||
const RANKS: RANK[] = [1, 2, 3, 4, 5, 6, 7, 8];
|
||||
|
||||
const FILES: FILE[] = [
|
||||
"a", "b", "c", "d", "e", "f", "g", "h",
|
||||
];
|
||||
const FILES: FILE[] = ["a", "b", "c", "d", "e", "f", "g", "h"];
|
||||
|
||||
const PIECES: PIECE[] = [
|
||||
"pawn", "rook", "knight", "bishop", "queen", "king"
|
||||
];
|
||||
const PIECES: PIECE[] = ["pawn", "rook", "knight", "bishop", "queen", "king"];
|
||||
|
||||
const COLORS: COLOR[] = [
|
||||
"white", "black"
|
||||
]
|
||||
const COLORS: COLOR[] = ["white", "black"];
|
||||
|
||||
const iconFor = ({ kind, color }: PieceState): string => {
|
||||
switch (kind) {
|
||||
|
@ -82,20 +77,28 @@ const iconFor = ({ kind, color }: PieceState): string => {
|
|||
}
|
||||
};
|
||||
|
||||
const Cell = ({ boardState, playerColor, rank, file, selected, onSelectDestination, onSelectPiece }: CellProps): JSX.Element => {
|
||||
const Cell = ({
|
||||
boardState,
|
||||
playerColor,
|
||||
rank,
|
||||
file,
|
||||
selected,
|
||||
onSelectDestination,
|
||||
onSelectPiece,
|
||||
}: CellProps): JSX.Element => {
|
||||
const filed = boardState[file];
|
||||
|
||||
const onEmptyClick = async () => {
|
||||
return await onSelectDestination({ rank, file });
|
||||
};
|
||||
|
||||
if (typeof (filed) === "undefined") {
|
||||
if (typeof filed === "undefined") {
|
||||
return <td className="icon-cell" onClick={onEmptyClick}></td>;
|
||||
}
|
||||
|
||||
const piece = filed[rank];
|
||||
|
||||
if (typeof (piece) === "undefined") {
|
||||
if (typeof piece === "undefined") {
|
||||
return <td className="icon-cell" onClick={onEmptyClick}></td>;
|
||||
}
|
||||
|
||||
|
@ -113,18 +116,28 @@ const Cell = ({ boardState, playerColor, rank, file, selected, onSelectDestinati
|
|||
|
||||
const maybeOnClick = piece.color === playerColor ? onClick : undefined;
|
||||
|
||||
const classNames = selected !== null
|
||||
&& selected.piece.kind === piece.kind
|
||||
&& selected.piece.color === piece.color
|
||||
&& selected.location.file === file
|
||||
&& selected.location.rank === rank
|
||||
? ["icon-cell", "selected"]
|
||||
: ["icon-cell"];
|
||||
const classNames =
|
||||
selected !== null &&
|
||||
selected.piece.kind === piece.kind &&
|
||||
selected.piece.color === piece.color &&
|
||||
selected.location.file === file &&
|
||||
selected.location.rank === rank
|
||||
? ["icon-cell", "selected"]
|
||||
: ["icon-cell"];
|
||||
|
||||
return <td className={classNames.join(" ")} onClick={maybeOnClick}><span className="icon">{iconFor(piece)}</span></td>;
|
||||
return (
|
||||
<td className={classNames.join(" ")} onClick={maybeOnClick}>
|
||||
<span className="icon">{iconFor(piece)}</span>
|
||||
</td>
|
||||
);
|
||||
};
|
||||
|
||||
const Board = ({ boardState, onMovePiece, onSelectPiece: superOnSelectPiece, playerColor }: BoardProps): JSX.Element => {
|
||||
const Board = ({
|
||||
boardState,
|
||||
onMovePiece,
|
||||
onSelectPiece: superOnSelectPiece,
|
||||
playerColor,
|
||||
}: BoardProps): JSX.Element => {
|
||||
const [selected, setSelected] = React.useState<Selected | null>(null);
|
||||
|
||||
const onSelectPiece: OnSelectPiece = async (selected) => {
|
||||
|
@ -133,7 +146,9 @@ const Board = ({ boardState, onMovePiece, onSelectPiece: superOnSelectPiece, pla
|
|||
return await superOnSelectPiece(selected);
|
||||
};
|
||||
|
||||
const onSelectDestination = async (destination: Coordinates): Promise<void> => {
|
||||
const onSelectDestination = async (
|
||||
destination: Coordinates
|
||||
): Promise<void> => {
|
||||
if (selected === null) {
|
||||
return;
|
||||
}
|
||||
|
@ -193,6 +208,4 @@ const Board = ({ boardState, onMovePiece, onSelectPiece: superOnSelectPiece, pla
|
|||
};
|
||||
|
||||
export default Board;
|
||||
export {
|
||||
PIECES, COLORS, FILES, RANKS,
|
||||
};
|
||||
export { PIECES, COLORS, FILES, RANKS };
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
||||
monospace;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import "./index.css";
|
||||
import App from "./App";
|
||||
import reportWebVitals from "./reportWebVitals";
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
document.getElementById("root")
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { ReportHandler } from 'web-vitals';
|
||||
import { ReportHandler } from "web-vitals";
|
||||
|
||||
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom';
|
||||
import "@testing-library/jest-dom";
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
import { validateBoardState } from './validate';
|
||||
import { validateBoardState } from "./validate";
|
||||
|
||||
test('validates valid states', () => {
|
||||
test("validates valid states", () => {
|
||||
const inputs = [
|
||||
{
|
||||
"a": {
|
||||
a: {
|
||||
3: {
|
||||
kind: "king",
|
||||
color: "black",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"b": {
|
||||
b: {
|
||||
5: {
|
||||
kind: "rook",
|
||||
color: "white",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"c": {
|
||||
c: {
|
||||
8: {
|
||||
kind: "bishop",
|
||||
color: "black",
|
||||
}
|
||||
},
|
||||
},
|
||||
"e": {
|
||||
e: {
|
||||
4: {
|
||||
kind: "pawn",
|
||||
color: "white",
|
||||
|
@ -37,9 +37,9 @@ test('validates valid states', () => {
|
|||
7: {
|
||||
kind: "queen",
|
||||
color: "black",
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
inputs.map((input) => {
|
||||
|
@ -49,32 +49,32 @@ test('validates valid states', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('does not validate invalid states', () => {
|
||||
test("does not validate invalid states", () => {
|
||||
const inputs = [
|
||||
{
|
||||
"j": {
|
||||
j: {
|
||||
3: {
|
||||
kind: "king",
|
||||
color: "black",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"b": {
|
||||
b: {
|
||||
9: {
|
||||
kind: "rook",
|
||||
color: "white",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"c": {
|
||||
c: {
|
||||
8: {
|
||||
kind: "bishop",
|
||||
color: "black",
|
||||
}
|
||||
},
|
||||
},
|
||||
"e": {
|
||||
e: {
|
||||
4: {
|
||||
kind: "pawn",
|
||||
color: "white",
|
||||
|
@ -86,9 +86,9 @@ test('does not validate invalid states', () => {
|
|||
7: {
|
||||
kind: "queen",
|
||||
color: "black",
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
inputs.map((input) => {
|
||||
|
|
|
@ -6,29 +6,29 @@ const FILES_AS_STRINGS: string[] = FILES.map((file) => file as string);
|
|||
const RANKS_AS_NUMBERS: number[] = RANKS.map((rank) => rank as number);
|
||||
|
||||
const validateBoardState = (input: unknown): BoardState | null => {
|
||||
if (typeof (input) !== "object" || Array.isArray(input) || input === null) {
|
||||
if (typeof input !== "object" || Array.isArray(input) || input === null) {
|
||||
console.error("Input is not keyed object");
|
||||
return null;
|
||||
}
|
||||
|
||||
const hasInvalidShape = Object.entries(input).some(([file, ranks]) => {
|
||||
if (typeof (file) !== "string") {
|
||||
if (typeof file !== "string") {
|
||||
console.error("file is not string");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!FILES_AS_STRINGS.includes(file)) {
|
||||
console.error("file is not included in valid files")
|
||||
console.error("file is not included in valid files");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof (ranks) !== "object" || Array.isArray(ranks) || ranks === null) {
|
||||
if (typeof ranks !== "object" || Array.isArray(ranks) || ranks === null) {
|
||||
console.error("ranks is not a keyed object");
|
||||
return true;
|
||||
}
|
||||
|
||||
return Object.entries(ranks).some(([rank, pieces]) => {
|
||||
if (typeof (rank) !== "string") {
|
||||
if (typeof rank !== "string") {
|
||||
console.error("rank is not a string");
|
||||
return true;
|
||||
}
|
||||
|
@ -38,26 +38,36 @@ const validateBoardState = (input: unknown): BoardState | null => {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (typeof (pieces) !== "object" || Array.isArray(pieces) || pieces === null) {
|
||||
if (
|
||||
typeof pieces !== "object" ||
|
||||
Array.isArray(pieces) ||
|
||||
pieces === null
|
||||
) {
|
||||
console.error("piece state is not a keyed object");
|
||||
return true;
|
||||
}
|
||||
|
||||
return Object.entries(pieces).some(([key, value]) => {
|
||||
if (typeof (key) !== "string") {
|
||||
if (typeof key !== "string") {
|
||||
console.error("piece key is not a string");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!["kind", "color"].includes(key)) {
|
||||
console.error("piece key is not included in valid keys")
|
||||
console.error("piece key is not included in valid keys");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key === "kind" && (typeof (value) !== "string" || !PIECES_AS_STRINGS.includes(value))) {
|
||||
if (
|
||||
key === "kind" &&
|
||||
(typeof value !== "string" || !PIECES_AS_STRINGS.includes(value))
|
||||
) {
|
||||
console.error("kind's value is not a string, or not a valid piece");
|
||||
return true;
|
||||
} else if (key === "color" && (typeof (value) !== "string" || !COLORS_AS_STRINGS.includes(value))) {
|
||||
} else if (
|
||||
key === "color" &&
|
||||
(typeof value !== "string" || !COLORS_AS_STRINGS.includes(value))
|
||||
) {
|
||||
console.error("colors' value is not a string, or not a valid color");
|
||||
return true;
|
||||
}
|
||||
|
@ -73,7 +83,5 @@ const validateBoardState = (input: unknown): BoardState | null => {
|
|||
|
||||
return input as BoardState;
|
||||
};
|
||||
|
||||
export {
|
||||
validateBoardState,
|
||||
};
|
||||
|
||||
export { validateBoardState };
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
|
@ -20,7 +16,5 @@
|
|||
"noEmit": true,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue