163 lines
4.8 KiB
TypeScript
163 lines
4.8 KiB
TypeScript
|
|
"use client";
|
|||
|
|
|
|||
|
|
import React from "react";
|
|||
|
|
|
|||
|
|
interface TableProps {
|
|||
|
|
title: string;
|
|||
|
|
columns: string[];
|
|||
|
|
rows: any[];
|
|||
|
|
total: number;
|
|||
|
|
limit?: number;
|
|||
|
|
variant?: "preview" | "warning";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function Table({ title, columns, rows, total, limit = 100, variant = "preview" }: TableProps) {
|
|||
|
|
const displayedRows = rows.slice(0, limit);
|
|||
|
|
|
|||
|
|
const shorten = (text: any, max = 80) => {
|
|||
|
|
if (!text) return "—";
|
|||
|
|
const strText = String(text);
|
|||
|
|
return strText.length > max ? strText.slice(0, max) + "..." : strText;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="w-full">
|
|||
|
|
<div className="overflow-x-auto border border-gray-200 rounded-lg shadow-sm bg-white">
|
|||
|
|
<table className="min-w-max text-sm text-gray-800 w-full">
|
|||
|
|
<thead
|
|||
|
|
className={`border-b ${
|
|||
|
|
variant === "warning" ? "bg-red-50" : "bg-gray-100"
|
|||
|
|
}`}
|
|||
|
|
>
|
|||
|
|
<tr>
|
|||
|
|
{columns.map((col) => (
|
|||
|
|
<th
|
|||
|
|
key={col}
|
|||
|
|
className="px-4 py-3 text-left font-medium text-gray-700 whitespace-nowrap"
|
|||
|
|
>
|
|||
|
|
{col}
|
|||
|
|
</th>
|
|||
|
|
))}
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
|
|||
|
|
<tbody>
|
|||
|
|
{displayedRows.length > 0 ? (
|
|||
|
|
displayedRows.map((row, idx) => (
|
|||
|
|
<tr
|
|||
|
|
key={idx}
|
|||
|
|
className={`border-t ${
|
|||
|
|
variant === "warning"
|
|||
|
|
? "bg-red-50/50 hover:bg-red-100/50"
|
|||
|
|
: "even:bg-gray-50 hover:bg-blue-50"
|
|||
|
|
} transition-colors`}
|
|||
|
|
>
|
|||
|
|
{columns.map((col) => (
|
|||
|
|
<td
|
|||
|
|
key={col}
|
|||
|
|
className="px-4 py-2 border-t border-gray-100 whitespace-nowrap max-w-[250px] overflow-hidden text-ellipsis"
|
|||
|
|
title={String(row[col] ?? "")}
|
|||
|
|
>
|
|||
|
|
{row[col] !== null && row[col] !== undefined && row[col] !== "" ? (
|
|||
|
|
col === "geometry" ? (
|
|||
|
|
shorten(row[col], 50)
|
|||
|
|
) : (
|
|||
|
|
shorten(row[col], 80)
|
|||
|
|
)
|
|||
|
|
) : (
|
|||
|
|
<span className="text-gray-300">—</span>
|
|||
|
|
)}
|
|||
|
|
</td>
|
|||
|
|
))}
|
|||
|
|
</tr>
|
|||
|
|
))
|
|||
|
|
) : (
|
|||
|
|
<tr>
|
|||
|
|
<td
|
|||
|
|
colSpan={columns.length}
|
|||
|
|
className="text-center text-gray-500 py-6 italic"
|
|||
|
|
>
|
|||
|
|
Tidak ada data yang dapat ditampilkan
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
)}
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
<div className="flex justify-between items-center px-1 py-2 text-xs text-gray-500">
|
|||
|
|
<p>
|
|||
|
|
Menampilkan {Math.min(limit, displayedRows.length)} dari {total} baris.
|
|||
|
|
</p>
|
|||
|
|
{variant === "preview" && (
|
|||
|
|
<p className="italic text-gray-400">
|
|||
|
|
Hanya menampilkan cuplikan data
|
|||
|
|
</p>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
interface TablePreviewProps {
|
|||
|
|
result: {
|
|||
|
|
columns?: string[];
|
|||
|
|
preview?: any[];
|
|||
|
|
geometry_valid?: number;
|
|||
|
|
geometry_empty?: number;
|
|||
|
|
warning_rows?: any[];
|
|||
|
|
[key: string]: any;
|
|||
|
|
} | null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default function TablePreview({ result }: TablePreviewProps) {
|
|||
|
|
if (!result) return null;
|
|||
|
|
|
|||
|
|
const {
|
|||
|
|
columns = [],
|
|||
|
|
preview = [],
|
|||
|
|
geometry_valid = 0,
|
|||
|
|
geometry_empty = 0,
|
|||
|
|
warning_rows = [],
|
|||
|
|
} = result;
|
|||
|
|
|
|||
|
|
return (
|
|||
|
|
<div className="w-full space-y-6">
|
|||
|
|
{/* 1. WARNING TABLE (Jika ada data yang tidak valid geometrinya) */}
|
|||
|
|
{warning_rows?.length > 0 && (
|
|||
|
|
<div className="border-l-4 border-yellow-400 pl-4 py-2 bg-yellow-50 rounded-r-lg">
|
|||
|
|
<h3 className="font-semibold text-yellow-800 mb-1">
|
|||
|
|
⚠️ Periksa Data Wilayah
|
|||
|
|
</h3>
|
|||
|
|
<p className="text-sm text-yellow-700 mb-3">
|
|||
|
|
Sistem tidak dapat mendeteksi geometri untuk data di bawah ini. Pastikan nama wilayah sesuai referensi.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<Table
|
|||
|
|
title="Data Perlu Diperiksa"
|
|||
|
|
columns={columns}
|
|||
|
|
rows={warning_rows}
|
|||
|
|
total={geometry_empty}
|
|||
|
|
limit={100}
|
|||
|
|
variant="warning"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
)}
|
|||
|
|
|
|||
|
|
{/* 2. PREVIEW TABLE (Data Valid) */}
|
|||
|
|
<div>
|
|||
|
|
{geometry_valid > 0 ? (
|
|||
|
|
<Table
|
|||
|
|
title="Cuplikan Data"
|
|||
|
|
columns={columns}
|
|||
|
|
rows={preview}
|
|||
|
|
total={geometry_valid}
|
|||
|
|
limit={10} // Tampilkan 10 baris saja agar tidak terlalu panjang
|
|||
|
|
variant="preview"
|
|||
|
|
/>
|
|||
|
|
) : (
|
|||
|
|
!warning_rows?.length && <div className="text-gray-500 italic">Tidak ada data preview tersedia.</div>
|
|||
|
|
)}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
);
|
|||
|
|
}
|