127 lines
3.7 KiB
TypeScript
127 lines
3.7 KiB
TypeScript
"use client";
|
|
|
|
import React, { useEffect, useState } from "react";
|
|
|
|
import { useLocale, useTranslations } from "next-intl";
|
|
import { NewsData } from "@/lib/types/NewsData.type";
|
|
import { baseAPI } from "@/lib/API";
|
|
import Loader from "@/components/ui/Loader";
|
|
import clsx from "clsx";
|
|
import { Card } from "@/components/shared/Card";
|
|
import { BorderBtn } from "@/components/ui/Buttons";
|
|
import { Pagination } from "@/components/ui/Pagination";
|
|
import { LayoutWithSidebar } from "@/components/page/LayoutWithSidebar";
|
|
|
|
const News = () => {
|
|
const locale = useLocale();
|
|
const t = useTranslations("news");
|
|
const tCommon = useTranslations("common");
|
|
|
|
const [current, setCurrent] = React.useState<number>(1);
|
|
const [perPage, setPerPage] = React.useState<number>(6);
|
|
const [totalNews, setTotalNews] = React.useState<number>(0);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
window.scrollTo({ behavior: "smooth", top: 0 });
|
|
}, [current]);
|
|
|
|
const [newsData, setNewsData] = React.useState<NewsData>();
|
|
|
|
const fetchNews = async () => {
|
|
try {
|
|
setLoading(true);
|
|
const response = await fetch(
|
|
`${baseAPI}news?page=${current}&per_page=${perPage}`,
|
|
{
|
|
headers: {
|
|
"Accept-Language": locale,
|
|
},
|
|
}
|
|
);
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Fetch failed with status ${response.status}`);
|
|
}
|
|
|
|
const data: NewsData = await response.json();
|
|
setNewsData(data);
|
|
setTotalNews(data.meta.total);
|
|
} catch (error) {
|
|
console.error("Fetch error:", error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
React.useEffect(() => {
|
|
fetchNews();
|
|
}, [current, perPage, locale]);
|
|
|
|
const handleOnClickButton = () => {
|
|
setPerPage((prev) => prev + 6);
|
|
};
|
|
|
|
if (loading) {
|
|
return <Loader className="h-[500px] mx-auto w-full " />;
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<LayoutWithSidebar
|
|
title={t("title")}
|
|
second={t("title")}
|
|
cursor={false}
|
|
>
|
|
<div>
|
|
<div className="flex flex-col">
|
|
<div className="flex flex-col">
|
|
<div
|
|
className={clsx(
|
|
"mb-[48px] lg:mb-[108px]",
|
|
"grid grid-cols-1 sm:grid-cols-2 gap-5 sm:gap-8 lg:gap-y-10"
|
|
)}
|
|
>
|
|
{newsData &&
|
|
newsData.data.map((item, i) => (
|
|
<Card
|
|
key={i}
|
|
id={item.id}
|
|
title={item.title}
|
|
date={item.published_at}
|
|
img={
|
|
item.featured_images.length > 0
|
|
? item.featured_images[0].path
|
|
: newsData.data[0].featured_images[0].path
|
|
}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
<div className="hidden sm:flex flex-col gap-6 w-full max-w-[180px] mx-auto justify-center items-center">
|
|
{newsData && totalNews > perPage && perPage >= totalNews && (
|
|
<div onClick={handleOnClickButton}>
|
|
<BorderBtn px text={tCommon("showMore")} />
|
|
</div>
|
|
)}
|
|
|
|
{newsData?.meta && (
|
|
<Pagination
|
|
current={current}
|
|
setCurrent={setCurrent}
|
|
totalPage={newsData?.meta.total}
|
|
lastPage={newsData?.meta.last_page}
|
|
currentPage={newsData?.meta.current_page}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</LayoutWithSidebar>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default News;
|