/* Bonyan ERP — الحركات (Audit Log): من فعل ماذا ومتى، بالتفصيل. الرؤية للمدير فقط (صلاحية activity + RLS في القاعدة). */ const BNY_ACTIONS = { invoice_create: { label: "تسجيل فاتورة", tone: "brand" }, invoice_update: { label: "تعديل فاتورة", tone: "warning" }, invoice_delete: { label: "حذف فاتورة", tone: "danger" }, transfer: { label: "نقل مخزني", tone: "brand" }, material_add: { label: "إضافة مادة", tone: "success" }, material_update: { label: "تعديل مادة", tone: "warning" }, customer_add: { label: "عميل جديد", tone: "success" }, customer_edit: { label: "تعديل عميل", tone: "warning" }, supplier_add: { label: "مورد جديد", tone: "success" }, supplier_edit: { label: "تعديل مورد", tone: "warning" }, payment_in: { label: "دفعة واردة", tone: "success" }, payment_out: { label: "دفعة صادرة", tone: "warning" }, warehouse_add: { label: "إضافة مخزن", tone: "success" }, warehouse_edit: { label: "تعديل مخزن", tone: "warning" }, warehouse_delete: { label: "حذف مخزن", tone: "danger" }, category_add: { label: "إضافة فئة", tone: "success" }, category_edit: { label: "تعديل فئة", tone: "warning" }, category_delete: { label: "حذف فئة", tone: "danger" }, user_save: { label: "حفظ مستخدم", tone: "brand" }, user_delete: { label: "حذف مستخدم", tone: "danger" }, }; function ActivityScreen({ user }) { const I = window.BnyIcon; const D = window.BnyData; const { Card, Button, Input, Badge, Avatar } = window.BonyanDesignSystem_ad3ca0; const isMobile = window.useBnyMobile(); const [rows, setRows] = React.useState(() => (D.activity || []).slice()); const [loading, setLoading] = React.useState(false); const [q, setQ] = React.useState(""); const [actF, setActF] = React.useState("all"); const load = React.useCallback(async () => { if (!(window.BnyConfigured && window.BnyDB && window.BnyDB.fetchActivity)) { setRows((D.activity || []).slice()); return; } setLoading(true); try { setRows(await window.BnyDB.fetchActivity(300)); } catch (e) { console.warn("بُنيان: فشل جلب الحركات", e); setRows((D.activity || []).slice()); } finally { setLoading(false); } }, []); React.useEffect(() => { load(); }, [load]); if (!window.BnyCan(user, "activity")) { return (

لا تملك صلاحية الوصول

سجل الحركات متاح للمدير فقط.

); } const fmtAt = (iso) => { try { const d = new Date(iso); return window.BnyDate(iso.slice(0, 10)) + " · " + String(d.getHours()).padStart(2, "0") + ":" + String(d.getMinutes()).padStart(2, "0"); } catch (e) { return iso; } }; const openRef = (r) => { if (r.ref && window.BnyInvoices && window.BnyInvoices.get(r.ref)) window.BnyOpenInvoice(r.ref); }; const filtered = rows.filter((r) => { if (actF !== "all" && r.action !== actF) return false; if (q) { const t = (r.userName || "") + (r.details || "") + (r.ref || ""); if (!t.includes(q)) return false; } return true; }); const usedActions = Array.from(new Set(rows.map((r) => r.action))); return (
} onClick={load} disabled={loading}>{loading ? "جارٍ التحديث…" : "تحديث"}}>
setQ(e.target.value)} placeholder="ابحث باسم المستخدم أو التفاصيل أو المرجع" icon={} />
{filtered.map((r, i) => { const meta = BNY_ACTIONS[r.action] || { label: r.action, tone: "neutral" }; const clickable = !!(r.ref && window.BnyInvoices && window.BnyInvoices.get(r.ref)); return (
openRef(r) : undefined} onMouseEnter={clickable ? (e) => (e.currentTarget.style.background = "var(--surface-hover)") : undefined} onMouseLeave={clickable ? (e) => (e.currentTarget.style.background = "transparent") : undefined} style={{ display: "flex", alignItems: "flex-start", gap: 12, padding: "12px 8px", margin: "0 -8px", borderRadius: "var(--radius-md)", borderTop: i > 0 ? "1px solid var(--border-subtle)" : "none", cursor: clickable ? "pointer" : "default", transition: "background var(--dur-fast,160ms) ease" }}>
{r.userName || "غير معروف"} {meta.label} {r.ref && {r.ref}}
{r.details}
{fmtAt(r.at)}
); })} {filtered.length === 0 && (
لا حركات مسجّلة بعد
كل فاتورة أو نقل مخزني أو إضافة مادة ستظهر هنا تلقائيًا مع اسم من قام بها.
)}
); } window.ActivityScreen = ActivityScreen;