Update: 2026-05-03 21:37:02
This commit is contained in:
37
app/modules_app/dashboard/stats.php
Normal file
37
app/modules_app/dashboard/stats.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Dashboard Stats Endpoint
|
||||||
|
*/
|
||||||
|
|
||||||
|
use App\Core\Database;
|
||||||
|
use App\Middleware\AuthMiddleware;
|
||||||
|
|
||||||
|
// 1. Auth Check
|
||||||
|
AuthMiddleware::check();
|
||||||
|
|
||||||
|
$db = Database::getInstance();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Total Invoices
|
||||||
|
$stmt = $db->query("SELECT COUNT(*) FROM invoices");
|
||||||
|
$total = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
// Pending Invoices
|
||||||
|
$stmt = $db->query("SELECT COUNT(*) FROM invoices WHERE status = 'pending'");
|
||||||
|
$pending = $stmt->fetchColumn();
|
||||||
|
|
||||||
|
// Approved Invoices
|
||||||
|
$stmt = $db->query("SELECT COUNT(*) FROM invoices WHERE status = 'approved'");
|
||||||
|
$approved = $stmt->fetchColumn();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Fallback if table doesn't exist yet
|
||||||
|
$total = 0;
|
||||||
|
$pending = 0;
|
||||||
|
$approved = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_success([
|
||||||
|
'total' => $total,
|
||||||
|
'pending' => $pending,
|
||||||
|
'approved' => $approved
|
||||||
|
]);
|
||||||
@@ -20,6 +20,7 @@ $routes = [
|
|||||||
'v1/auth/refresh' => ['POST', 'auth/refresh.php'],
|
'v1/auth/refresh' => ['POST', 'auth/refresh.php'],
|
||||||
'v1/auth/logout' => ['POST', 'auth/logout.php'],
|
'v1/auth/logout' => ['POST', 'auth/logout.php'],
|
||||||
'v1/users' => ['GET', 'users/index.php'],
|
'v1/users' => ['GET', 'users/index.php'],
|
||||||
|
'v1/dashboard/stats' => ['GET', 'dashboard/stats.php'],
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isset($routes[$route])) {
|
if (isset($routes[$route])) {
|
||||||
|
|||||||
@@ -50,15 +50,15 @@
|
|||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
<div class="p-6 bg-surface border border-gray-800 rounded">
|
<div class="p-6 bg-surface border border-gray-800 rounded">
|
||||||
<p class="text-gray-500 text-sm">إجمالي الفواتير</p>
|
<p class="text-gray-500 text-sm">إجمالي الفواتير</p>
|
||||||
<p class="text-3xl font-bold mt-2">1,240</p>
|
<p class="text-3xl font-bold mt-2" x-text="stats.total"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-6 bg-surface border border-gray-800 rounded">
|
<div class="p-6 bg-surface border border-gray-800 rounded">
|
||||||
<p class="text-gray-500 text-sm">قيد المعالجة</p>
|
<p class="text-gray-500 text-sm">قيد المعالجة</p>
|
||||||
<p class="text-3xl font-bold mt-2 text-yellow-500">12</p>
|
<p class="text-3xl font-bold mt-2 text-yellow-500" x-text="stats.pending"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-6 bg-surface border border-gray-800 rounded">
|
<div class="p-6 bg-surface border border-gray-800 rounded">
|
||||||
<p class="text-gray-500 text-sm">تم الاعتماد</p>
|
<p class="text-gray-500 text-sm">تم الاعتماد</p>
|
||||||
<p class="text-3xl font-bold mt-2 text-emerald-500">1,228</p>
|
<p class="text-3xl font-bold mt-2 text-emerald-500" x-text="stats.approved"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -96,10 +96,12 @@
|
|||||||
user: JSON.parse(localStorage.getItem('user')),
|
user: JSON.parse(localStorage.getItem('user')),
|
||||||
page: 'dashboard',
|
page: 'dashboard',
|
||||||
users: [],
|
users: [],
|
||||||
|
stats: { total: 0, pending: 0, approved: 0 },
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
if (!this.user) window.location.href = '/login.php';
|
if (!this.user) window.location.href = '/login.php';
|
||||||
this.loadUsers();
|
this.loadUsers();
|
||||||
|
this.loadStats();
|
||||||
},
|
},
|
||||||
|
|
||||||
title() {
|
title() {
|
||||||
@@ -107,7 +109,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
async loadUsers() {
|
async loadUsers() {
|
||||||
const res = await fetch('/api/users', {
|
const res = await fetch('/api/v1/users', {
|
||||||
headers: { 'Authorization': 'Bearer ' + localStorage.getItem('access_token') }
|
headers: { 'Authorization': 'Bearer ' + localStorage.getItem('access_token') }
|
||||||
});
|
});
|
||||||
if (res.status === 401) this.logout();
|
if (res.status === 401) this.logout();
|
||||||
@@ -115,6 +117,14 @@
|
|||||||
if (json.success) this.users = json.data;
|
if (json.success) this.users = json.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async loadStats() {
|
||||||
|
const res = await fetch('/api/v1/dashboard/stats', {
|
||||||
|
headers: { 'Authorization': 'Bearer ' + localStorage.getItem('access_token') }
|
||||||
|
});
|
||||||
|
const json = await res.json();
|
||||||
|
if (json.success) this.stats = json.data;
|
||||||
|
},
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
window.location.href = '/login.php';
|
window.location.href = '/login.php';
|
||||||
|
|||||||
Reference in New Issue
Block a user