Skip to content

Commit

Permalink
refactor: refactor components
Browse files Browse the repository at this point in the history
  • Loading branch information
phatnguyenuit committed Feb 12, 2021
1 parent 0c191b3 commit 2486746
Show file tree
Hide file tree
Showing 16 changed files with 411 additions and 213 deletions.
2 changes: 2 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
REACT_APP_CRYPTO_KEY=example
REACT_APP_CRYPTO_SECRET=example
5 changes: 5 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# TODO

- [ ] Responsive
- [ ] Unit test
- [ ] i18n
16 changes: 16 additions & 0 deletions public/images/sync.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 8 additions & 46 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,54 +24,16 @@
right: 0;
}

.amount {
position: absolute;
top: 0;
right: 10%;
font-weight: bold;
font-size: 200%;
color: #ff9800;
}

.game-plate {
display: grid;
gap: 16px;
grid-template-columns: repeat(3, 100px);
margin: 0 auto 8px;
width: fit-content;
}

.play-button {
.amount-section {
align-items: center;
border: none;
color: #ff9800;
display: flex;
height: 100px;
justify-content: center;
margin: 0 auto;
outline: none;
padding: 8px;
width: 100px;
border: 5px solid #ff9800;
border-radius: 50%;
background-color: #ffffff;
}

.play-button:hover {
opacity: 0.8;
}

.play-button:disabled {
cursor: not-allowed;
pointer-events: none;
}

.game-plate>.play-button {
grid-column: 1 / span 3;
}

.plate-item {
position: relative;
padding-top: 100%;
font-size: 200%;
font-weight: bold;
gap: 16px;
position: absolute;
right: 10%;
top: 0;
}

.game-grid {
Expand Down
53 changes: 17 additions & 36 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,35 @@
import { images, useRollDices, ImageName } from './utils';
import NewGameButton from './components/new-game-button';
import DicePlate from './components/dice-plate';
import useDiceGame from './hooks/useDiceGame';
import { diceImages, DiceName } from './constants';
import { formatThousand } from './utils';

import './App.css';

function App() {
const {
amount,
betState,
names,
rolling,
needToShowResult,
betState,
amount,
handleRoll,
rolling,
handleBet,
handleResetBet,
} = useRollDices();
handleRoll,
startNewSession,
} = useDiceGame();

return (
<div data-testid="App" className="App">
<div className="side-section left-side">Happy new year 2021</div>
<div className="side-section right-side">Happy new year 2021</div>
<div className="amount">
<span>${amount}</span>
</div>
<div className="game-plate">
{names.map((name, index) => (
<div key={`${name}-${index}`} className="plate-item">
<div className="content">
<img
width={64}
height="auto"
src={images[name]}
alt={`rolled-${name}`}
/>
</div>
</div>
))}
<button
type="button"
className={`play-button`}
disabled={rolling}
onClick={handleRoll}
>
<img
width={64}
height="auto"
src="/images/dice.svg"
alt="play-icon"
/>
</button>
<div className="amount-section">
<span>${formatThousand(amount)}</span>
<NewGameButton onClick={startNewSession} />
</div>
<DicePlate disabled={rolling} items={names} onStart={handleRoll} />
<div className="game-grid">
{(Object.entries(images) as Array<[ImageName, string]>).map(
{(Object.entries(diceImages) as Array<[DiceName, string]>).map(
([name, src]) => {
const betted = betState[name] > 0;
return (
Expand Down
43 changes: 43 additions & 0 deletions src/components/dice-plate/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { memo } from 'react';
import { diceImages, DiceName } from '../../constants';
import classes from './styles.module.css';

export const DicePlateComponent: React.FC<DicePlateProps> = ({
items,
disabled,
onStart,
}) => (
<div className={classes.root}>
{items.map((item, index) => (
<div key={`${item}-${index}`} className={classes.item}>
<div className={classes.content}>
<img
width={64}
height="auto"
src={diceImages[item]}
alt={`rolled-${item}`}
/>
</div>
</div>
))}
<button
type="button"
className={classes['play-button']}
disabled={disabled}
onClick={onStart}
>
<img width={64} height="auto" src="/images/dice.svg" alt="play-icon" />
</button>
</div>
);

const DicePlate = memo(DicePlateComponent);
DicePlate.displayName = 'DicePlate';

export default DicePlate;

export interface DicePlateProps {
disabled: boolean;
items: DiceName[];
onStart: React.MouseEventHandler<any>;
}
52 changes: 52 additions & 0 deletions src/components/dice-plate/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.root {
display: grid;
gap: 16px;
grid-template-columns: repeat(3, 100px);
margin: 0 auto 8px;
width: fit-content;
}

.item {
position: relative;
padding-top: 100%;
}

.content {
align-items: center;
background-color: transparent;
border-radius: 8px;
border: 5px solid #ff9800;
bottom: 0;
display: flex;
justify-content: center;
left: 0;
padding: 8px 16px;
position: absolute;
right: 0;
top: 0;
}

.play-button {
align-items: center;
border: none;
display: flex;
height: 100px;
justify-content: center;
margin: 0 auto;
outline: none;
padding: 8px;
width: 100px;
border: 5px solid #ff9800;
border-radius: 50%;
background-color: #ffffff;
grid-column: 1 / span 3;
}

.play-button:hover {
opacity: 0.8;
}

.play-button:disabled {
cursor: not-allowed;
pointer-events: none;
}
20 changes: 20 additions & 0 deletions src/components/new-game-button/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { memo } from 'react';

import classes from './styles.module.css';

export const NewGameButtonComponent: React.FC<NewGameButtonProps> = ({
onClick,
}) => (
<button title="New game" className={classes.root} onClick={onClick}>
<img width={24} height="auto" src="/images/sync.svg" alt="new-game-icon" />
</button>
);

const NewGameButton = memo(NewGameButtonComponent);
NewGameButton.displayName = 'NewGameButton';

export default NewGameButton;

export interface NewGameButtonProps {
onClick: React.EventHandler<any>;
}
11 changes: 11 additions & 0 deletions src/components/new-game-button/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.root {
background-color: transparent;
border: none;
cursor: pointer;
outline: none;
padding: 4px;
}

.root:hover {
opacity: 0.7;
}
18 changes: 18 additions & 0 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const CRYPTO_KEY = process.env.REACT_APP_CRYPTO_KEY;
export const CRYPTO_SECRET = process.env.REACT_APP_CRYPTO_SECRET;

export const diceNames = [
'deer',
'calabash',
'rooster',
'fish',
'crab',
'shrimp',
] as const;

export type DiceName = typeof diceNames[number];

export const diceImages = diceNames.reduce(
(prev, name) => ({ ...prev, [name]: `/images/${name}.svg` }),
{},
) as Record<DiceName, string>;
Loading

1 comment on commit 2486746

@vercel
Copy link

@vercel vercel bot commented on 2486746 Feb 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.