pagination and api blog metadata all page
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 (
|
||||
<>
|
||||
<Head>
|
||||
<title>درباره کارخانه آجرپزی پاسارگاد</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="معرفی کارخانه آجرپزی پاسارگاد، تاریخچه، چشمانداز، ظرفیت تولید و تیم متخصص ما."
|
||||
/>
|
||||
</Head>
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
<InnerPageBanner
|
||||
title={t('pages_about_title')}
|
||||
imageSrc={images.aboutBanner.src}
|
||||
/>
|
||||
<AboutTopInfo />
|
||||
</main>
|
||||
</>
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
<InnerPageBanner
|
||||
title={t('pages_about_title')}
|
||||
imageSrc={images.aboutBanner.src}
|
||||
/>
|
||||
<AboutTopInfo />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<>
|
||||
<Head>
|
||||
<title>مقالات آموزشی درباره آجر و ساختوساز - پاسارگاد</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="مطالب تخصصی درباره آجر، نحوه انتخاب و کاربرد انواع آجر در ساختمانسازی و معماری."
|
||||
/>
|
||||
</Head>
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
<InnerPageBanner
|
||||
title={t('pages_blog_title')}
|
||||
imageSrc={images.blogBanner.src}
|
||||
/>
|
||||
const { data: posts, pagination } = await getPosts();
|
||||
|
||||
<PostsGrid />
|
||||
</main>
|
||||
</>
|
||||
return (
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
<InnerPageBanner
|
||||
title={t('pages_blog_title')}
|
||||
imageSrc={images.blogBanner.src}
|
||||
/>
|
||||
<PostsGrid initialPosts={posts} initialPagination={pagination} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<>
|
||||
<Head>
|
||||
<title>تماس با کارخانه آجرپزی پاسارگاد</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="راههای ارتباطی با کارخانه آجرپزی پاسارگاد شامل شماره تلفن، آدرس، نقشه و فرم تماس آنلاین."
|
||||
/>
|
||||
</Head>
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
<InnerPageBanner
|
||||
title={t('pages_contact_title')}
|
||||
imageSrc={images.blogBanner.src}
|
||||
/>
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
<InnerPageBanner
|
||||
title={t('pages_contact_title')}
|
||||
imageSrc={images.blogBanner.src}
|
||||
/>
|
||||
|
||||
<div className="relative flex w-full flex-col bg-gray-200 pt-4 md:pt-28">
|
||||
<div className="absolute inset-x-0 inset-y-64 z-2 flex items-end justify-start">
|
||||
<div className="max-md:hidden md:w-1/2">
|
||||
<Image
|
||||
alt="footer-bg"
|
||||
src={images.factoryVector}
|
||||
className="h-full w-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="container mx-auto flex w-full flex-col items-stretch overflow-hidden rounded-lg md:flex-row">
|
||||
<TouchUs />
|
||||
<ContactForm />
|
||||
</div>
|
||||
|
||||
<div className="mt-4 w-full md:mt-28">
|
||||
<div className="h-64 w-full overflow-hidden rounded-lg bg-gray-200">
|
||||
<ContactMap />
|
||||
</div>
|
||||
<div className="relative flex w-full flex-col bg-gray-200 pt-4 md:pt-28">
|
||||
<div className="absolute inset-x-0 inset-y-64 z-2 flex items-end justify-start">
|
||||
<div className="max-md:hidden md:w-1/2">
|
||||
<Image
|
||||
alt="footer-bg"
|
||||
src={images.factoryVector}
|
||||
className="h-full w-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
<div className="container mx-auto flex w-full flex-col items-stretch overflow-hidden rounded-lg md:flex-row">
|
||||
<TouchUs />
|
||||
<ContactForm />
|
||||
</div>
|
||||
|
||||
<div className="mt-4 w-full md:mt-28">
|
||||
<div className="h-64 w-full overflow-hidden rounded-lg bg-gray-200">
|
||||
<ContactMap />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
<Header />
|
||||
|
||||
@@ -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<IParams>;
|
||||
}) {
|
||||
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<IParams>;
|
||||
}) {
|
||||
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 (
|
||||
<main className="">
|
||||
<InnerPageBanner
|
||||
title={productCategory.title}
|
||||
title={productCategory?.title || t('page_products_default_title')}
|
||||
imageSrc={images.homeProductBack.src}
|
||||
/>
|
||||
<div className="container-fluid mx-auto my-24">
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 (
|
||||
<>
|
||||
<Head>
|
||||
<title>پروژههای اجراشده با آجر پاسارگاد</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="نمونه پروژههای موفق اجراشده با آجرهای باکیفیت کارخانه آجرپزی پاسارگاد در سراسر کشور."
|
||||
/>
|
||||
</Head>
|
||||
<main>
|
||||
<InnerPageBanner
|
||||
title={t('pages_projects_title')}
|
||||
imageSrc={images.aboutBanner.src}
|
||||
/>
|
||||
<div className="container-fluid mx-auto my-24">
|
||||
<ProjectsGridView />
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
<main>
|
||||
<InnerPageBanner
|
||||
title={t('pages_projects_title')}
|
||||
imageSrc={images.aboutBanner.src}
|
||||
/>
|
||||
<div className="container-fluid mx-auto my-24">
|
||||
<ProjectsGridView />
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
}));
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user