54 lines
1.6 KiB
JavaScript
54 lines
1.6 KiB
JavaScript
/** Shared client-side catalog search (catalog.dedupe2.json). */
|
|
|
|
let catalogPromise = null;
|
|
|
|
export function loadSearchCatalog() {
|
|
if (!catalogPromise) {
|
|
catalogPromise = fetch("/data/catalog.dedupe2.json")
|
|
.then((r) => {
|
|
if (!r.ok) throw new Error("catalog fetch failed");
|
|
return r.json();
|
|
})
|
|
.then((data) => data.products || []);
|
|
}
|
|
return catalogPromise;
|
|
}
|
|
|
|
export function displayName(p) {
|
|
const variants = p.colorVariants;
|
|
let title = p.name;
|
|
if (variants && variants.length >= 2) {
|
|
const shade = variants.find((v) => v.slug === p.slug)?.shade;
|
|
if (shade) {
|
|
const trimmed = p.name.trim();
|
|
if (trimmed.endsWith(shade)) title = trimmed.slice(0, -shade.length).trim();
|
|
}
|
|
}
|
|
const fa = p.categoryFa || null;
|
|
if (fa && !title.includes(fa)) return `\u2067${fa} · \u2066${title}\u2069\u2069`;
|
|
return title;
|
|
}
|
|
|
|
export function searchCatalogProducts(products, query, limit) {
|
|
const needle = String(query || "").trim().toLowerCase();
|
|
if (!needle) return [];
|
|
const hits = products.filter((p) => {
|
|
const hay = `${p.name} ${p.category || ""} ${p.categoryFa || ""}`.toLowerCase();
|
|
return hay.includes(needle);
|
|
});
|
|
return limit != null ? hits.slice(0, limit) : hits;
|
|
}
|
|
|
|
export function formatSearchPrice(price) {
|
|
const amount = Number.isFinite(price) ? Math.round(price) : 0;
|
|
return `${new Intl.NumberFormat("fa-IR", { maximumFractionDigits: 0 }).format(amount)} تومان`;
|
|
}
|
|
|
|
export function escapeSearchHtml(s) {
|
|
return String(s)
|
|
.replaceAll("&", "&")
|
|
.replaceAll("<", "<")
|
|
.replaceAll(">", ">")
|
|
.replaceAll('"', """);
|
|
}
|