// admin-finance.jsx — Full financial system: dashboard, transactions, expenses, invoices, P&L, tax const fmtAED = (n) => (n < 0 ? '−' : '') + 'AED ' + Math.abs(Math.round(n)).toLocaleString(); const fmtCompact = (n) => { const a = Math.abs(n); if (a >= 1000) return (n / 1000).toFixed(1) + 'K'; return String(n); }; // ─── Finance Dashboard ────────────────────────────────────── function FinanceDashboard({ lang }) { const t = (ar, en) => lang === 'ar' ? ar : en; const revSum = FINANCE_30D.revenue.reduce((a, b) => a + b, 0); const expSum = FINANCE_30D.expenses.reduce((a, b) => a + b, 0); const netProfit = revSum - expSum; const margin = (netProfit / revSum * 100).toFixed(1); const revMax = Math.max(...FINANCE_30D.revenue); const cashOnHand = 184320; const acctsRecv = INVOICES.filter(i => i.status !== 'paid').reduce((s, i) => s + i.total, 0); const pendingPay = TRANSACTIONS.filter(t => t.status === 'pending').reduce((s, t) => s + Math.abs(t.amount), 0); const kpis = [ { lbl: t('الإيرادات · 30 يوم', 'Revenue · 30d'), val: fmtAED(revSum), delta: '+18.2%', up: true, icon: , tone: '#6B7050' }, { lbl: t('المصاريف · 30 يوم', 'Expenses · 30d'), val: fmtAED(expSum), delta: '+8.4%', up: false, icon: , tone: '#C97B5E' }, { lbl: t('صافي الربح', 'Net profit'), val: fmtAED(netProfit), delta: '+24.6%', up: true, icon: , tone: '#2A1F18' }, { lbl: t('هامش الربح', 'Profit margin'), val: margin + '%', delta: '+2.1pt', up: true, icon: , tone: '#8C4A2B' }, ]; // Combined area chart paths const W = 600, H = 200; const xs = FINANCE_30D.revenue.map((_, i) => (i / 29) * W); const maxY = revMax * 1.1; const yRev = FINANCE_30D.revenue.map(v => H - (v / maxY) * H); const yExp = FINANCE_30D.expenses.map(v => H - (v / maxY) * H); const buildArea = (ys) => { let d = `M0 ${H} `; ys.forEach((y, i) => d += `L${xs[i]} ${y} `); d += `L${W} ${H} Z`; return d; }; const buildLine = (ys) => ys.map((y, i) => `${i ? 'L' : 'M'}${xs[i]} ${y}`).join(' '); return ( <>
{t('المالية · 01', 'Finance · 01')}

{t('لوحة الإيرادات', 'Financial Overview')}

{t('آخر ٣٠ يوماً · جميع المبالغ بالدرهم الإماراتي', 'Last 30 days · all amounts in AED')}
{kpis.map((k, i) => (
{k.icon}
{k.lbl}
{k.val}
{k.up ? : } {k.delta} {t('vs الفترة السابقة', 'vs prev')}
))}
{/* Cash position strip */}
{t('السيولة المتاحة', 'Cash on hand')}
{fmtAED(cashOnHand)}
{t('عبر ٣ حسابات بنكية', 'across 3 bank accounts')}
{t('ذمم مدينة', 'Accounts receivable')}
{fmtAED(acctsRecv)}
{INVOICES.filter(i => i.status !== 'paid').length} {t('فاتورة معلّقة', 'unpaid invoices')}
{t('مدفوعات معلّقة', 'Pending payments')}
{fmtAED(pendingPay)}
{t('للمورّدين', 'to suppliers')}
{t('ضريبة القيمة المضافة', 'VAT payable')}
{fmtAED(Math.round(revSum * 0.05))}
{t('Q2 · يستحق ٣٠ يونيو', 'Q2 · due Jun 30')}
{/* Main chart: revenue vs expenses */}

{t('الإيرادات مقابل المصاريف · آخر ٣٠ يوماً', 'Revenue vs Expenses · 30 days')}

{t('إيرادات', 'Revenue')} {t('مصاريف', 'Expenses')}
{/* gridlines */} {[0, 0.25, 0.5, 0.75, 1].map((g, i) => ( ))} {/* dots on last point */} {/* x labels */} Apr 19 May 4 May 18
{/* Two-up: expense breakdown + payment methods */}

{t('توزيع المصاريف', 'Expense breakdown')}

{EXPENSE_CATEGORIES.map(c => (
{lang === 'ar' ? c.ar : c.en} {fmtAED(Math.round(expSum * c.pct / 100))}
{c.pct}% {t('من الإجمالي', 'of total')}
))}

