163 lines
4.8 KiB
TypeScript
Executable File
163 lines
4.8 KiB
TypeScript
Executable File
"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>
|
||
);
|
||
} |