Connect the storefront to Meshkee catalog, blogs, and static image slots.
Wire homepage specials, product/blog pages, instant search, and the customer portal so the live pharmacy site can be managed from the dashboard. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
cd2f9dfc9d
commit
66e604c426
@@ -0,0 +1,65 @@
|
||||
import { meshkeeGet, tenantPath } from "@/lib/meshkee";
|
||||
|
||||
export type ApiCategory = {
|
||||
id: string;
|
||||
parentId?: string | null;
|
||||
name?: string | null;
|
||||
nameFa?: string | null;
|
||||
slug?: string | null;
|
||||
sortOrder?: number | null;
|
||||
isActive?: boolean;
|
||||
};
|
||||
|
||||
export type NavCategory = {
|
||||
id: string;
|
||||
title: string;
|
||||
href: string;
|
||||
image?: string;
|
||||
children: { id: string; title: string; href: string }[];
|
||||
};
|
||||
|
||||
function titleOf(category: ApiCategory) {
|
||||
return category.nameFa?.trim() || category.name?.trim() || "دستهبندی";
|
||||
}
|
||||
|
||||
function hrefOf(category: ApiCategory) {
|
||||
return `/products?categoryId=${encodeURIComponent(category.id)}`;
|
||||
}
|
||||
|
||||
export async function fetchProductCategories() {
|
||||
const data = await meshkeeGet<{ items?: ApiCategory[] }>(tenantPath("/categories?entityType=product"), {
|
||||
items: [],
|
||||
});
|
||||
return (data.items ?? []).filter((category) => category.isActive !== false);
|
||||
}
|
||||
|
||||
export function buildCategoryTree(flat: ApiCategory[]): NavCategory[] {
|
||||
const byId = new Map(flat.map((category) => [String(category.id), category]));
|
||||
const children = new Map<string, ApiCategory[]>();
|
||||
|
||||
for (const category of flat) {
|
||||
const parentId = category.parentId ? String(category.parentId) : "";
|
||||
const key = parentId && byId.has(parentId) ? parentId : "root";
|
||||
const list = children.get(key) ?? [];
|
||||
list.push(category);
|
||||
children.set(key, list);
|
||||
}
|
||||
|
||||
const sort = (list: ApiCategory[]) =>
|
||||
[...list].sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0) || titleOf(a).localeCompare(titleOf(b), "fa"));
|
||||
|
||||
return sort(children.get("root") ?? []).map((root) => ({
|
||||
id: String(root.id),
|
||||
title: titleOf(root),
|
||||
href: hrefOf(root),
|
||||
children: sort(children.get(String(root.id)) ?? []).map((child) => ({
|
||||
id: String(child.id),
|
||||
title: titleOf(child),
|
||||
href: hrefOf(child),
|
||||
})),
|
||||
}));
|
||||
}
|
||||
|
||||
export async function getNavCategories() {
|
||||
return buildCategoryTree(await fetchProductCategories());
|
||||
}
|
||||
Reference in New Issue
Block a user