✨ Save score in IndexedDB
This commit is contained in:
@@ -3,18 +3,36 @@
|
|||||||
// ---------------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// ----------------------------------------------------- Styles --------------------------------------------------------
|
// ----------------------------------------------------- Styles --------------------------------------------------------
|
||||||
import { useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
import './styles.scss';
|
import './styles.scss';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
import { gameStateAtom } from '../../contexts/gameState';
|
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 Home = () => {
|
||||||
const difficultyRef = useRef<HTMLSelectElement>(null);
|
const difficultyRef = useRef<HTMLSelectElement>(null);
|
||||||
const sizeRef = useRef<HTMLSelectElement>(null);
|
const sizeRef = useRef<HTMLSelectElement>(null);
|
||||||
|
|
||||||
const [, setGameState] = useRecoilState(gameStateAtom);
|
const [, setGameState] = useRecoilState(gameStateAtom);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const initIDB = async () => {
|
||||||
|
if ((await store.getItem('leaderboard')) === null) {
|
||||||
|
await store.setItem('leaderboard', []);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
initIDB();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
if (difficultyRef.current !== null && sizeRef.current !== null) {
|
if (difficultyRef.current !== null && sizeRef.current !== null) {
|
||||||
const difficulty = difficultyRef.current.value;
|
const difficulty = difficultyRef.current.value;
|
||||||
|
|||||||
@@ -39,9 +39,8 @@ const LeaderBoard = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const getData = async () => {
|
const getData = async () => {
|
||||||
const storeData = await store.getItem<LeaderBoardItem[]>('leaderboard');
|
const storeData = await store.getItem<LeaderBoardItem[]>('leaderboard');
|
||||||
if (storeData) {
|
|
||||||
setData(storeData);
|
setData(storeData || []);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import Clock from '../../../assets/clock';
|
|||||||
import '../styles.scss';
|
import '../styles.scss';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
import { gameStateAtom } from '../../../contexts/gameState';
|
import { gameStateAtom } from '../../../contexts/gameState';
|
||||||
|
import { saveToLocalStorage } from '../../../utils/generics';
|
||||||
// ---------------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
const Timer = () => {
|
const Timer = () => {
|
||||||
@@ -53,7 +54,9 @@ const Timer = () => {
|
|||||||
...prev,
|
...prev,
|
||||||
gameTime: displayedTime,
|
gameTime: displayedTime,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
clearInterval(intervalId);
|
clearInterval(intervalId);
|
||||||
|
saveToLocalStorage(displayedTime);
|
||||||
}
|
}
|
||||||
}, [intervalId, gameState.endType, setGameState, displayedTime]);
|
}, [intervalId, gameState.endType, setGameState, displayedTime]);
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { atom } from 'recoil';
|
|||||||
export const gameStateAtom = atom({
|
export const gameStateAtom = atom({
|
||||||
key: 'gameState',
|
key: 'gameState',
|
||||||
default: {
|
default: {
|
||||||
status: 'settings',
|
status: 'board',
|
||||||
difficulty: 'beginner',
|
difficulty: 'beginner',
|
||||||
gridSize: 12,
|
gridSize: 12,
|
||||||
bombs: 0,
|
bombs: 0,
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
export type Difficulty = 'beginner' | 'intermediate' | 'expert';
|
export type Difficulty = 'beginner' | 'intermediate' | 'expert';
|
||||||
export type CellValue = 'empty' | 'bomb' | number;
|
export type CellValue = 'empty' | 'bomb' | number;
|
||||||
export type GridType = { hidden: boolean; value: CellValue; flag: boolean }[][];
|
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 };
|
||||||
|
|||||||
@@ -1,3 +1,46 @@
|
|||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
//! Imports
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ---------------------------------------------------- Stockage -------------------------------------------------------
|
||||||
|
import localforage from 'localforage';
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ------------------------------------------------------ Types --------------------------------------------------------
|
||||||
|
import { LeaderBoardItem } from '../types/game';
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
export const getRandomArbitrary = (min: number, max: number): number => {
|
export const getRandomArbitrary = (min: number, max: number): number => {
|
||||||
return Math.floor(Math.random() * (max - min) + min);
|
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<LeaderBoardItem[]>('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);
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user