Wire Meshkee static images, SEO, and customer account menu.

Connect homepage image slots and favicon to the API, add sitemap config and page metadata, and implement header login with profile/admin dropdown.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-09-01 11:22:02 +03:30
co-authored by Cursor
parent 424e339986
commit 7e8a1ef7dc
33 changed files with 1708 additions and 150 deletions
+55
View File
@@ -0,0 +1,55 @@
import { meshkeeApiBase, websiteDomain } from "@/lib/config";
export async function meshkeeGet<T>(path: string, fallback: T, revalidate = 60): Promise<T> {
try {
const response = await fetch(`${meshkeeApiBase}${path}`, {
next: { revalidate },
});
if (!response.ok) return fallback;
return (await response.json()) as T;
} catch {
return fallback;
}
}
export function tenantPath(suffix: string) {
return `/tenants/${encodeURIComponent(websiteDomain)}${suffix}`;
}
export type WebsiteFavicon = {
faviconUrl: string | null;
logoUrl: string | null;
logoDarkUrl: string | null;
hasDedicatedFavicon: boolean;
};
export type BusinessInfo = {
id: string;
name: string;
nameFa: string;
about: string;
vision: string;
logoUrl: string | null;
logoDarkUrl: string | null;
faviconUrl: string | null;
};
const defaultFavicon: WebsiteFavicon = {
faviconUrl: null,
logoUrl: null,
logoDarkUrl: null,
hasDedicatedFavicon: false,
};
export async function getWebsiteFavicon() {
return meshkeeGet<WebsiteFavicon>(tenantPath("/website/favicon"), defaultFavicon);
}
export async function getBusinessInfo() {
return meshkeeGet<BusinessInfo | null>(tenantPath("/website/business-info"), null);
}
export async function getBusinessId() {
const business = await getBusinessInfo();
return business?.id != null ? String(business.id) : "";
}