// Supplier Credits - Admin-only view for tracking credit purchases and payments function SupplierCredits({ salesUrl, token }) { const [credits, setCredits] = React.useState([]); const [summary, setSummary] = React.useState([]); const [loading, setLoading] = React.useState(true); const [error, setError] = React.useState(''); const [activeTab, setActiveTab] = React.useState('summary'); // summary | all | pending const [payModal, setPayModal] = React.useState(null); const [payAmount, setPayAmount] = React.useState(''); const [payNote, setPayNote] = React.useState(''); const [paying, setPaying] = React.useState(false); const [filterSupplier, setFilterSupplier] = React.useState(''); const getToken = () => { const storedBranchToken = typeof window !== 'undefined' ? (localStorage.getItem('branch_token') || '') : ''; return token || storedBranchToken || ''; }; const loadCredits = async (status) => { try { const effectiveToken = getToken(); let url = salesUrl + '/api/supplier-credits'; const params = []; if (status && status !== 'all') params.push('status=' + status); if (filterSupplier) params.push('supplier_id=' + filterSupplier); if (params.length) url += '?' + params.join('&'); const res = await fetch(url, { headers: { Authorization: 'Bearer ' + effectiveToken } }); const data = await res.json(); if (!res.ok) throw new Error(data.message || 'Failed to load credits'); setCredits(data.credits || []); } catch (e) { setError(e.message); } }; const loadSummary = async () => { try { const effectiveToken = getToken(); const res = await fetch(salesUrl + '/api/supplier-credits/summary', { headers: { Authorization: 'Bearer ' + effectiveToken } }); const data = await res.json(); if (!res.ok) throw new Error(data.message || 'Failed to load summary'); setSummary(data.summary || []); } catch (e) { setError(e.message); } }; const loadAll = async () => { setLoading(true); setError(''); await Promise.all([loadSummary(), loadCredits(activeTab === 'pending' ? 'pending' : undefined)]); setLoading(false); }; React.useEffect(() => { loadAll(); }, [activeTab, filterSupplier]); const formatCurrency = (n) => new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR' }).format(n || 0); const totals = summary.reduce((acc, s) => ({ totalCredit: acc.totalCredit + (s.totalCredit || 0), totalPaid: acc.totalPaid + (s.totalPaid || 0), outstanding: acc.outstanding + (s.outstanding || 0), count: acc.count + (s.count || 0) }), { totalCredit: 0, totalPaid: 0, outstanding: 0, count: 0 }); const handlePay = async () => { if (!payModal || !payAmount || Number(payAmount) <= 0) return; setPaying(true); setError(''); try { const effectiveToken = getToken(); const res = await fetch(salesUrl + '/api/supplier-credits/' + payModal._id + '/pay', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + effectiveToken }, body: JSON.stringify({ amount: Number(payAmount), note: payNote }) }); const data = await res.json(); if (!res.ok) throw new Error(data.message || 'Payment failed'); setPayModal(null); setPayAmount(''); setPayNote(''); await loadAll(); } catch (e) { setError(e.message); } finally { setPaying(false); } }; const tabStyle = (active) => ({ padding: '10px 24px', borderRadius: '8px', fontSize: '14px', fontWeight: '600', cursor: 'pointer', border: 'none', background: active ? '#1e293b' : 'transparent', color: active ? '#fff' : '#64748b', transition: 'all 0.2s ease' }); const cardStyle = { background: '#fff', borderRadius: '16px', border: '1px solid #e5e7eb', boxShadow: '0 1px 3px rgba(0,0,0,0.1)', overflow: 'hidden' }; return (
{/* Summary Cards */}
Total Credit Given
{formatCurrency(totals.totalCredit)}
{totals.count} entries
Total Paid Back
{formatCurrency(totals.totalPaid)}
Outstanding Balance
0 ? '#dc2626' : '#059669' }}>{formatCurrency(totals.outstanding)}
{/* Tabs */}
{error && (
⚠️ {error}
)} {loading ? (
Loading…
) : activeTab === 'summary' ? ( /* Summary Tab - Per Supplier */

Supplier Credit Summary

{summary.length === 0 ? (
💳
No Credit Entries
Credit purchases will appear here
) : (
{summary.map((s, i) => ( ))}
Supplier Entries Total Credit Paid Outstanding
🏢 {s.supplierName || s.supplier_id?.supplierName || s.supplier_id?.agencyName || 'Unknown'} {s.count} {formatCurrency(s.totalCredit)} {formatCurrency(s.totalPaid)} 0 ? '#dc2626' : '#059669' }}> {formatCurrency(s.outstanding)}
)}
) : ( /* All / Pending Credits Tab */

{activeTab === 'pending' ? '⏳ Pending Credits' : '📋 All Credit Entries'}

{credits.length} entries
{credits.length === 0 ? (
No {activeTab === 'pending' ? 'Pending ' : ''}Credits
) : (
{credits.map((credit) => { const outstanding = (credit.totalAmount || 0) - (credit.paidAmount || 0); return (
🏢 {credit.supplier_id?.supplierName || credit.supplier_id?.agencyName || 'Unknown Supplier'}
{new Date(credit.createdAt).toLocaleDateString('en-IN', { day: 'numeric', month: 'short', year: 'numeric' })} {credit.inStock_id?.items?.length ? ` • ${credit.inStock_id.items.length} product(s)` : ''}
{credit.status === 'settled' ? '✅ Settled' : credit.status === 'partial' ? '🔶 Partial' : '🔴 Pending'}
{/* Products Purchased */} {credit.inStock_id?.items && credit.inStock_id.items.length > 0 && (
📦 Products Purchased
{credit.inStock_id.items.map((item, ii) => (
{item.productName}{item.brand ? ` (${item.brand})` : ''}{item.model ? ` - ${item.model}` : ''} Qty: {item.quantity || 1}{item.costPrice ? ` × ${formatCurrency(item.costPrice)}` : ''}
))}
)}
Credit
{formatCurrency(credit.totalAmount)}
Paid
{formatCurrency(credit.paidAmount)}
Due
0 ? '#dc2626' : '#059669' }}>{formatCurrency(outstanding)}
{/* Payment History */} {credit.payments && credit.payments.length > 0 && (
Payment History
{credit.payments.map((p, pi) => (
{new Date(p.createdAt || p.paidAt).toLocaleDateString('en-IN', { day: 'numeric', month: 'short' })} {p.note ? `- ${p.note}` : ''} {formatCurrency(p.amount)}
))}
)} {credit.status !== 'settled' && ( )}
); })}
)}
)} {/* Payment Modal */} {payModal && (

Record Payment

{payModal.supplier_id?.supplierName || payModal.supplier_id?.agencyName || 'Supplier'} — Outstanding: {formatCurrency((payModal.totalAmount || 0) - (payModal.paidAmount || 0))}

setPayAmount(e.target.value)} placeholder="Enter amount" style={{ width: '100%', padding: '12px 16px', border: '2px solid #e5e7eb', borderRadius: '8px', fontSize: '14px', outline: 'none' }} onFocus={(e) => e.target.style.borderColor = '#059669'} onBlur={(e) => e.target.style.borderColor = '#e5e7eb'} autoFocus />
setPayNote(e.target.value)} placeholder="e.g. Paid via UPI" style={{ width: '100%', padding: '12px 16px', border: '2px solid #e5e7eb', borderRadius: '8px', fontSize: '14px', outline: 'none' }} onFocus={(e) => e.target.style.borderColor = '#059669'} onBlur={(e) => e.target.style.borderColor = '#e5e7eb'} />
)}
); } window.SupplierCredits = SupplierCredits;