Update: 2026-05-05 00:01:17

This commit is contained in:
Hamza-Ayed
2026-05-05 00:01:17 +03:00
parent 5f7018390a
commit ac12106770
14 changed files with 969 additions and 8 deletions

View File

@@ -420,6 +420,18 @@
color: var(--teal);
}
.stat-red::after {
background: #e11d48;
}
.stat-red .stat-icon-box {
background: #fff1f2;
}
.stat-red .stat-value {
color: #e11d48;
}
/* ── QUICK ACTIONS ─────────────────────────── */
.quick-action-card {
background: white;
@@ -1069,12 +1081,16 @@
<span>فريق العمل</span>
</button>
<div x-show="user?.role === 'super_admin'">
<div x-show="user?.role === 'super_admin' || user?.role === 'admin'">
<div class="sb-section-label">الإدارة العليا</div>
<button @click="setPage('tenants')" class="nav-btn" :class="page==='tenants' ? 'active' : ''">
<button x-show="user?.role === 'super_admin'" @click="setPage('tenants')" class="nav-btn" :class="page==='tenants' ? 'active' : ''">
<span class="nav-icon">🏢</span>
<span>المكاتب المحاسبية</span>
</button>
<button @click="setPage('subscription')" class="nav-btn" :class="page==='subscription' ? 'active' : ''">
<span class="nav-icon">💎</span>
<span>اشتراكي</span>
</button>
</div>
</nav>
@@ -1128,7 +1144,7 @@
<div x-show="page === 'dashboard'" style="display:flex; flex-direction:column; gap:24px;">
<!-- Stat Cards -->
<div style="display:grid; grid-template-columns:repeat(3,1fr); gap:18px;">
<div style="display:grid; grid-template-columns:repeat(4,1fr); gap:18px;">
<div class="stat-card stat-navy">
<div class="stat-icon-box">📄</div>
<div class="stat-label">إجمالي الفواتير</div>
@@ -1144,6 +1160,11 @@
<div class="stat-label">مدققة ومعتمدة</div>
<div class="stat-value" x-text="stats.approved || 0"></div>
</div>
<div class="stat-card" :class="subscription?.invoices?.warning ? 'stat-red' : 'stat-navy'">
<div class="stat-icon-box">📊</div>
<div class="stat-label">استهلاك الحصة</div>
<div class="stat-value" x-text="(subscription?.invoices?.percent || 0) + '%'"></div>
</div>
</div>
<!-- Quick Actions -->
@@ -1464,6 +1485,85 @@
</div>
</div>
<!-- ── SUBSCRIPTION PAGE ──────────────────────── -->
<div x-show="page === 'subscription'">
<div class="table-container" style="margin-bottom:24px;">
<div class="table-top-bar">
<span style="font-size:18px;">💎</span>
<h3>اشتراكي الحالي</h3>
<span class="badge badge-teal" x-text="subscription?.plan_name"></span>
</div>
<div style="padding:24px; display:grid; grid-template-columns:repeat(3, 1fr); gap:20px;">
<!-- Progress: Invoices -->
<div class="stat-card stat-navy">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
<span style="font-size:13px; font-weight:700;">الفواتير الشهرية</span>
<span style="font-size:12px; font-family:'IBM Plex Mono';" x-text="subscription?.invoices?.used + ' / ' + subscription?.invoices?.limit"></span>
</div>
<div style="height:8px; background:rgba(255,255,255,0.2); border-radius:4px; overflow:hidden;">
<div :style="'width:' + (subscription?.invoices?.percent || 0) + '%; height:100%; background:var(--teal);'"></div>
</div>
<div style="font-size:11px; margin-top:8px; opacity:0.8;" x-text="'يتم التصفير في: ' + (subscription?.period_end?.split(' ')[0] || '—')"></div>
</div>
<!-- Progress: Companies -->
<div class="stat-card stat-navy">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
<span style="font-size:13px; font-weight:700;">الشركات المدارة</span>
<span style="font-size:12px; font-family:'IBM Plex Mono';" x-text="subscription?.companies?.used + ' / ' + subscription?.companies?.limit"></span>
</div>
<div style="height:8px; background:rgba(255,255,255,0.2); border-radius:4px; overflow:hidden;">
<div :style="'width:' + (subscription?.companies?.percent || 0) + '%; height:100%; background:var(--teal);'"></div>
</div>
<div style="font-size:11px; margin-top:8px; opacity:0.8;">إجمالي الشركات المسموح بها</div>
</div>
<!-- Progress: Users -->
<div class="stat-card stat-navy">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;">
<span style="font-size:13px; font-weight:700;">فريق العمل</span>
<span style="font-size:12px; font-family:'IBM Plex Mono';" x-text="subscription?.users?.used + ' / ' + subscription?.users?.limit"></span>
</div>
<div style="height:8px; background:rgba(255,255,255,0.2); border-radius:4px; overflow:hidden;">
<div :style="'width:' + (subscription?.users?.percent || 0) + '%; height:100%; background:var(--teal);'"></div>
</div>
<div style="font-size:11px; margin-top:8px; opacity:0.8;">مستخدمين نشطين في النظام</div>
</div>
</div>
</div>
<!-- Pricing Cards -->
<h3 style="font-size:18px; font-weight:700; color:var(--navy); margin:32px 0 20px;">تغيير أو ترقية الباقة</h3>
<div style="display:grid; grid-template-columns:repeat(auto-fit, minmax(250px, 1fr)); gap:20px;">
<template x-for="p in plans" :key="p.id">
<div class="table-container" style="padding:24px; display:flex; flex-direction:column; gap:16px; border:2px solid transparent;"
:style="subscription?.plan_id === p.id ? 'border-color:var(--gold);' : ''">
<div style="display:flex; justify-content:space-between; align-items:start;">
<div>
<h4 style="font-size:18px; font-weight:700; color:var(--navy);" x-text="p.name_ar"></h4>
<div style="font-size:12px; color:var(--text-3);" x-text="p.description_ar"></div>
</div>
<span x-show="subscription?.plan_id === p.id" class="badge badge-gold">باقتك الحالية</span>
</div>
<div style="font-size:32px; font-weight:800; color:var(--teal);">
<span x-text="p.price_jod"></span>
<span style="font-size:14px; font-weight:400; color:var(--text-3);">دينار / شهر</span>
</div>
<ul style="list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:10px;">
<template x-for="f in p.features">
<li style="font-size:13px; color:var(--text-2); display:flex; gap:8px; align-items:center;">
<span style="color:var(--teal);"></span>
<span x-text="f"></span>
</li>
</template>
</ul>
<button x-show="subscription?.plan_id !== p.id" class="btn-primary" style="margin-top:auto;"
@click="alert('يرجى التواصل مع الدعم الفني لترقية باقتك إلى ' + p.name_ar)">
ترقية الباقة الآن
</button>
</div>
</template>
</div>
</div>
</div><!-- /page-content -->
</div><!-- /main-area -->
</div><!-- /flex layout -->
@@ -2078,7 +2178,7 @@
Alpine.data('app', () => ({
user: JSON.parse(localStorage.getItem('user')),
page: 'dashboard',
users: [], companies: [], invoices: [], tenants: [],
users: [], companies: [], invoices: [], tenants: [], subscription: null, plans: [],
stats: { total: 0, pending: 0, approved: 0 },
showAddUserModal: false, showAddCompanyModal: false, showConnectModal: false,
@@ -2099,8 +2199,8 @@
this.loadAll();
},
setPage(p) { this.page = p; this.loadAll(); },
title() { return { dashboard: 'الرئيسية', users: 'فريق العمل', companies: 'الشركات', invoices: 'إدارة الفواتير', tenants: 'المكاتب المحاسبية' }[this.page] || ''; },
subtitle() { return { dashboard: 'نظرة شاملة على نشاط النظام', users: 'إدارة المستخدمين والصلاحيات', companies: 'إدارة الشركات والربط بالفوترة الحكومية', invoices: 'رفع ومعالجة الفواتير الضريبية', tenants: 'إدارة المكاتب المحاسبية المشتركة' }[this.page] || ''; },
title() { return { dashboard: 'الرئيسية', users: 'فريق العمل', companies: 'الشركات', invoices: 'إدارة الفواتير', tenants: 'المكاتب المحاسبية', subscription: 'إدارة الاشتراك' }[this.page] || ''; },
subtitle() { return { dashboard: 'نظرة شاملة على نشاط النظام', users: 'إدارة المستخدمين والصلاحيات', companies: 'إدارة الشركات والربط بالفوترة الحكومية', invoices: 'رفع ومعالجة الفواتير الضريبية', tenants: 'إدارة المكاتب المحاسبية المشتركة', subscription: 'تفاصيل باقتك الحالية واستهلاك الموارد' }[this.page] || ''; },
token() { return localStorage.getItem('access_token'); },
showError(msg) { this.globalError = msg; setTimeout(() => this.globalError = '', 8000); },
@@ -2121,8 +2221,10 @@
async loadAll() {
this.stats = await this.apiRequest('v1/dashboard/stats') || { total: 0, pending: 0, approved: 0 };
this.companies = await this.apiRequest('v1/companies') || [];
this.subscription = await this.apiRequest('v1/subscriptions/current');
if (this.page === 'users') this.users = await this.apiRequest('v1/users') || [];
if (this.page === 'invoices') this.invoices = await this.apiRequest('v1/invoices') || [];
if (this.page === 'subscription') this.plans = await this.apiRequest('v1/subscriptions/plans') || [];
if (this.user.role === 'super_admin') this.tenants = await this.apiRequest('v1/tenants') || [];
},
//