From e9f7bc2043b79fbea1fddedc662e854216f97e42 Mon Sep 17 00:00:00 2001 From: nico Date: Tue, 3 Mar 2026 16:38:15 +0800 Subject: [PATCH] feat(ui landing): add expandable realisasi detail in RealisasiTable Features: - Add expandable rows for each APBDes item - Show detailed realisasi breakdown per item - Each realisasi shows: * Keterangan/Uraian * Jumlah (formatted in Rupiah) * Tanggal (formatted date) - Chevron icon indicator (right/down) - Click row to expand/collapse - Hover effect on clickable rows - Info text: "Klik pada item untuk melihat detail realisasi" UI Components: - RealisasiDetail: Component to display list of realisasi - ItemRow: Expandable row with click handler - Updated Section: Manage expanded state per item Styling: - Gray background for detail section - Blue color for amount - Dimmed color for date - Responsive layout with wrap="nowrap" - Proper spacing between items Co-authored-by: Qwen-Coder --- .../main-page/apbdes/lib/realisasiTable.tsx | 155 +++++++++++++++--- 1 file changed, 131 insertions(+), 24 deletions(-) diff --git a/src/app/darmasaba/_com/main-page/apbdes/lib/realisasiTable.tsx b/src/app/darmasaba/_com/main-page/apbdes/lib/realisasiTable.tsx index 7d720f0b..4f2911a3 100644 --- a/src/app/darmasaba/_com/main-page/apbdes/lib/realisasiTable.tsx +++ b/src/app/darmasaba/_com/main-page/apbdes/lib/realisasiTable.tsx @@ -1,39 +1,142 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { Paper, Table, Title, Badge } from '@mantine/core'; +import { Paper, Table, Title, Badge, Group, Text, Box, Collapse } from '@mantine/core'; +import { useState } from 'react'; +import { IconChevronDown, IconChevronRight } from '@tabler/icons-react'; + +function RealisasiDetail({ realisasiItems }: { realisasiItems: any[] }) { + if (!realisasiItems || realisasiItems.length === 0) { + return ( + + Belum ada realisasi + + ); + } + + const formatRupiah = (amount: number) => { + return new Intl.NumberFormat('id-ID', { + style: 'currency', + currency: 'IDR', + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }).format(amount); + }; + + const formatDate = (dateString: string) => { + return new Date(dateString).toLocaleDateString('id-ID', { + day: 'numeric', + month: 'short', + year: 'numeric', + }); + }; + + return ( + + + Rincian Realisasi ({realisasiItems.length}): + + <> + {realisasiItems.map((realisasi: any, idx: number) => ( + + + + {realisasi.keterangan || `Realisasi ${idx + 1}`} + + + {formatRupiah(realisasi.jumlah)} + + + {formatDate(realisasi.tanggal)} + + + + ))} + + + ); +} + +function ItemRow({ item, expanded, onToggle }: any) { + const formatRupiah = (amount: number) => { + return new Intl.NumberFormat('id-ID', { + style: 'currency', + currency: 'IDR', + minimumFractionDigits: 0, + maximumFractionDigits: 0, + }).format(amount); + }; + + const hasRealisasi = item.realisasiItems && item.realisasiItems.length > 0; + + return ( + <> + + + + {hasRealisasi ? ( + expanded ? ( + + ) : ( + + ) + ) : ( + + )} + {item.kode} - {item.uraian} + + + + + {formatRupiah(item.totalRealisasi)} + + + + = 100 + ? 'teal' + : item.persentase >= 60 + ? 'yellow' + : 'red' + } + > + {item.persentase.toFixed(2)}% + + + + + + + {hasRealisasi && } + + + + + ); +} function Section({ title, data }: any) { if (!data || data.length === 0) return null; + const [expandedId, setExpandedId] = useState(null); + return ( <> - {title} + {title} {data.map((item: any) => ( - - - {item.kode} - {item.uraian} - - - Rp {item.totalRealisasi.toLocaleString('id-ID')} - - - = 100 - ? 'teal' - : item.persentase >= 60 - ? 'yellow' - : 'red' - } - > - {item.persentase.toFixed(2)}% - - - + setExpandedId(expandedId === item.id ? null : item.id)} + /> ))} ); @@ -55,11 +158,15 @@ export default function RealisasiTable({ apbdesData }: any) { {title} + + 💡 Klik pada item untuk melihat detail realisasi + + Uraian - Realisasi (Rp) + Total Realisasi (Rp) %