1 <?php 2 require_once __DIR__ . '/../includes/bootstrap.php'; 3 must_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 20 include __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> 79 var 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'; ?>