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:
162
web/js/ui-world-map-sales.js
Normal file
162
web/js/ui-world-map-sales.js
Normal file
@@ -0,0 +1,162 @@
|
||||
import { addPendingBaby, addReceptionAnimal } from "./zoo.js";
|
||||
import { acceptSale, rejectSale, deliverSale, placeBid } from "./api-client.js";
|
||||
import {
|
||||
animalLabel,
|
||||
salesPanelMySales,
|
||||
salesPanelToRecover,
|
||||
salesPanelAuctions,
|
||||
salesBtnAccept,
|
||||
salesBtnReject,
|
||||
salesBtnDeliver,
|
||||
salesBtnBid,
|
||||
salesPendingValidation,
|
||||
salesValidationInMinutes,
|
||||
salesBidInputAriaLabel,
|
||||
noFreeNursery,
|
||||
noFreeReception,
|
||||
} from "./texts-fr.js";
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} panel
|
||||
* @param {{ asSeller?: Array<{ id: string, animal_id: string, is_baby: boolean, initial_price: number, best_bid_amount?: number | null }> }} api
|
||||
* @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void, animalEmoji: Record<string, string> }} ctx
|
||||
*/
|
||||
export function addSalesPanelSellerSection(panel, api, ctx) {
|
||||
if (!api.asSeller || api.asSeller.length === 0) return;
|
||||
const { state, setState, setError, animalEmoji } = ctx;
|
||||
const sellerTitle = document.createElement("div");
|
||||
sellerTitle.className = "sales-panel-title";
|
||||
sellerTitle.textContent = salesPanelMySales;
|
||||
panel.appendChild(sellerTitle);
|
||||
for (const s of api.asSeller) {
|
||||
const row = document.createElement("div");
|
||||
row.className = "sales-panel-row";
|
||||
const emoji = animalEmoji[s.animal_id] ?? "🐾";
|
||||
const label = s.is_baby ? `Bébé ${animalLabel[s.animal_id] ?? s.animal_id}` : (animalLabel[s.animal_id] ?? s.animal_id);
|
||||
row.innerHTML = `<span class="offer-emoji">${emoji}</span><span class="offer-label">${label}</span><span class="offer-price">${s.initial_price} 💰</span>`;
|
||||
if (s.best_bid_amount !== null) {
|
||||
const btnWrap = document.createElement("div");
|
||||
btnWrap.className = "sales-panel-actions";
|
||||
const acceptBtn = document.createElement("button");
|
||||
acceptBtn.type = "button";
|
||||
acceptBtn.textContent = salesBtnAccept;
|
||||
acceptBtn.className = "sales-btn-accept";
|
||||
acceptBtn.addEventListener("click", () => {
|
||||
acceptSale(s.id).then(() => { state.salesFromApi = undefined; setState(); }).catch((e) => { setError(e.message || "Erreur"); setState(); });
|
||||
});
|
||||
const rejectBtn = document.createElement("button");
|
||||
rejectBtn.type = "button";
|
||||
rejectBtn.textContent = salesBtnReject;
|
||||
rejectBtn.className = "sales-btn-reject";
|
||||
rejectBtn.addEventListener("click", () => {
|
||||
rejectSale(s.id).then(() => { state.salesFromApi = undefined; setState(); }).catch((e) => { setError(e.message || "Erreur"); setState(); });
|
||||
});
|
||||
btnWrap.appendChild(acceptBtn);
|
||||
btnWrap.appendChild(rejectBtn);
|
||||
row.appendChild(btnWrap);
|
||||
}
|
||||
panel.appendChild(row);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ id: string, animal_id: string, is_baby: boolean, status?: string, validated_at?: string }} s
|
||||
* @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void, animalEmoji: Record<string, string> }} ctx
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
export function createBuyerDeliverRow(s, ctx) {
|
||||
const { state, setState, setError, animalEmoji } = ctx;
|
||||
const row = document.createElement("div");
|
||||
row.className = "sales-panel-row";
|
||||
const emoji = animalEmoji[s.animal_id] ?? "🐾";
|
||||
const label = s.is_baby ? `Bébé ${animalLabel[s.animal_id] ?? s.animal_id}` : (animalLabel[s.animal_id] ?? s.animal_id);
|
||||
row.innerHTML = `<span class="offer-emoji">${emoji}</span><span class="offer-label">${label}</span>`;
|
||||
const validatedAtMs = s.validated_at ? new Date(s.validated_at).getTime() : 0;
|
||||
const nowMs = Date.now();
|
||||
const pendingValidation = s.status === "sold" && validatedAtMs > nowMs;
|
||||
if (pendingValidation) {
|
||||
const remainingMin = Math.ceil((validatedAtMs - nowMs) / 60000);
|
||||
const pendingEl = document.createElement("span");
|
||||
pendingEl.className = "sales-pending-validation";
|
||||
pendingEl.setAttribute("aria-label", salesPendingValidation);
|
||||
pendingEl.textContent = `⏳ ${salesValidationInMinutes.replace("%s", String(remainingMin))}`;
|
||||
row.appendChild(pendingEl);
|
||||
}
|
||||
const deliverBtn = document.createElement("button");
|
||||
deliverBtn.type = "button";
|
||||
deliverBtn.textContent = salesBtnDeliver;
|
||||
deliverBtn.className = "sales-btn-deliver";
|
||||
deliverBtn.disabled = pendingValidation;
|
||||
deliverBtn.addEventListener("click", () => {
|
||||
const [ok, keyOrReason] = s.is_baby ? addPendingBaby(state, s.animal_id, true) : addReceptionAnimal(state, s.animal_id);
|
||||
if (!ok) {
|
||||
setError(keyOrReason === "NoFreeNursery" ? noFreeNursery : keyOrReason === "NoFreeReception" ? noFreeReception : String(keyOrReason));
|
||||
setState();
|
||||
return;
|
||||
}
|
||||
setState();
|
||||
deliverSale(s.id).then(() => { state.salesFromApi = undefined; setState(); }).catch((e) => { setError(e.message || "Erreur"); setState(); });
|
||||
});
|
||||
row.appendChild(deliverBtn);
|
||||
return row;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} panel
|
||||
* @param {{ asBuyerUndelivered?: Array<{ id: string, animal_id: string, is_baby: boolean, status?: string, validated_at?: string }> }} api
|
||||
* @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void, animalEmoji: Record<string, string> }} ctx
|
||||
*/
|
||||
export function addSalesPanelBuyerSection(panel, api, ctx) {
|
||||
if (!api.asBuyerUndelivered || api.asBuyerUndelivered.length === 0) return;
|
||||
const buyerTitle = document.createElement("div");
|
||||
buyerTitle.className = "sales-panel-title";
|
||||
buyerTitle.textContent = salesPanelToRecover;
|
||||
panel.appendChild(buyerTitle);
|
||||
for (const s of api.asBuyerUndelivered) {
|
||||
panel.appendChild(createBuyerDeliverRow(s, ctx));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} panel
|
||||
* @param {{ active?: Array<{ id: string, seller_zoo_id: string, animal_id: string, is_baby: boolean, initial_price: number, best_bid_amount?: number | null }> }} api
|
||||
* @param {string} playerZooId
|
||||
* @param {{ state: import("./types.js").GameState, setState: () => void, setError: (s: string) => void, animalEmoji: Record<string, string> }} ctx
|
||||
*/
|
||||
export function addSalesPanelActiveSection(panel, api, playerZooId, ctx) {
|
||||
if (!api.active || api.active.length === 0) return;
|
||||
const { state, setState, setError, animalEmoji } = ctx;
|
||||
const activeTitle = document.createElement("div");
|
||||
activeTitle.className = "sales-panel-title";
|
||||
activeTitle.textContent = salesPanelAuctions;
|
||||
panel.appendChild(activeTitle);
|
||||
for (const s of api.active) {
|
||||
if (s.seller_zoo_id === playerZooId) {
|
||||
// skip own listings in active list
|
||||
} else {
|
||||
const row = document.createElement("div");
|
||||
row.className = "sales-panel-row sales-panel-row-bid";
|
||||
const emoji = animalEmoji[s.animal_id] ?? "🐾";
|
||||
const label = s.is_baby ? `Bébé ${animalLabel[s.animal_id] ?? s.animal_id}` : (animalLabel[s.animal_id] ?? s.animal_id);
|
||||
const minBid = (s.best_bid_amount ?? s.initial_price) + 1;
|
||||
row.innerHTML = `<span class="offer-emoji">${emoji}</span><span class="offer-label">${label}</span><span class="offer-price">${s.initial_price} 💰</span>`;
|
||||
const input = document.createElement("input");
|
||||
input.type = "number";
|
||||
input.min = String(minBid);
|
||||
input.value = String(minBid);
|
||||
input.className = "sales-bid-input";
|
||||
input.setAttribute("aria-label", salesBidInputAriaLabel);
|
||||
const bidBtn = document.createElement("button");
|
||||
bidBtn.type = "button";
|
||||
bidBtn.textContent = salesBtnBid;
|
||||
bidBtn.className = "sales-btn-bid";
|
||||
bidBtn.addEventListener("click", () => {
|
||||
const amount = Number(input.value) || minBid;
|
||||
placeBid(s.id, amount).then(() => { state.salesFromApi = undefined; setState(); }).catch((e) => { setError(e.message || "Erreur"); setState(); });
|
||||
});
|
||||
row.appendChild(input);
|
||||
row.appendChild(bidBtn);
|
||||
panel.appendChild(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user