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) => 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) => 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, }; }