'use client' import React, { useState, useEffect } from 'react' import { Card } from '@/components/ui/card' import { ChevronDown, ChevronUp, Users, CheckCircle2, Package, InboxIcon, ChevronLeft, ChevronRight, Search } from 'lucide-react' import { cn } from '@/lib/utils' import { Button } from '@/components/ui/button' import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogDescription } from '@/components/ui/dialog' import { updateBulkSubmissionPayment } from '@/app/actions' import { format } from 'date-fns' const ITEMS_PER_PAGE = 5 const formatRupiah = (value: number) => new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', maximumFractionDigits: 0 }).format(value) export default function ReportByPersonGrid({ data, onUpdate }: { data: any[]; onUpdate: () => void }) { const [expandedRows, setExpandedRows] = useState>({}) const [currentPage, setCurrentPage] = useState(1) const [searchQuery, setSearchQuery] = useState('') const [modalOpen, setModalOpen] = useState(false) const [saving, setSaving] = useState(false) const [target, setTarget] = useState<{ ids: string[]; label: string; amount: number }>({ ids: [], label: '', amount: 0 }) // Reset page + search when data changes (e.g. filter changed) useEffect(() => { setCurrentPage(1) setExpandedRows({}) setSearchQuery('') }, [data]) // Reset page when search changes useEffect(() => { setCurrentPage(1) }, [searchQuery]) const toggleRow = (id: string) => setExpandedRows(prev => ({ ...prev, [id]: !prev[id] })) // Group by user const usersMap = new Map() data.forEach(order => { order.submissions.forEach((sub: any) => { if (!usersMap.has(sub.user.id)) { usersMap.set(sub.user.id, { user: sub.user, totalPiutang: 0, totalPaid: 0, submissions: [] }) } const obj = usersMap.get(sub.user.id) const amount = Number(sub.bill) || 0 if (sub.payment_status !== 'LUNAS') obj.totalPiutang += amount else obj.totalPaid += amount obj.submissions.push({ ...sub, orderTitle: order.title, orderDate: order.date }) }) }) const userList = Array.from(usersMap.values()) .map(obj => ({ ...obj, // Sort each person's PO list by order date, newest first submissions: [...obj.submissions].sort( (a: any, b: any) => new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime() ) })) .sort((a, b) => b.totalPiutang - a.totalPiutang) const q = searchQuery.toLowerCase().trim() const filteredUserList = q ? userList.filter(u => u.user.name?.toLowerCase().includes(q)) : userList const totalPages = Math.ceil(filteredUserList.length / ITEMS_PER_PAGE) const paginatedList = filteredUserList.slice((currentPage - 1) * ITEMS_PER_PAGE, currentPage * ITEMS_PER_PAGE) const openModal = (e: React.MouseEvent, ids: string[], label: string, amount: number) => { e.stopPropagation() setTarget({ ids, label, amount }) setModalOpen(true) } const handleConfirm = async () => { if (!target.ids.length) return setSaving(true) const res = await updateBulkSubmissionPayment(target.ids, 'LUNAS') setSaving(false) if (res.success) { setModalOpen(false) onUpdate() } } return ( <>

Detail Piutang Berdasarkan Orang

setSearchQuery(e.target.value)} className="text-xs font-medium bg-transparent border-none outline-none w-full text-slate-700 dark:text-slate-200 placeholder:text-slate-400" />
{userList.length === 0 ? (

Tidak ada data pemesan di periode ini.

) : filteredUserList.length === 0 ? (

Tidak ada hasil untuk "{searchQuery}".

) : ( <>
{paginatedList.map((userObj) => { const isExpanded = !!expandedRows[userObj.user.id] const unpaid = userObj.submissions.filter((s: any) => s.payment_status !== 'LUNAS') return ( toggleRow(userObj.user.id)} className={cn( 'hover:bg-slate-50/50 dark:hover:bg-slate-800/40 cursor-pointer transition-colors group', isExpanded && 'bg-slate-50/30 dark:bg-slate-800/20' )} > {isExpanded && ( )} ) })}
Nama Pemesan Total PO Total Piutang Aksi
{userObj.user.photo ? ( {userObj.user.name} ) : (
{userObj.user.name.charAt(0).toUpperCase()}
)}

{userObj.user.name}

{userObj.submissions.length} PO {userObj.totalPiutang > 0 ? (

{formatRupiah(userObj.totalPiutang)}

) : (

Lunas Semua

)} {userObj.totalPaid > 0 && (

Lunas: {formatRupiah(userObj.totalPaid)}

)}
{unpaid.length > 0 ? ( ):( Selesai)}

Rincian Hutang per PO

{userObj.submissions.map((sub: any) => { const isUnpaid = sub.payment_status !== 'LUNAS' return ( ) })}
Judul PO Tgl Order Status Tagihan Aksi
{sub.orderTitle} {format(new Date(sub.orderDate), 'dd MMM yyyy')} {isUnpaid ? 'Belum' : 'Lunas'} {sub.bill ? formatRupiah(sub.bill) : 'Rp0'} {isUnpaid ? ( ) : ( Selesai )}
{/* Pagination */} {totalPages > 1 && (

Halaman {currentPage} dari{' '} {totalPages}

)} )}
{/* Confirmation Modal */} Konfirmasi Pelunasan Tandai {target.label} sebagai LUNAS?

Total Nominal

{formatRupiah(target.amount)}

) }