/* Bonyan ERP — Dashboard / home (لوحة مدير النظام) */ function DashboardScreen({ onNav }) { const I = window.BnyIcon; const D = window.BnyData; const { StatCard, Card, Badge, Money, Button } = window.BonyanDesignSystem_ad3ca0; const isMobile = window.useBnyMobile(); window.useBnyInvoices(); // إعادة الرسم عند تعديل/حذف فاتورة من أي مكان const openInv = (no) => window.BnyOpenInvoice(no); // اشتقاقات حيّة const outOfStock = window.BnyOutOfStockMaterials(); const lowStock = window.BnyLowStockMaterials(); const topProducts = window.BnyTopProductsThisMonth(5); const stagnant = window.BnyStagnantMaterials(); const stagDays = D.stagnantDays || 30; const aging = window.BnyDebtAging(); // يشمل ديون الدولار، ويرتّب حسب القيمة المكافئة بالدينار (١٠٠$ = ١٥٠٬٠٠٠ د.ع) const debts = D.customers.filter((c) => c.balance > 0 || c.balanceUsd > 0).sort((a, b) => window.BnyDebtIqd(b) - window.BnyDebtIqd(a)); // مؤشرات حيّة (تظهر صفرًا للمشترك الجديد — لا أرقام وهمية) const _today = new Date().toISOString().slice(0, 10); const salesMonth = (D.invoices || []).filter((i) => i.type === "sale" && i.cur === "iqd" && (i.date || "").slice(0, 7) === _today.slice(0, 7)) .reduce((s, i) => s + (Number(i.total) || 0), 0); const invToday = (D.invoices || []).filter((i) => i.date === _today).length; const [showStockModal, setShowStockModal] = React.useState(false); const [selCustomer, setSelCustomer] = React.useState(null); const quick = [ { label: "فاتورة بيع", icon: I.invoice, accent: true, go: "pos" }, { label: "إضافة عميل", icon: I.users, go: "customers" }, { label: "تسديد دين", icon: I.wallet, go: "customers" }, { label: "فاتورة شراء", icon: I.supplier, go: "suppliers" }, ]; const sectionTwo = { display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: "var(--space-7)" }; return (
{/* quick actions */}
{quick.map((q) => ( ))}
{/* KPIs — بطاقة تنبيه المخزون بارزة وقابلة للنقر */}
} value={salesMonth.toLocaleString("en-US")} unit="د.ع" /> } value={debts.reduce((s, c) => s + c.balance, 0).toLocaleString("en-US")} unit="د.ع" /> } value={String(invToday)} /> setShowStockModal(true)} />
{/* تنبيه: مواد تحتاج شراء (نافدة + ستنفد قريبًا) — قصير + عرض الكل */} { window.BnyPendingInvFilter = "reorder"; onNav("inventory"); }} /> {/* الرسم البياني — منحنى خطي مقارن مع Tooltip */} onNav("reports")}>التقارير}>

مرّر أو انقر فوق أي شهر لعرض الرقم التفصيلي.

p.m)} series={[{ name: "الأرباح", color: "var(--brand)", values: D.profit.map((p) => p.v) }]} unit="مليون د.ع" />
{/* أعلى الديون المعلقة + أعمار الديون */}
onNav("customers")}>الكل}>
{debts.map((c, i) => { const over = c.balance > c.limit; return (
setSelCustomer(c)} title="اعرض معلومات العميل" onMouseEnter={(e) => (e.currentTarget.style.background = "var(--surface-hover)")} onMouseLeave={(e) => (e.currentTarget.style.background = "transparent")} style={{ display: "flex", alignItems: "center", gap: 12, padding: "11px 8px", margin: "0 -8px", borderRadius: "var(--radius-md)", borderBottom: i < debts.length - 1 ? "1px solid var(--border-subtle)" : "none", cursor: "pointer", transition: "background var(--dur-fast,160ms) ease" }}>
{c.name.split(" ").slice(0, 2).map((w) => w[0]).join("")}
{c.name}
{over ? تجاوز السقف : ضمن الحد}
{c.balance > 0 && } {c.balanceUsd > 0 && }
); })} {debts.length === 0 &&
لا ديون معلّقة
}
{/* أعلى 5 منتجات هذا الشهر + المواد الراكدة */}
{topProducts.map((p, i) => (
{i + 1}
{p.name}
{p.qty.toLocaleString("en-US")} {p.unit} مُباعة
))} {topProducts.length === 0 &&
لا مبيعات لهذا الشهر بعد
}
onNav("inventory")}>ضبط المدة}>

لم تُبَع منذ {stagDays} يومًا أو أكثر — تُضبط المدة من إدارة المخازن.

