Files
website/src/lib/map-home-slots.ts
T

297 lines
8.2 KiB
TypeScript

import type { Category } from "@/data/home";
import {
ABOUT,
BLACK_ITEMS,
CATEGORIES,
MEGA_MENU_TABS,
} from "@/data/home";
import type { HeroSlideData } from "@/components/home/HeroSlider";
import { categoryPath } from "@/lib/category-path";
import type { PublicWebsiteSlotItem } from "@/lib/website-slots";
import { firstForSlot, itemsForSlot } from "@/lib/website-slots";
export type HomeSlotContent = {
heroSlides: HeroSlideData[];
categories: Category[];
leather: {
image: string;
nameFa: string;
nameEn: string;
subtext: string;
linkText: string;
link: string;
};
promoSale: {
image?: string;
nameFa?: string;
nameEn?: string;
subtext?: string;
link?: string;
} | null;
promoDiscount: {
image?: string;
nameFa?: string;
nameEn?: string;
subtext?: string;
link?: string;
} | null;
promoAutumn: {
image?: string;
nameFa?: string;
nameEn?: string;
subtext?: string;
link?: string;
} | null;
blackItems: Array<{
id: string;
image: string;
alt: string;
nameFa: string;
nameEn: string;
href: string;
}>;
about: {
titleFa: string;
titleEn: string;
lead: string;
body: string;
image: string;
imageSecondary: string;
};
paymentBadges: string;
megaTabs: Array<{
id: string;
nameFa: string;
nameEn: string;
href: string;
image: string;
links: readonly { label: string; href: string }[];
columns?: readonly {
title: string;
href: string;
links: readonly { label: string; href: string }[];
}[];
}>;
};
function slotItems(
items: PublicWebsiteSlotItem[],
slug: string,
...legacy: string[]
) {
const modern = itemsForSlot(items, slug);
if (modern.length) return modern;
for (const key of legacy) {
const found = itemsForSlot(items, key);
if (found.length) return found;
}
return [];
}
function firstSlot(
items: PublicWebsiteSlotItem[],
slug: string,
...legacy: string[]
) {
return slotItems(items, slug, ...legacy)[0] ?? null;
}
export function mapHomeSlots(
items: PublicWebsiteSlotItem[],
): HomeSlotContent {
const heroItems = slotItems(items, "hero-slider", "home.hero");
const heroSlides: HeroSlideData[] =
heroItems.length > 0
? heroItems.map((item) => ({
id: item.id,
image: item.imageUrl || "/images/home/banners/hero.jpg",
imagePosition: "object-[center_top]",
title: item.nameFa || item.nameEn || "مانا کالکشن",
subtitle: item.nameEn || item.subtext || "",
cta: {
label: item.linkText || "مشاهده",
href: item.link || "/products",
},
}))
: [];
const categoryItems = slotItems(items, "category-strip");
const categories: Category[] =
categoryItems.length > 0
? categoryItems.map((item, index) => {
const fallback = CATEGORIES[index % CATEGORIES.length];
return {
id: item.id || `cat-${index}`,
nameFa: item.nameFa || `دسته ${index + 1}`,
nameEn: item.nameEn || "",
image: item.imageUrl || fallback.image,
href:
item.link ||
(fallback
? categoryPath(fallback)
: categoryPath({ id: "coat", nameEn: "Coat", nameFa: "کت" })),
};
})
: CATEGORIES.map((cat) => {
const legacy = firstForSlot(items, `home.category.${cat.id}`);
if (!legacy) return cat;
return {
...cat,
nameFa: legacy.nameFa || cat.nameFa,
nameEn: legacy.nameEn || cat.nameEn,
image: legacy.imageUrl || cat.image,
href: legacy.link || cat.href || categoryPath(cat),
};
});
const leatherSlot = firstSlot(
items,
"leather-banner",
"home.banner.leather",
);
const leather = {
image: leatherSlot?.imageUrl || "/images/home/banners/leather.png",
nameFa: leatherSlot?.nameFa || "هنر پوشیدن",
nameEn: leatherSlot?.nameEn || "THE ART OF DRESSING",
subtext: leatherSlot?.subtext || "",
linkText: leatherSlot?.linkText || "کالکشن چرم",
link: leatherSlot?.link || "/products?collection=leather",
};
const saleSlot = firstSlot(
items,
"promo-1",
"promo-sale",
"home.promo.sale",
);
const promoSale = saleSlot
? {
image: saleSlot.imageUrl || undefined,
nameEn: saleSlot.nameEn || "",
nameFa: saleSlot.nameFa || "",
subtext: saleSlot.subtext || "",
link: saleSlot.link || "/products?sale=1",
}
: null;
const discountSlot = firstSlot(items, "promo-2", "promo-discount");
const promoDiscount = discountSlot
? {
image: discountSlot.imageUrl || undefined,
nameFa: discountSlot.nameFa || discountSlot.linkText || "",
nameEn: discountSlot.nameEn || "",
subtext: discountSlot.subtext || "",
link: discountSlot.link || "/products?sale=1",
}
: null;
const autumnSlot = firstSlot(
items,
"promo-3",
"promo-autumn",
"home.promo.autumn",
);
const promoAutumn = autumnSlot
? {
image: autumnSlot.imageUrl || undefined,
nameEn: autumnSlot.nameEn || "",
nameFa: autumnSlot.nameFa || autumnSlot.linkText || "",
subtext: autumnSlot.subtext || "",
link: autumnSlot.link || "/products?collection=autumn",
}
: null;
const portraitItems = slotItems(items, "four-portrait-banner");
const blackItems =
portraitItems.length > 0
? Array.from({ length: 4 }).map((_, index) => {
const slot =
portraitItems.find((row) => row.sortOrder === index) ??
portraitItems[index];
const fallback = BLACK_ITEMS[index] ?? BLACK_ITEMS[0];
return {
id: slot?.id || fallback.id,
image: slot?.imageUrl || fallback.image,
alt: slot?.nameFa || fallback.alt,
nameFa: slot?.nameFa || fallback.nameFa,
nameEn: slot?.nameEn || fallback.nameEn,
href:
slot?.link ||
`/products?color=black&item=${fallback.id}`,
};
})
: BLACK_ITEMS.map((item) => {
const slot = firstForSlot(items, `home.black.${item.id}`);
return {
id: item.id,
image: slot?.imageUrl || item.image,
alt: slot?.nameFa || item.alt,
nameFa: slot?.nameFa || item.nameFa,
nameEn: slot?.nameEn || item.nameEn,
href: slot?.link || `/products?color=black&item=${item.id}`,
};
});
const aboutItems = slotItems(items, "about");
const aboutPrimary =
aboutItems.find((row) => row.sortOrder === 0) ??
aboutItems[0] ??
firstSlot(items, "about-primary", "home.about.primary");
const aboutSecondary =
aboutItems.find((row) => row.sortOrder === 1) ??
aboutItems[1] ??
firstSlot(items, "about-secondary", "home.about.secondary");
const about = {
titleFa: aboutPrimary?.nameFa || ABOUT.titleFa,
titleEn: aboutPrimary?.nameEn || ABOUT.titleEn,
lead: aboutPrimary?.subtext || ABOUT.lead,
body: ABOUT.body,
image: aboutPrimary?.imageUrl || ABOUT.image,
imageSecondary: aboutSecondary?.imageUrl || ABOUT.imageSecondary,
};
const paymentSlot = firstSlot(
items,
"payment-badges",
"home.footer.payment_badges",
);
const paymentBadges =
paymentSlot?.imageUrl || "/images/home/banners/payment-badges.png";
const megaItems = slotItems(items, "mega-menu");
const megaTabs = MEGA_MENU_TABS.map((tab, index) => {
const slot =
megaItems.find((row) => row.sortOrder === index) ??
megaItems[index] ??
firstForSlot(items, `nav.mega.${tab.id}`);
return {
id: tab.id,
nameFa: slot?.nameFa || tab.nameFa,
nameEn: slot?.nameEn || tab.nameEn,
href: slot?.link || tab.href,
image: slot?.imageUrl || tab.image,
links: tab.links,
columns: [
{
title: slot?.nameFa || tab.nameFa,
href: slot?.link || tab.href,
links: tab.links,
},
],
};
});
return {
heroSlides,
categories,
leather,
promoSale,
promoDiscount,
promoAutumn,
blackItems,
about,
paymentBadges,
megaTabs,
};
}