diff --git a/src/components/Home/Home.tsx b/src/components/Home/Home.tsx index f90dbb6..832bcf3 100644 --- a/src/components/Home/Home.tsx +++ b/src/components/Home/Home.tsx @@ -3,18 +3,36 @@ // --------------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------- Styles -------------------------------------------------------- -import { useRef } from 'react'; +import { useEffect, useRef } from 'react'; import './styles.scss'; import { useRecoilState } from 'recoil'; import { gameStateAtom } from '../../contexts/gameState'; +import localforage from 'localforage'; // --------------------------------------------------------------------------------------------------------------------- +const store = localforage.createInstance({ + name: 'leaderboard', + driver: localforage.INDEXEDDB, + version: 1.0, + storeName: 'leaderboard', + description: 'Store 10 best game time', +}); + const Home = () => { const difficultyRef = useRef(null); const sizeRef = useRef(null); const [, setGameState] = useRecoilState(gameStateAtom); + useEffect(() => { + const initIDB = async () => { + if ((await store.getItem('leaderboard')) === null) { + await store.setItem('leaderboard', []); + } + }; + initIDB(); + }, []); + const onClick = () => { if (difficultyRef.current !== null && sizeRef.current !== null) { const difficulty = difficultyRef.current.value; diff --git a/src/components/Leaderboard/leaderboard.tsx b/src/components/Leaderboard/leaderboard.tsx index 4f81538..759057b 100644 --- a/src/components/Leaderboard/leaderboard.tsx +++ b/src/components/Leaderboard/leaderboard.tsx @@ -39,9 +39,8 @@ const LeaderBoard = () => { useEffect(() => { const getData = async () => { const storeData = await store.getItem('leaderboard'); - if (storeData) { - setData(storeData); - } + + setData(storeData || []); }; if (data.length === 0) { diff --git a/src/components/Stats/Timer/Timer.tsx b/src/components/Stats/Timer/Timer.tsx index cd1b2a8..1679b31 100644 --- a/src/components/Stats/Timer/Timer.tsx +++ b/src/components/Stats/Timer/Timer.tsx @@ -11,6 +11,7 @@ import Clock from '../../../assets/clock'; import '../styles.scss'; import { useRecoilState } from 'recoil'; import { gameStateAtom } from '../../../contexts/gameState'; +import { saveToLocalStorage } from '../../../utils/generics'; // --------------------------------------------------------------------------------------------------------------------- const Timer = () => { @@ -53,7 +54,9 @@ const Timer = () => { ...prev, gameTime: displayedTime, })); + clearInterval(intervalId); + saveToLocalStorage(displayedTime); } }, [intervalId, gameState.endType, setGameState, displayedTime]); diff --git a/src/contexts/gameState.ts b/src/contexts/gameState.ts index e43258a..6f02a46 100644 --- a/src/contexts/gameState.ts +++ b/src/contexts/gameState.ts @@ -14,7 +14,7 @@ import { atom } from 'recoil'; export const gameStateAtom = atom({ key: 'gameState', default: { - status: 'settings', + status: 'board', difficulty: 'beginner', gridSize: 12, bombs: 0, diff --git a/src/types/game.d.ts b/src/types/game.d.ts index edf151a..46c4a73 100644 --- a/src/types/game.d.ts +++ b/src/types/game.d.ts @@ -1,4 +1,4 @@ export type Difficulty = 'beginner' | 'intermediate' | 'expert'; export type CellValue = 'empty' | 'bomb' | number; export type GridType = { hidden: boolean; value: CellValue; flag: boolean }[][]; -export type LeaderBoardItem = { date: string; time: `${number | ''}${number}m ${number}${number}s` }; +export type LeaderBoardItem = { date: string; time: string }; diff --git a/src/utils/generics.ts b/src/utils/generics.ts index 36c5950..b234f8a 100644 --- a/src/utils/generics.ts +++ b/src/utils/generics.ts @@ -1,3 +1,46 @@ +// --------------------------------------------------------------------------------------------------------------------- +//! Imports +// --------------------------------------------------------------------------------------------------------------------- + +// ---------------------------------------------------- Stockage ------------------------------------------------------- +import localforage from 'localforage'; +// --------------------------------------------------------------------------------------------------------------------- + +// ------------------------------------------------------ Types -------------------------------------------------------- +import { LeaderBoardItem } from '../types/game'; +// --------------------------------------------------------------------------------------------------------------------- + export const getRandomArbitrary = (min: number, max: number): number => { return Math.floor(Math.random() * (max - min) + min); }; + +const store = localforage.createInstance({ + name: 'leaderboard', + driver: localforage.INDEXEDDB, + version: 1.0, + storeName: 'leaderboard', + description: 'Store 10 best game time', +}); + +export const saveToLocalStorage = async (time: string) => { + let leaderboard = await store.getItem('leaderboard'); + + const currentDate = new Date().toLocaleString().split(' ')[0]; + + if (!leaderboard) { + leaderboard = []; + } + + leaderboard.push({ + date: currentDate, + time: `${time.replace(':', 'm ')}s`, + }); + + leaderboard = leaderboard.sort((a, b) => (a.time > b.time ? 1 : -1)); + + if (leaderboard.length > 20) { + leaderboard = leaderboard.slice(0, 20); + } + + await store.setItem('leaderboard', leaderboard); +};