diff --git a/messages/en.d.json.ts b/messages/en.d.json.ts index 0fc822e..6db926b 100644 --- a/messages/en.d.json.ts +++ b/messages/en.d.json.ts @@ -36,7 +36,6 @@ declare const messages: { "com_home_projects_title_bold": "initiatives", "com_home_projects_description": "Our successful project initiatives showcase our commitment to excellence and innovation across various industries.", - "footer_title": "Industrial Solutions for a Modern World", "footer_description": "We are committed to providing personalized industrial solutions that meet the unique needs of our clients. Our team of experts is dedicated to delivering high-quality products and services that drive success in today’s competitive market.", "footer_slogan": "We are committed to providing personalized industrial solutions.", @@ -65,38 +64,57 @@ declare const messages: { "com_products_products_category_title": "Products of {title} Category", + "com_contact_touch_title": "Get in touch", + "com_contact_touch_title_bold": "with us", + "com_contact_touch_description": "Reach out for any inquiries, support, or to discuss how we can meet your industrial needs.", + "com_contact_touch_option_1": "Contact", + "com_contact_touch_option_2": "e-mail", + "com_contact_touch_option_3": "Our Address", + "com_contact_touch_option_3_description": "7 San Juan Lane Graaf Florisstraat 22A,3021 CH", + "com_contact_title": "Contact ", + "com_contact_title_bold": "me", + "com_contact_first_name": "Enter first name", + "com_contact_last_name": "Enter last name", + "com_contact_email": "Enter your e-mail", + "com_contact_phone": "Enter your phone no.", + "com_contact_textarea": "Write Message", + "com_contact_first_name_required": "Name is required", + "com_contact_last_name_required": "Last name is required", + "com_contact_email_required": "Email is required", + "com_contact_phone_required": "Phone is required", + "com_contact_textarea_required": "Message is required", - -"com_contact_touch_title": "Get in touch", -"com_contact_touch_title_bold": "with us", -"com_contact_touch_description": "Reach out for any inquiries, support, or to discuss how we can meet your industrial needs.", -"com_contact_touch_option_1":"Contact", -"com_contact_touch_option_2":"e-mail", -"com_contact_touch_option_3":"Our Address", -"com_contact_touch_option_3_description":"7 San Juan Lane Graaf Florisstraat 22A,3021 CH", -"com_contact_title": "Contact ", -"com_contact_title_bold": "me", -"com_contact_first_name": "Enter first name", -"com_contact_last_name": "Enter last name", -"com_contact_email": "Enter your e-mail", -"com_contact_phone": "Enter your phone no.", -"com_contact_textarea": "Write Message", + "com_contact_email_error": "Email is not valid", + "com_contact_phone_error": "The contact number is not valid (for example: 09123456789)", + "com_contact_textarea_error": "Message must be at least 10 characters long.", + "com_contact_button_submit": "Submit Message", + "pages_notFound_title": "404 Not Found Page", + "pages_notFound_description": "You can either head back to the Homepage or try a search.", + "pages_notFound_button": "Go To Home", -"com_contact_first_name_required": "Name is required", -"com_contact_last_name_required": "Last name is required", -"com_contact_email_required": "Email is required", -"com_contact_phone_required": "Phone is required", -"com_contact_textarea_required": "Message is required", + "page_about_metadata_title": "About Us - Brick Factory", + "page_about_metadata_description": "Learn more about our commitment to producing high-quality bricks using both traditional and modern manufacturing techniques.", + "page_home_metadata_title": "Home - Brick Factory", + "page_home_metadata_description": "Welcome to our official website, where we showcase our expertise, quality, and innovation in brick manufacturing.", -"com_contact_email_error": "Email is not valid", -"com_contact_phone_error": "The contact number is not valid (for example: 09123456789)", -"com_contact_textarea_error": "Message must be at least 10 characters long.", -"com_contact_button_submit": "Submit Message", -"pages_notFound_title": "404 Not Found Page", -"pages_notFound_description": "You can either head back to the Homepage or try a search.", -"pages_notFound_button":"Go To Home" + "page_contact_metadata_title": "Contact Us - Brick Factory", + "page_contact_metadata_description": "Get in touch with us for more information or to place an order. Our team is here to support your building needs.", + "page_products_metadata_title": "Products - Brick Factory", + "page_products_metadata_description": "Explore our variety of traditional and industrial bricks designed to meet the demands of different construction projects.", + + "page_blog_metadata_title": "Blog - Brick Factory", + "page_blog_metadata_description": "Stay informed with our latest articles, news, and tips related to bricks and building materials.", + + "page_projects_metadata_title": "Projects - Brick Factory", + "page_projects_metadata_description": "Discover successful projects completed using our high-quality bricks and expert craftsmanship.", + + "page_product_categories_metadata_title": "Product Categories - Brick Factory", + "page_product_categories_metadata_description": "Browse through our product categories including Ghazaghi, yellow bricks, facing bricks, and more to find the right solution for your project.", + + "page_not_found_metadata_title": "404 Not Found - Brick Factory", + "page_not_found_metadata_description": "The page you are looking for doesn’t exist. You can return to the homepage or search for what you need." }; export default messages; \ No newline at end of file diff --git a/messages/en.json b/messages/en.json index f819236..61878d1 100644 --- a/messages/en.json +++ b/messages/en.json @@ -33,7 +33,6 @@ "com_home_projects_title_bold": "initiatives", "com_home_projects_description": "Our successful project initiatives showcase our commitment to excellence and innovation across various industries.", - "footer_title": "Industrial Solutions for a Modern World", "footer_description": "We are committed to providing personalized industrial solutions that meet the unique needs of our clients. Our team of experts is dedicated to delivering high-quality products and services that drive success in today’s competitive market.", "footer_slogan": "We are committed to providing personalized industrial solutions.", @@ -62,37 +61,56 @@ "com_products_products_category_title": "Products of {title} Category", + "com_contact_touch_title": "Get in touch", + "com_contact_touch_title_bold": "with us", + "com_contact_touch_description": "Reach out for any inquiries, support, or to discuss how we can meet your industrial needs.", + "com_contact_touch_option_1": "Contact", + "com_contact_touch_option_2": "e-mail", + "com_contact_touch_option_3": "Our Address", + "com_contact_touch_option_3_description": "7 San Juan Lane Graaf Florisstraat 22A,3021 CH", + "com_contact_title": "Contact ", + "com_contact_title_bold": "me", + "com_contact_first_name": "Enter first name", + "com_contact_last_name": "Enter last name", + "com_contact_email": "Enter your e-mail", + "com_contact_phone": "Enter your phone no.", + "com_contact_textarea": "Write Message", + "com_contact_first_name_required": "Name is required", + "com_contact_last_name_required": "Last name is required", + "com_contact_email_required": "Email is required", + "com_contact_phone_required": "Phone is required", + "com_contact_textarea_required": "Message is required", - -"com_contact_touch_title": "Get in touch", -"com_contact_touch_title_bold": "with us", -"com_contact_touch_description": "Reach out for any inquiries, support, or to discuss how we can meet your industrial needs.", -"com_contact_touch_option_1":"Contact", -"com_contact_touch_option_2":"e-mail", -"com_contact_touch_option_3":"Our Address", -"com_contact_touch_option_3_description":"7 San Juan Lane Graaf Florisstraat 22A,3021 CH", -"com_contact_title": "Contact ", -"com_contact_title_bold": "me", -"com_contact_first_name": "Enter first name", -"com_contact_last_name": "Enter last name", -"com_contact_email": "Enter your e-mail", -"com_contact_phone": "Enter your phone no.", -"com_contact_textarea": "Write Message", + "com_contact_email_error": "Email is not valid", + "com_contact_phone_error": "The contact number is not valid (for example: 09123456789)", + "com_contact_textarea_error": "Message must be at least 10 characters long.", + "com_contact_button_submit": "Submit Message", + "pages_notFound_title": "404 Not Found Page", + "pages_notFound_description": "You can either head back to the Homepage or try a search.", + "pages_notFound_button": "Go To Home", -"com_contact_first_name_required": "Name is required", -"com_contact_last_name_required": "Last name is required", -"com_contact_email_required": "Email is required", -"com_contact_phone_required": "Phone is required", -"com_contact_textarea_required": "Message is required", + "page_about_metadata_title": "About Us - Brick Factory", + "page_about_metadata_description": "Learn more about our commitment to producing high-quality bricks using both traditional and modern manufacturing techniques.", + "page_home_metadata_title": "Home - Brick Factory", + "page_home_metadata_description": "Welcome to our official website, where we showcase our expertise, quality, and innovation in brick manufacturing.", -"com_contact_email_error": "Email is not valid", -"com_contact_phone_error": "The contact number is not valid (for example: 09123456789)", -"com_contact_textarea_error": "Message must be at least 10 characters long.", -"com_contact_button_submit": "Submit Message", -"pages_notFound_title": "404 Not Found Page", -"pages_notFound_description": "You can either head back to the Homepage or try a search.", -"pages_notFound_button":"Go To Home" + "page_contact_metadata_title": "Contact Us - Brick Factory", + "page_contact_metadata_description": "Get in touch with us for more information or to place an order. Our team is here to support your building needs.", + "page_products_metadata_title": "Products - Brick Factory", + "page_products_metadata_description": "Explore our variety of traditional and industrial bricks designed to meet the demands of different construction projects.", + + "page_blog_metadata_title": "Blog - Brick Factory", + "page_blog_metadata_description": "Stay informed with our latest articles, news, and tips related to bricks and building materials.", + + "page_projects_metadata_title": "Projects - Brick Factory", + "page_projects_metadata_description": "Discover successful projects completed using our high-quality bricks and expert craftsmanship.", + + "page_product_categories_metadata_title": "Product Categories - Brick Factory", + "page_product_categories_metadata_description": "Browse through our product categories including Ghazaghi, yellow bricks, facing bricks, and more to find the right solution for your project.", + + "page_not_found_metadata_title": "404 Not Found - Brick Factory", + "page_not_found_metadata_description": "The page you are looking for doesn’t exist. You can return to the homepage or search for what you need." } diff --git a/messages/fa.json b/messages/fa.json index 4cdb196..98c6fd4 100644 --- a/messages/fa.json +++ b/messages/fa.json @@ -56,30 +56,54 @@ "pages_products_content_description": "آجرها به عنوان یکی از قدیمی‌ترین و پرکاربردترین مصالح ساختمانی بشر، در طول تاریخ دچار تحول زیادی شده‌اند. امروزه این مصالح در طیف بسیار متنوعی تولید و عرضه می‌شوند و به مهندسان و معماران این امکان را می‌دهند تا مناسب‌ترین آجر را برای هر پروژه و نیازی، از سازه‌های سنتی و تاریخی تا ساختمان‌های مدرن و پیشرفته، انتخاب کنند. برای درک بهتر این تنوع، می‌توان آجرها را بر اساس چند معیار کلیدی طبقه‌بندی کرد که هر یک ویژگی‌ها و کاربردهای خاص خود را دارند.\n۱. طبقه‌بندی بر اساس روش تولید: از سنت تا صنعت پیشرفته\nروش تولید آجرها مستقیماً بر ظاهر، بافت و ویژگی‌های آن‌ها تأثیر می‌گذارد.\nآجرهای دستی/قالبی: این آجرها با فشار دادن دستی خاک رس در قالب تولید می‌شوند. نتیجه، آجری با بافت نسبتاً زبر، لبه‌های نامنظم و ظاهری سنتی‌تر است که هر قطعه حس منحصر به فردی دارد. این نوع آجر اغلب برای پروژه‌های مرمت یا ساخت ساختمان‌هایی با سبک روستایی یا قدیمی استفاده می‌شود.\nآجرهای ماشینی: این آجرها با استفاده از ماشین‌آلات صنعتی تولید می‌شوند که دقت ابعادی و یکنواختی ظاهری بسیار بالاتری دارند. آجرهای ماشینی خود به دو دسته اصلی تقسیم می‌شوند:\nآجرهای سوراخ‌دار/توخالی: این آجرها دارای سوراخ‌هایی هستند که چندین مزیت دارند: کاهش وزن ساختمان، بهبود عایق حرارتی و صوتی و افزایش چسبندگی ملات.\nآجرهای توپر: این آجرها بدون سوراخ بوده و مقاومت فشاری بسیار بالایی دارند. آن‌ها برای سازه‌های باربر و دیوارهایی که به حداکثر استحکام نیاز دارند، ایده‌آل هستند.\n۲. طبقه‌بندی بر اساس نوع و ترکیب مواد اولیه: از خاک رس تا بتن\nجنس آجر تعیین‌کننده ویژگی‌های فیزیکی و شیمیایی آن است.", "com_products_products_category_title": "محصولات دسته {title}", -"com_contact_touch_title": "با ما تماس بگیرید", -"com_contact_touch_title_bold": "", -"com_contact_touch_description": "برای هرگونه سوال، پشتیبانی یا بحث در مورد چگونگی رفع نیازهای صنعتی خود با ما تماس بگیرید.", -"com_contact_touch_option_1":"تماس بگیرید", -"com_contact_touch_option_2":"ایمیل", -"com_contact_touch_option_3":"آدرس ما", -"com_contact_touch_option_3_description":"خیابان سن خوان، پلاک ۷، گراف، فلوریسترات ۲۲A، کد پستی ۳۰۲۱", -"com_contact_title": "با ما تماس بگیرید", -"com_contact_title_bold": "", -"com_contact_first_name": "نام خود را وارد کنید", -"com_contact_last_name": "نام خانوادگی خود را وارد کنید", -"com_contact_email": "ایمیل خود را وارد کنید.", -"com_contact_phone": "شماره تلفن خود را وارد کنید.", -"com_contact_textarea": "پیام خود را وارد کنید", -"com_contact_first_name_required": "نام الزامی است", -"com_contact_last_name_required": "نام خانوادگی الزامی است", -"com_contact_email_required": "ایمیل الزامی است", -"com_contact_phone_required": "شماره تلفن الزامی است", -"com_contact_textarea_required": "پیام الزامی است", -"com_contact_email_error": "ایمیل معتبر نیست", -"com_contact_phone_error": "شماره تماس معتبر نیست (مثلاً: 09123456789)", -"com_contact_textarea_error": "پیام باید حداقل ۱۰ کاراکتر باشد", -"com_contact_button_submit": "ارسال پیام", + "com_contact_touch_title": "با ما تماس بگیرید", + "com_contact_touch_title_bold": "", + "com_contact_touch_description": "برای هرگونه سوال، پشتیبانی یا بحث در مورد چگونگی رفع نیازهای صنعتی خود با ما تماس بگیرید.", + "com_contact_touch_option_1": "تماس بگیرید", + "com_contact_touch_option_2": "ایمیل", + "com_contact_touch_option_3": "آدرس ما", + "com_contact_touch_option_3_description": "خیابان سن خوان، پلاک ۷، گراف، فلوریسترات ۲۲A، کد پستی ۳۰۲۱", + "com_contact_title": "با ما تماس بگیرید", + "com_contact_title_bold": "", + "com_contact_first_name": "نام خود را وارد کنید", + "com_contact_last_name": "نام خانوادگی خود را وارد کنید", + "com_contact_email": "ایمیل خود را وارد کنید.", + "com_contact_phone": "شماره تلفن خود را وارد کنید.", + "com_contact_textarea": "پیام خود را وارد کنید", + "com_contact_first_name_required": "نام الزامی است", + "com_contact_last_name_required": "نام خانوادگی الزامی است", + "com_contact_email_required": "ایمیل الزامی است", + "com_contact_phone_required": "شماره تلفن الزامی است", + "com_contact_textarea_required": "پیام الزامی است", + "com_contact_email_error": "ایمیل معتبر نیست", + "com_contact_phone_error": "شماره تماس معتبر نیست (مثلاً: 09123456789)", + "com_contact_textarea_error": "پیام باید حداقل ۱۰ کاراکتر باشد", + "com_contact_button_submit": "ارسال پیام", "pages_notFound_title": "صفحه ۴۰۴ پیدا نشد", "pages_notFound_description": "صفحه‌ای که به دنبال آن هستید وجود ندارد یا منتقل شده است. لطفاً آدرس را بررسی کنید یا به صفحه اصلی بازگردید.", - "pages_notFound_button": "بازگشت به صفحه اصلی" + "pages_notFound_button": "بازگشت به صفحه اصلی", + + "page_about_metadata_title": "درباره ما - کارخانه آجرسازی", + "page_about_metadata_description": "با ما بیشتر آشنا شوید؛ متعهد به تولید آجرهای باکیفیت با بهره‌گیری از فناوری‌های نوین و روش‌های ساخت پیشرفته.", + + "page_home_metadata_title": "خانه - کارخانه آجرسازی", + "page_home_metadata_description": "به وب‌سایت رسمی ما خوش آمدید؛ جایی که کیفیت، تجربه و نوآوری در تولید انواع آجر به نمایش گذاشته می‌شود.", + + "page_contact_metadata_title": "تماس با ما - کارخانه آجرسازی", + "page_contact_metadata_description": "برای دریافت اطلاعات بیشتر یا ثبت سفارش با ما تماس بگیرید. تیم ما آماده پاسخگویی به شماست.", + + "page_products_metadata_title": "محصولات - کارخانه آجرسازی", + "page_products_metadata_description": "انواع آجرهای سنتی و صنعتی را در این بخش مشاهده کنید؛ مناسب برای پروژه‌های ساختمانی گوناگون.", + + "page_blog_metadata_title": "بلاگ - کارخانه آجرسازی", + "page_blog_metadata_description": "با مقالات، اخبار و آموزش‌های ما در حوزه آجر و مصالح ساختمانی به‌روز بمانید.", + + "page_projects_metadata_title": "پروژه‌ها - کارخانه آجرسازی", + "page_projects_metadata_description": "نگاهی به پروژه‌های موفق ما که با استفاده از آجرهای با کیفیت اجرا شده‌اند.", + + "page_product_categories_metadata_title": "دسته‌بندی محصولات - کارخانه آجرسازی", + "page_product_categories_metadata_description": "دسته‌بندی کامل آجرها شامل آجر قزاقی، آجر زرد، آجر نما و موارد دیگر را در این بخش بررسی کنید.", + + "page_not_found_metadata_title": "۴۰۴ - صفحه پیدا نشد", + "page_not_found_metadata_description": "صفحه‌ای که به دنبال آن هستید یافت نشد. می‌توانید به صفحه اصلی بازگردید یا مجدد جستجو کنید." } diff --git a/src/app/[...not_found]/page.tsx b/src/app/[...not_found]/page.tsx index ce79a51..c40c051 100644 --- a/src/app/[...not_found]/page.tsx +++ b/src/app/[...not_found]/page.tsx @@ -2,7 +2,18 @@ import routeFactory from '@/assets/constants/routeFactory'; import images from '@/assets/images/images'; import Button from '@/components/uikit/button'; import { IPageParams } from '@/models/layout'; -import { getTranslations } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; + +export async function generateMetadata({ params }: { params: IPageParams }) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + + return { + title: t('page_not_found_metadata_title'), + description: t('page_not_found_metadata_description'), + }; +} export default async function NotFound({ params }: { params: IPageParams }) { const paramsData = await params; diff --git a/src/app/[locale]/about-us/page.tsx b/src/app/[locale]/about-us/page.tsx index 4e8d0c8..a6bd762 100644 --- a/src/app/[locale]/about-us/page.tsx +++ b/src/app/[locale]/about-us/page.tsx @@ -4,7 +4,17 @@ import AboutTopInfo from '@/components/pages/about/TopInfo'; import { IPageParams } from '@/models/layout'; import { setRequestLocale } from 'next-intl/server'; import { getTranslations } from 'next-intl/server'; -import Head from 'next/head'; + +export async function generateMetadata({ params }: { params: IPageParams }) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + + return { + title: t('page_about_metadata_title'), + description: t('page_about_metadata_description'), + }; +} export default async function AboutUs({ params, @@ -12,28 +22,16 @@ export default async function AboutUs({ params: IPageParams; }>) { const { locale } = await params; - - // Enable static rendering setRequestLocale(locale); - const t = await getTranslations({ locale }); return ( - <> - - درباره کارخانه آجرپزی پاسارگاد - - -
- - -
- +
+ + +
); } diff --git a/src/app/[locale]/blog/page.tsx b/src/app/[locale]/blog/page.tsx index 264b4cd..c1bbae2 100644 --- a/src/app/[locale]/blog/page.tsx +++ b/src/app/[locale]/blog/page.tsx @@ -2,30 +2,33 @@ import images from '@/assets/images/images'; import InnerPageBanner from '@/components/layout/innerPages/banner'; import PostsGrid from '@/components/pages/blog/PostsGrid'; import { IPageParams } from '@/models/layout'; -import { getTranslations } from 'next-intl/server'; -import Head from 'next/head'; +import { getPosts } from '@/services/blog'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; + +export async function generateMetadata({ params }: { params: IPageParams }) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + + return { + title: t('page_blog_metadata_title'), + description: t('page_blog_metadata_description'), + }; +} export default async function Blog({ params }: { params: IPageParams }) { const paramsData = await params; const t = await getTranslations({ locale: paramsData.locale }); - return ( - <> - - مقالات آموزشی درباره آجر و ساخت‌وساز - پاسارگاد - - -
- + const { data: posts, pagination } = await getPosts(); - -
- + return ( +
+ + +
); } diff --git a/src/app/[locale]/contact-us/page.tsx b/src/app/[locale]/contact-us/page.tsx index 7996e63..f0fc27e 100644 --- a/src/app/[locale]/contact-us/page.tsx +++ b/src/app/[locale]/contact-us/page.tsx @@ -4,52 +4,54 @@ import ContactMap from '@/components/layout/map'; import ContactForm from '@/components/pages/contact/ContactMeForm'; import TouchUs from '@/components/pages/contact/TouchUs'; import Image from 'next/image'; -import { getTranslations } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; import { IPageParams } from '@/models/layout'; import Head from 'next/head'; +export async function generateMetadata({ params }: { params: IPageParams }) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + + return { + title: t('page_contact_metadata_title'), + description: t('page_contact_metadata_description'), + }; +} + export default async function Contact({ params }: { params: IPageParams }) { const { locale } = await params; const t = await getTranslations({ locale }); return ( - <> - - تماس با کارخانه آجرپزی پاسارگاد - - -
- +
+ -
-
-
- footer-bg -
-
-
- - -
- -
-
- -
+
+
+
+ footer-bg
-
- +
+ + +
+ +
+
+ +
+
+ +
); } diff --git a/src/app/[locale]/page.tsx b/src/app/[locale]/page.tsx index b2540af..b6945d3 100644 --- a/src/app/[locale]/page.tsx +++ b/src/app/[locale]/page.tsx @@ -4,13 +4,23 @@ import HomeStorySection from '@/components/pages/home/HomeStorySection'; import HomePageProducts from '@/components/pages/home/Products'; import HomePageProjects from '@/components/pages/home/Projects'; import type { IPageParams } from '@/models/layout.d'; -import { getTranslations } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; +export async function generateMetadata({ params }: { params: IPageParams }) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + + return { + title: t('page_home_metadata_title'), + description: t('page_home_metadata_description'), + }; +} export default async function Home({ params }: { params: IPageParams }) { const { locale } = await params; await getTranslations({ locale }); - + const t = await getTranslations({ locale }); return (
diff --git a/src/app/[locale]/product-categories/[product_category_id]/page.tsx b/src/app/[locale]/product-categories/[product_category_id]/page.tsx index d7d6768..8f1efb5 100644 --- a/src/app/[locale]/product-categories/[product_category_id]/page.tsx +++ b/src/app/[locale]/product-categories/[product_category_id]/page.tsx @@ -7,18 +7,51 @@ import ProductCategoryCardInProducts from '@/components/pages/productCategories/ import ProductList from '@/components/pages/products/productList'; import { IPageParams } from '@/models/layout'; import { getProductCategoryById, getProducts } from '@/services/products'; -import { getTranslations } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; interface IParams { product_category_id: string; } +export async function generateMetadata({ + params, +}: { + params: IPageParams; +}) { + const { locale, product_category_id: productCategoryId } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + + const productCategory = await getProductCategoryById(productCategoryId); + + return { + title: productCategory?.meta_title || t('page_products_metadata_title'), + description: + productCategory?.meta_description || + t('page_products_metadata_description'), + keywords: + productCategory?.meta_keywords || t('page_products_metadata_keywords'), + alternates: { + canonical: `https://your-domain.com/${locale}/products/${productCategory?.slug || productCategoryId}`, + }, + openGraph: { + title: productCategory?.meta_title || t('page_products_metadata_title'), + description: + productCategory?.meta_description || + t('page_products_metadata_description'), + url: `https://your-domain.com/${locale}/products/${productCategory?.slug || productCategoryId}`, + type: 'website', + }, + }; +} + export default async function ProductPage({ params, }: { params: IPageParams; }) { const { product_category_id: productCategoryId, locale } = await params; + setRequestLocale(locale); const t = await getTranslations({ locale }); const routes = routeFactory(t, locale); @@ -30,15 +63,13 @@ export default async function ProductPage({ ...routes.productCategories, href: routes.productCategories.route(), }, - { title: productCategory.title }, + { title: productCategory?.title || t('page_products_default_category') }, ] as IBreadcrumbItem[]; - const refetch = () => {}; - return (
diff --git a/src/app/[locale]/product-categories/page.tsx b/src/app/[locale]/product-categories/page.tsx index 0cfc7b8..dac70cd 100644 --- a/src/app/[locale]/product-categories/page.tsx +++ b/src/app/[locale]/product-categories/page.tsx @@ -4,7 +4,18 @@ import ProductsCategoryCard from '@/components/pages/productCategories/ProductCa import type { IProductCategoryCardProps } from '@/components/pages/productCategories/productCategoryCard.d'; import { IPageParams } from '@/models/layout'; import { getProductCategories } from '@/services/products'; -import { getTranslations } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; + +export async function generateMetadata({ params }: { params: IPageParams }) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + + return { + title: t('page_products_metadata_title'), + description: t('page_products_metadata_description'), + }; +} export default async function ProductsPage({ params, diff --git a/src/app/[locale]/projects/page.tsx b/src/app/[locale]/projects/page.tsx index 1118adb..849c847 100644 --- a/src/app/[locale]/projects/page.tsx +++ b/src/app/[locale]/projects/page.tsx @@ -5,9 +5,19 @@ import ProjectsGrid from '@/components/pages/project/ProjectGrid'; import ProjectsGridView from '@/components/pages/project/projectGridView'; import { IPageParams } from '@/models/layout'; import { getProjects } from '@/services/projects'; -import { getTranslations } from 'next-intl/server'; +import { getTranslations, setRequestLocale } from 'next-intl/server'; import Head from 'next/head'; +export async function generateMetadata({ params }: { params: IPageParams }) { + const { locale } = await params; + setRequestLocale(locale); + const t = await getTranslations({ locale }); + + return { + title: t('page_projects_metadata_title'), + description: t('page_projects_metadata_description'), + }; +} export default async function ProjectsPage({ params, }: { @@ -16,25 +26,15 @@ export default async function ProjectsPage({ const { locale } = await params; const t = await getTranslations({ locale }); const projects: IProjectCardProps[] = await getProjects(); - console.log(projects, 'proj'); return ( - <> - - پروژه‌های اجراشده با آجر پاسارگاد - - -
- -
- -
-
- +
+ +
+ +
+
); } diff --git a/src/app/api/blog/data.ts b/src/app/api/blog/data.ts new file mode 100644 index 0000000..5943695 --- /dev/null +++ b/src/app/api/blog/data.ts @@ -0,0 +1,61 @@ +import images from '@/assets/images/images'; + +export interface IPostCardProps { + id: string; + title: string; + fa_title?: string; + imageSrc: string; + link: string; +} + +export const posts: IPostCardProps[] = [ + { + id: '1', + title: 'Sustainable Practices Reducing Waste in Industrial Production', + fa_title: 'روش‌های پایدار برای کاهش ضایعات در تولید صنعتی', + imageSrc: images.blogImg_1.src, + link: '#', + }, + { + id: '2', + title: 'Advanced Robotics Revolutionizing Industrial Workflows', + fa_title: 'رباتیک پیشرفته و تحول فرآیندهای صنعتی', + imageSrc: images.blogImg_1.src, + link: '#', + }, + { + id: '3', + title: 'Top Benefits of the Robotics in Manufacturing', + fa_title: 'مزایای اصلی استفاده از رباتیک در تولید', + imageSrc: images.blogImg_1.src, + link: '#', + }, + { + id: '4', + title: 'Leveraging Data Analytics for Smarter Production', + fa_title: 'استفاده از تحلیل داده برای تولید هوشمندتر', + imageSrc: images.blogImg_1.src, + link: '#', + }, + { + id: '5', + title: 'Reducing Operational Costs Through Automation', + fa_title: 'کاهش هزینه‌ها با اتوماسیون', + imageSrc: '/images/post5.jpg', + link: '#', + }, + { + id: '6', + title: 'The Advantages of Customized Manufacturing Solutions', + fa_title: 'مزایای راه‌حل‌های سفارشی‌سازی در تولید', + imageSrc: '/images/post6.jpg', + link: '#', + }, +]; + +export function generatePosts(): IPostCardProps[] { + return [...posts, ...posts, ...posts].map((e, i) => ({ + ...e, + id: String(i + 1), + })); +} diff --git a/src/app/api/blog/route.ts b/src/app/api/blog/route.ts new file mode 100644 index 0000000..41746a9 --- /dev/null +++ b/src/app/api/blog/route.ts @@ -0,0 +1,37 @@ +import { NextResponse } from 'next/server'; +import { cookies } from 'next/headers'; +import { generatePosts, IPostCardProps } from './data'; + +export async function GET(request: Request) { + const { searchParams } = new URL(request.url); + const page = parseInt(searchParams.get('page') || '1', 10); + const limit = parseInt(searchParams.get('limit') || '6', 10); + const lang = (await cookies()).get('lang')?.value || 'fa'; + + let posts = generatePosts(); + + let data: IPostCardProps[] = posts.map( + ({ id, title, fa_title, imageSrc, link }) => ({ + id, + title: lang === 'fa' && fa_title ? fa_title : title, + imageSrc, + link, + }), + ); + + const totalItems = data.length; + const totalPages = Math.ceil(totalItems / limit); + const startIndex = (page - 1) * limit; + const endIndex = startIndex + limit; + const paginatedData = data.slice(startIndex, endIndex); + + return NextResponse.json({ + data: paginatedData, + pagination: { + currentPage: page, + totalPages, + totalItems, + limit, + }, + }); +} diff --git a/src/app/api/product_categories/data.ts b/src/app/api/product_categories/data.ts index bc7c753..dbdddff 100644 --- a/src/app/api/product_categories/data.ts +++ b/src/app/api/product_categories/data.ts @@ -5,6 +5,11 @@ export const productCategories = [ fa_title: 'قزاقی', icon: 'categoryGhazaghi', typesCount: 22, + meta_title: 'Ghazaghi Bricks', + meta_description: + 'Ghazaghi Bricks are known for their durability and aesthetic appeal.', + meta_keywords: 'Ghazaghi, bricks, construction, building materials', + slug: 'ghazaghi', priceTypeTitle: 'Economy', fa_priceTypeTitle: 'اقتصادی', bestForTitle: 'Best For Interior Part', @@ -28,6 +33,11 @@ Facing Bricks: Characteristics and Features`, fa_title: 'قرمز', icon: 'categoryGhermez', typesCount: 12, + meta_title: 'Ghermez Bricks', + meta_description: + 'Ghermez Bricks are known for their durability and aesthetic appeal.', + meta_keywords: 'Ghermez, bricks, construction, building materials', + slug: 'ghermez', priceTypeTitle: 'Luxury', fa_priceTypeTitle: 'لاکچری', bestForTitle: 'Best For Exterior Part', @@ -51,6 +61,11 @@ Facing Bricks: Characteristics and Features`, fa_title: 'زرد', icon: 'categoryZard', typesCount: 11, + meta_title: 'Zard Bricks', + meta_description: + 'Zard Bricks are known for their durability and aesthetic appeal.', + meta_keywords: 'Zard, bricks, construction, building materials', + slug: 'zard', priceTypeTitle: 'Economy', fa_priceTypeTitle: 'اقتصادی', bestForTitle: 'Best For Facing', @@ -74,6 +89,11 @@ Facing Bricks: Characteristics and Features`, fa_title: 'سمیرم', icon: 'categorySemirom', typesCount: 40, + meta_title: 'Semirom Bricks', + meta_description: + 'Semirom Bricks are known for their durability and aesthetic appeal.', + meta_keywords: 'Semirom, bricks, construction, building materials', + slug: 'semirom', priceTypeTitle: 'Economy', fa_priceTypeTitle: 'اقتصادی', bestForTitle: 'Best For Building', @@ -99,6 +119,10 @@ interface APIProductCategoryEntity { fa_title?: string; icon: string; typesCount: number; + meta_title: string; + meta_description: string; + meta_keywords: string; + slug: string; priceTypeTitle: string; fa_priceTypeTitle?: string; bestForTitle: string; diff --git a/src/app/api/product_categories/route.ts b/src/app/api/product_categories/route.ts index 4cb1e56..7652ca3 100644 --- a/src/app/api/product_categories/route.ts +++ b/src/app/api/product_categories/route.ts @@ -18,6 +18,10 @@ export async function GET(request: Request) { typesCount, priceTypeTitle, fa_priceTypeTitle, + meta_description, + meta_keywords, + meta_title, + slug, bestForTitle, fa_bestForTitle, description, @@ -28,6 +32,10 @@ export async function GET(request: Request) { id, icon, typesCount, + meta_description, + meta_keywords, + meta_title, + slug, title: fa_title || title, priceTypeTitle: fa_priceTypeTitle || priceTypeTitle, bestForTitle: fa_bestForTitle || bestForTitle, @@ -41,6 +49,10 @@ export async function GET(request: Request) { title, priceTypeTitle, bestForTitle, + meta_description, + meta_keywords, + meta_title, + slug, description, }; }, diff --git a/src/assets/constants/routeFactory/index.ts b/src/assets/constants/routeFactory/index.ts index 8db0ada..4dd2e59 100644 --- a/src/assets/constants/routeFactory/index.ts +++ b/src/assets/constants/routeFactory/index.ts @@ -34,7 +34,7 @@ const routeFactory: RouteFactory = (t, locale) => ({ }, blog: { title: t('pages_blog_title'), - route: () => `/${locale}/blog-us`, + route: () => `/${locale}/blog`, }, contact: { title: t('pages_contact_title'), diff --git a/src/components/layout/hamburgerMenu/index.tsx b/src/components/layout/hamburgerMenu/index.tsx index cf446e3..b9ba01e 100644 --- a/src/components/layout/hamburgerMenu/index.tsx +++ b/src/components/layout/hamburgerMenu/index.tsx @@ -24,7 +24,14 @@ export default function HamburgerMenu({ isOpen, onClose }: Props) { // Generate links dynamically with current locale and translations const routes = routeFactory(t, locale); - const links = [routes.home, routes.about, routes.contact]; + const links = [ + routes.home, + routes.about, + routes.contact, + routes.products, + routes.projects, + routes.blog, + ]; useEffect(() => { function handleClickOutside(event: MouseEvent) { diff --git a/src/components/pages/blog/PostsGrid.tsx b/src/components/pages/blog/PostsGrid.tsx index 1d13e33..b6db168 100644 --- a/src/components/pages/blog/PostsGrid.tsx +++ b/src/components/pages/blog/PostsGrid.tsx @@ -1,64 +1,67 @@ -import images from '@/assets/images/images'; +'use client'; + +import { useState } from 'react'; +import Pagination from '@/components/layout/pagination'; + import Image from 'next/image'; +import Link from 'next/link'; +import { getPosts } from '@/services/blog'; +import { IPostCardProps } from '@/app/api/blog/data'; -const posts = [ - { - title: 'Sustainable Practices Reducing Waste in Industrial Production', - image: images.blogImg_1.src, - link: '#', - }, - { - title: 'Advanced Robotics Revolutionizing Industrial Workflows', - image: images.blogImg_1.src, - link: '#', - }, - { - title: 'Top Benefits of the Robotics in Manufacturing', - image: images.blogImg_1.src, - link: '#', - }, - { - title: 'Leveraging Data Analytics for Smarter Production', - image: images.blogImg_1.src, - link: '#', - }, - { - title: 'Reducing Operational Costs Through Automation', - image: '/images/post5.jpg', - link: '#', - }, - { - title: 'The Advantages of Customized Manufacturing Solutions', - image: '/images/post6.jpg', - link: '#', - }, -]; +export interface IPostsGridProps { + initialPosts: IPostCardProps[]; + initialPagination: { + currentPage: number; + totalPages: number; + totalItems: number; + limit: number; + }; +} + +export default function PostsGrid({ + initialPosts, + initialPagination, +}: IPostsGridProps) { + const [posts, setPosts] = useState(initialPosts); + const [pagination, setPagination] = useState(initialPagination); + + const fetchPage = (page: number) => { + getPosts(page) + .then((res) => { + setPosts(res.data); + setPagination(res.pagination); + }) + .catch((error) => { + console.error('Failed to fetch posts:', error); + }); + }; -export default function PostsGrid() { return ( -
- {posts.map((post, index) => ( -
-
- {post.title} +
+
+ {posts.map((post) => ( +
+
+ {post.title} +
+
+

{post.title}

+ + Read More → + +
- -
-

{post.title}

- - Read More → - -
-
- ))} + ))} +
+
); } diff --git a/src/components/pages/productCategories/productCategoryCard.d.ts b/src/components/pages/productCategories/productCategoryCard.d.ts index 9c9d1d8..cce6959 100644 --- a/src/components/pages/productCategories/productCategoryCard.d.ts +++ b/src/components/pages/productCategories/productCategoryCard.d.ts @@ -7,5 +7,9 @@ export interface IProductCategoryCardProps { typesCount: number; priceTypeTitle: string; bestForTitle: string; + meta_description: string; + meta_keywords: string; + meta_title: string; + slug: string; description: string; } diff --git a/src/services/blog.ts b/src/services/blog.ts new file mode 100644 index 0000000..e059a15 --- /dev/null +++ b/src/services/blog.ts @@ -0,0 +1,33 @@ +'use server'; + +import { IPostCardProps } from '@/app/api/blog/data'; +import api from '@/lib/axios'; +import { cookies } from 'next/headers'; + +export interface IResponse { + data: T; + pagination: { + currentPage: number; + totalPages: number; + totalItems: number; + limit: number; + }; +} + +export async function getPosts( + page = 1, + limit = 6, +): Promise> { + const cookiesStore = await cookies(); + return api + .get('/blog', { + headers: { + Cookie: cookiesStore.toString(), + }, + params: { page, limit }, + }) + .then(({ data }) => { + return Promise.resolve(data); + }) + .catch((error) => Promise.reject(error)); +}