{t('طرق الدفع', 'Payment methods')}

{PAYMENT_SPLIT.map(p => (
{p.id === 'cash' ? : p.id === 'bank' ? : }
{lang === 'ar' ? p.ar : p.en}
{p.pct}%
))}
{/* Recent transactions teaser */}

{t('أحدث المعاملات', 'Recent transactions')}

{t('انتقل إلى المعاملات لعرض الكل', 'Go to Transactions to see all')}
{TRANSACTIONS.slice(0, 6).map(tx => (
{lang === 'ar' ? tx.desc_ar : tx.desc_en}
{tx.date} · {tx.id}
0 ? 'pos' : 'neg')}>{fmtAED(tx.amount)}
))}
); } // ─── Transactions ────────────────────────────────────────── function FinanceTransactions({ lang }) { const t = (ar, en) => lang === 'ar' ? ar : en; const [filter, setFilter] = React.useState('all'); const [q, setQ] = React.useState(''); const filtered = TRANSACTIONS.filter(tx => { if (filter !== 'all' && tx.type !== filter) return false; if (q && !tx.desc_ar.includes(q) && !tx.desc_en.toLowerCase().includes(q.toLowerCase()) && !tx.id.includes(q)) return false; return true; }); const tabs = [ { id: 'all', label: t('الكل', 'All'), count: TRANSACTIONS.length }, { id: 'sale', label: t('مبيعات', 'Sales'), count: TRANSACTIONS.filter(t => t.type === 'sale').length }, { id: 'expense', label: t('مصاريف', 'Expenses'), count: TRANSACTIONS.filter(t => t.type === 'expense').length }, { id: 'refund', label: t('استرداد', 'Refunds'), count: TRANSACTIONS.filter(t => t.type === 'refund').length }, ]; const typeLabel = (type) => ({ sale: t('بيع', 'Sale'), expense: t('مصروف', 'Expense'), refund: t('استرداد', 'Refund'), })[type]; const methodLabel = (m) => ({ card: t('بطاقة', 'Card'), apple: 'Apple Pay', mada: 'Mada', bank: t('حوالة', 'Bank'), cash: t('نقد', 'Cash'), })[m]; return ( <>
{t('المالية · 02', 'Finance · 02')}

{t('المعاملات', 'Transactions')}

{TRANSACTIONS.length} {t('معاملة · يُحدّث آنياً', 'transactions · live ledger')}
setQ(e.target.value)} />
{tabs.map(tab => ( ))}
{filtered.map(tx => ( ))}
{t('المعرّف', 'ID')} {t('التاريخ', 'Date')} {t('النوع', 'Type')} {t('الوصف', 'Description')} {t('طريقة الدفع', 'Method')} {t('المرجع', 'Ref')} {t('المبلغ', 'Amount')} {t('الحالة', 'Status')}
{tx.id} {tx.date} {typeLabel(tx.type)} {lang === 'ar' ? tx.desc_ar : tx.desc_en} {methodLabel(tx.method)} {tx.ref} 0 ? 'tx-amount pos' : 'tx-amount neg'}>{fmtAED(tx.amount)} {tx.status === 'completed' ? t('مكتمل', 'Completed') : t('معلّق', 'Pending')}
{/* footer totals */}
{t('إجمالي المبيعات', 'Sales total')}
{fmtAED(filtered.filter(t => t.type === 'sale').reduce((s, t) => s + t.amount, 0))}
{t('إجمالي المصاريف', 'Expenses total')}
{fmtAED(filtered.filter(t => t.type === 'expense').reduce((s, t) => s + t.amount, 0))}
{t('استردادات', 'Refunds')}
{fmtAED(filtered.filter(t => t.type === 'refund').reduce((s, t) => s + t.amount, 0))}
{t('الصافي', 'Net')}
{fmtAED(filtered.reduce((s, t) => s + t.amount, 0))}
); } // ─── Expenses ────────────────────────────────────────────── function FinanceExpenses({ lang }) { const t = (ar, en) => lang === 'ar' ? ar : en; const [adding, setAdding] = React.useState(false); const expenses = TRANSACTIONS.filter(t => t.type === 'expense'); const expSum = expenses.reduce((s, t) => s + Math.abs(t.amount), 0); return ( <>
{t('المالية · 03', 'Finance · 03')}

{t('المصاريف', 'Expenses')}

