Files

150 lines
3.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 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.'
};
}
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;
}