Update carousels, card hover, and IranBay branding.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
import { apiRequest, getAccessToken } from "@/lib/meshkee-api";
|
||||
|
||||
export type CatalogEntityType = "product" | "blog" | "portfolio";
|
||||
|
||||
export type MeshkeeEntityCategory = {
|
||||
id: string;
|
||||
name: string;
|
||||
nameFa?: string | null;
|
||||
parentId: string | null;
|
||||
description?: string | null;
|
||||
seoMetaTitle?: string | null;
|
||||
seoMetaDescription?: string | null;
|
||||
sortOrder?: number;
|
||||
};
|
||||
|
||||
export type UpsertCategoryInput = {
|
||||
parentId?: string | null;
|
||||
name: string;
|
||||
nameFa?: string;
|
||||
description?: string;
|
||||
seoMetaTitle?: string | null;
|
||||
seoMetaDescription?: string | null;
|
||||
};
|
||||
|
||||
export type CreateProductInput = {
|
||||
title: string;
|
||||
nameFa?: string;
|
||||
summary?: string;
|
||||
descriptionHtml?: string;
|
||||
categoryId?: string;
|
||||
featuredMediaId?: string;
|
||||
galleryMediaIds?: string[];
|
||||
tags?: string[];
|
||||
seoMetaTitle?: string | null;
|
||||
seoMetaDescription?: string | null;
|
||||
status?: "draft" | "published" | "archived";
|
||||
};
|
||||
|
||||
export type CreateBlogInput = {
|
||||
title: string;
|
||||
type: "news" | "article" | "blog";
|
||||
abstract?: string;
|
||||
mainTextHtml?: string;
|
||||
categoryId?: string;
|
||||
featuredMediaId?: string;
|
||||
tags?: string[];
|
||||
seoMetaTitle?: string | null;
|
||||
seoMetaDescription?: string | null;
|
||||
status?: "draft" | "published" | "archived";
|
||||
};
|
||||
|
||||
export type CreatePortfolioInput = {
|
||||
titleFa: string;
|
||||
titleEn?: string;
|
||||
abstract?: string;
|
||||
projectUrl?: string;
|
||||
mainTextHtml?: string;
|
||||
categoryId?: string;
|
||||
featuredMediaId?: string;
|
||||
galleryMediaIds?: string[];
|
||||
tags?: string[];
|
||||
seoMetaTitle?: string | null;
|
||||
seoMetaDescription?: string | null;
|
||||
status?: "draft" | "published" | "archived";
|
||||
};
|
||||
|
||||
export async function listMeshkeeEntityCategories(
|
||||
businessId: string,
|
||||
entityType: CatalogEntityType,
|
||||
) {
|
||||
const params = new URLSearchParams({ entityType });
|
||||
const data = await apiRequest<{ items: MeshkeeEntityCategory[] }>(
|
||||
`/businesses/${businessId}/categories?${params}`,
|
||||
{ auth: true },
|
||||
);
|
||||
return (data.items ?? []).map((item) => ({
|
||||
...item,
|
||||
id: String(item.id),
|
||||
parentId: item.parentId == null ? null : String(item.parentId),
|
||||
description: item.description ?? "",
|
||||
seoMetaTitle: item.seoMetaTitle ?? "",
|
||||
seoMetaDescription: item.seoMetaDescription ?? "",
|
||||
}));
|
||||
}
|
||||
|
||||
export function categoryOptionLabel(category: MeshkeeEntityCategory) {
|
||||
if (category.nameFa && category.nameFa !== category.name) {
|
||||
return `${category.name} / ${category.nameFa}`;
|
||||
}
|
||||
return category.name || category.nameFa || "Category";
|
||||
}
|
||||
|
||||
export async function createMeshkeeEntityCategory(
|
||||
businessId: string,
|
||||
entityType: CatalogEntityType,
|
||||
body: UpsertCategoryInput,
|
||||
) {
|
||||
return apiRequest(`/businesses/${businessId}/categories`, {
|
||||
method: "POST",
|
||||
auth: true,
|
||||
body: {
|
||||
entityType,
|
||||
parentId: body.parentId || undefined,
|
||||
name: body.name.trim(),
|
||||
nameFa: body.nameFa?.trim() || undefined,
|
||||
description: body.description?.trim() || undefined,
|
||||
seoMetaTitle: body.seoMetaTitle?.trim() || null,
|
||||
seoMetaDescription: body.seoMetaDescription?.trim() || null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateMeshkeeEntityCategory(
|
||||
businessId: string,
|
||||
categoryId: string,
|
||||
body: UpsertCategoryInput,
|
||||
) {
|
||||
return apiRequest(`/businesses/${businessId}/categories/${categoryId}`, {
|
||||
method: "PATCH",
|
||||
auth: true,
|
||||
body: {
|
||||
parentId: body.parentId === undefined ? undefined : body.parentId || null,
|
||||
name: body.name.trim(),
|
||||
nameFa: body.nameFa?.trim() || null,
|
||||
description: body.description?.trim() || null,
|
||||
seoMetaTitle: body.seoMetaTitle?.trim() || null,
|
||||
seoMetaDescription: body.seoMetaDescription?.trim() || null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteMeshkeeEntityCategory(
|
||||
businessId: string,
|
||||
categoryId: string,
|
||||
) {
|
||||
return apiRequest<{ deletedIds?: string[] }>(
|
||||
`/businesses/${businessId}/categories/${categoryId}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
auth: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export async function uploadMeshkeeMediaFile(businessId: string, file: File) {
|
||||
const token = getAccessToken();
|
||||
const form = new FormData();
|
||||
form.append("files", file);
|
||||
const base =
|
||||
process.env.NEXT_PUBLIC_MESHKEE_API_URL?.replace(/\/$/, "") ||
|
||||
"http://localhost:3010/api/v1";
|
||||
|
||||
const response = await fetch(`${base}/businesses/${businessId}/media`, {
|
||||
method: "POST",
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : undefined,
|
||||
body: form,
|
||||
});
|
||||
const payload = await response.json().catch(() => null);
|
||||
if (!response.ok) {
|
||||
const message =
|
||||
typeof payload?.message === "string"
|
||||
? payload.message
|
||||
: Array.isArray(payload?.message)
|
||||
? payload.message.join(", ")
|
||||
: `Upload failed (${response.status})`;
|
||||
throw new Error(message);
|
||||
}
|
||||
const item = Array.isArray(payload?.items) ? payload.items[0] : payload;
|
||||
return {
|
||||
id: String(item.id),
|
||||
publicUrl: String(item.publicUrl ?? item.url ?? ""),
|
||||
};
|
||||
}
|
||||
|
||||
export async function createMeshkeeProduct(
|
||||
businessId: string,
|
||||
body: CreateProductInput,
|
||||
) {
|
||||
return apiRequest(`/businesses/${businessId}/products`, {
|
||||
method: "POST",
|
||||
auth: true,
|
||||
body: { status: "published", ...body },
|
||||
});
|
||||
}
|
||||
|
||||
export async function createMeshkeeBlog(
|
||||
businessId: string,
|
||||
body: CreateBlogInput,
|
||||
) {
|
||||
return apiRequest(`/businesses/${businessId}/blogs`, {
|
||||
method: "POST",
|
||||
auth: true,
|
||||
body: { status: "published", ...body },
|
||||
});
|
||||
}
|
||||
|
||||
export async function createMeshkeePortfolio(
|
||||
businessId: string,
|
||||
body: CreatePortfolioInput,
|
||||
) {
|
||||
return apiRequest(`/businesses/${businessId}/portfolios`, {
|
||||
method: "POST",
|
||||
auth: true,
|
||||
body: { status: "published", ...body },
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user