import React, { useState, useEffect, useMemo, useCallback } from 'react'; import { useQuery } from 'react-query'; import { CloudLoadingIndicator } from 'components' import PaymentMadeItemsTableEditor from './PaymentMadeItemsTableEditor'; import withPaymentMadeActions from './withPaymentMadeActions'; import withBillActions from '../Bill/withBillActions'; import withBills from '../Bill/withBills'; import { compose } from 'utils'; /** * Payment made items table. */ function PaymentMadeItemsTable({ // #ownProps paymentMadeId, vendorId, fullAmount, onUpdateData, paymentEntries = [], // { bill_id: number, payment_amount: number, id?: number } onClickClearAllLines, errors, // #withBillActions requestFetchDueBills, // #withBills vendorPayableBills, paymentMadePayableBills, // #withPaymentMadeDetail paymentMade, }) { const [tableData, setTableData] = useState([]); const [localAmount, setLocalAmount] = useState(fullAmount); // Payable bills based on selected vendor or specific payment made. const payableBills = useMemo( () => paymentMadeId ? paymentMadePayableBills : vendorId ? vendorPayableBills : [], [paymentMadeId, paymentMadePayableBills, vendorId, vendorPayableBills], ); const isNewMode = !paymentMadeId; const triggerUpdateData = useCallback((data) => { onUpdateData && onUpdateData(data); }, [onUpdateData]); // Merges payment entries with payable bills. const computedTableData = useMemo(() => { const entriesTable = new Map( paymentEntries.map((e) => [e.bill_id, e]), ); return payableBills.map((bill) => { const entry = entriesTable.get(bill.id); return { ...bill, bill_id: bill.id, bill_payment_amount: bill.payment_amount, payment_amount: entry ? entry.payment_amount : 0, id: entry ? entry.id : null, } }); }, [paymentEntries, payableBills]); useEffect(() => { setTableData(computedTableData); }, [computedTableData]); // Handle mapping `fullAmount` prop to `localAmount` state. useEffect(() => { if (localAmount !== fullAmount) { let _fullAmount = fullAmount; const newTableData = tableData.map((data) => { const amount = Math.min(data.due_amount, _fullAmount); _fullAmount -= Math.max(amount, 0); return { ...data, payment_amount: amount, }; }); setTableData(newTableData); setLocalAmount(fullAmount); triggerUpdateData(newTableData); } }, [ tableData, setTableData, setLocalAmount, triggerUpdateData, localAmount, fullAmount, ]); // Fetches vendor due bills. const fetchVendorDueBills = useQuery( ['vendor-due-bills', vendorId], (key, _vendorId) => requestFetchDueBills(_vendorId), { enabled: isNewMode && vendorId }, ); // Handle update data. const handleUpdateData = (rows) => { triggerUpdateData(rows); }; const noResultsMessage = (vendorId) ? 'There is no payable bills for this vendor that can be applied for this payment' : 'Please select a vendor to display all open bills for it.'; return ( ); } export default compose( withPaymentMadeActions, withBillActions, withBills(({ vendorPayableBills, paymentMadePayableBills }) => ({ vendorPayableBills, paymentMadePayableBills, })), )(PaymentMadeItemsTable);