create single project page and set blog section in home page

This commit is contained in:
2025-06-19 20:17:15 +03:30
parent e69e2bf7e1
commit d44e8037b1
25 changed files with 423 additions and 109 deletions
+2 -1
View File
@@ -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>
);
+4 -35
View File
@@ -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>
);
}
+11 -2
View File
@@ -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
View File
@@ -1,7 +1,7 @@
export interface IProjectCardProps {
imageSrc: string;
title: string;
link: string;
id: string;
}
export interface IProjectGridViewProps {