function BranchSalesReport({ salesUrl, token }) { const [branches, setBranches] = React.useState([]); const [selectedBranch, setSelectedBranch] = React.useState(''); const [sales, setSales] = React.useState([]); const [loading, setLoading] = React.useState(false); const [error, setError] = React.useState(''); const [page, setPage] = React.useState(1); const [total, setTotal] = React.useState(0); const [pageSize] = React.useState(25); const [dateFrom, setDateFrom] = React.useState(''); const [dateTo, setDateTo] = React.useState(''); const [expandedSale, setExpandedSale] = React.useState(null); const currency = (n) => new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR', maximumFractionDigits: 2 }).format(n || 0); const loadBranches = async () => { try { const res = await fetch(salesUrl + '/api/branches', { headers: { Authorization: 'Bearer ' + token } }); const data = await res.json(); if (res.ok) setBranches(Array.isArray(data.branches) ? data.branches : []); } catch (e) { /* ignore */ } }; const loadSales = async (pg) => { setLoading(true); setError(''); try { const url = new URL(salesUrl + '/api/sales'); if (selectedBranch) url.searchParams.set('branch_id', selectedBranch); url.searchParams.set('page', String(pg || page)); url.searchParams.set('pageSize', String(pageSize)); if (dateFrom) url.searchParams.set('from', dateFrom); if (dateTo) url.searchParams.set('to', dateTo); const res = await fetch(url, { headers: { Authorization: 'Bearer ' + token } }); const data = await res.json(); if (!res.ok) throw new Error(data.message || 'Failed to load sales'); setSales(Array.isArray(data.sales) ? data.sales : []); setTotal(data.total || 0); setPage(data.page || pg || 1); } catch (e) { setError(e.message); } finally { setLoading(false); } }; React.useEffect(() => { loadBranches(); }, []); React.useEffect(() => { loadSales(1); }, [selectedBranch, dateFrom, dateTo]); const totalPages = Math.ceil(total / pageSize) || 1; // Summary calculations const totalRevenue = sales.reduce((s, sale) => s + (Number(sale.totalAmount) || 0), 0); const totalItems = sales.reduce((s, sale) => s + (Array.isArray(sale.items) ? sale.items.reduce((a, it) => a + (Number(it.qty) || 0), 0) : 0), 0); return (
{error &&
{error}
} {/* Filters */}
setDateFrom(e.target.value)} style={{ padding: '8px 12px' }} />
setDateTo(e.target.value)} style={{ padding: '8px 12px' }} />
{/* Summary Cards */}
Total Sales
{total}
Page Revenue
{currency(totalRevenue)}
Items Sold (page)
{totalItems}
{/* Sales Table */}
{loading ? (
Loading...
) : sales.length === 0 ? (
No sales found
) : ( {sales.map((sale, si) => { const isExpanded = expandedSale === sale._id; const itemCount = Array.isArray(sale.items) ? sale.items.reduce((a, it) => a + (Number(it.qty) || 0), 0) : 0; const taxAmount = (Number(sale.cgstAmount) || 0) + (Number(sale.sgstAmount) || 0) + (Number(sale.igstAmount) || 0); return ( setExpandedSale(isExpanded ? null : sale._id)}> {isExpanded && ( )} ); })}
Branch Customer Items Subtotal Discount Tax Total Payment Date & Time
{isExpanded ? '▼' : '▶'} {sale.branchName || sale.branch_id?.slice(-6) || '-'}
{sale.customerName || 'Walk-in'}
{sale.customerNo &&
{sale.customerNo}
}
{itemCount} {currency(sale.subTotal)} {sale.discount ? sale.discount + '%' : '-'} {taxAmount > 0 ? currency(taxAmount) : '-'} {currency(sale.totalAmount)} {sale.paymentMethod || '-'} {sale.createdAt ? new Date(sale.createdAt).toLocaleString('en-IN') : '-'}
Subtotal: {currency(sale.subTotal)}
{sale.discount > 0 &&
Discount: {sale.discount}% ({currency(sale.discountAmount)})
} {sale.cgst > 0 &&
CGST: {sale.cgst}% ({currency(sale.cgstAmount)})
} {sale.sgst > 0 &&
SGST: {sale.sgst}% ({currency(sale.sgstAmount)})
} {sale.igst > 0 &&
IGST: {sale.igst}% ({currency(sale.igstAmount)})
}
Amount Paid: {currency(sale.amountPaid)}
{(Array.isArray(sale.items) ? sale.items : []).map((it, ii) => ( ))}
Product No Product Name Qty Unit Price Line Total IMEIs
{it.productNo || '-'} {it.productName || '-'} {it.qty} {currency(it.sellingPrice)} {currency(it.lineTotal)} {Array.isArray(it.imes) && it.imes.length ? it.imes.join(', ') : '-'}
)}
{/* Pagination */} {totalPages > 1 && (
Page {page} of {totalPages}
)}
); } window.BranchSalesReport = BranchSalesReport;