165 lines
5.1 KiB
TypeScript
165 lines
5.1 KiB
TypeScript
"use client";
|
|
import {
|
|
BreadcrumbItem,
|
|
Breadcrumbs,
|
|
Button,
|
|
Input,
|
|
Pagination,
|
|
} from "@heroui/react";
|
|
import {
|
|
CalendarIcon,
|
|
Calender,
|
|
ChevronRightIcon,
|
|
ClockIcon,
|
|
EyeFilledIcon,
|
|
SearchIcon,
|
|
UserIcon,
|
|
} from "../../icons";
|
|
import Link from "next/link";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { getListArticle } from "@/service/article";
|
|
import { formatMonthString, htmlToString, textEllipsis } from "@/utils/global";
|
|
import Image from "next/image";
|
|
import {
|
|
useParams,
|
|
usePathname,
|
|
useRouter,
|
|
useSearchParams,
|
|
} from "next/navigation";
|
|
|
|
export default function ListNews() {
|
|
const [article, setArticle] = useState<any>([]);
|
|
const [page, setPage] = useState(1);
|
|
const router = useRouter();
|
|
const pathname = usePathname();
|
|
const [totalPage, setTotalPage] = useState(1);
|
|
const topRef = useRef<HTMLDivElement>(null);
|
|
const params = useParams();
|
|
const category = params?.name;
|
|
const searchParams = useSearchParams();
|
|
const search = searchParams.get("search");
|
|
const [searchValue, setSearchValue] = useState(search || "");
|
|
|
|
useEffect(() => {
|
|
getArticle();
|
|
}, [page, category]);
|
|
|
|
async function getArticle() {
|
|
// loading();
|
|
topRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
|
|
const req = {
|
|
page: page,
|
|
search: searchValue || "",
|
|
limit: "9",
|
|
category: String(category),
|
|
isPublish: true,
|
|
};
|
|
const response = await getListArticle(req);
|
|
setArticle(response?.data?.data);
|
|
setTotalPage(response?.data?.meta?.totalPage);
|
|
// close();
|
|
}
|
|
|
|
return (
|
|
<div className="bg-white border-b-1" ref={topRef}>
|
|
<div className="text-black py-5 px-3 lg:w-[75vw] mx-auto bg-white">
|
|
<div className="flex flex-row gap-4">
|
|
<Link href="/" className="text-black font-semibold">
|
|
Beranda
|
|
</Link>
|
|
<ChevronRightIcon />
|
|
<p className="text-black">Berita</p>
|
|
</div>
|
|
<div className="py-5 lg:py-10 lg:px-24 ">
|
|
<Input
|
|
aria-label="Search"
|
|
className="w-full"
|
|
classNames={{
|
|
inputWrapper: "bg-white hover:!bg-gray-100 border-1",
|
|
input: "text-sm !text-black",
|
|
}}
|
|
onKeyDown={(event) => {
|
|
if (event.key === "Enter") {
|
|
router.push(pathname + `?search=${searchValue}`);
|
|
getArticle();
|
|
}
|
|
}}
|
|
labelPlacement="outside"
|
|
placeholder="Search..."
|
|
value={searchValue || ""}
|
|
onValueChange={setSearchValue}
|
|
endContent={
|
|
<Button
|
|
onPress={() => {
|
|
router.push(pathname + `?search=${searchValue}`);
|
|
getArticle();
|
|
}}
|
|
size="sm"
|
|
className="bg-red-500 font-semibold"
|
|
>
|
|
<SearchIcon className="text-white" />
|
|
</Button>
|
|
}
|
|
type="search"
|
|
/>
|
|
</div>
|
|
<section
|
|
id="content"
|
|
className=" grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-7"
|
|
>
|
|
{article?.map((news: any) => (
|
|
<Link
|
|
href={`/news/detail/${news?.id}-${news?.slug}`}
|
|
key={news?.id}
|
|
>
|
|
<div className="">
|
|
<Image
|
|
src={
|
|
news.thumbnailUrl == ""
|
|
? "/no-image.jpg"
|
|
: news.thumbnailUrl
|
|
}
|
|
width={1920}
|
|
height={1080}
|
|
alt="thumbnail"
|
|
className="rounded-t-md h-[27vh] w-full object-cover"
|
|
/>
|
|
</div>
|
|
<div className="p-2 lg:p-5 bg-[#f0f0f0] rounded-b-md">
|
|
<div className="font-semibold text-lg">{news?.title}</div>
|
|
<div className="flex flex-row items-center py-1 text-[10px] gap-2">
|
|
<div className="flex flex-row items-center gap-1">
|
|
<CalendarIcon size={18} />
|
|
<p>{formatMonthString(news?.updatedAt)}</p>
|
|
</div>
|
|
<div className="flex flex-row items-center">
|
|
<ClockIcon size={18} />
|
|
<p>{`${new Date(news?.updatedAt)
|
|
.getHours()
|
|
.toString()
|
|
.padStart(2, "0")}:${new Date(news?.updatedAt)
|
|
.getMinutes()
|
|
.toString()
|
|
.padStart(2, "0")}`}</p>
|
|
</div>
|
|
<div className="flex flex-row items-center gap-1">
|
|
<UserIcon size={14} />
|
|
<p>{news?.createdByName}</p>
|
|
</div>
|
|
</div>
|
|
<div className="text-sm">
|
|
{textEllipsis(htmlToString(news?.description), 165)}
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</section>
|
|
<div className="flex justify-center mt-5">
|
|
<Pagination page={page} total={totalPage} onChange={setPage} />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|