fix slider post and add skeleton
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
count?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SliderThumbSkeleton({ count = 3 }: Props) {
|
||||||
|
return (
|
||||||
|
<div className="flex gap-4 overflow-hidden">
|
||||||
|
{Array.from({ length: count }).map((_, i) => (
|
||||||
|
<div
|
||||||
|
key={i}
|
||||||
|
className="flex w-full animate-pulse flex-col gap-4 overflow-hidden rounded-xl bg-white"
|
||||||
|
>
|
||||||
|
<div className="aspect-[1.09] w-full bg-gray-200" />
|
||||||
|
<div className="mx-auto mb-4 h-4 w-3/4 rounded bg-gray-200" />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ const PostThumb = ({ post, locale }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={post.id}
|
key={post.id}
|
||||||
className="group flex flex-col gap-3 overflow-hidden bg-white md:gap-5"
|
className="group flex w-full flex-col gap-3 overflow-hidden bg-white md:gap-5"
|
||||||
>
|
>
|
||||||
<div className="relative aspect-[1.09] w-full overflow-hidden rounded-2xl">
|
<div className="relative aspect-[1.09] w-full overflow-hidden rounded-2xl">
|
||||||
<Image
|
<Image
|
||||||
|
|||||||
@@ -1,14 +1,58 @@
|
|||||||
|
// 'use client';
|
||||||
|
|
||||||
|
// import { Swiper, SwiperSlide } from 'swiper/react';
|
||||||
|
// import { FreeMode } from 'swiper/modules';
|
||||||
|
// import 'swiper/css';
|
||||||
|
// import 'swiper/css/free-mode';
|
||||||
|
// import { IPostThumbResponseData } from '@/app/api/blog/data';
|
||||||
|
// import { useTranslations } from 'use-intl';
|
||||||
|
// import routeFactory from '@/assets/constants/routeFactory';
|
||||||
|
// import { TLocales } from '@/models/layout';
|
||||||
|
// import PostThumb from './PostThumb';
|
||||||
|
|
||||||
|
// interface Props {
|
||||||
|
// posts: IPostThumbResponseData[];
|
||||||
|
// locale: TLocales;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export default function PostsGridViewSlider({ posts, locale }: Props) {
|
||||||
|
// const t = useTranslations();
|
||||||
|
// const routes = routeFactory(t, locale);
|
||||||
|
// return (
|
||||||
|
// <div className="w-full">
|
||||||
|
// <Swiper
|
||||||
|
// modules={[FreeMode]}
|
||||||
|
// freeMode
|
||||||
|
// spaceBetween={16}
|
||||||
|
// breakpoints={{
|
||||||
|
// 0: { slidesPerView: 1.1 },
|
||||||
|
// 768: { slidesPerView: Math.min(posts.length, 3), spaceBetween: 24 },
|
||||||
|
// }}
|
||||||
|
// className="w-full"
|
||||||
|
// >
|
||||||
|
// {posts.map((post) => (
|
||||||
|
// <SwiperSlide key={post.id} className="w-auto">
|
||||||
|
// <PostThumb post={post} locale={locale} />
|
||||||
|
// </SwiperSlide>
|
||||||
|
// ))}
|
||||||
|
// </Swiper>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||||
import { FreeMode } from 'swiper/modules';
|
import { FreeMode } from 'swiper/modules';
|
||||||
import 'swiper/css';
|
import 'swiper/css';
|
||||||
import 'swiper/css/free-mode';
|
import 'swiper/css/free-mode';
|
||||||
|
|
||||||
|
import PostThumb from './PostThumb';
|
||||||
import { IPostThumbResponseData } from '@/app/api/blog/data';
|
import { IPostThumbResponseData } from '@/app/api/blog/data';
|
||||||
|
import { TLocales } from '@/models/layout';
|
||||||
import { useTranslations } from 'use-intl';
|
import { useTranslations } from 'use-intl';
|
||||||
import routeFactory from '@/assets/constants/routeFactory';
|
import routeFactory from '@/assets/constants/routeFactory';
|
||||||
import { TLocales } from '@/models/layout';
|
import SliderThumbSkeleton from '@/components/layout/sliderSkeleton';
|
||||||
import PostThumb from './PostThumb';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
posts: IPostThumbResponseData[];
|
posts: IPostThumbResponseData[];
|
||||||
@@ -16,8 +60,18 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function PostsGridViewSlider({ posts, locale }: Props) {
|
export default function PostsGridViewSlider({ posts, locale }: Props) {
|
||||||
|
const [hasMounted, setHasMounted] = useState(false);
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const routes = routeFactory(t, locale);
|
const routes = routeFactory(t, locale);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setHasMounted(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!hasMounted) {
|
||||||
|
return <SliderThumbSkeleton count={3} />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Swiper
|
<Swiper
|
||||||
@@ -26,12 +80,12 @@ export default function PostsGridViewSlider({ posts, locale }: Props) {
|
|||||||
spaceBetween={16}
|
spaceBetween={16}
|
||||||
breakpoints={{
|
breakpoints={{
|
||||||
0: { slidesPerView: 1.1 },
|
0: { slidesPerView: 1.1 },
|
||||||
768: { slidesPerView: posts.length, spaceBetween: 24 },
|
768: { slidesPerView: Math.min(posts.length, 3), spaceBetween: 24 },
|
||||||
}}
|
}}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
{posts.map((post) => (
|
{posts.map((post) => (
|
||||||
<SwiperSlide key={post.id}>
|
<SwiperSlide key={post.id} className="w-auto">
|
||||||
<PostThumb post={post} locale={locale} />
|
<PostThumb post={post} locale={locale} />
|
||||||
</SwiperSlide>
|
</SwiperSlide>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ export default async function HomePageBlog({ locale, className }: Props) {
|
|||||||
<h4 className="text-base font-extralight tracking-normal max-lg:hidden">
|
<h4 className="text-base font-extralight tracking-normal max-lg:hidden">
|
||||||
{t('com_home_blog_description')}
|
{t('com_home_blog_description')}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
|
<div className="flex w-full justify-end">
|
||||||
<Button
|
<Button
|
||||||
link={routes.blog.route()}
|
link={routes.blog.route()}
|
||||||
endIcon="showMore"
|
endIcon="showMore"
|
||||||
@@ -37,6 +39,7 @@ export default async function HomePageBlog({ locale, className }: Props) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="mt-10">
|
<div className="mt-10">
|
||||||
<PostsGridViewSlider
|
<PostsGridViewSlider
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export default async function HomePageProjects({ locale }: Props) {
|
|||||||
<h4 className="text-base font-extralight tracking-normal max-lg:hidden">
|
<h4 className="text-base font-extralight tracking-normal max-lg:hidden">
|
||||||
{t('com_home_projects_description')}
|
{t('com_home_projects_description')}
|
||||||
</h4>
|
</h4>
|
||||||
|
<div className="flex w-full justify-end">
|
||||||
<Button
|
<Button
|
||||||
link={routes.projects.route()}
|
link={routes.projects.route()}
|
||||||
endIcon="showMore"
|
endIcon="showMore"
|
||||||
@@ -38,6 +39,7 @@ export default async function HomePageProjects({ locale }: Props) {
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="mt-10">
|
<div className="mt-10">
|
||||||
<ProjectsGridSlider
|
<ProjectsGridSlider
|
||||||
projects={projects.data?.slice(0, 3)}
|
projects={projects.data?.slice(0, 3)}
|
||||||
|
|||||||
Reference in New Issue
Block a user