diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..963354f
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,3 @@
+{
+ "printWidth": 120
+}
diff --git a/package.json b/package.json
index 4667c95..9f6b8da 100644
--- a/package.json
+++ b/package.json
@@ -12,9 +12,12 @@
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@types/react-redux": "^7.1.7",
+ "axios": "^0.21.1",
+ "classnames": "^2.2.6",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.0",
+ "react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"typescript": "~3.8.2"
},
@@ -38,5 +41,9 @@
"last 1 firefox version",
"last 1 safari version"
]
+ },
+ "devDependencies": {
+ "@types/classnames": "^2.2.11",
+ "@types/react-router-dom": "^5.1.7"
}
}
diff --git a/src/App.css b/src/App.css
deleted file mode 100644
index 355c49b..0000000
--- a/src/App.css
+++ /dev/null
@@ -1,39 +0,0 @@
-.App {
- text-align: center;
-}
-
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-float infinite 3s ease-in-out;
- }
-}
-
-.App-header {
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
-}
-
-.App-link {
- color: rgb(112, 76, 182);
-}
-
-@keyframes App-logo-float {
- 0% {
- transform: translateY(0);
- }
- 50% {
- transform: translateY(10px)
- }
- 100% {
- transform: translateY(0px)
- }
-}
diff --git a/src/App.test.tsx b/src/App.test.tsx
deleted file mode 100644
index 27f1965..0000000
--- a/src/App.test.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react';
-import { render } from '@testing-library/react';
-import { Provider } from 'react-redux';
-import { store } from './app/store';
-import App from './App';
-
-test('renders learn react link', () => {
- const { getByText } = render(
-
-
-
- );
-
- expect(getByText(/learn/i)).toBeInTheDocument();
-});
diff --git a/src/App.tsx b/src/App.tsx
deleted file mode 100644
index 2dc188f..0000000
--- a/src/App.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import React from 'react';
-import logo from './logo.svg';
-import { Counter } from './features/counter/Counter';
-import './App.css';
-
-function App() {
- return (
-
- );
-}
-
-export default App;
diff --git a/src/app/App.css b/src/app/App.css
new file mode 100644
index 0000000..2877950
--- /dev/null
+++ b/src/app/App.css
@@ -0,0 +1,9 @@
+.app {
+ min-height: 100vh;
+ /* Why did I put linear gradient? Because every bg I found looks like sh*t */
+ background-image: linear-gradient(217deg, rgba(255, 0, 0, 0.6), rgba(255, 0, 0, 0) 70.71%),
+ linear-gradient(127deg, rgba(0, 255, 0, 0.6), rgba(0, 255, 0, 0) 70.71%),
+ linear-gradient(336deg, rgba(0, 0, 255, 0.6), rgba(0, 0, 255, 0) 70.71%),
+ url("assets/bigstock-poker-table-background-26587844-2-1.jpg");
+ background-size: cover;
+}
diff --git a/src/app/App.test.tsx b/src/app/App.test.tsx
new file mode 100644
index 0000000..c55e803
--- /dev/null
+++ b/src/app/App.test.tsx
@@ -0,0 +1,15 @@
+import React from "react";
+import { render } from "@testing-library/react";
+import { Provider } from "react-redux";
+import { store } from "./store";
+import App from "./App";
+
+test("renders learn react link", () => {
+ const { getByText } = render(
+
+
+
+ );
+
+ expect(getByText(/learn/i)).toBeInTheDocument();
+});
diff --git a/src/app/App.tsx b/src/app/App.tsx
new file mode 100644
index 0000000..2bdbce5
--- /dev/null
+++ b/src/app/App.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+
+function App() {
+ return (
+
+
+
+ );
+}
+
+export default App;
diff --git a/src/app/store.ts b/src/app/store.ts
index 078cca0..2a5b012 100644
--- a/src/app/store.ts
+++ b/src/app/store.ts
@@ -1,16 +1,8 @@
-import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
-import counterReducer from '../features/counter/counterSlice';
+import { configureStore, ThunkAction, Action } from "@reduxjs/toolkit";
export const store = configureStore({
- reducer: {
- counter: counterReducer,
- },
+ reducer: {},
});
export type RootState = ReturnType;
-export type AppThunk = ThunkAction<
- ReturnType,
- RootState,
- unknown,
- Action
->;
+export type AppThunk = ThunkAction>;
diff --git a/src/assets/1.jpg b/src/assets/1.jpg
new file mode 100644
index 0000000..ce85d0e
Binary files /dev/null and b/src/assets/1.jpg differ
diff --git a/src/assets/7f89c1ae58a1fb6a01e026367807a87b.jpg b/src/assets/7f89c1ae58a1fb6a01e026367807a87b.jpg
new file mode 100644
index 0000000..574cd89
Binary files /dev/null and b/src/assets/7f89c1ae58a1fb6a01e026367807a87b.jpg differ
diff --git a/src/assets/bigstock-poker-table-background-26587844-2-1.jpg b/src/assets/bigstock-poker-table-background-26587844-2-1.jpg
new file mode 100644
index 0000000..59e71eb
Binary files /dev/null and b/src/assets/bigstock-poker-table-background-26587844-2-1.jpg differ
diff --git a/src/assets/istockphoto-96655837-612x612.jpg b/src/assets/istockphoto-96655837-612x612.jpg
new file mode 100644
index 0000000..191402f
Binary files /dev/null and b/src/assets/istockphoto-96655837-612x612.jpg differ
diff --git a/src/assets/poker-table-background-green-color_47243-1094.jpg b/src/assets/poker-table-background-green-color_47243-1094.jpg
new file mode 100644
index 0000000..a78c5ca
Binary files /dev/null and b/src/assets/poker-table-background-green-color_47243-1094.jpg differ
diff --git a/src/features/Board/Board.module.css b/src/features/Board/Board.module.css
new file mode 100644
index 0000000..128f807
--- /dev/null
+++ b/src/features/Board/Board.module.css
@@ -0,0 +1,80 @@
+.board {
+ display: grid;
+ align-items: center;
+ min-height: 100vh;
+ max-width: 1440px;
+ margin-left: auto;
+ margin-right: auto;
+ animation: fadeIn 1s forwards;
+}
+
+/* Last child is discard pile. - this is the moment where I started hating css modules */
+.board > :last-child {
+ place-self: center;
+}
+
+.threePlayer > :last-child {
+ grid-row: 1;
+ grid-column: 2;
+}
+
+.twoPlayer {
+ grid-template-rows: repeat(3, 1fr);
+ justify-content: center;
+}
+
+.twoPlayer :nth-child(1) {
+ grid-row: 3;
+}
+
+.threePlayer {
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: repeat(2, 1fr);
+}
+
+.threePlayer :nth-child(1) {
+ grid-row: 2;
+ grid-column: 2;
+}
+
+.threePlayer :nth-child(3) {
+ grid-column: 3;
+}
+
+.fourPlayer {
+ grid-template-columns: 1fr 2fr 1fr;
+ grid-template-rows: 1fr 2fr 1fr;
+}
+
+.fourPlayer :nth-child(1) {
+ grid-column: 2;
+ grid-row: 3;
+}
+
+.fourPlayer :nth-child(2) {
+ grid-row: 2;
+}
+
+.fourPlayer :nth-child(3) {
+ grid-column: 2;
+}
+
+.fourPlayer :nth-child(4) {
+ grid-column: 3;
+ grid-row: 2;
+}
+
+.fourPlayer > :last-child {
+ grid-column: 2;
+ grid-row: 2;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
diff --git a/src/features/Board/Board.tsx b/src/features/Board/Board.tsx
new file mode 100644
index 0000000..493056b
--- /dev/null
+++ b/src/features/Board/Board.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+import styles from "./Board.module.css";
+
+export function Board({ playerCount, children }: React.PropsWithChildren<{ playerCount: number }>) {
+ const getBoardVariant = (variant: string) => {children}
;
+ switch (playerCount) {
+ case 2:
+ return getBoardVariant(styles.twoPlayer);
+ case 3:
+ return getBoardVariant(styles.threePlayer);
+ case 4:
+ return getBoardVariant(styles.fourPlayer);
+ default:
+ throw new Error("Invalid number of players");
+ }
+}
diff --git a/src/features/counter/Counter.module.css b/src/features/counter/Counter.module.css
deleted file mode 100644
index 6c2b58f..0000000
--- a/src/features/counter/Counter.module.css
+++ /dev/null
@@ -1,74 +0,0 @@
-.row {
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.row:not(:last-child) {
- margin-bottom: 16px;
-}
-
-.value {
- font-size: 78px;
- padding-left: 16px;
- padding-right: 16px;
- margin-top: 2px;
- font-family: 'Courier New', Courier, monospace;
-}
-
-.button {
- appearance: none;
- background: none;
- font-size: 32px;
- padding-left: 12px;
- padding-right: 12px;
- outline: none;
- border: 2px solid transparent;
- color: rgb(112, 76, 182);
- padding-bottom: 4px;
- cursor: pointer;
- background-color: rgba(112, 76, 182, 0.1);
- border-radius: 2px;
- transition: all 0.15s;
-}
-
-.textbox {
- font-size: 32px;
- padding: 2px;
- width: 64px;
- text-align: center;
- margin-right: 8px;
-}
-
-.button:hover, .button:focus {
- border: 2px solid rgba(112, 76, 182, 0.4);
-}
-
-.button:active {
- background-color: rgba(112, 76, 182, 0.2);
-}
-
-.asyncButton {
- composes: button;
- position: relative;
- margin-left: 8px;
-}
-
-.asyncButton:after {
- content: "";
- background-color: rgba(112, 76, 182, 0.15);
- display: block;
- position: absolute;
- width: 100%;
- height: 100%;
- left: 0;
- top: 0;
- opacity: 0;
- transition: width 1s linear, opacity 0.5s ease 1s;
-}
-
-.asyncButton:active:after {
- width: 0%;
- opacity: 1;
- transition: 0s
-}
diff --git a/src/features/counter/Counter.tsx b/src/features/counter/Counter.tsx
deleted file mode 100644
index 2ca6ed0..0000000
--- a/src/features/counter/Counter.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import React, { useState } from 'react';
-import { useSelector, useDispatch } from 'react-redux';
-import {
- decrement,
- increment,
- incrementByAmount,
- incrementAsync,
- selectCount,
-} from './counterSlice';
-import styles from './Counter.module.css';
-
-export function Counter() {
- const count = useSelector(selectCount);
- const dispatch = useDispatch();
- const [incrementAmount, setIncrementAmount] = useState('2');
-
- return (
-
-
-
- {count}
-
-
-
- setIncrementAmount(e.target.value)}
- />
-
-
-
-
- );
-}
diff --git a/src/features/counter/counterSlice.ts b/src/features/counter/counterSlice.ts
deleted file mode 100644
index f9ee20a..0000000
--- a/src/features/counter/counterSlice.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import { createSlice, PayloadAction } from '@reduxjs/toolkit';
-import { AppThunk, RootState } from '../../app/store';
-
-interface CounterState {
- value: number;
-}
-
-const initialState: CounterState = {
- value: 0,
-};
-
-export const counterSlice = createSlice({
- name: 'counter',
- initialState,
- reducers: {
- increment: state => {
- // Redux Toolkit allows us to write "mutating" logic in reducers. It
- // doesn't actually mutate the state because it uses the Immer library,
- // which detects changes to a "draft state" and produces a brand new
- // immutable state based off those changes
- state.value += 1;
- },
- decrement: state => {
- state.value -= 1;
- },
- // Use the PayloadAction type to declare the contents of `action.payload`
- incrementByAmount: (state, action: PayloadAction) => {
- state.value += action.payload;
- },
- },
-});
-
-export const { increment, decrement, incrementByAmount } = counterSlice.actions;
-
-// The function below is called a thunk and allows us to perform async logic. It
-// can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This
-// will call the thunk with the `dispatch` function as the first argument. Async
-// code can then be executed and other actions can be dispatched
-export const incrementAsync = (amount: number): AppThunk => dispatch => {
- setTimeout(() => {
- dispatch(incrementByAmount(amount));
- }, 1000);
-};
-
-// The function below is called a selector and allows us to select a value from
-// the state. Selectors can also be defined inline where they're used instead of
-// in the slice file. For example: `useSelector((state: RootState) => state.counter.value)`
-export const selectCount = (state: RootState) => state.counter.value;
-
-export default counterSlice.reducer;
diff --git a/src/index.css b/src/index.css
index bd5bd6d..d50bafc 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,13 +1,93 @@
body {
margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
+ 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',
- monospace;
+ font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+
+html {
+ box-sizing: border-box;
+ font-size: 16px;
+}
+
+*,
+*:before,
+*:after {
+ box-sizing: inherit;
+}
+
+body,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+ol,
+ul {
+ margin: 0;
+ padding: 0;
+ font-weight: normal;
+}
+
+ol,
+ul {
+ list-style: none;
+}
+
+img {
+ max-width: 100%;
+ height: auto;
+}
+
+button {
+ padding: 0;
+ border: none;
+ background-color: transparent;
+}
+
+code {
+ font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+
+.text-error {
+ font-size: 18px;
+ color: #ff3333;
+}
+
+.text-gold {
+ color: #ffd700;
+}
+
+.text-white {
+ color: #ffffff;
+}
+
+.text-info {
+ color: #17a2b8;
+ font-weight: bold;
+ text-shadow: 2px 2px 5px #000000;
+}
+
+.text-center {
+ text-align: center;
+}
+
+.py-2 {
+ padding-top: 8px;
+ padding-bottom: 8px;
+}
+
+.pb-2 {
+ padding-bottom: 8px;
+}
+
+.flex {
+ display: flex;
}
diff --git a/src/index.tsx b/src/index.tsx
index ca43bac..879b42c 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
-import App from './App';
+import App from './app/App';
import { store } from './app/store';
import { Provider } from 'react-redux';
import * as serviceWorker from './serviceWorker';
diff --git a/src/logo.svg b/src/logo.svg
deleted file mode 100644
index 9e96334..0000000
--- a/src/logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tsconfig.json b/tsconfig.json
index 7b1d3c6..bf09654 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -18,9 +18,10 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
- "jsx": "react"
+ "jsx": "react",
+ "baseUrl": "src"
},
"include": [
"src"
]
-}
+}
\ No newline at end of file