Corregeix imports duplicats a app.js
This commit is contained in:
@@ -2,10 +2,18 @@ import {
|
||||
API_URL,
|
||||
AUTO_REFRESH_MS,
|
||||
BLOODBROS_LOGO_URL,
|
||||
WHATSAPP_PHONE,
|
||||
CREATE_CHECKOUT_URL
|
||||
} from './config.js';
|
||||
|
||||
import {
|
||||
fmtPrice,
|
||||
parseDescription,
|
||||
getStockState,
|
||||
getSalesHook,
|
||||
buildWhatsappLink,
|
||||
getFilteredProducts
|
||||
} from './catalog.js';
|
||||
|
||||
const els = {
|
||||
cards: document.getElementById('cards'),
|
||||
errorBox: document.getElementById('errorBox'),
|
||||
@@ -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 d’esgotar-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';
|
||||
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
import { WHATSAPP_PHONE } from './config.js';
|
||||
|
||||
export 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 '-';
|
||||
}
|
||||
|
||||
export function normalizeText(v) {
|
||||
return String(v ?? '').toLowerCase().trim();
|
||||
}
|
||||
|
||||
export function parseDescription(description) {
|
||||
const raw = String(description ?? '').trim();
|
||||
if (!raw) return [];
|
||||
return raw
|
||||
.split(/\n|\r|\||•|;/g)
|
||||
.map(s => s.trim())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
export 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`
|
||||
};
|
||||
}
|
||||
|
||||
export 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 d’esgotar-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.'
|
||||
};
|
||||
}
|
||||
|
||||
export 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)}`;
|
||||
}
|
||||
|
||||
export function getFilteredProducts(products, filters) {
|
||||
const q = normalizeText(filters.search);
|
||||
const top = filters.top;
|
||||
const sort = filters.sort;
|
||||
const price = filters.price;
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user