satupeta-main/app/(modules)/(landing)/components/news-section/index.tsx
2026-02-23 12:21:05 +07:00

115 lines
3.4 KiB
TypeScript
Executable File

"use client";
import React from "react";
import Link from "next/link";
import { useQuery } from "@tanstack/react-query";
import newsApi from "@/shared/services/news";
import { Button } from "@/shared/components/button/button";
import { NewsMainCard } from "./news-main-card";
import { NewsSecondaryCard } from "./news-secondary-card";
import {
NewsMainCardSketelon,
NewsSecondaryCardSkeleton,
} from "./_components/news-card-skeleton";
import Image from "next/image";
import { ErrorState } from "@/shared/components/error-state";
export function NewsSection() {
const {
data: news,
isLoading,
isError,
error,
isSuccess,
refetch,
isFetching,
} = useQuery({
queryKey: ["news"],
queryFn: () =>
newsApi
.getNewsList(
{
limit: 5,
filter: ["is_active=true"],
},
{ skipAuth: true },
)
.then((res) => res.items),
staleTime: 5000,
retry: 1,
});
const showSkeleton = isLoading || (isFetching && !isSuccess);
return (
<>
<section
id="news"
className="bg-biru-300 font-onest relative mt-40 min-h-[540px] py-18"
>
<Image
src={"/landing/ornaments/ornament2.webp"}
alt="ornament"
width={340}
height={340}
className="absolute bottom-0 left-0 mix-blend-overlay"
/>
<div className="@container relative container">
<div className="flex items-center justify-between">
<div className="flex flex-col justify-start gap-y-2">
<div className="flex items-center text-white">
<div className="h-8 w-1 rounded-full bg-white"></div>
<h2 className="font-onest ms-3 text-3xl font-bold">
Berita & Pengumuman
</h2>
</div>
<p className="text-md text-white">
Informasi terbaru seputar perkembangan data geospasial Jawa
Timur
</p>
</div>
<Link href="/news">
<Button variant={"whiteOutlined"}>Lihat Semua</Button>
</Link>
</div>
{(() => {
if (showSkeleton) {
return (
<div className="mt-8 grid gap-8 md:grid-cols-2 lg:grid-cols-3 lg:grid-rows-2">
<div className="lg:col-span-2 lg:row-span-2">
<NewsMainCardSketelon />
</div>
<NewsSecondaryCardSkeleton />
<NewsSecondaryCardSkeleton />
</div>
);
}
if (isError) {
return <ErrorState message={error?.message} onRetry={refetch} />;
}
if (isSuccess && (!news || news.length === 0)) {
return (
<div className="mt-6 rounded-xl border border-zinc-200 bg-white p-6 text-zinc-600">
Belum ada berita untuk ditampilkan.
</div>
);
}
if (isSuccess && news && news.length > 0) {
return (
<div className="mt-8 grid gap-8 md:grid-cols-2 lg:grid-cols-3 lg:grid-rows-2">
<NewsMainCard news={news[0]} />
<NewsSecondaryCard news={news[1]} />
<NewsSecondaryCard news={news[2]} />
</div>
);
}
})()}
</div>
</section>
</>
);
}