{expenses.length} {t('مصروف هذا الشهر · إجمالي ', 'this month · total ')} {fmtAED(expSum)}
{/* Category cards */}
{EXPENSE_CATEGORIES.map(c => (
{lang === 'ar' ? c.ar : c.en}
{fmtAED(Math.round(expSum * c.pct / 100))}
{c.pct}% {Math.round(expenses.length * c.pct / 100)} {t('قيد', 'entries')}
))}
{expenses.map(e => { const cat = EXPENSE_CATEGORIES.find(c => c.id === e.cat); return ( ); })}
{t('التاريخ', 'Date')} {t('الوصف', 'Description')} {t('الفئة', 'Category')} {t('طريقة الدفع', 'Method')} {t('المرجع', 'Reference')} {t('المبلغ', 'Amount')} {t('الحالة', 'Status')}
{e.date} {lang === 'ar' ? e.desc_ar : e.desc_en} {cat && ( {lang === 'ar' ? cat.ar : cat.en} )} {e.method.toUpperCase()} {e.ref} {fmtAED(e.amount)} {e.status === 'completed' ? t('مدفوع', 'Paid') : t('معلّق', 'Pending')}
); } // ─── Invoices ────────────────────────────────────────────── function FinanceInvoices({ lang }) { const t = (ar, en) => lang === 'ar' ? ar : en; const [viewing, setViewing] = React.useState(null); const totalPaid = INVOICES.filter(i => i.status === 'paid').reduce((s, i) => s + i.total, 0); const totalUnpaid = INVOICES.filter(i => i.status !== 'paid').reduce((s, i) => s + i.total, 0); const overdue = INVOICES.filter(i => i.status === 'overdue').length; const statusLabel = (s) => ({ paid: t('مدفوعة', 'Paid'), sent: t('مرسلة', 'Sent'), overdue: t('متأخرة', 'Overdue'), draft: t('مسودة', 'Draft'), })[s]; return ( <>
{t('المالية · 04', 'Finance · 04')}

{t('الفواتير', 'Invoices')}

