function MobileCreateSupplier({ salesUrl, token }) { const [rows, setRows] = React.useState([]); const [inStockEntries, setInStockEntries] = React.useState([]); const [saving, setSaving] = React.useState(false); const [loading, setLoading] = React.useState(false); const [error, setError] = React.useState(''); const [page, setPage] = React.useState(1); const [pageSize] = React.useState(10); const formTopRef = React.useRef(null); const nameInputRef = React.useRef(null); const { features, getFeatureLimit, isLimitReached } = window.useSalesFeatures ? window.useSalesFeatures() : { features: {}, getFeatureLimit: () => 999, isLimitReached: () => false }; const supplierLimit = getFeatureLimit('supplier_limit', 'maxSuppliers'); const currentSupplierCount = rows.length; const isAtLimit = isLimitReached('supplier_limit', 'maxSuppliers', currentSupplierCount); const decodeJwt = (tk) => { try { const base64 = tk.split('.')[1] || ''; const json = atob(base64.replace(/-/g, '+').replace(/_/g, '/')); return JSON.parse(json); } catch (_e) { return null; } }; const storedBranchToken = typeof window !== 'undefined' ? (localStorage.getItem('branch_token') || '') : ''; const effectiveToken = token || storedBranchToken || ''; const decodedEffective = effectiveToken ? decodeJwt(effectiveToken) : null; const branchUserDecoded = decodedEffective && decodedEffective.branch_id ? decodedEffective : null; const effectiveIsAtLimit = branchUserDecoded ? false : isAtLimit; const [agencyFilter, setAgencyFilter] = React.useState(''); const [phoneFilter, setPhoneFilter] = React.useState(''); const [panFilter, setPanFilter] = React.useState(''); const [amountSort, setAmountSort] = React.useState(''); const [form, setForm] = React.useState({ supplierName: '', agencyName: '', phoneNumber: '', address: '', gstNumber: '', panNumber: '' }); const onChange = (e) => { const { name, value } = e.target; setForm((f) => ({ ...f, [name]: value })); }; const fetchSuppliers = React.useCallback(async () => { setLoading(true); try { setError(''); let res = await fetch(salesUrl + '/api/suppliers', { headers: { Authorization: 'Bearer ' + effectiveToken } }); if (res.status === 401 && storedBranchToken && storedBranchToken !== effectiveToken) { res = await fetch(salesUrl + '/api/suppliers', { headers: { Authorization: 'Bearer ' + storedBranchToken } }); } const data = await res.json(); if (!res.ok) throw new Error(data.message || 'Failed to load'); const list = Array.isArray(data.suppliers) ? data.suppliers : []; setRows(list); setPage(1); } catch (err) { if (!branchUserDecoded) setError(err.message); } finally { setLoading(false); } }, [salesUrl, effectiveToken, storedBranchToken, branchUserDecoded]); const fetchInStock = React.useCallback(async () => { try { let res = await fetch(salesUrl + '/api/in-stock', { headers: { Authorization: 'Bearer ' + effectiveToken } }); if (res.status === 401 && storedBranchToken && storedBranchToken !== effectiveToken) { res = await fetch(salesUrl + '/api/in-stock', { headers: { Authorization: 'Bearer ' + storedBranchToken } }); } const data = await res.json(); if (!res.ok) throw new Error(data.message || 'Failed to load in-stock'); setInStockEntries(Array.isArray(data.entries) ? data.entries : []); } catch (err) { console.error(err); } }, [salesUrl, effectiveToken, storedBranchToken]); React.useEffect(() => { fetchSuppliers(); fetchInStock(); }, [fetchSuppliers, fetchInStock]); const supplierAmountMap = React.useMemo(() => { const map = {}; for (const e of inStockEntries) { const supplierId = e.supplier_id?._id || e.supplier_id; if (!supplierId) continue; map[supplierId] = (map[supplierId] || 0) + (Number(e.supplierAmount) || 0); } return map; }, [inStockEntries]); const supplierItemsCountMap = React.useMemo(() => { const map = {}; for (const e of inStockEntries) { const supplierId = e.supplier_id?._id || e.supplier_id; if (!supplierId) continue; const cnt = Array.isArray(e.items) ? e.items.length : 0; map[supplierId] = (map[supplierId] || 0) + cnt; } return map; }, [inStockEntries]); const filteredRows = React.useMemo(() => { let result = (rows || []).filter((r) => { const agencyMatch = !agencyFilter || (r.agencyName && r.agencyName.toLowerCase().includes(agencyFilter.toLowerCase())); const phoneMatch = !phoneFilter || (r.phoneNumber && r.phoneNumber.toLowerCase().includes(phoneFilter.toLowerCase())); const panMatch = !panFilter || (r.panNumber && r.panNumber.toLowerCase().includes(panFilter.toLowerCase())); return agencyMatch && phoneMatch && panMatch; }); if (amountSort) { result = result.slice().sort((a, b) => { const aAmt = supplierAmountMap[a._id] || 0; const bAmt = supplierAmountMap[b._id] || 0; return amountSort === 'high' ? bAmt - aAmt : aAmt - bAmt; }); } return result; }, [rows, agencyFilter, phoneFilter, panFilter, amountSort, supplierAmountMap]); const total = filteredRows.length; const totalPages = Math.max(1, Math.ceil(total / pageSize)); const clampedPage = Math.min(totalPages, Math.max(1, page)); const startIndex = total === 0 ? 0 : (clampedPage - 1) * pageSize + 1; const endIndex = Math.min(clampedPage * pageSize, total); const visible = filteredRows.slice((clampedPage - 1) * pageSize, (clampedPage - 1) * pageSize + pageSize); const submit = async (e) => { e.preventDefault(); if (effectiveIsAtLimit) { window.checkSalesFeatureLimit('supplier_limit', 'maxSuppliers', currentSupplierCount, features, 'Supplier'); return; } setSaving(true); setError(''); try { let res = await fetch(salesUrl + '/api/suppliers', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + effectiveToken }, body: JSON.stringify(form) }); if (res.status === 401 && storedBranchToken && storedBranchToken !== effectiveToken) { res = await fetch(salesUrl + '/api/suppliers', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + storedBranchToken }, body: JSON.stringify(form) }); } const data = await res.json(); if (!res.ok || !data.success) throw new Error(data.message || 'Save failed'); setForm({ supplierName: '', agencyName: '', phoneNumber: '', address: '', gstNumber: '', panNumber: '' }); await fetchSuppliers(); try { if (nameInputRef.current) nameInputRef.current.focus(); } catch (_e) {} } catch (err) { if (!branchUserDecoded) setError(err.message); } finally { setSaving(false); } }; const clearFilters = () => { setAgencyFilter(''); setPhoneFilter(''); setPanFilter(''); setAmountSort(''); setPage(1); }; const scrollToCreate = () => { try { if (formTopRef.current) formTopRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' }); setTimeout(() => { try { if (nameInputRef.current) nameInputRef.current.focus(); } catch (_e) {} }, 250); } catch (_e) {} }; const badgeStyle = { display: 'inline-flex', alignItems: 'center', gap: 6, padding: '6px 10px', borderRadius: 999, border: '1px solid var(--border)', background: 'var(--bg)', fontSize: 12, fontWeight: 700, color: 'var(--text)' }; return (