150 lines
3.8 KiB
JavaScript
150 lines
3.8 KiB
JavaScript
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;
|
||
} |