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

120 lines
3.6 KiB
TypeScript
Executable File

"use client";
import React, { useState } from "react";
import OrganizationCard from "./organization-card";
import { useQuery } from "@tanstack/react-query";
import organizationApi from "@/shared/services/organization";
import { Button } from "@/shared/components/button/button";
import { ErrorState } from "@/shared/components/error-state";
export function OrganizationSection() {
const [showAll, setShowAll] = useState(false);
const {
data: organizations,
isLoading,
isError,
error,
isSuccess,
refetch,
isFetching,
} = useQuery({
queryKey: ["organizations-list", showAll],
queryFn: () =>
organizationApi
.getOrganizations(
{
...(showAll ? {} : { limit: 8 }),
filter: ["is_active=true"],
},
{ skipAuth: true },
)
.then((res) => res.items),
staleTime: 5000,
retry: 1,
});
const showSkeleton = isLoading || (isFetching && !isSuccess);
return (
<>
<section
id="organization"
className="font-onest @container container mt-24"
>
<div className="flex items-center justify-between">
<div className="flex items-center">
<div className="h-8 w-1 rounded-full bg-blue-500"></div>
<h2 className="font-onest text-dark-500 ms-3 text-[28px] font-bold">
Data Geospasial Lintas OPD
</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">
Organisasi Perangkat Daerah yang berkontribusi dalam penyediaan data
</p>
{(() => {
if (showSkeleton) {
return (
<div className="mt-8 mb-4 grid grid-cols-1 gap-4 md:grid-cols-4">
{[...Array(8)].map((_, i) => (
<div
className="aspect-video w-full animate-pulse rounded-xl bg-zinc-200"
key={i}
/>
))}
</div>
);
}
if (isError) {
return <ErrorState message={error?.message} onRetry={refetch} />;
}
const visibleOrgs = (organizations ?? []).filter((o) => (o?.count_mapset ?? 0) > 0);
if (isSuccess && visibleOrgs.length === 0) {
return (
<div className="mt-6 rounded-xl border border-zinc-200 bg-white p-6 text-zinc-600">
Belum ada data geospasial lintas OPD untuk ditampilkan.
</div>
);
}
if (isSuccess && visibleOrgs.length > 0) {
return (
<div className="mt-8 mb-4 grid grid-cols-1 gap-4 md:grid-cols-4">
{visibleOrgs.map((org) => (
<OrganizationCard
name={org.name}
totalDataset={org?.count_mapset ?? 0}
link={`/maps?open-catalog=true&query=${org.name}&tab=organization&producer_id=${org.id}`}
icon={org.thumbnail ?? "/landing/logo_pemprov_jatim.png"}
key={org.id}
/>
))}
</div>
);
}
})()}
</section>
</>
);
}