Lint: fix errors and remove unused variables
**Motivations:** - Ensure lint config is not degraded and fix all lint errors for pousse workflow. **Root causes:** - Unused variables kept with _ prefix instead of removed (_row, _questReward, _i). - getAnimalBlockOrigin had 5 parameters (max 4). - use of continue statement (no-continue rule). **Correctifs:** - ESLint config verified; no eslint-disable in codebase. - Removed unused variable _row (biome-rules); removed dead function _questReward (quests); removed unused map param _i (state.js). - getAnimalBlockOrigin refactored to 4 params (pos object instead of x, y). - Replaced continue with if (cell) block in normalizeLoadedCells (state.js). - JSDoc param names aligned with _height, _y (biome-rules). **Evolutions:** - (none) **Pages affectées:** - web/js/biome-rules.js - web/js/quests.js - web/js/state.js - web/js/placement.js
This commit is contained in:
271
web/js/ui-render-gamebar.js
Normal file
271
web/js/ui-render-gamebar.js
Normal file
@@ -0,0 +1,271 @@
|
||||
import { makeHelpWrap } from "./ui-helpers.js";
|
||||
import { setMusicEnabled, isMusicEnabled } from "./audio.js";
|
||||
import {
|
||||
t,
|
||||
prestigeLabel,
|
||||
prestigeHint,
|
||||
visitorsLabel,
|
||||
musicLabel,
|
||||
restartButton,
|
||||
helpRestart,
|
||||
questsTitle,
|
||||
} from "./texts-fr.js";
|
||||
import { getApiBase, getSales } from "./api-client.js";
|
||||
import { buildAutoProfilePicker } from "./ui-render-gamebar-picker.js";
|
||||
|
||||
/**
|
||||
* @param {string} iconEmoji
|
||||
* @param {string} tooltipText
|
||||
* @param {string} initialValue
|
||||
* @returns {{ item: HTMLElement, valueEl: HTMLElement }}
|
||||
*/
|
||||
function addStatusItem(iconEmoji, tooltipText, initialValue) {
|
||||
const item = document.createElement("span");
|
||||
item.className = "status-bar-item";
|
||||
const icon = document.createElement("span");
|
||||
icon.className = "status-bar-icon";
|
||||
icon.setAttribute("aria-hidden", "true");
|
||||
icon.title = tooltipText;
|
||||
icon.textContent = iconEmoji;
|
||||
const value = document.createElement("span");
|
||||
value.className = "status-bar-value";
|
||||
value.textContent = initialValue;
|
||||
item.append(icon, value);
|
||||
return { item, valueEl: value };
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {{ gameBar: HTMLElement }}
|
||||
*/
|
||||
function buildGameBarTitle() {
|
||||
const gameBar = document.createElement("div");
|
||||
gameBar.className = "game-bar";
|
||||
gameBar.setAttribute("aria-label", "Barre du jeu");
|
||||
const gameBarTitleWrap = document.createElement("div");
|
||||
gameBarTitleWrap.className = "game-bar-title-wrap";
|
||||
const gameBarTitle = document.createElement("h1");
|
||||
gameBarTitle.className = "game-bar-title";
|
||||
gameBarTitle.textContent = t.title;
|
||||
const titleHelp = makeHelpWrap("", t.helpStatus);
|
||||
titleHelp.querySelector(".tooltip-bubble").classList.add("below");
|
||||
gameBarTitleWrap.append(gameBarTitle, titleHelp);
|
||||
gameBar.appendChild(gameBarTitleWrap);
|
||||
return { gameBar };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} gameBar
|
||||
* @returns {{ statusBarCoins: { item: HTMLElement, valueEl: HTMLElement }, statusBarPlot: object, statusBarCell: object, statusBarSkill: object, statusBarVisitors: object, statusBarOffers: object, statusBarTimeWeather: object }}
|
||||
*/
|
||||
function buildStatusBar(gameBar) {
|
||||
const statusBar = document.createElement("div");
|
||||
statusBar.className = "status-bar";
|
||||
statusBar.setAttribute("aria-label", "Indicateurs");
|
||||
const statusBarCoins = addStatusItem("🪙", "Pièces", "0");
|
||||
const statusBarPlot = addStatusItem("📐", "Parcelle", "1");
|
||||
const statusBarCell = addStatusItem("📍", "Case sélectionnée", "1 1");
|
||||
const statusBarSkill = addStatusItem("🎓", "Compétences", "1");
|
||||
const statusBarVisitors = addStatusItem("👤", visitorsLabel, "0");
|
||||
const statusBarOffers = addStatusItem("🥚", "Œufs à vendre", "0");
|
||||
const statusBarTimeWeather = addStatusItem("🌤️", "Météo et heure", "—");
|
||||
statusBar.append(
|
||||
statusBarCoins.item, statusBarPlot.item, statusBarCell.item, statusBarSkill.item,
|
||||
statusBarVisitors.item, statusBarOffers.item, statusBarTimeWeather.item
|
||||
);
|
||||
gameBar.appendChild(statusBar);
|
||||
return { statusBarCoins, statusBarPlot, statusBarCell, statusBarSkill, statusBarVisitors, statusBarOffers, statusBarTimeWeather };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} panelZoo
|
||||
* @param {HTMLElement} panelWorld
|
||||
* @param {{ state: import("./types.js").GameState, setState: () => void }} setup
|
||||
* @returns {{ viewSwitcherWrap: HTMLElement, viewToggleBtn: HTMLElement }}
|
||||
*/
|
||||
function buildViewSwitcher(panelZoo, panelWorld, setup) {
|
||||
const { state, setState } = setup;
|
||||
const viewSwitcherWrap = document.createElement("div");
|
||||
viewSwitcherWrap.className = "game-bar-view-switcher";
|
||||
viewSwitcherWrap.setAttribute("aria-label", "Zoo ou carte du monde");
|
||||
const viewToggleBtn = document.createElement("button");
|
||||
viewToggleBtn.className = "game-bar-btn game-bar-view-btn";
|
||||
viewToggleBtn.type = "button";
|
||||
viewToggleBtn.id = "view-toggle";
|
||||
viewToggleBtn.setAttribute("aria-label", "Afficher la carte du monde");
|
||||
viewToggleBtn.title = "Carte du monde (cliquer pour afficher)";
|
||||
viewToggleBtn.textContent = "🗺️";
|
||||
function setViewToggleIcon(isZooActive) {
|
||||
viewToggleBtn.textContent = isZooActive ? "🦒" : "🗺️";
|
||||
viewToggleBtn.setAttribute("aria-label", isZooActive ? "Afficher la carte du monde" : "Afficher la carte du zoo");
|
||||
viewToggleBtn.title = isZooActive ? "Carte du monde (cliquer pour afficher)" : "Carte du zoo (cliquer pour afficher)";
|
||||
}
|
||||
viewToggleBtn.addEventListener("click", () => {
|
||||
const showZoo = !panelZoo.classList.contains("active");
|
||||
if (showZoo) {
|
||||
panelZoo.classList.add("active");
|
||||
panelWorld.classList.remove("active");
|
||||
setViewToggleIcon(true);
|
||||
} else {
|
||||
panelWorld.classList.add("active");
|
||||
panelZoo.classList.remove("active");
|
||||
setViewToggleIcon(false);
|
||||
if (getApiBase()) {
|
||||
getSales().then((data) => { state.salesFromApi = data; setState(); }).catch(() => {});
|
||||
}
|
||||
}
|
||||
});
|
||||
setViewToggleIcon(true);
|
||||
viewSwitcherWrap.appendChild(viewToggleBtn);
|
||||
return { viewSwitcherWrap, viewToggleBtn };
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
function buildMusicBtn() {
|
||||
const musicBtn = document.createElement("button");
|
||||
musicBtn.className = "game-bar-btn game-bar-btn-music" + (isMusicEnabled() ? "" : " muted");
|
||||
musicBtn.type = "button";
|
||||
musicBtn.setAttribute("aria-label", musicLabel);
|
||||
musicBtn.title = musicLabel;
|
||||
musicBtn.textContent = "🎵";
|
||||
musicBtn.addEventListener("click", () => {
|
||||
const next = !isMusicEnabled();
|
||||
setMusicEnabled(next);
|
||||
try {
|
||||
localStorage.setItem("builazoo_music", next ? "1" : "0");
|
||||
} catch (_) {
|
||||
// ignore localStorage
|
||||
}
|
||||
musicBtn.classList.toggle("muted", !next);
|
||||
});
|
||||
return musicBtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ state: import("./types.js").GameState, updateState?: (p: Partial<import("./types.js").GameState>) => void }} setup
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
function buildAutoModeBtn(setup) {
|
||||
const { state, updateState } = setup;
|
||||
const autoModeBtn = document.createElement("button");
|
||||
autoModeBtn.className = "game-bar-btn game-bar-btn-auto-mode";
|
||||
autoModeBtn.type = "button";
|
||||
autoModeBtn.id = "auto-mode-btn";
|
||||
autoModeBtn.setAttribute("aria-pressed", state.autoMode ? "true" : "false");
|
||||
autoModeBtn.title = state.autoMode ? "Mode automatique (désactiver)" : "Mode automatique (activer)";
|
||||
autoModeBtn.setAttribute("aria-label", state.autoMode ? "Mode automatique actif" : "Activer le mode automatique");
|
||||
autoModeBtn.textContent = state.autoMode ? "🤖" : "✋";
|
||||
autoModeBtn.addEventListener("click", () => {
|
||||
if (state.autoMode && updateState) {
|
||||
updateState({ autoMode: false });
|
||||
} else if (updateState) {
|
||||
updateState({ autoProfilePickerOpen: true, autoProfilePickerFamily: undefined });
|
||||
}
|
||||
});
|
||||
return autoModeBtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ onRestart?: () => void }} setup
|
||||
* @param {HTMLElement} gameBarActions
|
||||
* @returns {{ prestigeBtn: HTMLElement, restartBtn: HTMLElement }}
|
||||
*/
|
||||
function buildPrestigeRestart(setup, gameBarActions) {
|
||||
const { onRestart } = setup;
|
||||
const prestigeBtn = document.createElement("button");
|
||||
prestigeBtn.className = "game-bar-btn game-bar-btn-prestige";
|
||||
prestigeBtn.type = "button";
|
||||
prestigeBtn.setAttribute("aria-label", prestigeLabel);
|
||||
prestigeBtn.title = prestigeHint;
|
||||
prestigeBtn.textContent = "⭐";
|
||||
gameBarActions.appendChild(prestigeBtn);
|
||||
const restartBtn = document.createElement("button");
|
||||
restartBtn.className = "game-bar-btn game-bar-btn-restart";
|
||||
restartBtn.type = "button";
|
||||
restartBtn.setAttribute("aria-label", restartButton);
|
||||
restartBtn.title = helpRestart;
|
||||
restartBtn.textContent = "🔄";
|
||||
if (onRestart) {
|
||||
restartBtn.addEventListener("click", () => onRestart());
|
||||
} else {
|
||||
restartBtn.disabled = true;
|
||||
}
|
||||
gameBarActions.appendChild(restartBtn);
|
||||
return { prestigeBtn, restartBtn };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} gameBarActions
|
||||
* @returns {{ questListEl: HTMLElement }}
|
||||
*/
|
||||
function buildQuestDropdown(gameBarActions) {
|
||||
const questWrap = document.createElement("div");
|
||||
questWrap.className = "game-bar-quest-wrap";
|
||||
const questBtn = document.createElement("button");
|
||||
questBtn.className = "game-bar-btn game-bar-btn-quest";
|
||||
questBtn.type = "button";
|
||||
questBtn.setAttribute("aria-label", questsTitle);
|
||||
questBtn.setAttribute("aria-expanded", "false");
|
||||
questBtn.title = questsTitle;
|
||||
questBtn.textContent = "📋";
|
||||
const questDropdown = document.createElement("div");
|
||||
questDropdown.className = "quest-dropdown";
|
||||
questDropdown.setAttribute("role", "dialog");
|
||||
questDropdown.setAttribute("aria-label", questsTitle);
|
||||
const questDropdownTitle = document.createElement("div");
|
||||
questDropdownTitle.className = "quest-dropdown-title";
|
||||
questDropdownTitle.textContent = questsTitle;
|
||||
questDropdown.appendChild(questDropdownTitle);
|
||||
const questListEl = document.createElement("div");
|
||||
questListEl.className = "quest-list";
|
||||
questDropdown.appendChild(questListEl);
|
||||
questWrap.appendChild(questBtn);
|
||||
questWrap.appendChild(questDropdown);
|
||||
questBtn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
const open = questWrap.classList.toggle("open");
|
||||
questBtn.setAttribute("aria-expanded", String(open));
|
||||
});
|
||||
document.addEventListener("click", () => {
|
||||
questWrap.classList.remove("open");
|
||||
questBtn.setAttribute("aria-expanded", "false");
|
||||
});
|
||||
questDropdown.addEventListener("click", (e) => e.stopPropagation());
|
||||
gameBarActions.appendChild(questWrap);
|
||||
return { questListEl };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ state: import("./types.js").GameState, setState: () => void, updateState?: (p: Partial<import("./types.js").GameState>) => void, onRestart?: () => void }} setup
|
||||
* @param {HTMLElement} panelZoo
|
||||
* @param {HTMLElement} panelWorld
|
||||
* @returns {{ gameBar: HTMLElement, gameBarActions: HTMLElement, statusBarCoins: object, statusBarPlot: object, statusBarCell: object, statusBarSkill: object, statusBarVisitors: object, statusBarOffers: object, statusBarTimeWeather: object, viewSwitcherWrap: HTMLElement, viewToggleBtn: HTMLElement, musicBtn: HTMLElement, autoModeBtn: HTMLElement, prestigeBtn: HTMLElement, restartBtn: HTMLElement, questListEl: HTMLElement }}
|
||||
*/
|
||||
export function buildGameBar(setup, panelZoo, panelWorld) {
|
||||
const { gameBar } = buildGameBarTitle();
|
||||
const statusBars = buildStatusBar(gameBar);
|
||||
const gameBarActions = document.createElement("div");
|
||||
gameBarActions.className = "game-bar-actions";
|
||||
const viewSwitcher = buildViewSwitcher(panelZoo, panelWorld, setup);
|
||||
const musicBtn = buildMusicBtn();
|
||||
const autoModeBtn = buildAutoModeBtn(setup);
|
||||
gameBarActions.appendChild(autoModeBtn);
|
||||
buildAutoProfilePicker(setup, gameBarActions);
|
||||
gameBarActions.insertBefore(viewSwitcher.viewSwitcherWrap, gameBarActions.firstChild);
|
||||
const { prestigeBtn, restartBtn } = buildPrestigeRestart(setup, gameBarActions);
|
||||
const { questListEl } = buildQuestDropdown(gameBarActions);
|
||||
gameBar.appendChild(gameBarActions);
|
||||
return {
|
||||
gameBar,
|
||||
gameBarActions,
|
||||
...statusBars,
|
||||
viewSwitcherWrap: viewSwitcher.viewSwitcherWrap,
|
||||
viewToggleBtn: viewSwitcher.viewToggleBtn,
|
||||
musicBtn,
|
||||
autoModeBtn,
|
||||
prestigeBtn,
|
||||
restartBtn,
|
||||
questListEl,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user