Files
Alireza HassaniandCursor c84147e765 Add Torob tags, Meshkee SEO routes, and updated static-image slots.
Product pages emit crawler-readable meta, public URLs use id plus Farsi slugs, and the homepage catalog matches the dashboard slot keys.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-01 16:12:26 +03:30

41 lines
1.5 KiB
TypeScript

import type { ApiBlog, ApiCategory, ApiProduct } from "./api";
import { detailPath, slugifyForUrl } from "./seo-slug";
export function productTitle(product: Pick<ApiProduct, "id" | "nameFa" | "title">) {
return product.nameFa?.trim() || product.title?.trim() || String(product.id);
}
export function categoryTitle(category: Pick<ApiCategory, "id" | "nameFa" | "name">) {
return category.nameFa?.trim() || category.name?.trim() || String(category.id);
}
/** Public product URL: /products/{id}/{nameFaSlug} — never use legacy DB slug. */
export function productHref(product: Pick<ApiProduct, "id" | "nameFa" | "title"> | string, title?: string | null) {
if (typeof product === "string") {
return detailPath("/products", product, title?.trim() || product);
}
return detailPath("/products", product.id, productTitle(product));
}
/** Public category URL: /products/category/{id}/{nameFaSlug} */
export function categoryHref(category: Pick<ApiCategory, "id" | "nameFa" | "name">) {
return detailPath("/products/category", category.id, categoryTitle(category));
}
/** Public blog URL: /blog/{id}/{titleSlug} */
export function blogHref(blog: Pick<ApiBlog, "id" | "title">) {
return detailPath("/blog", blog.id, blog.title);
}
export function productNameSlug(title: string) {
return slugifyForUrl(title);
}
export function categoryNameSlug(title: string) {
return slugifyForUrl(title);
}
export function blogTitleSlug(title: string) {
return slugifyForUrl(title);
}