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

89 lines
3.1 KiB
TypeScript
Executable File

"use client";
import React, { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import categoryApi from "@/shared/services/category";
import CategoryCard from "./category-card";
import { ErrorState } from "@/shared/components/error-state";
import { Button } from "@/shared/components/button/button";
export function CategorySection() {
const [showAll, setShowAll] = useState(false);
const { data: categories, isLoading, isFetching, isSuccess, isError, error, refetch } = useQuery({
queryKey: ["categories-list", showAll],
queryFn: () =>
categoryApi
.getCategories(
{
...(showAll ? {} : { limit: 6 }),
filter: ["is_active=true"],
},
{ skipAuth: true }
)
.then((res) => res.items),
staleTime: 5000,
retry: 1,
});
const showSkeleton = isLoading || (isFetching && !isSuccess);
return (
<section id="category" className="font-onest @container container mt-24 sm:mt-32 lg:mt-48">
<div className="flex items-center justify-between">
<div className="flex items-center">
<div className="h-8 w-1 rounded-full bg-blue-500" />
<h2 className="ms-3 text-[28px] font-bold text-dark-500">Topik</h2>
</div>
{!showAll ? (
<Button variant={"dangerOutlined"} onClick={() => setShowAll(true)} className="cursor-pointer">
Lihat Semua
</Button>
) : (
<Button variant={"dangerOutlined"} onClick={() => setShowAll(false)} className="cursor-pointer">
Lebih Sedikit
</Button>
)}
</div>
<p className="text-md text-gray-600">Telusuri ragam topik yang tersedia!</p>
{(() => {
if (showSkeleton) {
return (
<div className="mb-4 mt-8 grid grid-cols-1 gap-6 md:grid-cols-3 xl:grid-cols-6">
{[...Array(6)].map((_, i) => (
<div key={i} className="aspect-[4/3] w-full animate-pulse rounded-2xl bg-zinc-200" />
))}
</div>
);
}
if (isError) {
return <ErrorState message={error?.message} onRetry={refetch} />;
}
if (isSuccess && (!categories || categories.length === 0)) {
return (
<div className="mt-6 rounded-xl border border-zinc-200 bg-white p-6 text-zinc-600">Belum ada kategori untuk ditampilkan.</div>
);
}
if (isSuccess && categories && categories.length > 0) {
return (
<div className="mb-4 mt-8 grid grid-cols-1 gap-6 md:grid-cols-3 xl:grid-cols-6">
{categories.map((cat) => (
<CategoryCard
key={cat.id}
id={cat.id}
name={cat.name}
totalDataset={cat?.count_mapset ?? 0}
description={cat.description}
icon={cat.thumbnail}
link={`/maps?open-catalog=true&tab=category&category_id=${cat.id}`}
/>
))}
</div>
);
}
return null;
})()}
</section>
);
}