Files

157 lines
4.0 KiB
TypeScript

import type { MegaTab } from "@/data/home";
import type { MeshkeeCategory } from "@/lib/meshkee-categories";
type TreeNode = MeshkeeCategory & { children: TreeNode[] };
const FEATURED_BY_SLUG: Record<
string,
{ title: string; image: string; imageClass?: string }
> = {
industry: {
title: "Iranian industry",
image: "/images/categories/industry.png",
imageClass: "drum",
},
industries: {
title: "Iranian industry",
image: "/images/categories/industry.png",
imageClass: "drum",
},
stores: {
title: "Persian unique style",
image: "/images/categories/clothes.png",
imageClass: "dress",
},
wholesellers: {
title: "Wholesale market",
image: "/images/categories/shoes.png",
imageClass: "shoes",
},
"whole-sellers": {
title: "Wholesale market",
image: "/images/categories/shoes.png",
imageClass: "shoes",
},
services: {
title: "Professional services",
image: "/images/categories/services.png",
imageClass: "notebook",
},
};
const ICON_BY_SLUG: Record<string, string> = {
industry: "/images/icons/gear.svg",
industries: "/images/icons/gear.svg",
stores: "/images/icons/cart.svg",
wholesellers: "/images/icons/gear.svg",
"whole-sellers": "/images/icons/gear.svg",
services: "/images/icons/home-outline.svg",
};
const DEFAULT_FEATURED = {
title: "Explore IranBay",
image: "/images/categories/clothes.png",
imageClass: "dress",
};
function sortNodes(nodes: TreeNode[]) {
nodes.sort(
(a, b) =>
a.sortOrder - b.sortOrder ||
a.name.localeCompare(b.name, undefined, { sensitivity: "base" }),
);
for (const node of nodes) sortNodes(node.children);
}
function buildTree(categories: MeshkeeCategory[]): TreeNode[] {
const byId = new Map<string, TreeNode>();
for (const category of categories) {
byId.set(category.id, { ...category, children: [] });
}
const roots: TreeNode[] = [];
for (const node of byId.values()) {
if (node.parentId && byId.has(node.parentId)) {
byId.get(node.parentId)!.children.push(node);
} else {
roots.push(node);
}
}
sortNodes(roots);
return roots;
}
function categoryHref(category: MeshkeeCategory) {
const slug = category.slug?.trim();
if (slug) return `/businesses?category=${encodeURIComponent(slug)}`;
return `/businesses?categoryId=${encodeURIComponent(category.id)}`;
}
function resolveIcon(category: MeshkeeCategory) {
const icon = category.icon?.trim();
if (icon) {
if (
icon.startsWith("/") ||
icon.startsWith("http://") ||
icon.startsWith("https://")
) {
return icon;
}
}
return ICON_BY_SLUG[category.slug] ?? "/images/icons/category.svg";
}
function resolveFeatured(category: MeshkeeCategory) {
const mapped = FEATURED_BY_SLUG[category.slug];
if (mapped) return mapped;
return {
...DEFAULT_FEATURED,
title: category.name ? `Explore ${category.name}` : DEFAULT_FEATURED.title,
};
}
/** Roots → groups (L2) → links (L3) for the website mega menu. */
export function buildMegaMenuTabs(categories: MeshkeeCategory[]): MegaTab[] {
const roots = buildTree(categories).filter(
(root) => root.slug !== "other" && root.name.trim(),
);
return roots.map((root) => {
const groups = root.children.map((group) => {
const links = group.children.length
? group.children.map((child) => ({
label: child.name,
href: categoryHref(child),
}))
: [
{
label: group.name,
href: categoryHref(group),
},
];
return {
title: group.name,
links,
};
});
return {
id: root.slug || root.id,
label: root.name,
icon: resolveIcon(root),
groups:
groups.length > 0
? groups
: [
{
title: root.name,
links: [{ label: "Browse", href: categoryHref(root) }],
},
],
featured: resolveFeatured(root),
};
});
}