feat : add games database

This commit is contained in:
GuillaumeSD
2024-02-22 00:26:07 +01:00
parent 4502651492
commit 2a74b62bae
16 changed files with 450 additions and 7 deletions

View File

@@ -0,0 +1,87 @@
import { Game, GameEval } from "@/types/game";
import { openDB, DBSchema, IDBPDatabase } from "idb";
import { atom, useAtom } from "jotai";
import { useCallback, useEffect, useState } from "react";
interface GameDatabaseSchema extends DBSchema {
games: {
value: Game;
key: number;
};
}
const gamesAtom = atom<Game[]>([]);
const fetchGamesAtom = atom<boolean>(false);
export const useGameDatabase = (shouldFetchGames?: boolean) => {
const [db, setDb] = useState<IDBPDatabase<GameDatabaseSchema> | null>(null);
const [games, setGames] = useAtom(gamesAtom);
const [fetchGames, setFetchGames] = useAtom(fetchGamesAtom);
useEffect(() => {
if (shouldFetchGames !== undefined) {
setFetchGames(shouldFetchGames);
}
}, [shouldFetchGames, setFetchGames]);
useEffect(() => {
const initDatabase = async () => {
const db = await openDB<GameDatabaseSchema>("games", 1, {
upgrade(db) {
db.createObjectStore("games", { keyPath: "id", autoIncrement: true });
},
});
setDb(db);
};
initDatabase();
}, []);
const loadGames = useCallback(async () => {
if (db && fetchGames) {
const games = await db.getAll("games");
setGames(games);
}
}, [db, fetchGames, setGames]);
useEffect(() => {
loadGames();
}, [loadGames]);
const addGame = async (game: Omit<Game, "id">) => {
if (!db) throw new Error("Database not initialized");
await db.add("games", game as Game);
loadGames();
};
const setGameEval = async (gameId: number, evaluation: GameEval) => {
if (!db) throw new Error("Database not initialized");
const game = await db.get("games", gameId);
if (!game) throw new Error("Game not found");
await db.put("games", { ...game, eval: evaluation });
loadGames();
};
const getGame = async (gameId: number) => {
if (!db) return undefined;
return db.get("games", gameId);
};
const deleteGame = async (gameId: number) => {
if (!db) throw new Error("Database not initialized");
await db.delete("games", gameId);
loadGames();
};
const isReady = db !== null;
return { addGame, setGameEval, getGame, deleteGame, games, isReady };
};

View File

@@ -5,17 +5,21 @@ type SetValue<T> = Dispatch<SetStateAction<T>>;
export function useLocalStorage<T>(
key: string,
initialValue: T
): [T, SetValue<T>] {
const [storedValue, setStoredValue] = useState<T>(initialValue);
): [T | null, SetValue<T>] {
const [storedValue, setStoredValue] = useState<T | null>(null);
useEffect(() => {
const item = window.localStorage.getItem(key);
if (item) {
setStoredValue(parseJSON<T>(item));
} else {
setStoredValue(initialValue);
}
}, [key]);
const setValue: SetValue<T> = (value) => {
if (storedValue === null)
throw new Error("setLocalStorage value isn't ready yet");
const newValue = value instanceof Function ? value(storedValue) : value;
window.localStorage.setItem(key, JSON.stringify(newValue));
setStoredValue(newValue);