{INVOICES.length} {t('فاتورة', 'invoices')} · {overdue} {t('متأخرة', 'overdue')}
{t('مدفوعة هذا الشهر', 'Paid this month')}
{fmtAED(totalPaid)}
{INVOICES.filter(i => i.status === 'paid').length} {t('فواتير', 'invoices')}
{t('غير مدفوعة', 'Outstanding')}
{fmtAED(totalUnpaid)}
{INVOICES.filter(i => i.status === 'sent').length} {t('مرسلة', 'sent')} · {overdue} {t('متأخرة', 'overdue')}
{t('متوسط وقت الدفع', 'Avg payment time')}
18 {t('يوم', 'days')}
{t('أسرع بـ ٤ أيام', '4 days faster')}
{INVOICES.map(inv => ( setViewing(inv)}> ))}
{t('الفاتورة', 'Invoice')} {t('العميل', 'Client')} {t('تاريخ الإصدار', 'Issue date')} {t('الاستحقاق', 'Due')} {t('العناصر', 'Items')} {t('المجموع الفرعي', 'Subtotal')} {t('ضريبة', 'VAT')} {t('الإجمالي', 'Total')} {t('الحالة', 'Status')}
{inv.id}
{lang === 'ar' ? inv.client : inv.client_en}
{inv.date} {inv.due} {inv.items} {inv.subtotal.toLocaleString()} {inv.vat.toLocaleString()} AED {inv.total.toLocaleString()} {statusLabel(inv.status)}
{viewing && setViewing(null)} lang={lang} />} ); } function InvoiceViewer({ invoice, onClose, lang }) { const t = (ar, en) => lang === 'ar' ? ar : en; return (
e.stopPropagation()}>
{t('استبرق', 'ISTABRAQ')}
{t('Indian perfumery · since 2018', 'Indian perfumery · since 2018')}
{t('شارع جميرا، دبي، الإمارات العربية المتحدة', 'Jumeirah St, Dubai, UAE')}
VAT TRN: 100123456700003
hello@istabraq.ae
{t('فاتورة', 'INVOICE')}
{invoice.id}
{t('تاريخ:', 'Issued:')} {invoice.date}
{t('استحقاق:', 'Due:')} {invoice.due}
{invoice.status === 'paid' ? t('مدفوعة', 'Paid') : invoice.status === 'overdue' ? t('متأخرة', 'Overdue') : t('مرسلة', 'Sent')}

{t('من', 'From')}
{t('استبرق للعطور ذ.م.م', 'Istabraq Perfumery LLC')}
Dubai · UAE
{t('إلى', 'Bill to')}
{lang === 'ar' ? invoice.client : invoice.client_en}
{t('عميل تجزئة بالجملة', 'Wholesale account')}
{[0, 6, 4].map((i, idx) => { const p = PRODUCTS[i]; const qty = [6, 4, 8][idx]; return ( ); })}
{t('الوصف', 'Description')} {t('الكمية', 'Qty')} {t('السعر', 'Unit')} {t('المجموع', 'Amount')}
{lang === 'ar' ? p.name_ar : p.name_en}
{p.concentration} · 50ml · {p.origin}
{qty} {p.price.toLocaleString()} AED {(p.price * qty).toLocaleString()}
{t('المجموع الفرعي', 'Subtotal')}AED {invoice.subtotal.toLocaleString()}
{t('ضريبة القيمة المضافة (٥٪)', 'VAT (5%)')}AED {invoice.vat.toLocaleString()}
{t('الإجمالي المستحق', 'Total due')}AED {invoice.total.toLocaleString()}
{t('شروط الدفع', 'Payment terms')}
{t('الدفع خلال ٣٠ يوماً من تاريخ الإصدار. تحويل بنكي إلى Emirates NBD · AE12 0260 0010 1234 5678 901.', 'Payment due within 30 days. Bank transfer to Emirates NBD · AE12 0260 0010 1234 5678 901.')}
{invoice.status !== 'paid' && }
); } // ─── P&L ─────────────────────────────────────────────────── function FinancePnL({ lang }) { const t = (ar, en) => lang === 'ar' ? ar : en; const max = Math.max(...PNL_MONTHLY.map(m => m.rev)); const totRev = PNL_MONTHLY.reduce((s, m) => s + m.rev, 0); const totExp = PNL_MONTHLY.reduce((s, m) => s + m.exp, 0); const totNet = totRev - totExp; // P&L line items const breakdown = [ { label_ar: 'مبيعات تجزئة', label_en: 'Retail sales', amount: 892400, kind: 'rev' }, { label_ar: 'مبيعات الجملة (B2B)', label_en: 'Wholesale (B2B)', amount: 274200, kind: 'rev' }, { label_ar: 'العينات', label_en: 'Sample sales', amount: 18400, kind: 'rev' }, { label_ar: 'أخرى', label_en: 'Other revenue', amount: 6800, kind: 'rev' }, { label_ar: 'تكلفة البضاعة المباعة', label_en: 'Cost of goods sold', amount: -284600,kind: 'cogs' }, { label_ar: 'الرواتب', label_en: 'Salaries & wages', amount: -92400, kind: 'opex' }, { label_ar: 'الإيجار والمرافق', label_en: 'Rent & utilities', amount: -48200, kind: 'opex' }, { label_ar: 'التسويق والإعلان', label_en: 'Marketing & ads', amount: -38400, kind: 'opex' }, { label_ar: 'الشحن والخدمات', label_en: 'Shipping & fulfilment', amount: -52800, kind: 'opex' }, { label_ar: 'متفرقات', label_en: 'Misc & admin', amount: -19600, kind: 'opex' }, ]; const totalRev = breakdown.filter(b => b.kind === 'rev').reduce((s, b) => s + b.amount, 0); const totalCOGS = Math.abs(breakdown.filter(b => b.kind === 'cogs').reduce((s, b) => s + b.amount, 0)); const totalOpex = Math.abs(breakdown.filter(b => b.kind === 'opex').reduce((s, b) => s + b.amount, 0)); const grossProfit = totalRev - totalCOGS; const netIncome = grossProfit - totalOpex; return ( <>
{t('المالية · 05', 'Finance · 05')}

{t('الأرباح والخسائر', 'Profit & Loss')}

{t('آخر ٦ أشهر · ديسمبر إلى مايو', 'Last 6 months · Dec → May')}
{/* 6-month chart */}

{t('الإيرادات والمصاريف وصافي الربح', 'Revenue, expenses, net profit')}

{PNL_MONTHLY.map((m, i) => (
{lang === 'ar' ? m.m_ar : m.m_en}
))}
{t('إيرادات', 'Revenue')} {t('مصاريف', 'Expenses')} {t('صافي الربح', 'Net profit')} {t('الإجمالي:', 'Total:')} {fmtAED(totRev)} · {fmtAED(totExp)} · {fmtAED(totNet)}
{/* P&L statement */}

{t('بيان الدخل · مايو ٢٠٢٦', 'Income statement · May 2026')}

