function MobileBranchSalesReport({ 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 [showFilters, setShowFilters] = React.useState(false); 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; 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}
} {/* Filter toggle */}
{showFilters && (
setDateFrom(e.target.value)} style={{ width: '100%', padding: '8px', marginTop: 4 }} />
setDateTo(e.target.value)} style={{ width: '100%', padding: '8px', marginTop: 4 }} />
)} {/* Summary */}
Sales
{total}
Revenue
{currency(totalRevenue)}
Items
{totalItems}
{/* Sales list */} {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)}>
{sale.branchName || sale.branch_id?.slice(-6) || '-'}
{sale.customerName || 'Walk-in'} {sale.customerNo ? '• ' + sale.customerNo : ''}
{currency(sale.totalAmount)}
{sale.createdAt ? new Date(sale.createdAt).toLocaleString('en-IN') : '-'}
{sale.paymentMethod || '-'} {itemCount} item(s) {sale.discount > 0 && {sale.discount}% off} {taxAmount > 0 && Tax: {currency(taxAmount)}} {isExpanded ? '▼' : '▶'}
{isExpanded && (
Subtotal: {currency(sale.subTotal)} {sale.discount > 0 && Disc: {sale.discount}% ({currency(sale.discountAmount)})} {sale.cgst > 0 && CGST: {sale.cgst}%} {sale.sgst > 0 && SGST: {sale.sgst}%} {sale.igst > 0 && IGST: {sale.igst}%} Paid: {currency(sale.amountPaid)}
{(Array.isArray(sale.items) ? sale.items : []).map((it, ii) => (
{it.productName || '-'}
#{it.productNo || '-'} • Qty: {it.qty} × {currency(it.sellingPrice)}
{currency(it.lineTotal)}
{Array.isArray(it.imes) && it.imes.length > 0 && (
IMEIs: {it.imes.join(', ')}
)}
))}
)}
); })}
)} {/* Pagination */} {totalPages > 1 && (
Page {page}/{totalPages}
)}
); } window.MobileBranchSalesReport = MobileBranchSalesReport;