Corregeix imports duplicats a app.js

This commit is contained in:
2026-04-07 23:50:37 +02:00
parent 618efcd05f
commit fefcd7f704
2 changed files with 170 additions and 139 deletions
+20 -139
View File
@@ -1,10 +1,18 @@
import {
API_URL,
AUTO_REFRESH_MS,
BLOODBROS_LOGO_URL,
WHATSAPP_PHONE,
CREATE_CHECKOUT_URL
import {
API_URL,
AUTO_REFRESH_MS,
BLOODBROS_LOGO_URL,
CREATE_CHECKOUT_URL
} from './config.js';
import {
fmtPrice,
parseDescription,
getStockState,
getSalesHook,
buildWhatsappLink,
getFilteredProducts
} from './catalog.js';
const els = {
cards: document.getElementById('cards'),
@@ -39,14 +47,6 @@ import {
.replaceAll("'", ''');
}
function fmtPrice(product) {
if (product.europe_price_text) return product.europe_price_text;
const n = Number(product.europe_price_number);
if (Number.isFinite(n)) {
return new Intl.NumberFormat('ca-ES', { style: 'currency', currency: 'EUR' }).format(n);
}
return '-';
}
function fmtTime(value) {
if (!value) return '--:--';
@@ -55,130 +55,6 @@ import {
return d.toLocaleTimeString('ca-ES', { hour: '2-digit', minute: '2-digit' });
}
function normalizeText(v) {
return String(v ?? '').toLowerCase().trim();
}
function parseDescription(description) {
const raw = String(description ?? '').trim();
if (!raw) return [];
const lines = raw
.split(/\n|\r|\||•|;/g)
.map(s => s.trim())
.filter(Boolean);
return lines;
}
function getStockState(stock) {
const n = Number(stock || 0);
if (n <= 1) {
return {
cls: 'stock-last',
label: '🔥 Última unitat'
};
}
if (n <= 3) {
return {
cls: 'stock-low',
label: `⚠️ Queden poques unitats · ${n} disponibles`
};
}
return {
cls: 'stock-ok',
label: `Stock disponible · ${n} unitats`
};
}
function getSalesHook(product) {
if (product.top_vendes) {
return null;
}
const stock = Number(product.stock || 0);
if (stock <= 1) {
return {
badge: 'Última oportunitat',
text: 'Aquest model està a punt desgotar-se.'
};
}
if (stock <= 3) {
return {
badge: 'Alta demanda',
text: 'Model amb poques unitats disponibles.'
};
}
return {
badge: 'Selecció premium',
text: 'Una aposta segura per estil i rendiment.'
};
}
function buildWhatsappLink(product) {
const text = [
'Hola Blood Bros Sports,',
'voldria encomanar aquest model:',
`${product.product_code || ''}`,
product.model ? `Model: ${product.model}` : '',
product.category ? `Família: ${product.category}` : '',
product.colors ? `Colors: ${product.colors}` : '',
Number(product.europe_price_number) ? `Preu: ${fmtPrice(product)}` : '',
`Stock visible: ${product.stock ?? ''}`
].filter(Boolean).join('\n');
if (WHATSAPP_PHONE) {
return `https://wa.me/${encodeURIComponent(WHATSAPP_PHONE)}?text=${encodeURIComponent(text)}`;
}
return `https://api.whatsapp.com/send?text=${encodeURIComponent(text)}`;
}
function getFilteredProducts() {
const q = normalizeText(els.searchInput.value);
const top = els.topFilter.value;
const sort = els.sortFilter.value;
const price = els.priceFilter.value;
let data = products.filter(p => Number(p.stock) >= 1);
if (q) {
data = data.filter(p => {
const hay = [p.product_code, p.model, p.category, p.colors, p.description]
.map(normalizeText).join(' ');
return hay.includes(q);
});
}
if (top === 'top') data = data.filter(p => !!p.top_vendes);
if (top === 'normal') data = data.filter(p => !p.top_vendes);
if (price !== 'all') {
data = data.filter(p => {
const n = Number(p.europe_price_number);
if (!Number.isFinite(n)) return false;
if (price === '0-60') return n <= 60;
if (price === '60-80') return n > 60 && n <= 80;
if (price === '80+') return n > 80;
return true;
});
}
data.sort((a, b) => {
const codeA = String(a.product_code || '');
const codeB = String(b.product_code || '');
const priceA = Number.isFinite(Number(a.europe_price_number)) ? Number(a.europe_price_number) : -Infinity;
const priceB = Number.isFinite(Number(b.europe_price_number)) ? Number(b.europe_price_number) : -Infinity;
const stockA = Number(a.stock || 0);
const stockB = Number(b.stock || 0);
switch (sort) {
case 'code-desc': return codeB.localeCompare(codeA, 'ca');
case 'price-asc': return priceA - priceB;
case 'price-desc': return priceB - priceA;
case 'stock-desc': return stockB - stockA;
default: return codeA.localeCompare(codeB, 'ca');
}
});
return data;
}
function renderDescription(product) {
const items = parseDescription(product.description);
@@ -199,7 +75,12 @@ import {
}
function render() {
const data = getFilteredProducts();
const data = getFilteredProducts(products, {
search: els.searchInput.value,
top: els.topFilter.value,
sort: els.sortFilter.value,
price: els.priceFilter.value
});
els.cards.innerHTML = '';
els.errorBox.style.display = 'none';