first deployment of kikomiko with url photos
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
8d98304137
commit
ae3ed7c7b7
Vendored
+167
@@ -0,0 +1,167 @@
|
||||
import {
|
||||
displayName,
|
||||
escapeSearchHtml,
|
||||
formatSearchPrice,
|
||||
loadSearchCatalog,
|
||||
searchCatalogProducts,
|
||||
} from "/js/search-catalog.js?v=persianCopyRtl2";
|
||||
import { initCardShadePickers } from "/js/buy.js?v=priceSort2";
|
||||
import { refreshProductFilters } from "/js/filters.js?v=priceSort2";
|
||||
import { loveYourEyesPillHtml } from "/js/love-your-eyes.js?v=lyeOff";
|
||||
|
||||
function shadeDots(p) {
|
||||
const variants = p.colorVariants;
|
||||
if (!variants || variants.length < 2) return "";
|
||||
const shown = variants.slice(0, 5);
|
||||
const extra = variants.length - shown.length;
|
||||
return `<div class="shade-dots" role="listbox" aria-label="رنگ">${shown
|
||||
.map((v) => {
|
||||
const active = v.slug === p.slug ? " is-active" : "";
|
||||
const bg = v.heroImage
|
||||
? `background-image:url('${escapeSearchHtml(v.heroImage)}')`
|
||||
: "";
|
||||
const href = `/products/${escapeSearchHtml(v.slug)}/`;
|
||||
return `<button
|
||||
type="button"
|
||||
class="shade-dot${active}"
|
||||
style="${bg}"
|
||||
title="${escapeSearchHtml(v.shade)}"
|
||||
aria-label="${escapeSearchHtml(v.shade)}"
|
||||
aria-selected="${active ? "true" : "false"}"
|
||||
data-card-shade
|
||||
data-slug="${escapeSearchHtml(v.slug)}"
|
||||
data-image="${escapeSearchHtml(v.heroImage || "")}"
|
||||
data-price="${v.price}"
|
||||
data-compare="${v.compareAtPrice ?? ""}"
|
||||
data-href="${href}"
|
||||
></button>`;
|
||||
})
|
||||
.join("")}${
|
||||
extra > 0
|
||||
? `<span class="shade-dot-more">+${extra.toLocaleString("fa-IR")} عدد</span>`
|
||||
: ""
|
||||
}</div>`;
|
||||
}
|
||||
|
||||
function cardIsInStock(p) {
|
||||
const variants = p.colorVariants;
|
||||
if (variants && variants.length > 1) {
|
||||
return variants.some((v) => Number(v.stock) > 0);
|
||||
}
|
||||
return Number(p.stock) > 0;
|
||||
}
|
||||
|
||||
function stockBadge(p) {
|
||||
if (cardIsInStock(p)) return "";
|
||||
return `<span class="stock-badge stock-badge--oos">نا موجود</span>`;
|
||||
}
|
||||
|
||||
function filterAttrs(p) {
|
||||
const updated = p.updatedAt ? new Date(p.updatedAt).getTime() : 0;
|
||||
const discount =
|
||||
p.compareAtPrice && p.compareAtPrice > p.price
|
||||
? Math.round((1 - p.price / p.compareAtPrice) * 100)
|
||||
: 0;
|
||||
const prices = [Number(p.price) || 0];
|
||||
for (const v of p.colorVariants || []) {
|
||||
const n = Number(v.price);
|
||||
if (Number.isFinite(n)) prices.push(n);
|
||||
}
|
||||
const min = Math.min(...prices);
|
||||
const max = Math.max(...prices);
|
||||
return [
|
||||
`data-category="${escapeSearchHtml(p.category || "")}"`,
|
||||
`data-category-fa="${escapeSearchHtml(p.categoryFa || "")}"`,
|
||||
`data-price="${p.price}"`,
|
||||
`data-price-min="${min}"`,
|
||||
`data-price-max="${max}"`,
|
||||
`data-name="${escapeSearchHtml(p.name)}"`,
|
||||
`data-updated="${Number.isFinite(updated) ? updated : 0}"`,
|
||||
`data-rating="${p.ratingAvg || 0}"`,
|
||||
`data-reviews="${p.reviewCount || 0}"`,
|
||||
`data-featured="${p.featured ? 1 : 0}"`,
|
||||
`data-in-stock="${cardIsInStock(p) ? 1 : 0}"`,
|
||||
`data-discount="${discount}"`,
|
||||
].join(" ");
|
||||
}
|
||||
|
||||
function productCardHtml(p) {
|
||||
const title = displayName(p);
|
||||
const href = `/products/${escapeSearchHtml(p.slug)}/`;
|
||||
const discount =
|
||||
p.compareAtPrice && p.compareAtPrice > p.price
|
||||
? Math.round((1 - p.price / p.compareAtPrice) * 100)
|
||||
: 0;
|
||||
const badge =
|
||||
discount >= 1 ? `<span class="offer-badge">−${discount}%</span>` : "";
|
||||
const priceHtml =
|
||||
discount >= 1
|
||||
? `<p class="price price--offer" data-card-price>
|
||||
<span class="price-now">${formatSearchPrice(p.price)}</span>
|
||||
<span class="price-was">${formatSearchPrice(p.compareAtPrice)}</span>
|
||||
</p>`
|
||||
: `<p class="price" data-card-price>${formatSearchPrice(p.price)}</p>`;
|
||||
return `<article class="product-card${discount >= 1 ? " product-card--offer" : ""}" data-product-card ${filterAttrs(p)}>
|
||||
<a class="thumb" href="${href}" data-card-link>
|
||||
${badge}
|
||||
${stockBadge(p)}
|
||||
${
|
||||
p.heroImage
|
||||
? `<img src="${escapeSearchHtml(p.heroImage)}" alt="${escapeSearchHtml(title)}" loading="lazy" data-card-image />`
|
||||
: ""
|
||||
}
|
||||
</a>
|
||||
<div class="meta">
|
||||
${loveYourEyesPillHtml(p.slug)}
|
||||
<p class="name"><a href="${href}" data-card-link>${escapeSearchHtml(title)}</a></p>
|
||||
${shadeDots(p)}
|
||||
<div class="card-action-row">
|
||||
${priceHtml}
|
||||
<button type="button" class="card-add-btn" data-add-to-cart data-product-id="${escapeSearchHtml(p.id)}" data-slug="${escapeSearchHtml(p.slug)}" data-name="${escapeSearchHtml(title)}" data-price="${p.price}" data-image="${escapeSearchHtml(p.heroImage || "")}" data-category="${escapeSearchHtml(p.category || "")}" data-category-fa="${escapeSearchHtml(p.categoryFa || "")}" aria-label="افزودن به سبد خرید">
|
||||
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/><line x1="3" y1="6" x2="21" y2="6"/><path d="M16 10a4 4 0 0 1-8 0"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</article>`;
|
||||
}
|
||||
|
||||
const params = new URLSearchParams(location.search);
|
||||
const q = (params.get("q") || "").trim();
|
||||
|
||||
const titleEl = document.querySelector("[data-search-title]");
|
||||
const resultsEl = document.querySelector("[data-search-results]");
|
||||
const emptyEl = document.querySelector("[data-search-empty]");
|
||||
const countEl = document.querySelector("[data-listing-count]");
|
||||
const resultPill = document.querySelector("[data-filters-result-count]");
|
||||
|
||||
if (titleEl && q) titleEl.textContent = `نتایج برای «${q}»`;
|
||||
|
||||
try {
|
||||
const products = await loadSearchCatalog();
|
||||
const hits = searchCatalogProducts(products, q);
|
||||
|
||||
if (!resultsEl) {
|
||||
/* no-op */
|
||||
} else if (!hits.length) {
|
||||
if (emptyEl) emptyEl.hidden = false;
|
||||
resultsEl.innerHTML = "";
|
||||
if (countEl) countEl.textContent = "۰";
|
||||
if (resultPill) resultPill.textContent = "۰";
|
||||
} else {
|
||||
if (emptyEl) emptyEl.hidden = true;
|
||||
|
||||
resultsEl.innerHTML = hits.map(productCardHtml).join("");
|
||||
const n = hits.length.toLocaleString("fa-IR");
|
||||
if (countEl) countEl.textContent = n;
|
||||
if (resultPill) resultPill.textContent = n;
|
||||
|
||||
initCardShadePickers();
|
||||
refreshProductFilters();
|
||||
}
|
||||
} catch {
|
||||
if (emptyEl) {
|
||||
emptyEl.hidden = false;
|
||||
emptyEl.querySelector("p") &&
|
||||
(emptyEl.querySelector("p").textContent = "بارگذاری نتایج ممکن نشد.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user