1<?php
2require_once __DIR__ . '/../includes/bootstrap.php';
3must_admin();
4$PAGE_TITLE = 'Dashboard';
5$ADMIN_PAGE = 'dashboard';
6
7$stats = [
8 'users' => (int)DB::val('SELECT COUNT(*) FROM users'),
9 'topics' => (int)DB::val('SELECT COUNT(*) FROM topics'),
10 'posts' => (int)DB::val("SELECT COUNT(*) FROM posts WHERE deleted=0"),
11 'cats' => (int)DB::val('SELECT COUNT(*) FROM categories'),
12 'u_today'=> (int)DB::val("SELECT COUNT(*) FROM users WHERE DATE(joined_at)=DATE('now')"),
13 't_today'=> (int)DB::val("SELECT COUNT(*) FROM topics WHERE DATE(created_at)=DATE('now')"),
14 'p_today'=> (int)DB::val("SELECT COUNT(*) FROM posts WHERE DATE(created_at)=DATE('now') AND deleted=0"),
15];
16$recent_users = DB::rows('SELECT * FROM users ORDER BY joined_at DESC LIMIT 6');
17$recent_topics = DB::rows("SELECT t.*,u.username,c.name AS cat FROM topics t JOIN users u ON u.id=t.user_id JOIN categories c ON c.id=t.category_id ORDER BY t.created_at DESC LIMIT 6");
18$activity = DB::rows("SELECT DATE(created_at) AS day, COUNT(*) AS cnt FROM posts WHERE created_at>=DATE('now','-7 days') AND deleted=0 GROUP BY DATE(created_at) ORDER BY day");
19
20include __DIR__ . '/../views/partials/admin_layout.php';
21?>
22
23<div class="stat-grid">
24 <?php foreach ([
25 ['๐ฅ','Total Users',$stats['users'],'+'. $stats['u_today'].' today','#3b82f6'],
26 ['๐ฌ','Topics', $stats['topics'],'+'. $stats['t_today'].' today','#10b981'],
27 ['๐','Posts', $stats['posts'],'+'. $stats['p_today'].' today','#8b5cf6'],
28 ['๐','Categories', $stats['cats'],'','#f59e0b'],
29 ] as [$icon,$label,$num,$sub,$col]): ?>
30 <div class="stat-card">
31 <div class="stat-icon" style="background:<?= $col ?>22;color:<?= $col ?>"><?= $icon ?></div>
32 <div>
33 <div class="stat-num"><?= number_format($num) ?></div>
34 <div class="stat-label"><?= $label ?></div>
35 <?php if ($sub): ?><div class="stat-sub"><?= $sub ?></div><?php endif; ?>
36 </div>
37 </div>
38 <?php endforeach; ?>
39</div>
40
41<div class="acard">
42 <div class="acard-head"><h2>Post Activity โ Last 7 Days</h2></div>
43 <div class="acard-body"><canvas id="actChart" height="70"></canvas></div>
44</div>
45
46<div class="admin-two-col">
47 <div class="acard">
48 <div class="acard-head"><h2>Recent Users</h2><a href="<?= u('admin/users.php') ?>" class="btn-ghost btn-sm">All</a></div>
49 <table class="atable">
50 <thead><tr><th>User</th><th>Role</th><th>Joined</th></tr></thead>
51 <tbody>
52 <?php foreach ($recent_users as $u): ?>
53 <tr>
54 <td><a href="<?= u('admin/user.php?id='.$u['id']) ?>">@<?= e($u['username']) ?></a></td>
55 <td><span class="role-tag role-<?= e($u['role']) ?>"><?= e($u['role']) ?></span></td>
56 <td><span class="ago" data-ts="<?= e($u['joined_at']) ?>"></span></td>
57 </tr>
58 <?php endforeach; ?>
59 </tbody>
60 </table>
61 </div>
62 <div class="acard">
63 <div class="acard-head"><h2>Recent Topics</h2><a href="<?= u('admin/topics.php') ?>" class="btn-ghost btn-sm">All</a></div>
64 <table class="atable">
65 <thead><tr><th>Title</th><th>By</th></tr></thead>
66 <tbody>
67 <?php foreach ($recent_topics as $t): ?>
68 <tr>
69 <td><a href="<?= u('forum/topic.php?slug='.urlencode($t['slug'])) ?>" target="_blank"><?= e(mb_substr($t['title'],0,40)) ?></a></td>
70 <td>@<?= e($t['username']) ?></td>
71 </tr>
72 <?php endforeach; ?>
73 </tbody>
74 </table>
75 </div>
76</div>
77
78<script>
79var actData = <?= json_encode($activity) ?>;
80(function(){
81 var s=document.createElement('script');
82 s.src='https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js';
83 s.onload=function(){
84 new Chart(document.getElementById('actChart'),{
85 type:'bar',
86 data:{labels:actData.map(function(d){return d.day;}),datasets:[{label:'Posts',data:actData.map(function(d){return d.cnt;}),backgroundColor:'rgba(59,130,246,.6)',borderColor:'#3b82f6',borderWidth:1,borderRadius:4}]},
87 options:{responsive:true,plugins:{legend:{display:false}},scales:{y:{beginAtZero:true,ticks:{stepSize:1}}}}
88 });
89 };
90 document.head.appendChild(s);
91})();
92</script>
93<?php include __DIR__ . '/../views/partials/admin_layout_end.php'; ?>