create single project page and set blog section in home page
This commit is contained in:
@@ -45,6 +45,12 @@ declare const messages: {
|
||||
"com_home_projects_show_more": "More Projects",
|
||||
"com_home_projects_details_CTA": "Show Details",
|
||||
|
||||
"com_home_blog_title": "Our Blog",
|
||||
"com_home_blog_title_bold": "initiatives",
|
||||
"com_home_blog_description": "Our blog content",
|
||||
"com_home_blog_show_more": "More Content",
|
||||
"com_home_blog_details_CTA": "Show Details",
|
||||
|
||||
"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.",
|
||||
|
||||
@@ -42,6 +42,12 @@
|
||||
"com_home_projects_show_more": "More Projects",
|
||||
"com_home_projects_details_CTA": "Show Details",
|
||||
|
||||
"com_home_blog_title": "Our Blog",
|
||||
"com_home_blog_title_bold": "initiatives",
|
||||
"com_home_blog_description": "Our blog content",
|
||||
"com_home_blog_show_more": "More Content",
|
||||
"com_home_blog_details_CTA": "Show Details",
|
||||
|
||||
"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.",
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
"pages_contact_title": "تماس با ما",
|
||||
"pages_product_categories_title": "محصولات",
|
||||
"pages_products_title": "محصولات",
|
||||
"pages_blog_title": "وبلاگ",
|
||||
"pages_blog_title": "مقالات",
|
||||
"pages_projects_title": "پروژهها",
|
||||
"pages_contact_description": "از طریق این صفحه با ما در تماس باشید",
|
||||
"com_home_banner_title": "نوآوری در تعالی",
|
||||
@@ -109,7 +109,7 @@
|
||||
"page_products_metadata_title": "محصولات",
|
||||
"page_products_metadata_description": "انواع آجرهای سنتی و صنعتی را در این بخش مشاهده کنید؛ مناسب برای پروژههای ساختمانی گوناگون.",
|
||||
|
||||
"page_blog_metadata_title": "بلاگ",
|
||||
"page_blog_metadata_title": "مقالات",
|
||||
"page_blog_metadata_description": "با مقالات، اخبار و آموزشهای ما در حوزه آجر و مصالح ساختمانی بهروز بمانید.",
|
||||
"page_blog_details_CTA": "جزییات مقاله",
|
||||
|
||||
|
||||
@@ -12,6 +12,17 @@ interface IPageParams extends ILayoutLocaleParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: { params: IPageParams }) {
|
||||
const { id: postId, locale } = await params;
|
||||
const t = await getTranslations({ locale });
|
||||
const postData = await getPost(postId);
|
||||
|
||||
return {
|
||||
title: postData.title,
|
||||
description: t('page_blog_metadata_description'),
|
||||
};
|
||||
}
|
||||
|
||||
export default async function PostPage({ params }: { params: IPageParams }) {
|
||||
const paramsData = await params;
|
||||
const t = await getTranslations({ locale: paramsData.locale });
|
||||
@@ -32,7 +43,7 @@ export default async function PostPage({ params }: { params: IPageParams }) {
|
||||
return (
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
<InnerPageBanner
|
||||
title={t('pages_blog_title')}
|
||||
subtitle={postData.title}
|
||||
imageSrc={images.blogBanner.src}
|
||||
/>
|
||||
<div className="container-fluid mx-auto my-12 md:my-24">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Header from '@/components/layout/header';
|
||||
import AboutTopInfo from '@/components/pages/about/TopInfo';
|
||||
import HomePageBlog from '@/components/pages/home/HomePageBlog';
|
||||
import HomeStorySection from '@/components/pages/home/HomeStorySection';
|
||||
import HomePageProducts from '@/components/pages/home/Products';
|
||||
import HomePageProjects from '@/components/pages/home/Projects';
|
||||
@@ -27,7 +28,8 @@ export default async function Home({ params }: { params: IPageParams }) {
|
||||
<AboutTopInfo />
|
||||
<HomePageProducts locale={locale} />
|
||||
<HomePageProjects locale={locale} />
|
||||
<HomeStorySection className="my-24 max-lg:my-12" />
|
||||
<HomeStorySection className="my-12 lg:my-24" />
|
||||
<HomePageBlog locale={locale} className="my-12 lg:my-24" />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import routeFactory from '@/assets/constants/routeFactory';
|
||||
import images from '@/assets/images/images';
|
||||
import Breadcrumb from '@/components/layout/breadcrumb';
|
||||
import { IBreadcrumbItem } from '@/components/layout/breadcrumb/breadcrumb';
|
||||
import ContentGenerator from '@/components/layout/contentGenerator';
|
||||
import InnerPageBanner from '@/components/layout/innerPages/banner';
|
||||
import { ILayoutLocaleParams } from '@/models/layout';
|
||||
import { getProject } from '@/services/projects';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
|
||||
interface IPageParams extends ILayoutLocaleParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: { params: IPageParams }) {
|
||||
const { id: projectId, locale } = await params;
|
||||
const t = await getTranslations({ locale });
|
||||
const project = await getProject(projectId);
|
||||
|
||||
return {
|
||||
title: project.title,
|
||||
description: t('page_blog_metadata_description'),
|
||||
};
|
||||
}
|
||||
|
||||
export default async function ProjectPage({ params }: { params: IPageParams }) {
|
||||
const paramsData = await params;
|
||||
const t = await getTranslations({ locale: paramsData.locale });
|
||||
|
||||
const { id: projectId, locale } = await params;
|
||||
const routes = routeFactory(t, locale);
|
||||
|
||||
const project = await getProject(projectId);
|
||||
|
||||
const breadcrumbItems = [
|
||||
{
|
||||
...routes.projects,
|
||||
href: routes.projects.route(),
|
||||
},
|
||||
{ title: project?.title },
|
||||
] as IBreadcrumbItem[];
|
||||
|
||||
return (
|
||||
<main className="flex flex-col items-center justify-between">
|
||||
<InnerPageBanner
|
||||
subtitle={project.title}
|
||||
imageSrc={images.projectImg_1.src}
|
||||
/>
|
||||
<div className="container-fluid mx-auto my-12 md:my-24">
|
||||
<Breadcrumb items={breadcrumbItems} />
|
||||
{project.content && project.content.length ? (
|
||||
<ContentGenerator data={project.content} className="mt-10" />
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IProjectCardProps } from '@/app/api/projects/data';
|
||||
import { IProjectData } from '@/app/api/projects/data';
|
||||
import routeFactory from '@/assets/constants/routeFactory';
|
||||
import images from '@/assets/images/images';
|
||||
import InnerPageBanner from '@/components/layout/innerPages/banner';
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import images from '@/assets/images/images';
|
||||
import { IDynamicContent } from '@/models/dynamicContent';
|
||||
|
||||
export interface IPostThumbResponseData {
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
zardCategoryProducts,
|
||||
} from './productsSeparatedByCode';
|
||||
|
||||
const productsRelatedByCategory = {
|
||||
export const productsRelatedByCategory = {
|
||||
'1': ghazaghiCategoryProducts,
|
||||
'2': ghermezCategoryProducts,
|
||||
'3': zardCategoryProducts,
|
||||
|
||||
@@ -4,14 +4,6 @@ import { NextResponse, NextRequest } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { productCategoriesData } from '../data';
|
||||
|
||||
interface IContext {
|
||||
params: {
|
||||
id: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface IParams {}
|
||||
|
||||
export async function GET(request: NextRequest, context: any) {
|
||||
const cookieStore = await cookies();
|
||||
const lang = cookieStore.get('locale')?.value || 'en';
|
||||
|
||||
@@ -127,16 +127,6 @@ interface APIProductCategoryEntity {
|
||||
fa_priceTypeTitle?: string;
|
||||
bestForTitle: string;
|
||||
fa_bestForTitle?: string;
|
||||
fa_description?: `Facing Bricks: Characteristics and Features
|
||||
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
|
||||
Facing Bricks: Characteristics and Features
|
||||
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
|
||||
|
||||
Facing Bricks: Characteristics and Features`;
|
||||
description?: `Facing Bricks: Characteristics and Features
|
||||
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
|
||||
Facing Bricks: Characteristics and Features
|
||||
Facing bricks, also known as face bricks or veneer bricks, are specially designed for visible areas of a building, primarily the exterior facades, but also for interior walls where aesthetics are important. Unlike common bricks which are often covered by plaster or other materials, facing bricks are chosen for their visual appeal and ability to withstand environmental conditions.
|
||||
|
||||
Facing Bricks: Characteristics and Features`;
|
||||
fa_description?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,18 @@ import { NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { APIProductCategoryEntity } from '@/models/api';
|
||||
import { productCategoriesData } from './data';
|
||||
import { productsRelatedByCategory } from './[id]/products/data';
|
||||
|
||||
const getTypesCount = (categoryId: string) =>
|
||||
productsRelatedByCategory[categoryId]?.length || 0;
|
||||
|
||||
const setRelatedLocaleData = (productCategory: APIProductCategoryEntity) => ({
|
||||
title: productCategory.fa_title || productCategory.title,
|
||||
priceTypeTitle:
|
||||
productCategory.fa_priceTypeTitle || productCategory.priceTypeTitle,
|
||||
bestForTitle: productCategory.fa_bestForTitle || productCategory.bestForTitle,
|
||||
description: productCategory.fa_description || productCategory.description,
|
||||
});
|
||||
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
@@ -10,18 +22,11 @@ export async function GET(request: Request) {
|
||||
const cookieStore = await cookies();
|
||||
const lang = (await cookieStore).get('locale')?.value || 'en';
|
||||
|
||||
if (lang === 'fa') {
|
||||
data = productCategoriesData.map((productCategory) => ({
|
||||
...productCategory,
|
||||
title: (lang && productCategory.fa_title) || productCategory.title,
|
||||
priceTypeTitle:
|
||||
productCategory.fa_priceTypeTitle || productCategory.priceTypeTitle,
|
||||
bestForTitle:
|
||||
productCategory.fa_bestForTitle || productCategory.bestForTitle,
|
||||
description:
|
||||
productCategory.fa_description || productCategory.description,
|
||||
...(lang === 'fa' ? setRelatedLocaleData(productCategory) : {}),
|
||||
typesCount: getTypesCount(productCategory.id),
|
||||
}));
|
||||
}
|
||||
|
||||
return NextResponse.json({ data });
|
||||
} catch (error) {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { projects } from '../data';
|
||||
|
||||
export async function GET(request: Request, context: any) {
|
||||
const params = await context.params;
|
||||
const projectId = params.id;
|
||||
|
||||
const cookieStore = await cookies();
|
||||
const lang = cookieStore.get('locale')?.value || 'en';
|
||||
|
||||
let project = projects.find((project) => project.id === projectId);
|
||||
if (!project) {
|
||||
return NextResponse.json({ error: 'Not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
if (lang === 'fa') {
|
||||
project = {
|
||||
...project,
|
||||
title: project.fa_title || project.title,
|
||||
content: project.fa_content || project.content,
|
||||
};
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
data: project,
|
||||
});
|
||||
}
|
||||
@@ -1,10 +1,23 @@
|
||||
import images from '@/assets/images/images';
|
||||
import { tempContent } from '@/assets/temp/tempContent';
|
||||
import { IDynamicContent } from '@/models/dynamicContent';
|
||||
|
||||
export interface IProjectCardProps {
|
||||
export interface IProjectData {
|
||||
id: string;
|
||||
title: string;
|
||||
fa_title?: string;
|
||||
imageSrc: string;
|
||||
content: IDynamicContent[];
|
||||
fa_content: IDynamicContent[];
|
||||
}
|
||||
|
||||
export interface IProjectThumbResponseData {
|
||||
id: string;
|
||||
title: string;
|
||||
imageSrc: string;
|
||||
}
|
||||
export interface IProjectResponseData extends IProjectThumbResponseData {
|
||||
content: IDynamicContent[];
|
||||
}
|
||||
|
||||
export const projects = [
|
||||
@@ -13,40 +26,46 @@ export const projects = [
|
||||
title: 'Sustainable Practices Reducing Waste in Industrial Production',
|
||||
fa_title: 'روشهای پایدار برای کاهش ضایعات در تولید صنعتی',
|
||||
imageSrc: `/images/project1.jpeg`,
|
||||
...tempContent,
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: 'Advanced Robotics Revolutionizing Industrial Workflows',
|
||||
fa_title: 'رباتیک پیشرفته و تحول فرآیندهای صنعتی',
|
||||
imageSrc: `/images/project2.jpeg`,
|
||||
...tempContent,
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
title: 'Top Benefits of the Robotics in Manufacturing',
|
||||
fa_title: 'مزایای اصلی استفاده از رباتیک در تولید',
|
||||
imageSrc: `/images/project3.jpeg`,
|
||||
...tempContent,
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
title: 'Leveraging Data Analytics for Smarter Production',
|
||||
fa_title: 'استفاده از تحلیل داده برای تولید هوشمندتر',
|
||||
imageSrc: `/images/project4.jpeg`,
|
||||
...tempContent,
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
title: 'Reducing Operational Costs Through Automation',
|
||||
fa_title: 'کاهش هزینهها با اتوماسیون',
|
||||
imageSrc: `/images/project1.jpeg`,
|
||||
...tempContent,
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
title: 'The Advantages of Customized Manufacturing Solutions',
|
||||
fa_title: 'مزایای راهحلهای سفارشیسازی در تولید',
|
||||
imageSrc: `/images/project1.jpeg`,
|
||||
...tempContent,
|
||||
},
|
||||
] as IProjectCardProps[];
|
||||
] as IProjectData[];
|
||||
|
||||
export function generateProjects(): IProjectCardProps[] {
|
||||
export function generateProjects(): IProjectData[] {
|
||||
return [...projects, ...projects, ...projects, ...projects, ...projects].map(
|
||||
(e, i) => ({
|
||||
...e,
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { generateProjects } from './data';
|
||||
import {
|
||||
generateProjects,
|
||||
IProjectData,
|
||||
IProjectThumbResponseData,
|
||||
} from './data';
|
||||
|
||||
export async function GET(request: Request) {
|
||||
let projects = generateProjects();
|
||||
let data = projects;
|
||||
let data = projects as IProjectThumbResponseData[];
|
||||
|
||||
const cookieStore = await cookies();
|
||||
const lang = (await cookieStore).get('lang')?.value || 'fa';
|
||||
@@ -19,20 +23,20 @@ export async function GET(request: Request) {
|
||||
const end = start + perPage;
|
||||
const paginatedProjects = projects.slice(start, end);
|
||||
|
||||
if (lang === 'fa') {
|
||||
data = paginatedProjects.map((project) => {
|
||||
if (lang === 'fa') {
|
||||
return {
|
||||
...project,
|
||||
const setRelatedLocaleData = (project: IProjectData) => ({
|
||||
title: project.fa_title || project.title,
|
||||
};
|
||||
}
|
||||
return project;
|
||||
});
|
||||
}
|
||||
|
||||
data = paginatedProjects.map((project) => ({
|
||||
id: project.id,
|
||||
imageSrc: project.imageSrc,
|
||||
...(lang === 'fa'
|
||||
? setRelatedLocaleData(project)
|
||||
: { title: project.title }),
|
||||
}));
|
||||
|
||||
return NextResponse.json({
|
||||
data: data,
|
||||
data,
|
||||
pagination: {
|
||||
page,
|
||||
perPage,
|
||||
|
||||
@@ -6,6 +6,7 @@ type RouteFactory = (
|
||||
productCategories: { title: string; route: () => string };
|
||||
products: { title: string; route: (productId: string) => string };
|
||||
projects: { title: string; route: () => string };
|
||||
project: { title: string; route: (projectId: string) => string };
|
||||
about: { title: string; route: () => string };
|
||||
blog: { title: string; route: () => string };
|
||||
singlePost: { title: string; route: (postId: string) => string };
|
||||
@@ -29,6 +30,10 @@ const routeFactory: RouteFactory = (t, locale) => ({
|
||||
title: t('pages_projects_title'),
|
||||
route: () => `/${locale}/projects`,
|
||||
},
|
||||
project: {
|
||||
title: '',
|
||||
route: (projectId: string) => `/${locale}/projects/${projectId}`,
|
||||
},
|
||||
about: {
|
||||
title: t('pages_about_title'),
|
||||
route: () => `/${locale}/about-us`,
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
export const tempContent = {
|
||||
content: [
|
||||
{
|
||||
type: 'title',
|
||||
data: 'روشهای پایدار برای کاهش ضایعات در تولید صنعتی',
|
||||
},
|
||||
{
|
||||
type: 'content',
|
||||
data: 'لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.',
|
||||
},
|
||||
{
|
||||
type: 'bullet',
|
||||
data: [
|
||||
'روشهای پایدار برای کاهش ضایعات در تولید صنعتی',
|
||||
'رباتیک پیشرفته و تحول فرآیندهای صنعتی',
|
||||
'مزایای اصلی استفاده از رباتیک در تولید',
|
||||
'استفاده از تحلیل داده برای تولید هوشمندتر',
|
||||
'کاهش هزینهها با اتوماسیون',
|
||||
'مزایای راهحلهای سفارشیسازی در تولید',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'image',
|
||||
data: {
|
||||
src: '/images/project2.jpeg',
|
||||
alt: '',
|
||||
thumbTitle:
|
||||
'لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'numberList',
|
||||
data: [
|
||||
'روشهای پایدار برای کاهش ضایعات در تولید صنعتی',
|
||||
'رباتیک پیشرفته و تحول فرآیندهای صنعتی',
|
||||
'مزایای اصلی استفاده از رباتیک در تولید',
|
||||
'استفاده از تحلیل داده برای تولید هوشمندتر',
|
||||
'کاهش هزینهها با اتوماسیون',
|
||||
'مزایای راهحلهای سفارشیسازی در تولید',
|
||||
],
|
||||
},
|
||||
],
|
||||
fa_content: [
|
||||
{
|
||||
type: 'title',
|
||||
data: 'روشهای پایدار برای کاهش ضایعات در تولید صنعتی',
|
||||
},
|
||||
{
|
||||
type: 'content',
|
||||
data: {
|
||||
links: [
|
||||
{
|
||||
link: '/',
|
||||
key: '_link',
|
||||
label: 'ایپسوم',
|
||||
},
|
||||
],
|
||||
data: 'لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم ایپسوم\n متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم _link متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده\n از طراحان گرافیک است. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'bullet',
|
||||
data: [
|
||||
'روشهای پایدار برای کاهش ضایعات در تولید صنعتی',
|
||||
'رباتیک پیشرفته و تحول فرآیندهای صنعتی',
|
||||
'مزایای اصلی استفاده از رباتیک در تولید',
|
||||
'استفاده از تحلیل داده برای تولید هوشمندتر',
|
||||
'کاهش هزینهها با اتوماسیون',
|
||||
'مزایای راهحلهای سفارشیسازی در تولید',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'image',
|
||||
data: {
|
||||
src: '/images/project1.jpeg',
|
||||
alt: '',
|
||||
thumbTitle:
|
||||
'لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'title',
|
||||
data: 'روشهای پایدار برای کاهش ضایعات در تولید صنعتی',
|
||||
},
|
||||
{
|
||||
type: 'numberList',
|
||||
data: [
|
||||
'روشهای پایدار برای کاهش ضایعات در تولید صنعتی',
|
||||
'رباتیک پیشرفته و تحول فرآیندهای صنعتی',
|
||||
'مزایای اصلی استفاده از رباتیک در تولید',
|
||||
'استفاده از تحلیل داده برای تولید هوشمندتر',
|
||||
'کاهش هزینهها با اتوماسیون',
|
||||
'مزایای راهحلهای سفارشیسازی در تولید',
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
export interface IInnerPageBannerProps {
|
||||
imageSrc: string;
|
||||
title: string;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { IInnerPageBannerProps } from './banner';
|
||||
export default function InnerPageBanner({
|
||||
title,
|
||||
imageSrc,
|
||||
subtitle,
|
||||
}: IInnerPageBannerProps) {
|
||||
return (
|
||||
<header
|
||||
@@ -13,7 +14,8 @@ export default function InnerPageBanner({
|
||||
<div className="absolute inset-0 z-0 bg-black opacity-50" />
|
||||
<Navbar />
|
||||
<div className="relative z-10 container mx-auto flex flex-col bg-cover bg-right-top py-20 text-white">
|
||||
<h2 className="text-[4rem] text-white">{title}</h2>
|
||||
{title ? <h2 className="text-[4rem] text-white">{title}</h2> : <></>}
|
||||
{subtitle ? <h2 className="text-lg text-white">{subtitle}</h2> : <></>}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
|
||||
@@ -3,19 +3,17 @@
|
||||
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 { IPostData } from '@/app/api/blog/data';
|
||||
import { IPostThumbResponseData } from '@/app/api/blog/data';
|
||||
import { IPagination } from '@/models/response';
|
||||
import routeFactory from '@/assets/constants/routeFactory';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { TLocales } from '@/models/layout';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Button from '@/components/uikit/button';
|
||||
import PostsGridView from './PostsGridView';
|
||||
|
||||
export interface IPostsGridProps {
|
||||
initialPosts: IPostData[];
|
||||
initialPosts: IPostThumbResponseData[];
|
||||
initialPagination: IPagination;
|
||||
}
|
||||
|
||||
@@ -45,36 +43,7 @@ export default function PostsGrid({
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-14 md:py-28">
|
||||
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{posts.map((post) => (
|
||||
<div
|
||||
key={post.id}
|
||||
className="group flex flex-col gap-4 overflow-hidden bg-white md:gap-6"
|
||||
>
|
||||
<div className="relative aspect-[1.09] w-full overflow-hidden rounded-4xl">
|
||||
<Image
|
||||
src={post.imageSrc}
|
||||
alt={post.title}
|
||||
fill
|
||||
className="h-auto w-full object-cover"
|
||||
/>
|
||||
|
||||
<div className="invisible absolute inset-0 flex items-center justify-center bg-black/20 opacity-0 backdrop-blur-xs transition-all group-hover:visible group-hover:opacity-100">
|
||||
<Button
|
||||
link={routes.singlePost.route(post.id)}
|
||||
endIcon="showMore"
|
||||
>
|
||||
{t('page_blog_details_CTA')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
href={routes.singlePost.route(post.id)}
|
||||
className="group-hover:text-primary text-center text-gray-500"
|
||||
>
|
||||
<h2 className="text-xl font-semibold">{post.title}</h2>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
<PostsGridView posts={posts} locale={locale as TLocales} />
|
||||
</div>
|
||||
<Pagination {...pagination} onPageChange={fetchPage} />
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { IPostThumbResponseData } from '@/app/api/blog/data';
|
||||
import routeFactory from '@/assets/constants/routeFactory';
|
||||
import Button from '@/components/uikit/button';
|
||||
import { TLocales } from '@/models/layout';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
|
||||
export default async function PostsGridView({
|
||||
posts,
|
||||
locale,
|
||||
}: {
|
||||
posts: IPostThumbResponseData[];
|
||||
locale: TLocales;
|
||||
}) {
|
||||
const t = await getTranslations({ locale });
|
||||
const routes = routeFactory(t, locale);
|
||||
|
||||
return (
|
||||
<>
|
||||
{posts.map((post) => (
|
||||
<div
|
||||
key={post.id}
|
||||
className="group flex flex-col gap-3 overflow-hidden bg-white md:gap-5"
|
||||
>
|
||||
<div className="relative aspect-[1.09] w-full overflow-hidden rounded-2xl">
|
||||
<Image
|
||||
src={post.imageSrc}
|
||||
alt={post.title}
|
||||
fill
|
||||
className="h-auto w-full object-cover"
|
||||
/>
|
||||
|
||||
<div className="invisible absolute inset-0 flex items-center justify-center bg-black/20 opacity-0 backdrop-blur-xs transition-all group-hover:visible group-hover:opacity-100">
|
||||
<Button
|
||||
link={routes.singlePost.route(post.id)}
|
||||
endIcon="showMore"
|
||||
>
|
||||
{t('page_blog_details_CTA')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
href={routes.singlePost.route(post.id)}
|
||||
className="group-hover:text-primary mb-4 text-center text-gray-500"
|
||||
>
|
||||
<h2 className="text-base font-medium">{post.title}</h2>
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import SectionTitle from '@/components/layout/sectionTitle';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
import { TLocales } from '@/models/layout';
|
||||
import Button from '@/components/uikit/button';
|
||||
import routeFactory from '@/assets/constants/routeFactory';
|
||||
import { getPosts } from '@/services/blog';
|
||||
import PostsGridView from '../blog/PostsGridView';
|
||||
interface Props {
|
||||
locale: TLocales;
|
||||
className?: string;
|
||||
}
|
||||
export default async function HomePageBlog({ locale, className }: Props) {
|
||||
const t = await getTranslations({ locale });
|
||||
const posts = await getPosts();
|
||||
|
||||
const routes = routeFactory(t, locale);
|
||||
return (
|
||||
<div className={`w-full ${className}`}>
|
||||
<div className="relative container mx-auto w-full bg-white">
|
||||
<div className="relative z-20 grid grid-cols-1 lg:grid-cols-2 lg:gap-28">
|
||||
<SectionTitle
|
||||
title={t('pages_blog_title')}
|
||||
description={t('com_home_blog_title')}
|
||||
description_bold={t('com_home_blog_title_bold')}
|
||||
locale={locale}
|
||||
/>
|
||||
<div className="pt-10 max-lg:hidden">
|
||||
<h4 className="text-base font-extralight tracking-normal max-lg:hidden">
|
||||
{t('com_home_blog_description')}
|
||||
</h4>
|
||||
<Button
|
||||
link={routes.blog.route()}
|
||||
endIcon="showMore"
|
||||
className="mt-5"
|
||||
>
|
||||
{t('com_home_blog_show_more')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-10 grid grid-cols-1 gap-4 md:grid-cols-2 md:gap-6 lg:grid-cols-3 lg:gap-8">
|
||||
<PostsGridView posts={posts.data?.slice(0, 3)} locale={locale} />
|
||||
</div>
|
||||
<Button
|
||||
link={routes.blog.route()}
|
||||
endIcon="showMore"
|
||||
className="mx-auto mt-10 lg:hidden"
|
||||
>
|
||||
{t('com_home_blog_show_more')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -5,6 +5,9 @@ import Link from 'next/link';
|
||||
import { IProjectCardProps } from './project';
|
||||
import Button from '@/components/uikit/button';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import routeFactory from '@/assets/constants/routeFactory';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { TLocales } from '@/models/layout';
|
||||
|
||||
export default function ProjectsGrid({
|
||||
projects,
|
||||
@@ -14,6 +17,9 @@ export default function ProjectsGrid({
|
||||
className?: string;
|
||||
}) {
|
||||
const t = useTranslations();
|
||||
const { locale } = useParams();
|
||||
|
||||
const routes = routeFactory(t, locale as TLocales);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -29,14 +35,17 @@ export default function ProjectsGrid({
|
||||
className="h-auto w-full object-cover"
|
||||
/>
|
||||
<div className="invisible absolute inset-0 flex items-center justify-center bg-black/20 opacity-0 backdrop-blur-xs transition-all group-hover:visible group-hover:opacity-100">
|
||||
<Button endIcon="showMore">
|
||||
<Button
|
||||
endIcon="showMore"
|
||||
link={routes.project.route(project.id)}
|
||||
>
|
||||
{t('com_home_projects_details_CTA')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href={'/'}
|
||||
href={routes.project.route(project.id)}
|
||||
key={index}
|
||||
className="group-hover:text-primary mb-4 text-center text-gray-500"
|
||||
>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
export interface IProjectCardProps {
|
||||
imageSrc: string;
|
||||
title: string;
|
||||
link: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface IProjectGridViewProps {
|
||||
|
||||
+16
-13
@@ -1,5 +1,6 @@
|
||||
'use server';
|
||||
|
||||
import { IProjectResponseData } from '@/app/api/projects/data';
|
||||
import api from '@/lib/axios';
|
||||
import { cookies } from 'next/headers';
|
||||
|
||||
@@ -17,16 +18,18 @@ export async function getProjects(page = 1 as number) {
|
||||
.catch((error) => Promise.reject(error));
|
||||
}
|
||||
|
||||
// export async function getProjectById(
|
||||
// projectId: string,
|
||||
// ): Promise<IProjectCardProps> {
|
||||
// const cookiesStore = await cookies();
|
||||
// return api
|
||||
// .get(`/projects/${projectId}`, {
|
||||
// headers: {
|
||||
// Cookie: cookiesStore.toString(),
|
||||
// },
|
||||
// })
|
||||
// .then(({ data }) => Promise.resolve(data.data))
|
||||
// .catch((error) => Promise.reject(error));
|
||||
// }
|
||||
export async function getProject(
|
||||
projectId: string,
|
||||
): Promise<IProjectResponseData> {
|
||||
const cookiesStore = await cookies();
|
||||
return api
|
||||
.get(`/projects/${projectId}`, {
|
||||
headers: {
|
||||
Cookie: cookiesStore.toString(),
|
||||
},
|
||||
})
|
||||
.then(({ data }) => {
|
||||
return Promise.resolve(data.data);
|
||||
})
|
||||
.catch((error) => Promise.reject(error));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user