{stagnant.slice(0, 6).map((x, i, arr) => (
onNav("inventory")} style={{ display: "flex", alignItems: "center", gap: 12, padding: "11px 0", borderBottom: i < arr.length - 1 ? "1px solid var(--border-subtle)" : "none", cursor: "pointer" }}>
{x.m.name}
رصيد {x.m.stock.toLocaleString("en-US")} {x.m.unit} · {x.m.wh}
{x.lastSold ? آخر بيع
{window.BnyDate(x.lastSold)}
: لم تُبَع}
))} {stagnant.length === 0 &&
لا مواد راكدة ✓
}
{showStockModal && setShowStockModal(false)} onGo={() => { setShowStockModal(false); onNav("inventory"); }} />} {selCustomer && setSelCustomer(null)} onNav={onNav} />}
); } /* بطاقة تنبيه المخزون — لون تحذيري بارز + قابلة للنقر */ function StockAlertCard({ outCount, lowCount, onClick }) { const I = window.BnyIcon; const critical = outCount > 0; // ألوان صريحة (hex) — لصق الشفافية على var() يُبطل الخلفية فيصبح النص غير مقروء const bg = critical ? "#D93B3B" : "#E08A00"; const bg2 = critical ? "#B82F2F" : "#B86F00"; return ( ); } /* نافذة قائمة المواد التي تحتاج إعادة طلب (النافدة ثم المنخفضة) */ function StockAlertModal({ out, low, onClose, onGo }) { const I = window.BnyIcon; const { Button } = window.BonyanDesignSystem_ad3ca0; const lowOnly = low.filter((m) => m.stock > 0); // المنخفضة غير النافدة const Row = (m, tone) => (
{m.name}
{m.sku} · {m.wh}
{m.stock.toLocaleString("en-US")} {m.unit}
{tone === "out" ? "نفدت" : "منخفضة"} · حد {m.low}
); return (
e.stopPropagation()} className="bny-card" style={{ width: "100%", maxWidth: 540, maxHeight: "85vh", display: "flex", flexDirection: "column", padding: 0 }}>

مواد تحتاج إعادة طلب

{out.length > 0 &&
نفدت ({out.length})
} {out.map((m) => Row(m, "out"))} {lowOnly.length > 0 &&
منخفضة ({lowOnly.length})
} {lowOnly.map((m) => Row(m, "low"))} {out.length === 0 && lowOnly.length === 0 &&
كل المواد ضمن الحد ✓
}
); } /* كارت أعلى الفواتير تأخّرًا — انقر أي فاتورة لفتحها/تعديلها/حذفها */ function OverdueInvoicesCard({ list, onOpen }) { const I = window.BnyIcon; const { Card, Money } = window.BonyanDesignSystem_ad3ca0; const top = (list || []).slice(0, 5); return (

انقر أي فاتورة لفتحها وتعديلها أو حذفها.

{top.map((r, i) => (
onOpen(r.no)} title="افتح الفاتورة" onMouseEnter={(e) => (e.currentTarget.style.background = "var(--surface-hover)")} onMouseLeave={(e) => (e.currentTarget.style.background = "transparent")} style={{ display: "flex", alignItems: "center", gap: 10, padding: "11px 8px", margin: "0 -8px", borderRadius: "var(--radius-md)", borderBottom: i < top.length - 1 ? "1px solid var(--border-subtle)" : "none", cursor: "pointer", transition: "background var(--dur-fast,160ms) ease" }}> #{r.no}
{r.party}
متأخرة {r.age} يومًا
المتبقّي
))} {top.length === 0 &&
لا فواتير متأخّرة ✓
}
); } /* نافذة معلومات العميل الكاملة + رابط واتساب مباشر */ function CustomerInfoModal({ customer: c, onClose, onNav }) { const I = window.BnyIcon; const D = window.BnyData; const { Button } = window.BonyanDesignSystem_ad3ca0; const org = c.org ? (D.organizations || []).find((o) => o.id === c.org) : null; const shop = (D.shop && D.shop.name) || "بُنيان"; const waMsg = "السلام عليكم " + c.name + "، نذكّركم بالرصيد المستحق لدى " + shop + (c.balance > 0 ? " بمبلغ " + c.balance.toLocaleString("en-US") + " د.ع" : "") + ". شكرًا لتعاملكم."; const wa = window.BnyWaLink(c.phone, waMsg); const initials = c.name.split(" ").slice(0, 2).map((w) => w[0]).join(""); const Field = (icon, label, value, href) => value ? (
{icon} {label} {href ? {value} : {value}}
) : null; return (
e.stopPropagation()} className="bny-card" style={{ width: "100%", maxWidth: 460, maxHeight: "88vh", display: "flex", flexDirection: "column", padding: 0 }}>
{initials}
{c.name}
{c.title || (org ? org.name : (c.type === "نقدي" ? "عميل نقدي" : "عميل آجل"))}
{Field(, "الهاتف", c.phone, c.phone ? "tel:" + c.phone : null)} {org && Field(, "الجهة", org.name)} {org && org.phone && Field(, "هاتف الجهة", org.phone, "tel:" + org.phone)} {Field(, "العنوان", c.address)} {Field(, "النوع", c.type)}
الرصيد المستحق (د.ع)
{(c.balance || 0).toLocaleString("en-US")}
{c.balanceUsd ?
بالدولار ($)
{(c.balanceUsd || 0).toLocaleString("en-US")}
: null}
{c.limitEnabled &&
c.limit ? "var(--danger)" : "var(--text-muted)", marginTop: 10 }}> السقف الائتماني: {c.limit.toLocaleString("en-US")} د.ع {c.balance > c.limit ? "— تجاوز السقف!" : ""}
}
{wa && }
); } /* كارت «مواد تحتاج شراء» — تنبيه قصير (5) + عرض الكل (يفتح المخزن مفلترًا) */ function ReorderCard({ items, onSeeAll }) { const I = window.BnyIcon; const { Card, Button } = window.BonyanDesignSystem_ad3ca0; const all = items || []; const top = all.slice(0, 5); return ( } onClick={onSeeAll}>عرض الكل{all.length > 5 ? " (" + all.length + ")" : ""}}>

مواد نفدت أو قاربت على النفاد — راجعها لإعادة الطلب.

{top.map((m, i) => { const out = Number(m.stock) === 0; return (
{m.name}
{m.wh} · حد التنبيه {m.low} {m.unit}
{m.stock.toLocaleString("en-US")} {m.unit}
{out ? "نفدت" : "ستنفد قريبًا"}
); })} {top.length === 0 &&
كل المواد ضمن الحد ✓
}
); } window.DashboardScreen = DashboardScreen;