create single project page and set blog section in home page
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user