120 lines
3.6 KiB
TypeScript
Executable File
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>
|
|
</>
|
|
);
|
|
}
|