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>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
db7d00e473
commit
2249a07dee
@@ -6,24 +6,34 @@ import { FreeMode } from "swiper/modules";
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import "swiper/css";
|
||||
import "swiper/css/free-mode";
|
||||
import { categoryHref } from "@/lib/slug";
|
||||
import { findNodeBySlug } from "@/lib/categoryTree";
|
||||
import { categoryHref, categorySlugFromLinkUrl } from "@/lib/slug";
|
||||
import type { CategoryNode, StaticImageSlot } from "@/lib/types";
|
||||
|
||||
// Circular category thumbnails. The "categories" static-image slot has no
|
||||
// per-category id, so its images (kind: list, duplicatable) are matched
|
||||
// positionally to the category list, in the same order the business fills
|
||||
// them in — each still links to its real category page, only the art swaps.
|
||||
// A category past the end of the slot, or the whole thing when the slot is
|
||||
// empty, keeps its placeholder at public/images/categories/{id}.svg.
|
||||
// Fully slot-driven: each image in the "categories" slot carries its own
|
||||
// linkUrl (e.g. "...?category=mobile"), whose `category` param is the real
|
||||
// DB slug — that's what identifies which category a photo is for, not the
|
||||
// image's position in the list or its (business-typed, sometimes wrong)
|
||||
// titleFa. A category the business hasn't uploaded a photo for simply isn't
|
||||
// shown here — no placeholder, per the "only what's in the panel" brief.
|
||||
// See AGENTS.md "Static-image slots" for the mismatch this replaced.
|
||||
export default function CategoryCarousel({
|
||||
categories,
|
||||
roots,
|
||||
slot,
|
||||
}: {
|
||||
categories: CategoryNode[];
|
||||
roots: CategoryNode[];
|
||||
slot?: StaticImageSlot;
|
||||
}) {
|
||||
if (categories.length === 0) return null;
|
||||
const slotImages = slot?.images ?? [];
|
||||
const items = (slot?.images ?? [])
|
||||
.map((img) => {
|
||||
const catSlug = categorySlugFromLinkUrl(img.linkUrl);
|
||||
const cat = catSlug ? findNodeBySlug(roots, catSlug) : undefined;
|
||||
if (!cat) return null;
|
||||
return { key: img.id, art: img.url, cat };
|
||||
})
|
||||
.filter((x): x is { key: string; art: string; cat: CategoryNode } => Boolean(x));
|
||||
|
||||
if (items.length === 0) return null;
|
||||
|
||||
return (
|
||||
<section className="boxed mt-8" aria-label="دستهبندی محصولات">
|
||||
@@ -39,11 +49,10 @@ export default function CategoryCarousel({
|
||||
1024: { slidesPerView: 7 },
|
||||
}}
|
||||
>
|
||||
{categories.map((cat, i) => {
|
||||
{items.map(({ key, art, cat }) => {
|
||||
const label = cat.nameFa || cat.name;
|
||||
const art = slotImages[i]?.url || `/images/categories/${cat.id}.svg`;
|
||||
return (
|
||||
<SwiperSlide key={cat.id}>
|
||||
<SwiperSlide key={key}>
|
||||
<Link href={categoryHref(cat.id, cat.nameFa, cat.name)} className="group flex flex-col items-center gap-2">
|
||||
<span className="relative size-[104px] overflow-hidden rounded-full bg-surface transition group-hover:bg-brand-soft sm:size-[124px] lg:size-[140px]">
|
||||
<Image src={art} alt={label} fill sizes="140px" className="object-contain p-3" />
|
||||
|
||||
Reference in New Issue
Block a user