satupeta-main/app/(modules)/maps/components/feature-information/index.tsx
2026-01-27 09:31:12 +07:00

99 lines
3.6 KiB
TypeScript

"use client";
import { useAtom } from "jotai";
import { featureInformationAtom } from "../../state/feature-information";
import { useState } from "react";
import { ChevronDown, ChevronRight, X } from "lucide-react";
import { Button } from "@/shared/components/ui/button";
import { ColumnDef, RowData } from "@tanstack/react-table";
import { DataTable } from "@/shared/components/data-table";
export default function FeatureInformation() {
const [featureInformation, setFeatureInformation] = useAtom(featureInformationAtom);
const [expandedFeatures, setExpandedFeatures] = useState<Record<string, boolean>>({});
if (!featureInformation || featureInformation.length === 0) {
return null;
}
const toggleFeature = (featureName: string) => {
setExpandedFeatures((prev) => ({
...prev,
[featureName]: !prev[featureName],
}));
};
return (
<div className="z-[403] absolute top-5 right-5 bg-white rounded-lg shadow-md p-4 text-gray-900 w-[800px] max-h-[600px] overflow-auto">
<div className="flex items-center justify-between mb-4">
<div className="text-lg font-semibold">Feature Information</div>
<Button
variant="ghost"
size="icon"
title="Tutup"
aria-label="Tutup feature information"
onClick={() => {
setExpandedFeatures({});
setFeatureInformation([]);
}}
>
<X className="h-4 w-4" />
</Button>
</div>
<div className="">
{featureInformation.map((feature) => {
if (feature.info.length === 0) return null;
const propertyKeys = Array.from(
new Set(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
feature.info.flatMap((infoItem: { properties: any }) => Object.keys(infoItem.properties || {}))
)
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const columns: ColumnDef<RowData>[] = propertyKeys.map((key: any) => {
const column: ColumnDef<RowData> = {
accessorKey: key,
header: key,
};
return column;
});
const tableData = feature.info.map(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(infoItem: { properties: { id: any } }) => ({
...infoItem.properties,
id: infoItem.properties?.id || Math.random().toString(36).substring(7),
})
);
const isExpanded = expandedFeatures[feature.name] ?? false;
return (
<div key={feature.name} className="border overflow-hidden">
<Button variant="ghost" className="w-full flex justify-between items-center p-4 hover:bg-gray-50" onClick={() => toggleFeature(feature.name)}>
<span className="font-medium">{feature.name}</span>
{isExpanded ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
</Button>
{isExpanded && (
<div className="p-4 border-t">
{tableData.length > 0 ? (
<div style={{ maxHeight: "500px", overflowY: "auto" }}>
<DataTable columns={columns} data={tableData} searchPlaceholder={`Search ${feature.name}...`} pageSize={5} />
</div>
) : (
<div className="text-sm text-gray-500 py-4 text-center">No properties available</div>
)}
</div>
)}
</div>
);
})}
</div>
</div>
);
}