diff --git a/next.config.ts b/next.config.ts index a9194aa..28d368a 100644 --- a/next.config.ts +++ b/next.config.ts @@ -7,6 +7,10 @@ const nextConfig: NextConfig = { protocol: "https", hostname: "images.unsplash.com", }, + { + protocol: "https", + hostname: "c804387.parspack.net", + }, ], }, }; diff --git a/src/app/blog/[slug]/page.tsx b/src/app/blog/[slug]/page.tsx index fcdb812..c955e83 100644 --- a/src/app/blog/[slug]/page.tsx +++ b/src/app/blog/[slug]/page.tsx @@ -5,10 +5,22 @@ import { notFound } from "next/navigation"; import Container from "@/components/Container"; import PageBanner from "@/components/PageBanner"; import PostCard from "@/components/PostCard"; -import { getPostBySlug, getRelatedPosts, posts } from "@/data/posts"; +import { + getPost, + getPosts, + postContent, + postDate, + postExcerpt, + postImage, + postReadingTime, + postTitle, +} from "@/lib/meshkee"; -export function generateStaticParams() { - return posts.map((p) => ({ slug: p.slug })); +export const revalidate = 300; + +export async function generateStaticParams() { + const { items } = await getPosts({ page: 1, pageSize: 100 }); + return items.map((p) => ({ slug: p.slug })); } export async function generateMetadata({ @@ -17,11 +29,11 @@ export async function generateMetadata({ params: Promise<{ slug: string }>; }): Promise { const { slug } = await params; - const post = getPostBySlug(slug); + const post = await getPost(slug); if (!post) return {}; return { - title: `${post.title} | آراد آریسمان`, - description: post.excerpt, + title: `${postTitle(post)} | آراد آریسمان`, + description: postExcerpt(post, 160), }; } @@ -31,14 +43,22 @@ export default async function BlogDetailPage({ params: Promise<{ slug: string }>; }) { const { slug } = await params; - const post = getPostBySlug(slug); + const post = await getPost(slug); if (!post) notFound(); - const related = getRelatedPosts(post); + const title = postTitle(post); + const image = postImage(post); + const content = postContent(post); + + const related = post.categoryId + ? (await getPosts({ categoryId: post.categoryId, pageSize: 4 })).items + .filter((p) => p.id !== post.id) + .slice(0, 3) + : []; return ( <> - +
@@ -56,32 +76,35 @@ export default async function BlogDetailPage({
- - {post.category} - - {post.date} + {post.categoryNameFa && ( + + {post.categoryNameFa} + + )} + {postDate(post)} - {post.readingTime} + {postReadingTime(post)}
-
- {post.title} + {title} +
+ )} + + {content && ( +
-
- -
- {post.content.map((paragraph) => ( -

- {paragraph} -

- ))} -
+ )}
diff --git a/src/app/blog/page.tsx b/src/app/blog/page.tsx index 9d2dfc4..7af30a8 100644 --- a/src/app/blog/page.tsx +++ b/src/app/blog/page.tsx @@ -3,7 +3,7 @@ import Container from "@/components/Container"; import PageBanner from "@/components/PageBanner"; import PostCard from "@/components/PostCard"; import Pagination from "@/components/Pagination"; -import { posts } from "@/data/posts"; +import { getPosts } from "@/lib/meshkee"; export const metadata: Metadata = { title: "مقالات | آراد آریسمان", @@ -19,10 +19,15 @@ export default async function BlogPage({ searchParams: Promise<{ page?: string }>; }) { const { page } = await searchParams; - const totalPages = Math.max(1, Math.ceil(posts.length / PAGE_SIZE)); - const currentPage = Math.min(Math.max(1, Number(page) || 1), totalPages); - const start = (currentPage - 1) * PAGE_SIZE; - const pageItems = posts.slice(start, start + PAGE_SIZE); + const requestedPage = Math.max(1, Number(page) || 1); + + const { items, total } = await getPosts({ + page: requestedPage, + pageSize: PAGE_SIZE, + }); + + const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE)); + const currentPage = Math.min(requestedPage, totalPages); return ( <> @@ -34,17 +39,25 @@ export default async function BlogPage({
-
- {pageItems.map((post) => ( - - ))} -
+ {items.length > 0 ? ( + <> +
+ {items.map((post) => ( + + ))} +
- + + + ) : ( +

+ به‌زودی مقالات آموزشی جدیدی منتشر می‌شود. +

+ )}
diff --git a/src/app/globals.css b/src/app/globals.css index f5c90cd..5882e12 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -26,3 +26,45 @@ body { color: var(--foreground); font-family: var(--font-vazirmatn), Tahoma, sans-serif; } + +.rich-content { + color: var(--foreground); + line-height: 2; +} + +.rich-content p { + margin-bottom: 1rem; +} + +.rich-content table { + width: 100% !important; + height: auto !important; + border-collapse: collapse; + margin: 1.5rem 0; + font-size: 0.9rem; + overflow: hidden; + border-radius: 0.75rem; +} + +.rich-content table, +.rich-content th, +.rich-content td { + border: 1px solid rgba(0, 0, 0, 0.08) !important; +} + +.rich-content th, +.rich-content td { + padding: 0.6rem 0.75rem; + text-align: center !important; + height: auto !important; +} + +.rich-content tr:first-child { + background: var(--surface); + font-weight: 700; + color: var(--secondary); +} + +.rich-content strong { + color: var(--secondary); +} diff --git a/src/app/products/[slug]/page.tsx b/src/app/products/[slug]/page.tsx index d9a2d1d..f17f247 100644 --- a/src/app/products/[slug]/page.tsx +++ b/src/app/products/[slug]/page.tsx @@ -6,13 +6,18 @@ import Container from "@/components/Container"; import PageBanner from "@/components/PageBanner"; import ProductCard from "@/components/ProductCard"; import { - getProductBySlug, - getRelatedProducts, - products, -} from "@/data/products"; + getProduct, + getProducts, + productImage, + productPriceLabel, + stripHtml, +} from "@/lib/meshkee"; -export function generateStaticParams() { - return products.map((p) => ({ slug: p.slug })); +export const revalidate = 300; + +export async function generateStaticParams() { + const { items } = await getProducts({ page: 1, pageSize: 100 }); + return items.map((p) => ({ slug: p.slug })); } export async function generateMetadata({ @@ -21,11 +26,11 @@ export async function generateMetadata({ params: Promise<{ slug: string }>; }): Promise { const { slug } = await params; - const product = getProductBySlug(slug); + const product = await getProduct(slug); if (!product) return {}; return { - title: `${product.title} | آراد آریسمان`, - description: product.shortDesc, + title: `${product.nameFa} | آراد آریسمان`, + description: product.summary || stripHtml(product.descriptionHtml, 160), }; } @@ -35,18 +40,21 @@ export default async function ProductDetailPage({ params: Promise<{ slug: string }>; }) { const { slug } = await params; - const product = getProductBySlug(slug); + const product = await getProduct(slug); if (!product) notFound(); - const related = getRelatedProducts(product); + const image = productImage(product); + const shortDesc = product.summary || stripHtml(product.descriptionHtml, 160); + + const related = product.categoryId + ? (await getProducts({ categoryId: product.categoryId, pageSize: 4 })).items + .filter((p) => p.id !== product.id) + .slice(0, 3) + : []; return ( <> - +
@@ -65,34 +73,44 @@ export default async function ProductDetailPage({
- {product.title} - - {product.category} - + {image ? ( + {product.nameFa} + ) : ( +
+ آ +
+ )} + {product.categoryNameFa && ( + + {product.categoryNameFa} + + )}

- {product.title} + {product.nameFa}

-

- {product.shortDesc} -

+ {shortDesc && ( +

{shortDesc}

+ )}
- تماس بگیرید - - - ({product.packaging}) + {productPriceLabel(product)} + {!product.store.inStock && ( + + (استعلام موجودی) + + )}
@@ -110,48 +128,18 @@ export default async function ProductDetailPage({ استعلام قیمت
- -
-

نحوه مصرف

-

- {product.usage} -

-
- -
-

مزایای محصول

-
    - {product.benefits.map((b) => ( -
  • - - - - - - {b} -
  • - ))} -
-
-
-

معرفی محصول

-
- {product.description.map((paragraph) => ( -

- {paragraph} -

- ))} + {product.descriptionHtml && ( +
+

معرفی محصول

+
-
+ )}
diff --git a/src/app/products/page.tsx b/src/app/products/page.tsx index 0c7d9a9..b22d1ef 100644 --- a/src/app/products/page.tsx +++ b/src/app/products/page.tsx @@ -3,7 +3,7 @@ import Container from "@/components/Container"; import PageBanner from "@/components/PageBanner"; import ProductCard from "@/components/ProductCard"; import Pagination from "@/components/Pagination"; -import { products } from "@/data/products"; +import { getProducts } from "@/lib/meshkee"; export const metadata: Metadata = { title: "محصولات | آراد آریسمان", @@ -19,13 +19,15 @@ export default async function ProductsPage({ searchParams: Promise<{ page?: string }>; }) { const { page } = await searchParams; - const totalPages = Math.max(1, Math.ceil(products.length / PAGE_SIZE)); - const currentPage = Math.min( - Math.max(1, Number(page) || 1), - totalPages - ); - const start = (currentPage - 1) * PAGE_SIZE; - const pageItems = products.slice(start, start + PAGE_SIZE); + const requestedPage = Math.max(1, Number(page) || 1); + + const { items, total } = await getProducts({ + page: requestedPage, + pageSize: PAGE_SIZE, + }); + + const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE)); + const currentPage = Math.min(requestedPage, totalPages); return ( <> @@ -37,17 +39,25 @@ export default async function ProductsPage({
-
- {pageItems.map((product) => ( - - ))} -
+ {items.length > 0 ? ( + <> +
+ {items.map((product) => ( + + ))} +
- + + + ) : ( +

+ در حال حاضر محصولی برای نمایش وجود ندارد. +

+ )}
diff --git a/src/components/PostCard.tsx b/src/components/PostCard.tsx index 0da2682..63ad716 100644 --- a/src/components/PostCard.tsx +++ b/src/components/PostCard.tsx @@ -1,37 +1,58 @@ import Image from "next/image"; import Link from "next/link"; -import type { Post } from "@/data/posts"; +import type { Post } from "@/lib/meshkee"; +import { + postDate, + postExcerpt, + postImage, + postReadingTime, + postTitle, +} from "@/lib/meshkee"; export default function PostCard({ post }: { post: Post }) { + const title = postTitle(post); + const image = postImage(post); + const excerpt = postExcerpt(post, 90); + return (
- {post.title} - - {post.category} - + {image ? ( + {title} + ) : ( +
+ آ +
+ )} + {post.categoryNameFa && ( + + {post.categoryNameFa} + + )}
- {post.date} + {postDate(post)} - {post.readingTime} + {postReadingTime(post)}

- {post.title} + {title}

-

- {post.excerpt} -

+ {excerpt && ( +

+ {excerpt} +

+ )} ادامه مطلب
- {product.title} - - {product.category} - + {image ? ( + {product.nameFa} + ) : ( +
+ آ +
+ )} + {product.categoryNameFa && ( + + {product.categoryNameFa} + + )}

- {product.title} + {product.nameFa}

-

- {product.shortDesc} -

+ {excerpt && ( +

{excerpt}

+ )}
- تماس بگیرید + + {productPriceLabel(product)} + diff --git a/src/data/posts.ts b/src/data/posts.ts deleted file mode 100644 index b6d86f9..0000000 --- a/src/data/posts.ts +++ /dev/null @@ -1,211 +0,0 @@ -export type Post = { - id: number; - slug: string; - title: string; - excerpt: string; - cover: string; - category: string; - date: string; - readingTime: string; - content: string[]; -}; - -export const posts: Post[] = [ - { - id: 1, - slug: "increase-egg-production-tips", - title: "۵ نکته کلیدی برای افزایش بازده تخم‌گذاری مرغ‌های تخمگذار", - excerpt: - "بازده تخم‌گذاری به عوامل متعددی از جمله تغذیه، نور و مدیریت گله بستگی دارد. در این مقاله به مهم‌ترین نکاتی که می‌توانند بازده گله شما را بهبود دهند می‌پردازیم.", - cover: "/images/product-1.jpg", - category: "طیور", - date: "۱۲ اردیبهشت ۱۴۰۴", - readingTime: "۵ دقیقه مطالعه", - content: [ - "تولید تخم‌مرغ با کیفیت و پایدار، حاصل ترکیبی از تغذیه صحیح، مدیریت محیط پرورش و سلامت عمومی گله است. در ادامه به پنج نکته کلیدی برای بهبود بازده تخم‌گذاری اشاره می‌کنیم.", - "۱. تعادل جیره غذایی: جیره مرغ تخمگذار باید ترکیبی متعادل از انرژی، پروتئین، کلسیم و فسفر باشد. کمبود یا مازاد هر یک از این اجزا می‌تواند مستقیما بر کیفیت پوسته و میزان تولید اثر بگذارد.", - "۲. تامین کلسیم کافی: با نزدیک‌شدن به اوج تولید، نیاز مرغ به کلسیم افزایش می‌یابد. استفاده از مکمل‌های معدنی استاندارد به حفظ استحکام پوسته و کاهش تخم‌های شکسته کمک می‌کند.", - "۳. مدیریت نور: برنامه نوری منظم و پایدار نقش مهمی در تحریک و حفظ چرخه تولید دارد. تغییرات ناگهانی در ساعات روشنایی می‌تواند باعث افت موقت تولید شود.", - "۴. کنترل استرس محیطی: دمای نامناسب، تراکم بالا و جابجایی‌های مکرر از عوامل استرس‌زا هستند که بر بازده تولید تاثیر منفی می‌گذارند.", - "۵. استفاده از مکمل‌های ویتامینه: مکمل‌های ویتامینه با تامین ویتامین‌های ضروری، به حفظ سلامت عمومی گله و پایداری تولید در بلندمدت کمک می‌کنند.", - "رعایت این نکات به همراه مشورت مستمر با کارشناسان تغذیه دام و طیور، می‌تواند بازده اقتصادی واحدهای پرورش مرغ تخمگذار را به‌طور محسوسی افزایش دهد.", - ], - }, - { - id: 2, - slug: "increase-calf-growth-rate", - title: "چگونه رشد گوساله‌های پرواری را افزایش دهیم؟", - excerpt: - "دستیابی به وزن هدف در کوتاه‌ترین زمان ممکن، هدف اصلی هر واحد پرواربندی است. در این مطلب راهکارهای عملی برای افزایش رشد گوساله‌های پرواری را بررسی می‌کنیم.", - cover: "/images/stats-banner.jpg", - category: "دام سنگین", - date: "۳ خرداد ۱۴۰۴", - readingTime: "۶ دقیقه مطالعه", - content: [ - "افزایش وزن‌گیری روزانه و بهبود بازده تبدیل خوراک، دو شاخص کلیدی موفقیت در واحدهای پرواربندی گوساله هستند. دستیابی به این اهداف نیازمند برنامه‌ریزی دقیق تغذیه‌ای و مدیریتی است.", - "شروع دوره پروار با گوساله‌های سالم و عاری از استرس انتقال، پایه‌ای برای موفقیت دوره است. دوره تطبیق اولیه باید با دقت و بدون تغییرات ناگهانی در جیره انجام شود.", - "افزایش تدریجی سهم کنسانتره در جیره، همراه با تامین فیبر کافی از منابعی مانند سبوس گندم، به حفظ سلامت شکمبه و جلوگیری از اسیدوز کمک می‌کند.", - "استفاده از مکمل‌های معدنی و ویتامینه استاندارد، نقش مهمی در پیشگیری از اختلالات متابولیک و حفظ اشتها در طول دوره پروار دارد.", - "پایش منظم وزن گله در بازه‌های زمانی مشخص، امکان ارزیابی روند رشد و اصلاح به‌موقع برنامه تغذیه‌ای را فراهم می‌کند.", - "در نهایت، همکاری نزدیک با کارشناس تغذیه دام برای تنظیم جیره متناسب با نژاد، سن و وزن گوساله‌ها، بهترین نتیجه اقتصادی را در پی خواهد داشت.", - ], - }, - { - id: 3, - slug: "vitamin-supplements-poultry-importance", - title: "اهمیت مکمل‌های ویتامینه در تغذیه طیور", - excerpt: - "ویتامین‌ها اگرچه در مقادیر کم مورد نیاز هستند، اما نقشی حیاتی در سلامت، رشد و تولید طیور ایفا می‌کنند. در این مقاله به نقش مکمل‌های ویتامینه می‌پردازیم.", - cover: "/images/product-3.jpg", - category: "طیور", - date: "۱۸ خرداد ۱۴۰۴", - readingTime: "۴ دقیقه مطالعه", - content: [ - "ویتامین‌ها گروهی از ترکیبات آلی هستند که بدن طیور به مقدار کم به آن‌ها نیاز دارد، اما نقش آن‌ها در فرآیندهای حیاتی بسیار پررنگ است.", - "ویتامین‌های محلول در چربی مانند A، D3، E و K در عملکردهایی مانند بینایی، جذب کلسیم، سیستم ایمنی و انعقاد خون نقش دارند. ویتامین‌های گروه B نیز در متابولیسم انرژی و رشد سلولی موثرند.", - "در سیستم‌های پرورش صنعتی، طیور معمولا دسترسی محدودی به منابع طبیعی ویتامین دارند؛ به همین دلیل تامین این ترکیبات از طریق مکمل‌های استاندارد ضروری است.", - "کمبود ویتامین می‌تواند خود را به شکل کاهش رشد، افت تولید، ضعف سیستم ایمنی و افزایش حساسیت به بیماری‌ها نشان دهد.", - "استفاده منظم و متناسب با سن و مرحله تولید از مکمل‌های ویتامینه استاندارد، یکی از موثرترین و مقرون‌به‌صرفه‌ترین راهکارها برای حفظ سلامت و بازده گله است.", - ], - }, - { - id: 4, - slug: "choosing-right-sheep-concentrate", - title: "راهنمای انتخاب کنسانتره مناسب برای گوسفند", - excerpt: - "انتخاب کنسانتره مناسب باید بر اساس هدف پرورش، سن و وضعیت فیزیولوژیک گله انجام شود. در این مطلب معیارهای انتخاب کنسانتره گوسفند را بررسی می‌کنیم.", - cover: "/images/product-5.jpg", - category: "گوسفند", - date: "۲ تیر ۱۴۰۴", - readingTime: "۵ دقیقه مطالعه", - content: [ - "کنسانتره‌های موجود در بازار از نظر ترکیب انرژی، پروتئین و ریزمغذی‌ها با یکدیگر متفاوت هستند و انتخاب نادرست می‌تواند بر بازده اقتصادی پرورش تاثیر منفی بگذارد.", - "برای گله‌های پرواری، کنسانتره باید انرژی بالایی داشته باشد تا وزن‌گیری روزانه در کوتاه‌ترین زمان ممکن حاصل شود. در مقابل، برای میش‌های مولد، تعادل پروتئین و مواد معدنی اهمیت بیشتری دارد.", - "توجه به مرحله فیزیولوژیک گله (نگهداری، آبستنی، شیردهی یا پروار) در انتخاب فرمول کنسانتره ضروری است، زیرا نیاز غذایی در هر مرحله متفاوت است.", - "کیفیت مواد اولیه و ثبات ترکیبات کنسانتره از بچی به بچ دیگر، از عوامل مهم در انتخاب تامین‌کننده معتبر است.", - "مشورت با کارشناس تغذیه دام برای تنظیم دقیق جیره بر اساس شرایط منطقه، نژاد گله و اهداف تولیدی، بهترین نتیجه را در پی خواهد داشت.", - ], - }, - { - id: 5, - slug: "mineral-supplements-role-livestock-health", - title: "نقش مکمل‌های معدنی در سلامت دام", - excerpt: - "عناصر معدنی اگرچه درصد کمی از وزن بدن دام را تشکیل می‌دهند، اما نقشی اساسی در سلامت، رشد و تولیدمثل دارند. در این مقاله به این نقش می‌پردازیم.", - cover: "/images/product-4.jpg", - category: "دام سنگین", - date: "۱۵ تیر ۱۴۰۴", - readingTime: "۴ دقیقه مطالعه", - content: [ - "عناصر معدنی به دو دسته کلی ماکرومعدنی‌ها (مانند کلسیم، فسفر، سدیم) و ریزمغذی‌های معدنی (مانند روی، مس و منگنز) تقسیم می‌شوند که هر یک نقش مشخصی در بدن دام ایفا می‌کنند.", - "کلسیم و فسفر در ساختار استخوان و تولید شیر نقش دارند، در حالی که عناصر کمیابی مانند روی و مس در عملکرد سیستم ایمنی و باروری اهمیت ویژه‌ای دارند.", - "کمبود مواد معدنی معمولا به آرامی و بدون علائم واضح بروز می‌کند و می‌تواند در بلندمدت باعث کاهش راندمان تولیدمثل و افت تولید شود.", - "استفاده از مکمل‌های معدنی استاندارد و متناسب با تحلیل خاک و علوفه منطقه، راهکاری موثر برای پیشگیری از این کمبودها است.", - "توصیه می‌شود برنامه مکمل‌دهی معدنی با مشورت کارشناس تغذیه و بر اساس وضعیت خاص هر گله تنظیم شود.", - ], - }, - { - id: 6, - slug: "winter-feeding-honeybee-colonies", - title: "تغذیه زنبور عسل در فصل زمستان", - excerpt: - "فصل زمستان به دلیل کمبود منابع طبیعی گرده و شهد، یکی از حساس‌ترین دوره‌ها برای بقای کلنی زنبور عسل است. در این مطلب به نکات تغذیه زمستانه می‌پردازیم.", - cover: "/images/category-8.jpg", - category: "زنبور عسل", - date: "۸ مرداد ۱۴۰۴", - readingTime: "۵ دقیقه مطالعه", - content: [ - "با کاهش دما و کمبود گل در فصل زمستان، کلنی‌های زنبور عسل با محدودیت شدید منابع طبیعی تغذیه مواجه می‌شوند و نیاز به تغذیه کمکی پیدا می‌کنند.", - "ذخیره‌سازی عسل کافی در کندو پیش از شروع سرما، اولین و مهم‌ترین اقدام برای عبور موفق کلنی از زمستان است.", - "در صورت کمبود ذخیره طبیعی، استفاده از مکمل‌های تغذیه‌ای مخصوص زنبور عسل که ترکیبی از قند و پروتئین هستند، می‌تواند از گرسنگی کلنی جلوگیری کند.", - "کنترل رطوبت داخل کندو و جلوگیری از نفوذ سرمای شدید نیز به همان اندازه تغذیه، در بقای کلنی موثر است.", - "بازدید دوره‌ای و محدود از کندوها در روزهای نسبتا گرم زمستان، امکان ارزیابی وضعیت ذخیره غذایی و انجام اقدامات لازم را فراهم می‌کند.", - ], - }, - { - id: 7, - slug: "why-processed-rice-bran", - title: "سبوس برنج فرآوری شده؛ چرا و چگونه؟", - excerpt: - "سبوس برنج خام به دلیل فعالیت آنزیمی بالا مستعد تندی سریع است. فرآیند پایدارسازی این مشکل را برطرف کرده و آن را به منبعی ارزشمند در تغذیه دام تبدیل می‌کند.", - cover: "/images/product-6.jpg", - category: "خوراک دام", - date: "۲۰ مرداد ۱۴۰۴", - readingTime: "۴ دقیقه مطالعه", - content: [ - "سبوس برنج یکی از فرآورده‌های جانبی صنعت شالی‌کوبی است که به دلیل ترکیب غنی از انرژی، فیبر و اسیدهای چرب، پتانسیل بالایی در تغذیه دام و طیور دارد.", - "با این حال، سبوس خام حاوی آنزیم لیپاز فعال است که به سرعت باعث تجزیه چربی و تندشدن آن می‌شود؛ این موضوع کیفیت و خوش‌خوراکی محصول را کاهش می‌دهد.", - "فرآیند پایدارسازی حرارتی، این آنزیم را غیرفعال کرده و ماندگاری، کیفیت تغذیه‌ای و خوش‌خوراکی سبوس را به طور قابل توجهی افزایش می‌دهد.", - "سبوس برنج فرآوری‌شده به دلیل قیمت مناسب و ارزش تغذیه‌ای بالا، گزینه‌ای اقتصادی برای گنجاندن در جیره دام و طیور محسوب می‌شود.", - "توجه به منبع تامین و فرآیند تولید، در انتخاب سبوس برنج با کیفیت باثبات اهمیت زیادی دارد.", - ], - }, - { - id: 8, - slug: "vitamin-d3-deficiency-poultry", - title: "علائم کمبود ویتامین D3 در طیور و راه‌حل آن", - excerpt: - "ویتامین D3 نقشی کلیدی در جذب کلسیم و سلامت استخوان طیور دارد. در این مقاله علائم کمبود آن و راهکارهای پیشگیری را بررسی می‌کنیم.", - cover: "/images/product-11.jpg", - category: "طیور", - date: "۵ شهریور ۱۴۰۴", - readingTime: "۵ دقیقه مطالعه", - content: [ - "ویتامین D3 با تسهیل جذب کلسیم و فسفر از روده، نقش تعیین‌کننده‌ای در استحکام استخوان و کیفیت پوسته تخم‌مرغ ایفا می‌کند.", - "از جمله علائم قابل مشاهده کمبود این ویتامین می‌توان به ضعف پا، کاهش استحکام پوسته تخم‌مرغ، افت تولید و کندی رشد در جوجه‌ها اشاره کرد.", - "از آنجا که طیور پرورش صنعتی معمولا دسترسی محدودی به نور مستقیم خورشید دارند، تامین ویتامین D3 عمدتا باید از طریق جیره غذایی صورت گیرد.", - "استفاده از پرمیکس‌های استاندارد حاوی ویتامین D3 با غلظت مناسب، ساده‌ترین و موثرترین راه پیشگیری از این کمبود است.", - "در صورت مشاهده علائم مشکوک، مشورت با دامپزشک یا کارشناس تغذیه برای بررسی دقیق‌تر و اصلاح جیره توصیه می‌شود.", - ], - }, - { - id: 9, - slug: "feed-supplement-storage-best-practices", - title: "بهترین شیوه‌های نگهداری مکمل‌های خوراک دام", - excerpt: - "نگهداری نامناسب می‌تواند کیفیت و اثربخشی مکمل‌های غذایی را به شدت کاهش دهد. در این مطلب اصول صحیح نگهداری این محصولات را مرور می‌کنیم.", - cover: "/images/category-3.jpg", - category: "خوراک دام", - date: "۱۲ شهریور ۱۴۰۴", - readingTime: "۳ دقیقه مطالعه", - content: [ - "بسیاری از ویتامین‌ها و ترکیبات فعال موجود در مکمل‌های غذایی نسبت به رطوبت، حرارت و نور حساس هستند و نگهداری نادرست می‌تواند اثربخشی آن‌ها را کاهش دهد.", - "مکمل‌ها باید در محیطی خشک، خنک و دور از تابش مستقیم نور خورشید نگهداری شوند. رطوبت بالا می‌تواند باعث کلوخه‌شدن و رشد کپک در محصول شود.", - "کیسه‌های باز‌شده باید به خوبی بسته و در اسرع وقت مصرف شوند تا از افت کیفیت جلوگیری شود.", - "رعایت اصل «اول وارد، اول مصرف» (FIFO) در انبارداری، به اطمینان از مصرف محصولات در تاریخ مناسب کمک می‌کند.", - "چیدمان کیسه‌ها بر روی پالت و دور از تماس مستقیم با کف و دیوار انبار، از رطوبت‌گیری و آسیب احتمالی جلوگیری می‌کند.", - ], - }, - { - id: 10, - slug: "nutrition-impact-on-meat-egg-quality", - title: "تاثیر تغذیه صحیح بر کیفیت گوشت و تخم‌مرغ", - excerpt: - "کیفیت نهایی گوشت و تخم‌مرغ تولیدی، ارتباط مستقیمی با نوع و کیفیت جیره مصرفی دارد. در این مقاله این رابطه را بررسی می‌کنیم.", - cover: "/images/hero-2.jpg", - category: "طیور", - date: "۲۸ شهریور ۱۴۰۴", - readingTime: "۴ دقیقه مطالعه", - content: [ - "ترکیب جیره غذایی طیور، تاثیر مستقیمی بر رنگ، طعم و ارزش تغذیه‌ای محصول نهایی اعم از گوشت و تخم‌مرغ دارد.", - "منابع پروتئینی و اسیدهای چرب موجود در جیره، بر بافت و طعم گوشت اثرگذارند، در حالی که رنگدانه‌های طبیعی موجود در برخی مکمل‌ها، رنگ زرده تخم‌مرغ را بهبود می‌بخشند.", - "مکمل‌های معدنی و ویتامینه با کیفیت، علاوه بر افزایش راندمان تولید، به بهبود شاخص‌های کیفی محصول نهایی نیز کمک می‌کنند.", - "توجه به کیفیت جیره از ابتدای دوره پرورش، نه‌تنها بر عملکرد گله بلکه بر رضایت مصرف‌کننده نهایی محصولات دامی نیز تاثیرگذار است.", - "سرمایه‌گذاری در تغذیه با کیفیت، در نهایت هم به نفع تولیدکننده و هم مصرف‌کننده تمام می‌شود.", - ], - }, -]; - -export function getPostBySlug(slug: string) { - return posts.find((p) => p.slug === slug); -} - -export function getRelatedPosts(post: Post, limit = 3) { - return posts - .filter((p) => p.id !== post.id && p.category === post.category) - .slice(0, limit) - .concat( - posts.filter((p) => p.id !== post.id && p.category !== post.category) - ) - .slice(0, limit); -} diff --git a/src/data/products.ts b/src/data/products.ts deleted file mode 100644 index 7654d05..0000000 --- a/src/data/products.ts +++ /dev/null @@ -1,325 +0,0 @@ -export type Product = { - id: number; - slug: string; - title: string; - category: string; - image: string; - shortDesc: string; - description: string[]; - packaging: string; - usage: string; - benefits: string[]; -}; - -export const products: Product[] = [ - { - id: 1, - slug: "mineral-supplement-laying-hen", - title: "مکمل معدنی مرغ تخمگذار", - category: "مرغ تخمگذار", - image: "/images/product-1.jpg", - shortDesc: "تامین‌کننده عناصر معدنی ضروری برای افزایش کیفیت و دوام پوسته تخم‌مرغ", - description: [ - "مکمل معدنی مرغ تخمگذار آراد آریسمان با فرمولاسیونی متعادل از عناصر ماکرو و میکرو معدنی، نیاز روزانه مرغ‌های تخمگذار را در دوره تولید تامین می‌کند.", - "استفاده منظم از این مکمل به بهبود استحکام پوسته، کاهش تخم‌های شکسته و افزایش یکنواختی وزن تخم‌مرغ کمک می‌کند.", - ], - packaging: "کیسه ۲۵ کیلوگرمی", - usage: "طبق دستور کارشناس تغذیه، معمولا به میزان ۱ تا ۲ درصد در جیره روزانه مخلوط می‌شود.", - benefits: [ - "افزایش استحکام و کیفیت پوسته تخم‌مرغ", - "کاهش درصد تخم‌های شکسته و بدشکل", - "تامین کلسیم و فسفر قابل جذب", - "بهبود یکنواختی تولید در گله", - ], - }, - { - id: 2, - slug: "vitamin-supplement-laying-hen", - title: "مکمل ویتامینه مرغ تخمگذار", - category: "مرغ تخمگذار", - image: "/images/product-2.jpg", - shortDesc: "پک کامل ویتامین‌های محلول در آب و چربی برای دوره تولید", - description: [ - "این مکمل ترکیبی متعادل از ویتامین‌های A، D3، E، K و گروه B است که برای حفظ سلامت عمومی و راندمان تولید مرغ تخمگذار طراحی شده است.", - "کمبود ویتامین در دوره تولید می‌تواند منجر به افت تخم‌گذاری شود؛ مصرف منظم این مکمل از این افت پیشگیری می‌کند.", - ], - packaging: "کیسه ۲۵ کیلوگرمی", - usage: "به صورت مخلوط در خوراک یا محلول در آب آشامیدنی طبق دستور دامپزشک قابل استفاده است.", - benefits: [ - "تقویت سیستم ایمنی گله", - "بهبود باروری و کیفیت جوجه‌درآوری", - "افزایش پایداری تولید در فصول گرم و سرد", - "کاهش استرس ناشی از تراکم و جابجایی", - ], - }, - { - id: 3, - slug: "vitamin-supplement-broiler", - title: "مکمل ویتامینه مرغ گوشتی", - category: "مرغ گوشتی", - image: "/images/product-3.jpg", - shortDesc: "پشتیبان رشد سریع و یکنواخت در دوره پرورش گوشتی", - description: [ - "مکمل ویتامینه مرغ گوشتی آراد آریسمان برای پوشش نیاز ویتامینی جوجه‌های گوشتی در تمامی مراحل رشد فرموله شده است.", - "این محصول با حمایت از سیستم ایمنی و بهبود متابولیسم، به افزایش ضریب تبدیل غذایی کمک می‌کند.", - ], - packaging: "کیسه ۲۵ کیلوگرمی", - usage: "بر اساس سن و وزن گله و طبق برنامه تغذیه‌ای توصیه‌شده مصرف شود.", - benefits: [ - "بهبود ضریب تبدیل غذایی", - "افزایش سرعت و یکنواختی رشد", - "کاهش تلفات دوره پرورش", - "تقویت مقاومت در برابر تنش‌های محیطی", - ], - }, - { - id: 4, - slug: "mineral-supplement-broiler", - title: "مکمل معدنی مرغ گوشتی", - category: "مرغ گوشتی", - image: "/images/product-4.jpg", - shortDesc: "تامین عناصر معدنی برای استخوان‌بندی و رشد سالم", - description: [ - "این مکمل معدنی، ترکیبی غنی از کلسیم، فسفر، سدیم و ریزمغذی‌های ضروری برای رشد اسکلتی سالم جوجه‌های گوشتی است.", - "استخوان‌بندی قوی، پیش‌نیاز دستیابی به وزن هدف در پایان دوره پرورش است.", - ], - packaging: "کیسه ۲۵ کیلوگرمی", - usage: "طبق فرمول جیره و با نظر کارشناس تغذیه دام و طیور در خوراک مخلوط شود.", - benefits: [ - "تقویت استخوان‌بندی و کاهش لنگش", - "بهبود جذب و بازده خوراک مصرفی", - "کاهش ریسک اختلالات متابولیک", - "پشتیبانی از رشد یکنواخت گله", - ], - }, - { - id: 5, - slug: "sheep-concentrate", - title: "کنسانتره گوسفند", - category: "گوسفند", - image: "/images/product-5.jpg", - shortDesc: "خوراک متعادل برای افزایش وزن و بازده پرواربندی", - description: [ - "کنسانتره گوسفند آراد آریسمان با ترکیبی متوازن از انرژی، پروتئین، ویتامین و مواد معدنی، برای دوره پرواربندی و نگهداری طراحی شده است.", - "این محصول مصرف خوراک را بهینه کرده و بازده اقتصادی پرورش را افزایش می‌دهد.", - ], - packaging: "کیسه ۲۵ و ۴۰ کیلوگرمی", - usage: "متناسب با سن، وزن و هدف پرورش (پروار یا نگهداری) در جیره روزانه استفاده شود.", - benefits: [ - "افزایش وزن‌گیری روزانه", - "بهبود بازده خوراک مصرفی", - "تامین انرژی و پروتئین متعادل", - "مناسب برای گله‌های پرواری و مولد", - ], - }, - { - id: 6, - slug: "processed-rice-bran", - title: "سبوس برنج فرآوری شده", - category: "خوراک دام", - image: "/images/product-6.jpg", - shortDesc: "منبع انرژی و فیبر با کیفیت برای جیره دام و طیور", - description: [ - "سبوس برنج فرآوری‌شده با فرآیند پایدارسازی، از تندشدن چربی جلوگیری کرده و ماندگاری و کیفیت تغذیه‌ای بالاتری نسبت به سبوس خام دارد.", - "این محصول منبع خوبی از انرژی، فیبر و اسیدهای چرب ضروری برای جیره دام و طیور است.", - ], - packaging: "کیسه ۲۵ کیلوگرمی", - usage: "به عنوان بخشی از جیره پایه، طبق فرمولاسیون کارشناس تغذیه در نظر گرفته شود.", - benefits: [ - "پایداری بالا در برابر تندی چربی", - "منبع انرژی و فیبر با کیفیت", - "بهبود سلامت دستگاه گوارش", - "مقرون‌به‌صرفه در فرمولاسیون جیره", - ], - }, - { - id: 7, - slug: "wheat-bran", - title: "سبوس گندم", - category: "خوراک دام", - image: "/images/product-7.jpg", - shortDesc: "منبع فیبر طبیعی برای تنظیم عملکرد گوارشی دام", - description: [ - "سبوس گندم به عنوان یک منبع فیبر طبیعی، نقش مهمی در تنظیم عملکرد شکمبه و دستگاه گوارش نشخوارکنندگان دارد.", - "این محصول با کیفیت یکنواخت و عاری از آلودگی، برای مصرف در جیره دام سبک و سنگین مناسب است.", - ], - packaging: "کیسه ۲۵ کیلوگرمی", - usage: "به عنوان جزئی از جیره فیبردار، مطابق فرمول تغذیه دام مصرف شود.", - benefits: [ - "تنظیم عملکرد شکمبه و گوارش", - "منبع فیبر و انرژی طبیعی", - "کیفیت و یکنواختی بالا", - "سازگار با انواع جیره دام", - ], - }, - { - id: 8, - slug: "dairy-cattle-supplement", - title: "مکمل دام شیری", - category: "دام سنگین", - image: "/images/product-8.jpg", - shortDesc: "پشتیبان تولید شیر و سلامت گاوهای شیری", - description: [ - "مکمل دام شیری با تامین انرژی، پروتئین قابل‌متابولیسم، ویتامین و مواد معدنی، از تولید پایدار شیر و سلامت باروری گاو شیری حمایت می‌کند.", - "فرمولاسیون این محصول با در نظر گرفتن نیاز دوره‌های مختلف شیردهی طراحی شده است.", - ], - packaging: "کیسه ۲۵ کیلوگرمی", - usage: "بر اساس مرحله شیردهی و میزان تولید، طبق برنامه تغذیه‌ای در جیره گنجانده شود.", - benefits: [ - "افزایش پایدار تولید شیر", - "بهبود درصد چربی و پروتئین شیر", - "پشتیبانی از باروری و سلامت سم", - "کاهش ریسک اختلالات متابولیک دوره زایمان", - ], - }, - { - id: 9, - slug: "fattening-cattle-supplement", - title: "مکمل دام پرواری", - category: "دام سنگین", - image: "/images/product-9.jpg", - shortDesc: "افزایش وزن‌گیری روزانه در دوره پروار", - description: [ - "مکمل دام پرواری آراد آریسمان با تمرکز بر افزایش بازده خوراک مصرفی، به دستیابی سریع‌تر به وزن هدف در پایان دوره پروار کمک می‌کند.", - "این محصول ترکیبی از مواد معدنی، ویتامین و افزودنی‌های بهبود‌دهنده گوارش را در خود دارد.", - ], - packaging: "کیسه ۲۵ کیلوگرمی", - usage: "متناسب با وزن اولیه و طول دوره پروار، طبق فرمول جیره مصرف شود.", - benefits: [ - "افزایش وزن‌گیری روزانه", - "بهبود بازده تبدیل خوراک", - "کاهش دوره پرواربندی", - "پشتیبانی از سلامت گوارشی دام", - ], - }, - { - id: 10, - slug: "premix-vitamin-k3", - title: "پرمیکس ویتامین K3", - category: "پرمیکس", - image: "/images/product-10.jpg", - shortDesc: "تامین‌کننده ویتامین K3 برای انعقاد خون و سلامت عمومی", - description: [ - "ویتامین K3 نقش کلیدی در فرآیند انعقاد خون و سلامت عمومی دام و طیور دارد و کمبود آن می‌تواند منجر به خونریزی‌های داخلی و کاهش راندمان تولید شود.", - "این پرمیکس با غلظت استاندارد، برای استفاده در فرمولاسیون خوراک کارخانه‌ای و مزرعه‌ای مناسب است.", - ], - packaging: "بسته‌بندی ۲۵ کیلوگرمی", - usage: "توسط کارخانجات خوراک دام و طیور، طبق فرمول استاندارد در پرمیکس نهایی گنجانده می‌شود.", - benefits: [ - "پشتیبانی از فرآیند طبیعی انعقاد خون", - "غلظت استاندارد و قابل اطمینان", - "سازگار با سایر اجزای پرمیکس", - "کنترل کیفی در هر batch تولید", - ], - }, - { - id: 11, - slug: "premix-vitamin-d3", - title: "پرمیکس ویتامین D3", - category: "پرمیکس", - image: "/images/product-11.jpg", - shortDesc: "ضروری برای جذب کلسیم و استخوان‌بندی سالم", - description: [ - "ویتامین D3 نقش تعیین‌کننده‌ای در جذب کلسیم و فسفر و در نتیجه استحکام استخوان و کیفیت پوسته تخم‌مرغ دارد.", - "این پرمیکس با پایداری بالا، برای نگهداری طولانی‌مدت و مصرف در شرایط مختلف اقلیمی مناسب است.", - ], - packaging: "بسته‌بندی ۲۵ کیلوگرمی", - usage: "طبق فرمول استاندارد پرمیکس، توسط واحدهای تولید خوراک دام و طیور استفاده می‌شود.", - benefits: [ - "بهبود جذب کلسیم و فسفر", - "افزایش استحکام استخوان و پوسته تخم‌مرغ", - "پایداری بالا در نگهداری", - "مناسب برای فرمولاسیون‌های صنعتی", - ], - }, - { - id: 12, - slug: "premix-vitamin-a", - title: "پرمیکس ویتامین A", - category: "پرمیکس", - image: "/images/product-12.jpg", - shortDesc: "پشتیبان سیستم ایمنی، بینایی و باروری", - description: [ - "ویتامین A در حفظ سلامت پوشش‌های مخاطی، سیستم ایمنی، بینایی و عملکرد تولیدمثلی دام و طیور نقش اساسی دارد.", - "این پرمیکس با غلظت دقیق و کنترل‌شده، در فرمولاسیون خوراک صنعتی مورد استفاده قرار می‌گیرد.", - ], - packaging: "بسته‌بندی ۲۵ کیلوگرمی", - usage: "طبق فرمول استاندارد پرمیکس و توسط کارشناسان تغذیه در ترکیب خوراک گنجانده می‌شود.", - benefits: [ - "تقویت سیستم ایمنی بدن", - "پشتیبانی از سلامت پوشش‌های مخاطی", - "بهبود عملکرد تولیدمثلی", - "غلظت دقیق و قابل اطمینان", - ], - }, - { - id: 13, - slug: "poultry-concentrate", - title: "کنسانتره طیور", - category: "طیور", - image: "/images/category-4.jpg", - shortDesc: "خوراک کامل و متعادل برای دوره رشد و تولید طیور", - description: [ - "کنسانتره طیور آراد آریسمان با ترکیبی کامل از پروتئین، انرژی، ویتامین و مواد معدنی، نیاز تغذیه‌ای طیور در مراحل مختلف پرورش را پوشش می‌دهد.", - "این محصول برای پرورش‌دهندگان صنعتی و نیمه‌صنعتی طراحی شده و کیفیت یکنواختی در هر بچ تولید دارد.", - ], - packaging: "کیسه ۲۵ کیلوگرمی", - usage: "با نسبت توصیه‌شده در فرمول جیره، متناسب با سن و نوع طیور مصرف شود.", - benefits: [ - "پوشش کامل نیاز تغذیه‌ای طیور", - "افزایش راندمان تولید", - "کیفیت یکنواخت در هر بچ", - "کاهش هزینه نهایی تولید", - ], - }, - { - id: 14, - slug: "sheep-supplement", - title: "مکمل گوسفند", - category: "گوسفند", - image: "/images/category-7.jpg", - shortDesc: "مکمل معدنی و ویتامینه برای سلامت و باروری گله گوسفند", - description: [ - "این مکمل با تامین ویتامین‌ها و عناصر معدنی کمیاب، از سلامت عمومی، باروری و مقاومت گله گوسفند در برابر تنش‌های محیطی پشتیبانی می‌کند.", - "مصرف منظم آن به‌ویژه در دوره‌های حساس تولیدمثل و شیردهی توصیه می‌شود.", - ], - packaging: "کیسه ۲۵ کیلوگرمی", - usage: "طبق دستور کارشناس دامپروری و متناسب با دوره فیزیولوژیک گله مصرف شود.", - benefits: [ - "بهبود باروری و درصد زایش", - "تقویت سیستم ایمنی گله", - "پشتیبانی از دوره شیردهی", - "کاهش تلفات بره در دوره پرورش", - ], - }, - { - id: 15, - slug: "honeybee-supplement", - title: "مکمل زنبور عسل", - category: "زنبور عسل", - image: "/images/category-8.jpg", - shortDesc: "تغذیه کمکی برای تقویت کلنی در فصول کم‌گل", - description: [ - "مکمل زنبور عسل آراد آریسمان به عنوان منبع تغذیه کمکی، در فصول کمبود گل و شهد، از قدرت و بقای کلنی پشتیبانی می‌کند.", - "این محصول با ترکیبی متعادل از قند، پروتئین و ریزمغذی‌ها، به حفظ فعالیت و تولیدمثل کلنی کمک می‌کند.", - ], - packaging: "بسته‌بندی ۱ و ۵ کیلوگرمی", - usage: "طبق راهنمای زنبورداری، معمولا در فصول پاییز و اوایل بهار مورد استفاده قرار می‌گیرد.", - benefits: [ - "تقویت کلنی در فصول کم‌گل", - "پشتیبانی از تولیدمثل ملکه", - "افزایش مقاومت کلنی در زمستان", - "ترکیب متعادل قند و پروتئین", - ], - }, -]; - -export function getProductBySlug(slug: string) { - return products.find((p) => p.slug === slug); -} - -export function getRelatedProducts(product: Product, limit = 3) { - return products - .filter((p) => p.id !== product.id && p.category === product.category) - .slice(0, limit); -} diff --git a/src/lib/meshkee.ts b/src/lib/meshkee.ts new file mode 100644 index 0000000..9426296 --- /dev/null +++ b/src/lib/meshkee.ts @@ -0,0 +1,210 @@ +import { toFa } from "@/lib/format"; + +const API_BASE = "https://api.meshkee.com/api/v1"; +export const TENANT_DOMAIN = "aradarisman.com"; + +export type ProductStore = { + variantCount: number; + minPrice: number | null; + maxPrice: number | null; + inStock: boolean; +}; + +export type Product = { + id: string; + businessId: string; + title: string; + nameFa: string; + summary: string; + descriptionHtml: string; + slug: string; + status: string; + categoryId: string | null; + categoryName: string | null; + categoryNameFa: string | null; + brandId: string | null; + brand: string | null; + tags: string[]; + thumbnailUrl: string | null; + thumbnail: string | null; + image: string | null; + images: string[]; + commentCount: number; + variantCount: number; + createdAt: string; + updatedAt: string; + store: ProductStore; +}; + +export type ProductListResponse = { + items: Product[]; + total: number; + page: number; + pageSize: number; +}; + +async function meshkeeFetch(path: string, revalidateSeconds = 300): Promise { + const res = await fetch(`${API_BASE}${path}`, { + next: { revalidate: revalidateSeconds }, + }); + if (!res.ok) { + throw new Error(`Meshkee API ${path} failed: ${res.status}`); + } + return res.json(); +} + +export function getProducts(params: { + page?: number; + pageSize?: number; + categoryId?: string; + name?: string; +} = {}): Promise { + const query = new URLSearchParams(); + if (params.page) query.set("page", String(params.page)); + if (params.pageSize) query.set("pageSize", String(params.pageSize)); + if (params.categoryId) query.set("categoryId", params.categoryId); + if (params.name) query.set("name", params.name); + + const qs = query.toString(); + return meshkeeFetch( + `/tenants/${TENANT_DOMAIN}/products${qs ? `?${qs}` : ""}` + ); +} + +export async function getProduct(slug: string): Promise { + const res = await fetch( + `${API_BASE}/tenants/${TENANT_DOMAIN}/products/${slug}`, + { next: { revalidate: 300 } } + ); + if (res.status === 404) return null; + if (!res.ok) throw new Error(`Meshkee API product "${slug}" failed: ${res.status}`); + const data = await res.json(); + return data.product as Product; +} + +export function productImage(product: Product): string | null { + return product.thumbnail || product.image || product.thumbnailUrl || null; +} + +export function productPriceLabel(product: Product): string { + if (product.store?.minPrice) { + const formatted = new Intl.NumberFormat("fa-IR").format(product.store.minPrice); + return `${formatted} تومان`; + } + return "تماس بگیرید"; +} + +export function stripHtml(html: string, maxLength = 140): string { + const text = html + .replace(/<[^>]*>/g, " ") + .replace(/ /g, " ") + .replace(/\s+/g, " ") + .trim(); + if (text.length <= maxLength) return text; + return text.slice(0, maxLength).trim() + "…"; +} + +/** + * Blog field names are inferred from the Product/Category convention on this + * same backend (bilingual title/nameFa, descriptionHtml, thumbnail/image, + * categoryNameFa) since no tenant currently has published posts to verify + * against. Accessors below fall back across the plausible field names so the + * UI keeps working once real posts appear, even if the exact name differs. + */ +export type Post = { + id: string; + businessId?: string; + title?: string; + titleFa?: string; + nameFa?: string; + summary?: string; + excerpt?: string; + descriptionHtml?: string; + contentHtml?: string; + content?: string; + slug: string; + status?: string; + categoryId?: string | null; + categoryName?: string | null; + categoryNameFa?: string | null; + tags?: string[]; + thumbnail?: string | null; + thumbnailUrl?: string | null; + image?: string | null; + images?: string[]; + commentCount?: number; + publishedAt?: string | null; + createdAt: string; + updatedAt?: string; +}; + +export type PostListResponse = { + items: Post[]; + total: number; + page: number; + pageSize: number; +}; + +export function getPosts(params: { + page?: number; + pageSize?: number; + categoryId?: string; + title?: string; + type?: "news" | "article" | "blog"; +} = {}): Promise { + const query = new URLSearchParams(); + if (params.page) query.set("page", String(params.page)); + if (params.pageSize) query.set("pageSize", String(params.pageSize)); + if (params.categoryId) query.set("categoryId", params.categoryId); + if (params.title) query.set("title", params.title); + if (params.type) query.set("type", params.type); + + const qs = query.toString(); + return meshkeeFetch( + `/tenants/${TENANT_DOMAIN}/blogs${qs ? `?${qs}` : ""}` + ); +} + +export async function getPost(slug: string): Promise { + const res = await fetch(`${API_BASE}/tenants/${TENANT_DOMAIN}/blogs/${slug}`, { + next: { revalidate: 300 }, + }); + if (res.status === 404) return null; + if (!res.ok) throw new Error(`Meshkee API blog "${slug}" failed: ${res.status}`); + const data = await res.json(); + return (data.blog ?? data.post ?? data) as Post; +} + +export function postTitle(post: Post): string { + return post.nameFa || post.titleFa || post.title || "بدون عنوان"; +} + +export function postContent(post: Post): string { + return post.descriptionHtml || post.contentHtml || post.content || ""; +} + +export function postImage(post: Post): string | null { + return post.thumbnail || post.image || post.thumbnailUrl || null; +} + +export function postExcerpt(post: Post, maxLength = 140): string { + if (post.summary) return post.summary; + if (post.excerpt) return post.excerpt; + return stripHtml(postContent(post), maxLength); +} + +export function postDate(post: Post): string { + const iso = post.publishedAt || post.createdAt; + return new Intl.DateTimeFormat("fa-IR-u-ca-persian", { + year: "numeric", + month: "long", + day: "numeric", + }).format(new Date(iso)); +} + +export function postReadingTime(post: Post): string { + const text = stripHtml(postContent(post), 100000); + const words = text.split(/\s+/).filter(Boolean).length; + const minutes = Math.max(1, Math.round(words / 150)); + return `${toFa(minutes)} دقیقه مطالعه`; +}