Files
moalem-shop/src/lib/slug.ts
T
amirhosein.ashourlooandClaude Sonnet 5 2249a07dee Fix category-slot matching: identity by linkUrl slug, not array position
The homepage category carousel and installments highlights matched
slot.images[i] to categoryList[i] by array index, assuming the business's
CMS upload order lines up with this site's own category sort order. It
doesn't - live data showed a laptop photo landing on "موبایل" and "لوازم
برقی" appearing on the site despite no photo ever being uploaded for it,
purely from index luck. titleFa isn't reliable either: the same laptop image
was titled "تبلت" in the CMS, contradicting its own linkUrl.

Fix: resolve each image's category from the `category` query param on its
own linkUrl (categorySlugFromLinkUrl() in slug.ts, matched against
ApiCategory.slug via the new findNodeBySlug()). The homepage carousel is now
fully slot-driven - it iterates slot.images (in the CMS's own sortOrder) and
simply omits any category with no matching image, per explicit product
direction, rather than falling back to a placeholder. Installments keeps its
curated HIGHLIGHT_IDS list with a placeholder for uncovered categories,
since that page always shows the same fixed set, but now uses the same
identity-based lookup instead of position.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 07:36:24 +03:30

40 lines
1.4 KiB
TypeScript

// Canonical Meshkee detail URLs are /{id}/{slug} — the slug segment is
// SEO-only, so it is built from the Farsi name rather than the DB slug.
export function faSlug(input: string | null | undefined): string {
if (!input) return "-";
return (
input
.trim()
.replace(/[\/\?%*:|"'<>.,()]/g, "")
.replace(/\s+/g, "-")
.slice(0, 80) || "-"
);
}
export function productHref(id: string, nameFa?: string | null, title?: string | null): string {
return `/products/${id}/${faSlug(nameFa || title)}`;
}
export function categoryHref(id: string, nameFa?: string | null, name?: string | null): string {
return `/products/category/${id}/${faSlug(nameFa || name)}`;
}
export function blogHref(id: string, title?: string | null): string {
return `/blog/${id}/${faSlug(title)}`;
}
// Static-image-slot items carry a business-picked linkUrl like
// "https://moalem.shop/products?category=mobile" — the `category` query
// param is the DB slug (ApiCategory.slug), the one reliable way to identify
// which category an uploaded photo is actually for. Position in the list
// and the item's own titleFa are NOT reliable — see AGENTS.md "Static-image
// slots" for the real mismatch this was built to fix.
export function categorySlugFromLinkUrl(linkUrl: string | null | undefined): string | null {
if (!linkUrl) return null;
try {
return new URL(linkUrl).searchParams.get("category");
} catch {
return null;
}
}