💄 (leaderboard): Ability to replay a game or change game settings

This commit is contained in:
2024-02-14 22:19:55 +01:00
parent 79962f45dc
commit 6d22409763
10 changed files with 366 additions and 96 deletions
+4 -4
View File
@@ -12,18 +12,18 @@ import { gameStateAtom } from './contexts/gameState';
// ---------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------- Components ------------------------------------------------------
import Grid from './components/Grid/Grid';
import Home from './components/Home/Home';
import Timer from './components/Stats/Timer/Timer';
import MinesCounter from './components/Stats/MinesCounter/MinesCounter';
import Grid from './components/Grid/Grid';
import Help from './components/Help/Help';
import LeaderBoard from './components/Leaderboard/Leaderboard';
// ---------------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------- Styles --------------------------------------------------------
import Logo from './assets/logo';
import './App.scss';
import Question from './assets/question';
import Home from './components/Home/Home';
import LeaderBoard from './components/Leaderboard/leaderboard';
import './App.scss';
// ---------------------------------------------------------------------------------------------------------------------
const App = () => {
+92
View File
@@ -0,0 +1,92 @@
const Calendar = (props: any) => {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 512 512'
{...props}
>
<rect
fill='none'
stroke='currentColor'
strokeLinejoin='round'
strokeWidth='32'
x='48'
y='80'
width='416'
height='384'
rx='48'
/>
<circle
cx='296'
cy='232'
r='24'
fill='currentColor'
/>
<circle
cx='376'
cy='232'
r='24'
fill='currentColor'
/>
<circle
cx='296'
cy='312'
r='24'
fill='currentColor'
/>
<circle
cx='376'
cy='312'
r='24'
fill='currentColor'
/>
<circle
cx='136'
cy='312'
r='24'
fill='currentColor'
/>
<circle
cx='216'
cy='312'
r='24'
fill='currentColor'
/>
<circle
cx='136'
cy='392'
r='24'
fill='currentColor'
/>
<circle
cx='216'
cy='392'
r='24'
fill='currentColor'
/>
<circle
cx='296'
cy='392'
r='24'
fill='currentColor'
/>
<path
fill='none'
stroke='currentColor'
strokeLinejoin='round'
strokeWidth='32'
strokeLinecap='round'
d='M128 48v32M384 48v32'
/>
<path
fill='none'
stroke='currentColor'
strokeLinejoin='round'
strokeWidth='32'
d='M464 160H48'
/>
</svg>
);
};
export default Calendar;
+28
View File
@@ -0,0 +1,28 @@
const Replay = (props: any) => {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 512 512'
{...props}
>
<path
d='M320 146s24.36-12-64-12a160 160 0 10160 160'
fill='none'
stroke='currentColor'
stroke-linecap='round'
stroke-miterlimit='10'
stroke-width='32'
/>
<path
fill='none'
stroke='currentColor'
stroke-linecap='round'
stroke-linejoin='round'
stroke-width='32'
d='M256 58l80 80-80 80'
/>
</svg>
);
};
export default Replay;
+20
View File
@@ -0,0 +1,20 @@
const Settings = (props: any) => {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 512 512'
{...props}
>
<path
d='M262.29 192.31a64 64 0 1057.4 57.4 64.13 64.13 0 00-57.4-57.4zM416.39 256a154.34 154.34 0 01-1.53 20.79l45.21 35.46a10.81 10.81 0 012.45 13.75l-42.77 74a10.81 10.81 0 01-13.14 4.59l-44.9-18.08a16.11 16.11 0 00-15.17 1.75A164.48 164.48 0 01325 400.8a15.94 15.94 0 00-8.82 12.14l-6.73 47.89a11.08 11.08 0 01-10.68 9.17h-85.54a11.11 11.11 0 01-10.69-8.87l-6.72-47.82a16.07 16.07 0 00-9-12.22 155.3 155.3 0 01-21.46-12.57 16 16 0 00-15.11-1.71l-44.89 18.07a10.81 10.81 0 01-13.14-4.58l-42.77-74a10.8 10.8 0 012.45-13.75l38.21-30a16.05 16.05 0 006-14.08c-.36-4.17-.58-8.33-.58-12.5s.21-8.27.58-12.35a16 16 0 00-6.07-13.94l-38.19-30A10.81 10.81 0 0149.48 186l42.77-74a10.81 10.81 0 0113.14-4.59l44.9 18.08a16.11 16.11 0 0015.17-1.75A164.48 164.48 0 01187 111.2a15.94 15.94 0 008.82-12.14l6.73-47.89A11.08 11.08 0 01213.23 42h85.54a11.11 11.11 0 0110.69 8.87l6.72 47.82a16.07 16.07 0 009 12.22 155.3 155.3 0 0121.46 12.57 16 16 0 0015.11 1.71l44.89-18.07a10.81 10.81 0 0113.14 4.58l42.77 74a10.8 10.8 0 01-2.45 13.75l-38.21 30a16.05 16.05 0 00-6.05 14.08c.33 4.14.55 8.3.55 12.47z'
fill='none'
stroke='currentColor'
stroke-linecap='round'
stroke-linejoin='round'
stroke-width='32'
/>
</svg>
);
};
export default Settings;
+24
View File
@@ -0,0 +1,24 @@
const Timer = (props: any) => {
return (
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 512 512'
{...props}
>
<path
d='M112.91 128A191.85 191.85 0 0064 254c-1.18 106.35 85.65 193.8 192 194 106.2.2 192-85.83 192-192 0-104.54-83.55-189.61-187.5-192a4.36 4.36 0 00-4.5 4.37V152'
fill='none'
stroke='currentColor'
strokeLinecap='round'
strokeLinejoin='round'
strokeWidth='32'
/>
<path
d='M233.38 278.63l-79-113a8.13 8.13 0 0111.32-11.32l113 79a32.5 32.5 0 01-37.25 53.26 33.21 33.21 0 01-8.07-7.94z'
fill='currentColor'
/>
</svg>
);
};
export default Timer;
+62 -29
View File
@@ -1,50 +1,83 @@
import React from 'react';
import { useRecoilState } from 'recoil';
import CalendarIcon from '../../assets/calendar';
import Replay from '../../assets/replay';
import Settings from '../../assets/settings';
import TimerIcon from '../../assets/timer';
import './styles.scss';
import { gameStateAtom } from '../../contexts/gameState';
const arrayBoard = [
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1.06' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
{ date: '12/06/2014', time: '1m 26s' },
];
const LeaderBoard = () => {
const [, setGameState] = useRecoilState(gameStateAtom);
return (
<div className='boardContainer'>
<p className='titleBoard'>Time Leaderboard</p>
<div className='completeBoard'>
<div className='lineInfo'>
<p className='infoDate'>Day</p>
<p className='infoScore'>Time</p>
<>
<h1 className='title'>Time Leaderboard</h1>
<div className='board'>
<div className='header'>
<p>#</p>
<p>
<CalendarIcon />
Date
</p>
<p>
<TimerIcon />
Time
</p>
</div>
<div className='containerLittle'>
<div className='scoresContainer'>
{arrayBoard.map((item, index) => {
return (
<div
className='lineBoard'
key={index}
className='score'
key={`score#${index}`}
>
<p className='blockDate'>{item.date}</p>
<p className='blockScore'>{item.time}</p>
<span>{index + 1}</span>
<span>{item.date}</span>
<span>{item.time}</span>
</div>
);
})}
;
</div>
</div>
</div>
<div className='controls'>
<button
className='controlButton home'
onClick={() => setGameState((prev) => ({ ...prev, status: 'settings' }))}
>
<Settings />
Paramètres
</button>
<button
className='controlButton replay'
onClick={() => setGameState((prev) => ({ ...prev, status: 'idle' }))}
>
<Replay />
Rejouer
</button>
</div>
</>
);
};
+101 -62
View File
@@ -1,72 +1,111 @@
.boardContainer {
.title {
margin-bottom: 40px;
font-size: 2rem;
font-weight: 600;
color: #ffffff;
}
.board {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
width: 95svw;
max-width: 450px;
border-radius: 5px;
background-color: #fff;
overflow: hidden;
& > .header {
display: grid;
grid-template-columns: 1em repeat(2, 1fr);
gap: 30px;
padding: 15px 20px;
background-color: #333;
& > * {
display: flex;
flex-wrap: nowrap;
align-items: center;
gap: 10px;
font-size: 1.3em;
font-weight: 400;
color: #fff;
& > svg {
height: 1.3em;
}
&:last-child {
justify-content: flex-end;
}
}
}
& > .scoresContainer {
height: 100%;
max-height: 400px;
overflow-y: auto;
& > .score {
display: grid;
grid-template-columns: 1em repeat(2, 1fr);
gap: 30px;
padding: 10px 20px;
background-color: #e1e1e1;
color: #333;
& > * {
&:first-child {
opacity: 0.5;
}
&:last-child {
justify-self: end;
font-weight: 600;
}
}
&:nth-child(2n) {
background-color: #ffffff;
}
}
}
}
.titleBoard {
font-size: 1.5rem;
margin-bottom: 1rem;
font-weight: bold;
}
.controls {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 100px;
width: 100%;
.completeBoard {
display: flex;
flex-direction: column;
gap: 1em;
border: 2px solid #fff;
border-radius: 5px;
padding: 15px;
background-color: #fff;
width: 100%;
max-width: 400px;
}
& > .controlButton {
display: flex;
flex-wrap: nowrap;
justify-content: center;
align-items: center;
gap: 10px;
padding: 10px 20px;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: 600;
transition: filter 0.3s ease;
color: #fff;
cursor: pointer;
.containerLittle {
overflow: scroll;
height: 100%;
max-height: 350px;
gap: 1em;
}
&:hover {
filter: brightness(1.1);
}
.lineInfo {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
border: 1.5px solid #fff;
border-radius: 3px;
padding: 10px;
background-color: #333;
color: #fff;
font-weight: 400;
}
&.home {
background-color: #ca5940;
}
.infoDate {
margin-left: 10px;
}
&.replay {
background-color: #f39440;
}
.infoScore {
text-align: right;
margin-right: 10px;
}
.lineBoard {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
border: 1.5px solid #fff;
margin-bottom: 10px;
border-radius: 3px;
padding: 5px;
background-color: #e1e1e1;
color: #333;
font-weight: 400;
}
.blockScore {
text-align: right;
& > svg {
width: 20px;
}
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ import { atom } from 'recoil';
export const gameStateAtom = atom({
key: 'gameState',
default: {
status: 'settings',
status: 'board',
difficulty: 'begginer',
gridSize: 20,
bombs: 0,