Initial commit: website
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
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",
|
||||
},
|
||||
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",
|
||||
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),
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user