✨ Integrated Home comp with the game comp
This commit is contained in:
+30
-25
@@ -7,7 +7,8 @@ import { useState } from 'react';
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------- Context -------------------------------------------------------
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { gameStateAtom } from './contexts/gameState';
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------- Components ------------------------------------------------------
|
||||
@@ -28,32 +29,36 @@ import LeaderBoard from './components/Leaderboard/leaderboard';
|
||||
const App = () => {
|
||||
const [helpDisplayed, displayHelp] = useState(false);
|
||||
|
||||
const [gameState] = useRecoilState(gameStateAtom);
|
||||
|
||||
return (
|
||||
<div className='App'>
|
||||
{/* <RecoilRoot>
|
||||
<div className='stats'>
|
||||
<Timer />
|
||||
<Logo className={'logo'} />
|
||||
<MinesCounter />
|
||||
</div>
|
||||
<Grid />
|
||||
<button
|
||||
className='helpButton'
|
||||
onClick={() => displayHelp(true)}
|
||||
>
|
||||
<Question />
|
||||
<span>Comment jouer</span>
|
||||
</button>
|
||||
</RecoilRoot>
|
||||
{helpDisplayed && (
|
||||
<Help
|
||||
onClose={() => {
|
||||
displayHelp(false);
|
||||
}}
|
||||
/>
|
||||
)} */}
|
||||
<Home />
|
||||
{/* <LeaderBoard /> */}
|
||||
{gameState.status === 'settings' && <Home />}
|
||||
{(gameState.status === 'idle' || gameState.status === 'playing') && (
|
||||
<>
|
||||
<div className='stats'>
|
||||
<Timer />
|
||||
<Logo className={'logo'} />
|
||||
<MinesCounter />
|
||||
</div>
|
||||
<Grid />
|
||||
<button
|
||||
className='helpButton'
|
||||
onClick={() => displayHelp(true)}
|
||||
>
|
||||
<Question />
|
||||
<span>Comment jouer</span>
|
||||
</button>
|
||||
{helpDisplayed && (
|
||||
<Help
|
||||
onClose={() => {
|
||||
displayHelp(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{gameState.status === 'board' && <LeaderBoard />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -22,10 +22,10 @@ import Flag from '../../assets/flag.png';
|
||||
import './styles.scss';
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
const Grid = ({ size = 12, difficulty = 'beginner' }) => {
|
||||
const Grid = () => {
|
||||
const [gameState, setGameState] = useRecoilState(gameStateAtom);
|
||||
|
||||
const [grid, setGrid] = useState(genGrid(size));
|
||||
const [grid, setGrid] = useState(genGrid(gameState.gridSize));
|
||||
|
||||
const [, updateGrid] = useState({});
|
||||
const forceUpdate = useCallback(() => updateGrid({}), []);
|
||||
@@ -37,7 +37,7 @@ const Grid = ({ size = 12, difficulty = 'beginner' }) => {
|
||||
if (grid[rowIndex][colIndex].hidden && !grid[rowIndex][colIndex].flag) {
|
||||
setGrid((prev) => {
|
||||
if (gameState.status === 'idle') {
|
||||
const { grid: newGrid, bombsCount } = startGame(prev, difficulty as Difficulty, true, rowIndex, colIndex);
|
||||
const { grid: newGrid, bombsCount } = startGame(prev, gameState.difficulty as Difficulty, true, rowIndex, colIndex);
|
||||
prev = newGrid;
|
||||
|
||||
setGameState((prevGameState) => ({
|
||||
@@ -59,7 +59,7 @@ const Grid = ({ size = 12, difficulty = 'beginner' }) => {
|
||||
if (grid[rowIndex][colIndex].hidden) {
|
||||
setGrid((prev) => {
|
||||
if (gameState.status === 'idle') {
|
||||
const { grid: newGrid, bombsCount } = startGame(prev, difficulty as Difficulty, false);
|
||||
const { grid: newGrid, bombsCount } = startGame(prev, gameState.difficulty as Difficulty, false);
|
||||
prev = newGrid;
|
||||
|
||||
setGameState((prevGameState) => ({
|
||||
@@ -97,7 +97,7 @@ const Grid = ({ size = 12, difficulty = 'beginner' }) => {
|
||||
<div
|
||||
className='grid'
|
||||
style={{
|
||||
gridTemplateRows: `repeat(${size}, var(--size))`,
|
||||
gridTemplateRows: `repeat(${gameState.gridSize}, var(--size))`,
|
||||
}}
|
||||
>
|
||||
{grid.map((row, rowIndex) => (
|
||||
@@ -105,7 +105,7 @@ const Grid = ({ size = 12, difficulty = 'beginner' }) => {
|
||||
key={`row${rowIndex}`}
|
||||
className='row'
|
||||
style={{
|
||||
gridTemplateColumns: `repeat(${size}, var(--size))`,
|
||||
gridTemplateColumns: `repeat(${gameState.gridSize}, var(--size))`,
|
||||
}}
|
||||
>
|
||||
{row.map((cell, cellIndex) => {
|
||||
|
||||
@@ -1,27 +1,79 @@
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
//! Imports
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------- Styles --------------------------------------------------------
|
||||
import { useRef } from 'react';
|
||||
import './styles.scss';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { gameStateAtom } from '../../contexts/gameState';
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
const Home = () => {
|
||||
const difficultyRef = useRef<HTMLSelectElement>(null);
|
||||
const sizeRef = useRef<HTMLSelectElement>(null);
|
||||
|
||||
const [, setGameState] = useRecoilState(gameStateAtom);
|
||||
|
||||
const onClick = () => {
|
||||
if (difficultyRef.current !== null && sizeRef.current !== null) {
|
||||
const difficulty = difficultyRef.current.value;
|
||||
const size = sizeRef.current.value;
|
||||
|
||||
setGameState((prev) => ({
|
||||
...prev,
|
||||
difficulty: difficulty,
|
||||
gridSize: parseInt(size),
|
||||
status: 'idle',
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='gameContainer'>
|
||||
<h1 className='gameTitle'>Démineur</h1>
|
||||
<h1 className='title'>Démineur</h1>
|
||||
|
||||
<div className='settingsContainer'>
|
||||
<div className='selectorBox'>
|
||||
<p className='chooseTitle'>Choisissez la taille de la grille</p>
|
||||
<select className='parameterBox'>
|
||||
<option value='little'>Petit</option>
|
||||
<option value='medium'>Moyen</option>
|
||||
<option value='big'>Grand</option>
|
||||
<p className='settingLabel'>Taille de la grille</p>
|
||||
<select
|
||||
ref={sizeRef}
|
||||
className='select'
|
||||
>
|
||||
<option
|
||||
value='12'
|
||||
selected
|
||||
>
|
||||
Petit
|
||||
</option>
|
||||
<option value='16'>Moyen</option>
|
||||
<option value='20'>Grand</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className='selectorBox'>
|
||||
<p className='chooseTitle'>Choisissez votre niveau</p>
|
||||
<select className='parameterBox'>
|
||||
<option value='easy'>Facile</option>
|
||||
<option value='medium'>Moyen</option>
|
||||
<option value='hard'>Difficile</option>
|
||||
<p className='settingLabel'>Difficulté</p>
|
||||
<select
|
||||
ref={difficultyRef}
|
||||
className='select'
|
||||
>
|
||||
<option
|
||||
value='beginner'
|
||||
selected
|
||||
>
|
||||
Facile
|
||||
</option>
|
||||
<option value='intermediate'>Moyen</option>
|
||||
<option value='expert'>Difficile</option>
|
||||
</select>
|
||||
</div>
|
||||
<button className='startGameBtn'>Commencer</button>
|
||||
|
||||
<button
|
||||
className='startButton'
|
||||
onClick={onClick}
|
||||
>
|
||||
Commencer
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,47 +1,64 @@
|
||||
.gameContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
}
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
gap: 30px;
|
||||
width: 95svw;
|
||||
max-width: 500px;
|
||||
|
||||
.gameTitle {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
& > .title {
|
||||
font-size: 2em;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.settingsContainer {
|
||||
display: grid;
|
||||
grid-template-rows: repeat(2, 1fr);
|
||||
margin: 1rem 0 1rem 0;
|
||||
gap: 10px;
|
||||
}
|
||||
& > .settingsContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
border: 2px solid #f39440;
|
||||
border-radius: 5px;
|
||||
background-color: #ffdccb;
|
||||
|
||||
.selectorBox {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
& > .selectorBox {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20px;
|
||||
|
||||
.chooseTitle{
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
& > .settingLabel {
|
||||
font-size: 1.2rem;
|
||||
color: #f39440;
|
||||
}
|
||||
|
||||
.parameterBox {
|
||||
font-size: 1rem;
|
||||
border-radius: 5px;
|
||||
padding: 2.5px 5px;
|
||||
}
|
||||
& > .select {
|
||||
padding: 2.5px 5px;
|
||||
border: 1px solid #f39440;
|
||||
border-radius: 5px;
|
||||
background-color: #ffdccb;
|
||||
font-size: 1rem;
|
||||
color: #f39440;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.startGameBtn {
|
||||
margin: 1rem 0 1rem 0;
|
||||
padding: 0.7rem 1rem;
|
||||
border-radius: 10px;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
background-color: #333;
|
||||
color: #FFF;
|
||||
border: #FFF 0.5px solid;
|
||||
cursor: pointer;
|
||||
}
|
||||
& > .startButton {
|
||||
padding: 10px;
|
||||
border: 2px solid #f39440;
|
||||
border-radius: 5px;
|
||||
background-color: #ffdccb;
|
||||
font-size: 1.2em;
|
||||
color: #f39440;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: #f39440;
|
||||
color: #ffdccb;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ import { atom } from 'recoil';
|
||||
export const gameStateAtom = atom({
|
||||
key: 'gameState',
|
||||
default: {
|
||||
status: 'settings',
|
||||
difficulty: 'begginer',
|
||||
gridSize: 20,
|
||||
bombs: 0,
|
||||
placedFlags: 0,
|
||||
status: 'idle',
|
||||
},
|
||||
});
|
||||
|
||||
+6
-1
@@ -5,12 +5,17 @@
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
width: 100svw;
|
||||
height: 100svh;
|
||||
background: #598b8e;
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
+4
-1
@@ -2,11 +2,14 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.scss';
|
||||
import App from './App';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
||||
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<RecoilRoot>
|
||||
<App />
|
||||
</RecoilRoot>
|
||||
</React.StrictMode>,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user