From d44e8037b12dbc013a643369437bff7fcc336375 Mon Sep 17 00:00:00 2001 From: ahasani194 Date: Thu, 19 Jun 2025 20:17:15 +0330 Subject: [PATCH] create single project page and set blog section in home page --- messages/en.d.json.ts | 6 ++ messages/en.json | 6 ++ messages/fa.json | 4 +- src/app/[locale]/blog/[id]/page.tsx | 13 ++- src/app/[locale]/page.tsx | 4 +- src/app/[locale]/projects/[id]/page.tsx | 59 +++++++++++ src/app/[locale]/projects/page.tsx | 2 +- src/app/api/blog/data.ts | 1 - .../product_categories/[id]/products/data.ts | 2 +- src/app/api/product_categories/[id]/route.ts | 8 -- src/app/api/product_categories/data.ts | 14 +-- src/app/api/product_categories/route.ts | 29 +++--- src/app/api/projects/[id]/route.ts | 28 ++++++ src/app/api/projects/data.ts | 25 ++++- src/app/api/projects/route.ts | 32 +++--- src/assets/constants/routeFactory/index.ts | 5 + src/assets/temp/tempContent.ts | 97 +++++++++++++++++++ .../layout/innerPages/banner/banner.d.ts | 3 +- .../layout/innerPages/banner/index.tsx | 4 +- src/components/pages/blog/PostsGrid.tsx | 39 +------- src/components/pages/blog/PostsGridView.tsx | 53 ++++++++++ src/components/pages/home/HomePageBlog.tsx | 54 +++++++++++ src/components/pages/project/ProjectGrid.tsx | 13 ++- src/components/pages/project/project.d.ts | 2 +- src/services/projects.ts | 29 +++--- 25 files changed, 423 insertions(+), 109 deletions(-) create mode 100644 src/app/[locale]/projects/[id]/page.tsx create mode 100644 src/app/api/projects/[id]/route.ts create mode 100644 src/assets/temp/tempContent.ts create mode 100644 src/components/pages/blog/PostsGridView.tsx create mode 100644 src/components/pages/home/HomePageBlog.tsx diff --git a/messages/en.d.json.ts b/messages/en.d.json.ts index 0c3e36a..4755642 100644 --- a/messages/en.d.json.ts +++ b/messages/en.d.json.ts @@ -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.", diff --git a/messages/en.json b/messages/en.json index 47b2f52..cdd01b7 100644 --- a/messages/en.json +++ b/messages/en.json @@ -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.", diff --git a/messages/fa.json b/messages/fa.json index c8c1f74..76439c7 100644 --- a/messages/fa.json +++ b/messages/fa.json @@ -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": "جزییات مقاله", diff --git a/src/app/[locale]/blog/[id]/page.tsx b/src/app/[locale]/blog/[id]/page.tsx index d6f03e3..dc36789 100644 --- a/src/app/[locale]/blog/[id]/page.tsx +++ b/src/app/[locale]/blog/[id]/page.tsx @@ -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 (
diff --git a/src/app/[locale]/page.tsx b/src/app/[locale]/page.tsx index b6945d3..2e5af2f 100644 --- a/src/app/[locale]/page.tsx +++ b/src/app/[locale]/page.tsx @@ -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 }) { - + +
); } diff --git a/src/app/[locale]/projects/[id]/page.tsx b/src/app/[locale]/projects/[id]/page.tsx new file mode 100644 index 0000000..2ed7733 --- /dev/null +++ b/src/app/[locale]/projects/[id]/page.tsx @@ -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 ( +
+ +
+ + {project.content && project.content.length ? ( + + ) : ( + <> + )} +
+
+ ); +} diff --git a/src/app/[locale]/projects/page.tsx b/src/app/[locale]/projects/page.tsx index 2e32f7f..aa47922 100644 --- a/src/app/[locale]/projects/page.tsx +++ b/src/app/[locale]/projects/page.tsx @@ -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'; diff --git a/src/app/api/blog/data.ts b/src/app/api/blog/data.ts index 9351edd..0d29b8c 100644 --- a/src/app/api/blog/data.ts +++ b/src/app/api/blog/data.ts @@ -1,4 +1,3 @@ -import images from '@/assets/images/images'; import { IDynamicContent } from '@/models/dynamicContent'; export interface IPostThumbResponseData { diff --git a/src/app/api/product_categories/[id]/products/data.ts b/src/app/api/product_categories/[id]/products/data.ts index 018d73f..92f4a8f 100644 --- a/src/app/api/product_categories/[id]/products/data.ts +++ b/src/app/api/product_categories/[id]/products/data.ts @@ -7,7 +7,7 @@ import { zardCategoryProducts, } from './productsSeparatedByCode'; -const productsRelatedByCategory = { +export const productsRelatedByCategory = { '1': ghazaghiCategoryProducts, '2': ghermezCategoryProducts, '3': zardCategoryProducts, diff --git a/src/app/api/product_categories/[id]/route.ts b/src/app/api/product_categories/[id]/route.ts index a82936e..c01b2b6 100644 --- a/src/app/api/product_categories/[id]/route.ts +++ b/src/app/api/product_categories/[id]/route.ts @@ -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'; diff --git a/src/app/api/product_categories/data.ts b/src/app/api/product_categories/data.ts index 14c70a8..5b57951 100644 --- a/src/app/api/product_categories/data.ts +++ b/src/app/api/product_categories/data.ts @@ -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; } diff --git a/src/app/api/product_categories/route.ts b/src/app/api/product_categories/route.ts index 3e8da82..0b64e66 100644 --- a/src/app/api/product_categories/route.ts +++ b/src/app/api/product_categories/route.ts @@ -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, - })); - } + data = productCategoriesData.map((productCategory) => ({ + ...productCategory, + ...(lang === 'fa' ? setRelatedLocaleData(productCategory) : {}), + typesCount: getTypesCount(productCategory.id), + })); return NextResponse.json({ data }); } catch (error) { diff --git a/src/app/api/projects/[id]/route.ts b/src/app/api/projects/[id]/route.ts new file mode 100644 index 0000000..c64e945 --- /dev/null +++ b/src/app/api/projects/[id]/route.ts @@ -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, + }); +} diff --git a/src/app/api/projects/data.ts b/src/app/api/projects/data.ts index a0a86cd..2a47a8b 100644 --- a/src/app/api/projects/data.ts +++ b/src/app/api/projects/data.ts @@ -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, diff --git a/src/app/api/projects/route.ts b/src/app/api/projects/route.ts index 5f6fa05..5db0284 100644 --- a/src/app/api/projects/route.ts +++ b/src/app/api/projects/route.ts @@ -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, - title: project.fa_title || project.title, - }; - } - return project; - }); - } + const setRelatedLocaleData = (project: IProjectData) => ({ + title: project.fa_title || project.title, + }); + + 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, diff --git a/src/assets/constants/routeFactory/index.ts b/src/assets/constants/routeFactory/index.ts index 289dcd3..5c0a2eb 100644 --- a/src/assets/constants/routeFactory/index.ts +++ b/src/assets/constants/routeFactory/index.ts @@ -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`, diff --git a/src/assets/temp/tempContent.ts b/src/assets/temp/tempContent.ts new file mode 100644 index 0000000..dc4885a --- /dev/null +++ b/src/assets/temp/tempContent.ts @@ -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: [ + 'روش‌های پایدار برای کاهش ضایعات در تولید صنعتی', + 'رباتیک پیشرفته و تحول فرآیندهای صنعتی', + 'مزایای اصلی استفاده از رباتیک در تولید', + 'استفاده از تحلیل داده برای تولید هوشمندتر', + 'کاهش هزینه‌ها با اتوماسیون', + 'مزایای راه‌حل‌های سفارشی‌سازی در تولید', + ], + }, + ], +}; diff --git a/src/components/layout/innerPages/banner/banner.d.ts b/src/components/layout/innerPages/banner/banner.d.ts index e2298e3..78ebb03 100644 --- a/src/components/layout/innerPages/banner/banner.d.ts +++ b/src/components/layout/innerPages/banner/banner.d.ts @@ -1,4 +1,5 @@ export interface IInnerPageBannerProps { imageSrc: string; - title: string; + title?: string; + subtitle?: string; } diff --git a/src/components/layout/innerPages/banner/index.tsx b/src/components/layout/innerPages/banner/index.tsx index 3aef131..64bd32b 100644 --- a/src/components/layout/innerPages/banner/index.tsx +++ b/src/components/layout/innerPages/banner/index.tsx @@ -4,6 +4,7 @@ import { IInnerPageBannerProps } from './banner'; export default function InnerPageBanner({ title, imageSrc, + subtitle, }: IInnerPageBannerProps) { return (
-

{title}

+ {title ?

{title}

: <>} + {subtitle ?

{subtitle}

: <>}
); diff --git a/src/components/pages/blog/PostsGrid.tsx b/src/components/pages/blog/PostsGrid.tsx index 4697bd2..a84edd7 100644 --- a/src/components/pages/blog/PostsGrid.tsx +++ b/src/components/pages/blog/PostsGrid.tsx @@ -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 (
- {posts.map((post) => ( -
-
- {post.title} - -
- -
-
- -

{post.title}

- -
- ))} +
diff --git a/src/components/pages/blog/PostsGridView.tsx b/src/components/pages/blog/PostsGridView.tsx new file mode 100644 index 0000000..5d79c24 --- /dev/null +++ b/src/components/pages/blog/PostsGridView.tsx @@ -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) => ( +
+
+ {post.title} + +
+ +
+
+ +

{post.title}

+ +
+ ))} + + ); +} diff --git a/src/components/pages/home/HomePageBlog.tsx b/src/components/pages/home/HomePageBlog.tsx new file mode 100644 index 0000000..73da452 --- /dev/null +++ b/src/components/pages/home/HomePageBlog.tsx @@ -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 ( +
+
+
+ +
+

+ {t('com_home_blog_description')} +

+ +
+
+ +
+ +
+ +
+
+ ); +} diff --git a/src/components/pages/project/ProjectGrid.tsx b/src/components/pages/project/ProjectGrid.tsx index 57d90c1..0cacf18 100644 --- a/src/components/pages/project/ProjectGrid.tsx +++ b/src/components/pages/project/ProjectGrid.tsx @@ -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 (
-
diff --git a/src/components/pages/project/project.d.ts b/src/components/pages/project/project.d.ts index a5533c2..f972e64 100644 --- a/src/components/pages/project/project.d.ts +++ b/src/components/pages/project/project.d.ts @@ -1,7 +1,7 @@ export interface IProjectCardProps { imageSrc: string; title: string; - link: string; + id: string; } export interface IProjectGridViewProps { diff --git a/src/services/projects.ts b/src/services/projects.ts index 8c684ac..e927d32 100644 --- a/src/services/projects.ts +++ b/src/services/projects.ts @@ -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 { -// 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 { + 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)); +}