UI: add console colors, state badges, sticky header and clearer actions

This commit is contained in:
Ponte
2026-02-14 23:52:19 +01:00
parent 9d350c2e09
commit 551d42a251
3 changed files with 174 additions and 5 deletions

82
app.js
View File

@@ -564,6 +564,13 @@ gamesList.addEventListener("click", async (event) => {
} }
if (apiReachable && dataMode !== "local-pending-import") { if (apiReachable && dataMode !== "local-pending-import") {
if (action === "delete") {
const confirmed = window.confirm("Etes-vous sur de vouloir supprimer ce jeu ?");
if (!confirmed) {
return;
}
}
try { try {
if (action === "delete") { if (action === "delete") {
await apiRequest(`/api/catalog/games/${id}`, { method: "DELETE" }); await apiRequest(`/api/catalog/games/${id}`, { method: "DELETE" });
@@ -603,6 +610,10 @@ gamesList.addEventListener("click", async (event) => {
} }
if (action === "delete") { if (action === "delete") {
const confirmed = window.confirm("Etes-vous sur de vouloir supprimer ce jeu ?");
if (!confirmed) {
return;
}
games.splice(idx, 1); games.splice(idx, 1);
if (editingGameId === id) { if (editingGameId === id) {
resetEditMode(); resetEditMode();
@@ -977,6 +988,58 @@ function badgeClassForGenre(genreValue) {
return "default"; return "default";
} }
function consoleThemeClass(consoleName) {
const normalized = normalizeText(consoleName).toLowerCase();
if (normalized.includes("playstation 5") || normalized === "ps5") {
return "console-theme-ps5";
}
if (normalized.includes("playstation 4") || normalized === "ps4") {
return "console-theme-ps4";
}
if (normalized.includes("playstation 3") || normalized === "ps3") {
return "console-theme-ps3";
}
if (normalized.includes("playstation 2") || normalized === "ps2") {
return "console-theme-ps2";
}
if (normalized.includes("playstation") || normalized === "ps1") {
return "console-theme-ps1";
}
if (normalized.includes("switch")) {
return "console-theme-switch";
}
if (normalized.includes("xbox")) {
return "console-theme-xbox";
}
if (normalized.includes("wii")) {
return "console-theme-wii";
}
if (normalized.includes("snes")) {
return "console-theme-snes";
}
if (normalized.includes("nes")) {
return "console-theme-nes";
}
return "console-theme-default";
}
function conditionBadgeClass(conditionValue) {
if (conditionValue == null || Number.isNaN(Number(conditionValue))) {
return "status-neutral";
}
const value = Number(conditionValue);
if (value >= 9) {
return "status-good";
}
if (value >= 7) {
return "status-medium";
}
if (value >= 5) {
return "status-warning";
}
return "status-low";
}
function renderSearchResults() { function renderSearchResults() {
if (!quickSearchResults) { if (!quickSearchResults) {
return; return;
@@ -1143,7 +1206,7 @@ function renderGames() {
}); });
if (v2StickyCount) { if (v2StickyCount) {
v2StickyCount.textContent = `${games.length} jeu${games.length > 1 ? "x" : ""}`; v2StickyCount.textContent = `${games.length} jeu${games.length > 1 ? "x" : ""} affiche${games.length > 1 ? "s" : ""}`;
} }
} }
@@ -1157,6 +1220,7 @@ function renderGames() {
for (const game of games) { for (const game of games) {
const card = gameCardTemplate.content.cloneNode(true); const card = gameCardTemplate.content.cloneNode(true);
const article = card.querySelector(".game-card"); const article = card.querySelector(".game-card");
article.classList.add(consoleThemeClass(game.consoleName));
if (inlineEditingGameId === game.id) { if (inlineEditingGameId === game.id) {
article.classList.add("editing"); article.classList.add("editing");
} }
@@ -1195,6 +1259,12 @@ function renderGames() {
} else { } else {
badgesContainer.innerHTML = ""; badgesContainer.innerHTML = "";
} }
if (game.condition != null && !Number.isNaN(Number(game.condition))) {
badgesContainer.insertAdjacentHTML(
"beforeend",
`<span class="status-badge ${conditionBadgeClass(game.condition)}">Etat ${escapeHtml(String(game.condition))}/10</span>`,
);
}
const coverEl = card.querySelector(".game-cover"); const coverEl = card.querySelector(".game-cover");
const coverUrl = normalizeText(game.coverUrl); const coverUrl = normalizeText(game.coverUrl);
if (coverUrl) { if (coverUrl) {
@@ -1214,10 +1284,18 @@ function renderGames() {
const deleteBtn = card.querySelector('[data-action="delete"]'); const deleteBtn = card.querySelector('[data-action="delete"]');
editBtn.dataset.id = game.id; editBtn.dataset.id = game.id;
editBtn.textContent = "✏️ Editer";
editBtn.title = "Editer ce jeu";
editBtn.setAttribute("aria-label", "Editer ce jeu");
toggleBtn.dataset.id = game.id; toggleBtn.dataset.id = game.id;
toggleBtn.textContent = game.loanedTo ? "Marquer comme rendu" : "Marquer comme prete"; toggleBtn.textContent = game.loanedTo ? "📥 Rendu" : "📤 Preter";
toggleBtn.title = game.loanedTo ? "Marquer comme rendu" : "Marquer comme prete";
toggleBtn.setAttribute("aria-label", toggleBtn.title);
deleteBtn.dataset.id = game.id; deleteBtn.dataset.id = game.id;
deleteBtn.textContent = "🗑️ Supprimer";
deleteBtn.title = "Supprimer ce jeu";
deleteBtn.setAttribute("aria-label", "Supprimer ce jeu");
if (inlineEditingGameId === game.id) { if (inlineEditingGameId === game.id) {
const editor = document.createElement("div"); const editor = document.createElement("div");

View File

@@ -63,7 +63,7 @@
<main class="app-shell"> <main class="app-shell">
<div id="v2StickyBar" class="v2-sticky hidden"> <div id="v2StickyBar" class="v2-sticky hidden">
<div class="v2-sticky-title">Vue catalogue</div> <div class="v2-sticky-title">Vue catalogue</div>
<div id="v2StickyCount" class="v2-sticky-count">0 jeu</div> <div id="v2StickyCount" class="v2-sticky-count">0 jeu affiche</div>
<div class="v2-sticky-actions"> <div class="v2-sticky-actions">
<button id="v2ToggleFormBtn" type="button" class="btn-secondary">Ajouter</button> <button id="v2ToggleFormBtn" type="button" class="btn-secondary">Ajouter</button>
<button id="v2QuickBackupBtn" type="button" class="btn-secondary">Sauvegarder</button> <button id="v2QuickBackupBtn" type="button" class="btn-secondary">Sauvegarder</button>

View File

@@ -439,6 +439,50 @@ button {
align-items: center; align-items: center;
} }
.console-theme-default {
background: #ffffff;
}
.console-theme-ps5 {
background: linear-gradient(165deg, #eef6ff 0%, #ffffff 52%);
}
.console-theme-ps4 {
background: linear-gradient(165deg, #f1f6ff 0%, #ffffff 54%);
}
.console-theme-ps3 {
background: linear-gradient(165deg, #f6f7ff 0%, #ffffff 54%);
}
.console-theme-ps2 {
background: linear-gradient(165deg, #f2f0ff 0%, #ffffff 56%);
}
.console-theme-ps1 {
background: linear-gradient(165deg, #f3f5ff 0%, #ffffff 56%);
}
.console-theme-switch {
background: linear-gradient(165deg, #fff0f1 0%, #ffffff 56%);
}
.console-theme-xbox {
background: linear-gradient(165deg, #ecfff6 0%, #ffffff 56%);
}
.console-theme-wii {
background: linear-gradient(165deg, #edf9ff 0%, #ffffff 56%);
}
.console-theme-snes {
background: linear-gradient(165deg, #f5f2ff 0%, #ffffff 56%);
}
.console-theme-nes {
background: linear-gradient(165deg, #f7f7f7 0%, #ffffff 56%);
}
.game-cover { .game-cover {
width: 56px; width: 56px;
height: 76px; height: 76px;
@@ -619,6 +663,47 @@ button {
border-color: #ffe6b9; border-color: #ffe6b9;
} }
.status-badge {
display: inline-flex;
align-items: center;
padding: 0.2rem 0.5rem;
border-radius: 999px;
font-size: 0.73rem;
font-weight: 700;
letter-spacing: 0.01em;
border: 1px solid transparent;
}
.status-badge.status-good {
background: #e5f9ef;
color: #126948;
border-color: #c3efd9;
}
.status-badge.status-medium {
background: #ebf7ff;
color: #135b84;
border-color: #cae9fa;
}
.status-badge.status-warning {
background: #fff6e6;
color: #915f12;
border-color: #ffe5b6;
}
.status-badge.status-low {
background: #ffecef;
color: #9a2d41;
border-color: #ffcfd9;
}
.status-badge.status-neutral {
background: #edf1f7;
color: #2f4255;
border-color: #d8e1ed;
}
.toast-container { .toast-container {
position: fixed; position: fixed;
right: 1rem; right: 1rem;
@@ -666,9 +751,9 @@ body.ui-v2 .game-card {
} }
body.ui-v2 .game-card:hover { body.ui-v2 .game-card:hover {
transform: translateY(-2px); transform: translateY(-1px);
border-color: #d3cef9; border-color: #d3cef9;
box-shadow: 0 12px 24px rgba(50, 50, 93, 0.14); box-shadow: 0 8px 16px rgba(50, 50, 93, 0.1);
} }
body.ui-v2 .game-cover { body.ui-v2 .game-cover {
@@ -681,6 +766,12 @@ body.ui-v2 .game-actions {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
body.ui-v2 .hero {
position: sticky;
top: 4.2rem;
z-index: 15;
}
@media (max-width: 1100px) { @media (max-width: 1100px) {
body.ui-v2 .games-list { body.ui-v2 .games-list {
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));