{breakdown.filter(b => b.kind === 'rev').map((b, i) => ( ))} {breakdown.filter(b => b.kind === 'cogs').map((b, i) => ( ))} {breakdown.filter(b => b.kind === 'opex').map((b, i) => ( ))}
{t('الإيرادات', 'Revenue')}
{lang === 'ar' ? b.label_ar : b.label_en} AED {b.amount.toLocaleString()}
{t('إجمالي الإيرادات', 'Total revenue')} AED {totalRev.toLocaleString()}
{t('تكلفة البضائع', 'Cost of goods sold')}
{lang === 'ar' ? b.label_ar : b.label_en} −AED {Math.abs(b.amount).toLocaleString()}
{t('إجمالي الربح', 'Gross profit')} AED {grossProfit.toLocaleString()} ({(grossProfit / totalRev * 100).toFixed(1)}%)
{t('المصاريف التشغيلية', 'Operating expenses')}
{lang === 'ar' ? b.label_ar : b.label_en} −AED {Math.abs(b.amount).toLocaleString()}
{t('إجمالي المصاريف التشغيلية', 'Total operating')} −AED {totalOpex.toLocaleString()}
{t('صافي الدخل', 'Net income')} AED {netIncome.toLocaleString()} ({(netIncome / totalRev * 100).toFixed(1)}%)
); } // ─── Tax / VAT ───────────────────────────────────────────── function FinanceTax({ lang }) { const t = (ar, en) => lang === 'ar' ? ar : en; const Q2_revenue = 671200; const Q2_vat_output = Q2_revenue * 0.05; const Q2_purchases = 312400; const Q2_vat_input = Q2_purchases * 0.05; const Q2_payable = Q2_vat_output - Q2_vat_input; const quarters = [ { id: 'Q1-2026', period: t('يناير - مارس ٢٠٢٦', 'Jan - Mar 2026'), rev: 531400, out: 26570, inp: 13420, paid: true }, { id: 'Q2-2026', period: t('أبريل - يونيو ٢٠٢٦', 'Apr - Jun 2026'), rev: Q2_revenue, out: Q2_vat_output, inp: Q2_vat_input, paid: false }, { id: 'Q4-2025', period: t('أكتوبر - ديسمبر ٢٠٢٥', 'Oct - Dec 2025'), rev: 482600, out: 24130, inp: 11890, paid: true }, { id: 'Q3-2025', period: t('يوليو - سبتمبر ٢٠٢٥', 'Jul - Sep 2025'), rev: 418200, out: 20910, inp: 10240, paid: true }, ]; return ( <>
{t('المالية · 06', 'Finance · 06')}

{t('ضريبة القيمة المضافة', 'VAT & Tax')}

{t('TRN: 100123456700003 · معدل الضريبة ٥٪', 'TRN: 100123456700003 · 5% rate')}
{/* current quarter — featured card */}
{t('الربع الحالي · Q2 ٢٠٢٦', 'Current quarter · Q2 2026')}
{fmtAED(Q2_payable)}
{t('ضريبة مستحقة', 'VAT payable')}
{t('تاريخ الاستحقاق: ٣٠ يونيو ٢٠٢٦', 'Due: 30 June 2026')}
{t('ضريبة المدخلات (قابل للخصم)', 'Input VAT (deductible)')}: {fmtAED(Q2_vat_input)} {t('ضريبة المخرجات', 'Output VAT')}: {fmtAED(Q2_vat_output)}
{t('المبيعات الخاضعة للضريبة', 'Taxable sales')} {fmtAED(Q2_revenue)}
{t('المشتريات الخاضعة للضريبة', 'Taxable purchases')} {fmtAED(Q2_purchases)}
{t('ضريبة المخرجات', 'Output VAT (5%)')} +{fmtAED(Q2_vat_output)}
{t('ضريبة المدخلات', 'Input VAT (5%)')} −{fmtAED(Q2_vat_input)}
{t('صافي الضريبة المستحقة', 'Net VAT due')} {fmtAED(Q2_payable)}
{/* quarters history */}

{t('سجل الإقرارات الضريبية', 'Tax return history')}

{quarters.map(q => ( ))}
{t('الفترة', 'Period')} {t('المبيعات', 'Sales')} {t('ضريبة المخرجات', 'Output VAT')} {t('ضريبة المدخلات', 'Input VAT')} {t('الصافي', 'Net VAT')} {t('الحالة', 'Status')}
{q.id}
{q.period}
AED {q.rev.toLocaleString()} AED {Math.round(q.out).toLocaleString()} −AED {Math.round(q.inp).toLocaleString()} AED {Math.round(q.out - q.inp).toLocaleString()} {q.paid ? : null} {q.paid ? t('مقدّم ومدفوع', 'Filed & paid') : t('قيد التحضير', 'Due')}
); } window.FinanceDashboard = FinanceDashboard; window.FinanceTransactions = FinanceTransactions; window.FinanceExpenses = FinanceExpenses; window.FinanceInvoices = FinanceInvoices; window.FinancePnL = FinancePnL; window.FinanceTax = FinanceTax;