From fefcd7f7041f7cd8c5c727f5cee5d4c3496547f1 Mon Sep 17 00:00:00 2001 From: Albert Date: Tue, 7 Apr 2026 23:50:37 +0200 Subject: [PATCH] Corregeix imports duplicats a app.js --- js/app.js | 159 +++++++------------------------------------------- js/catalog.js | 150 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 170 insertions(+), 139 deletions(-) diff --git a/js/app.js b/js/app.js index b29dd51..dd67f3f 100644 --- a/js/app.js +++ b/js/app.js @@ -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 d鈥檈sgotar-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'; diff --git a/js/catalog.js b/js/catalog.js index e69de29..4f98ee5 100644 --- a/js/catalog.js +++ b/js/catalog.js @@ -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鈥檈sgotar-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; +} \ No newline at end of file