diff --git a/app.js b/app.js index 8273a9f..9975a8c 100644 --- a/app.js +++ b/app.js @@ -40,6 +40,11 @@ const storageState = document.getElementById("storageState"); const toolsDrawer = document.getElementById("toolsDrawer"); const toolsToggleBtn = document.getElementById("toolsToggleBtn"); const toolsCloseBtn = document.getElementById("toolsCloseBtn"); +const gamesDrawer = document.getElementById("gamesDrawer"); +const gamesToggleBtn = document.getElementById("gamesToggleBtn"); +const gamesCloseBtn = document.getElementById("gamesCloseBtn"); +const totalGamesCount = document.getElementById("totalGamesCount"); +const totalGamesValue = document.getElementById("totalGamesValue"); const migrateBtn = document.getElementById("migrateBtn"); const backupControls = document.getElementById("backupControls"); const backupBtn = document.getElementById("backupBtn"); @@ -52,14 +57,17 @@ const googleBackupBtn = document.getElementById("googleBackupBtn"); const googleRestoreBtn = document.getElementById("googleRestoreBtn"); const quickSearchInput = document.getElementById("quickSearchInput"); const quickSearchResults = document.getElementById("quickSearchResults"); +const loanedFilterBtn = document.getElementById("loanedFilterBtn"); const gamesList = document.getElementById("gamesList"); const gameCardTemplate = document.getElementById("gameCardTemplate"); let editingGameId = null; let pendingRestoreMode = "merge"; let quickSearchTerm = ""; let googleStatus = { configured: false, connected: false, email: "" }; +let showLoanedOnly = false; toolsToggleBtn.addEventListener("click", () => { + gamesDrawer.classList.remove("open"); toolsDrawer.classList.toggle("open"); }); @@ -67,22 +75,37 @@ toolsCloseBtn.addEventListener("click", () => { toolsDrawer.classList.remove("open"); }); +gamesToggleBtn.addEventListener("click", () => { + toolsDrawer.classList.remove("open"); + gamesDrawer.classList.toggle("open"); +}); + +gamesCloseBtn.addEventListener("click", () => { + gamesDrawer.classList.remove("open"); +}); + document.addEventListener("click", (event) => { if (!(event.target instanceof Element)) { return; } - if (!toolsDrawer.classList.contains("open")) { + const toolsOpen = toolsDrawer.classList.contains("open"); + const gamesOpen = gamesDrawer.classList.contains("open"); + if (!toolsOpen && !gamesOpen) { return; } - if (toolsDrawer.contains(event.target) || toolsToggleBtn.contains(event.target)) { + const clickedInsideTools = toolsDrawer.contains(event.target) || toolsToggleBtn.contains(event.target); + const clickedInsideGames = gamesDrawer.contains(event.target) || gamesToggleBtn.contains(event.target); + if (clickedInsideTools || clickedInsideGames) { return; } toolsDrawer.classList.remove("open"); + gamesDrawer.classList.remove("open"); }); document.addEventListener("keydown", (event) => { if (event.key === "Escape") { toolsDrawer.classList.remove("open"); + gamesDrawer.classList.remove("open"); } }); @@ -133,6 +156,11 @@ quickSearchInput.addEventListener("input", (event) => { renderSearchResults(); }); +loanedFilterBtn.addEventListener("click", () => { + showLoanedOnly = !showLoanedOnly; + renderGames(); +}); + platformForm.addEventListener("submit", async (event) => { event.preventDefault(); @@ -317,18 +345,22 @@ gamesList.addEventListener("click", async (event) => { const action = target.dataset.action; const id = target.dataset.id; - if (!action || !id || !state.selectedConsole) { + if (!action || !id) { return; } - const games = state.gamesByConsole[state.selectedConsole] || []; - const idx = games.findIndex((game) => game.id === id); - if (idx === -1) { + const gameRef = findGameById(id); + if (!gameRef) { return; } + const { game, games, idx, consoleName, brand } = gameRef; if (action === "edit") { - startEditMode(games[idx]); + state.selectedBrand = brand; + state.selectedConsole = consoleName; + startEditMode(game); + persist(); + render(); return; } @@ -342,7 +374,24 @@ gamesList.addEventListener("click", async (event) => { } if (action === "toggle-loan") { - await apiRequest(`/api/catalog/games/${id}/toggle-loan`, { method: "POST" }); + if (game.loanedTo) { + await apiRequest(`/api/catalog/games/${id}/toggle-loan`, { method: "POST" }); + } else { + const borrower = window.prompt("Nom de la personne a qui tu pretes ce jeu :"); + if (borrower === null) { + return; + } + const loanedTo = borrower.trim(); + if (!loanedTo) { + alert("Le nom est obligatoire pour marquer le jeu comme prete."); + return; + } + const payload = buildGamePayload(game, brand, consoleName, { loanedTo }); + await apiRequest(`/api/catalog/games/${id}`, { + method: "PUT", + body: payload, + }); + } } await refreshFromApi(state.selectedBrand, state.selectedConsole); @@ -361,7 +410,20 @@ gamesList.addEventListener("click", async (event) => { } if (action === "toggle-loan") { - games[idx].loanedTo = games[idx].loanedTo ? "" : "A renseigner"; + if (games[idx].loanedTo) { + games[idx].loanedTo = ""; + } else { + const borrower = window.prompt("Nom de la personne a qui tu pretes ce jeu :"); + if (borrower === null) { + return; + } + const loanedTo = borrower.trim(); + if (!loanedTo) { + alert("Le nom est obligatoire pour marquer le jeu comme prete."); + return; + } + games[idx].loanedTo = loanedTo; + } } persist(); @@ -487,6 +549,7 @@ function render() { renderConsoleTabs(); renderGames(); renderSearchResults(); + renderCollectionStats(); } function renderDataMode() { @@ -576,6 +639,40 @@ function findBrandByConsole(consoleName) { return "INCONNUE"; } +function findGameById(id) { + for (const [consoleName, games] of Object.entries(state.gamesByConsole)) { + const idx = (games || []).findIndex((game) => game.id === id); + if (idx !== -1) { + return { + consoleName, + brand: findBrandByConsole(consoleName), + games, + idx, + game: games[idx], + }; + } + } + return null; +} + +function buildGamePayload(game, brand, consoleName, overrides = {}) { + return { + brand, + consoleName, + title: game.title || "", + version: game.version || "", + genre: game.genre || "", + publisher: game.publisher || "", + isDuplicate: Boolean(game.isDuplicate), + year: game.year != null ? Number(game.year) : null, + purchasePrice: game.purchasePrice != null ? Number(game.purchasePrice) : null, + value: game.value != null ? Number(game.value) : null, + condition: game.condition != null ? Number(game.condition) : null, + loanedTo: game.loanedTo || "", + ...overrides, + }; +} + function collectAllGames() { const all = []; for (const [consoleName, games] of Object.entries(state.gamesByConsole)) { @@ -587,6 +684,22 @@ function collectAllGames() { return all; } +function renderCollectionStats() { + if (!totalGamesCount || !totalGamesValue) { + return; + } + + const allGames = collectAllGames(); + const totalCount = allGames.length; + const totalValue = allGames.reduce((sum, game) => { + const value = typeof game.value === "number" ? game.value : Number(game.value); + return Number.isFinite(value) ? sum + value : sum; + }, 0); + + totalGamesCount.textContent = String(totalCount); + totalGamesValue.textContent = `${totalValue.toFixed(2)} EUR`; +} + function renderSearchResults() { if (!quickSearchResults) { return; @@ -691,17 +804,27 @@ function renderConsoleTabs() { function renderGames() { const selectedConsole = state.selectedConsole; - gameSectionTitle.textContent = selectedConsole ? `Jeux - ${selectedConsole}` : "Jeux"; + gameSectionTitle.textContent = showLoanedOnly + ? "Jeux pretes - Toutes consoles" + : selectedConsole + ? `Jeux - ${selectedConsole}` + : "Jeux"; gamesList.innerHTML = ""; + loanedFilterBtn.textContent = showLoanedOnly ? "Voir tous les jeux" : "Voir jeux pretes"; - if (!selectedConsole) { + if (!showLoanedOnly && !selectedConsole) { gamesList.innerHTML = '

Ajoute une section pour commencer.

'; return; } - const games = state.gamesByConsole[selectedConsole] || []; + const games = showLoanedOnly + ? collectAllGames().filter((game) => normalizeText(game.loanedTo)) + : state.gamesByConsole[selectedConsole] || []; + if (!games.length) { - gamesList.innerHTML = '

Aucun jeu sur cette console pour le moment.

'; + gamesList.innerHTML = showLoanedOnly + ? '

Aucun jeu prete actuellement.

' + : '

Aucun jeu sur cette console pour le moment.

'; return; } @@ -715,6 +838,7 @@ function renderGames() { card.querySelector(".game-title").textContent = game.title; const metaParts = [ + showLoanedOnly ? `${game.brand} / ${game.consoleName}` : null, game.version ? `Version: ${game.version}` : null, game.genre ? `Genre: ${game.genre}` : null, game.publisher ? `Editeur: ${game.publisher}` : null, @@ -770,6 +894,13 @@ function resetEditMode() { cancelEditBtn.classList.add("hidden"); } +function normalizeText(value) { + if (value == null) { + return ""; + } + return String(value).trim(); +} + function loadState() { try { const raw = localStorage.getItem(STORAGE_KEY); diff --git a/index.html b/index.html index 579706e..22dd050 100644 --- a/index.html +++ b/index.html @@ -14,6 +14,7 @@ + +
@@ -102,6 +120,9 @@

Jeux

+
+ +