WebOrbiton
v1.0.0.0

StocketBase

96 lines · 4.9 KB
  1. <?php
  2. ​
  3. declare(strict_types=1);
  4. ​
  5. if (count(get_included_files()) === 1) {
  6. http_response_code(403);
  7. exit;
  8. }
  9. ​
  10. require_once __DIR__ . '/../includes/currency.php';
  11. ​
  12. $db = Database::site();
  13. $isAdmin = Auth::isAdministrative();
  14. $storeCurrency = SiteFront::settings()['store_currency'] ?? 'USD';
  15. ​
  16. if ($isAdmin) {
  17. $topProducts = $db->query(
  18. 'SELECT title, views_count, sales_count, status, (SELECT COALESCE(SUM(f.download_count), 0) FROM product_files f WHERE f.product_id = products.id) AS downloads_count FROM products WHERE deleted_at IS NULL ORDER BY sales_count DESC, views_count DESC LIMIT 10'
  19. )->fetchAll();
  20. $totalViews = (int) $db->query('SELECT COALESCE(SUM(views_count), 0) AS total FROM products WHERE deleted_at IS NULL')->fetch()['total'];
  21. $totalSales = (int) $db->query('SELECT COALESCE(SUM(sales_count), 0) AS total FROM products WHERE deleted_at IS NULL')->fetch()['total'];
  22. $totalDownloads = (int) $db->query('SELECT COALESCE(SUM(download_count), 0) AS total FROM product_files')->fetch()['total'];
  23. } else {
  24. $statement = $db->prepare(
  25. 'SELECT title, views_count, sales_count, status, (SELECT COALESCE(SUM(f.download_count), 0) FROM product_files f WHERE f.product_id = products.id) AS downloads_count FROM products WHERE created_by = :id AND deleted_at IS NULL ORDER BY sales_count DESC, views_count DESC LIMIT 10'
  26. );
  27. $statement->execute(['id' => $currentUser['id']]);
  28. $topProducts = $statement->fetchAll();
  29. ​
  30. $totalStatement = $db->prepare('SELECT COALESCE(SUM(views_count), 0) AS total FROM products WHERE created_by = :id AND deleted_at IS NULL');
  31. $totalStatement->execute(['id' => $currentUser['id']]);
  32. $totalViews = (int) $totalStatement->fetch()['total'];
  33. ​
  34. $salesStatement = $db->prepare('SELECT COALESCE(SUM(sales_count), 0) AS total FROM products WHERE created_by = :id AND deleted_at IS NULL');
  35. $salesStatement->execute(['id' => $currentUser['id']]);
  36. $totalSales = (int) $salesStatement->fetch()['total'];
  37. ​
  38. $downloadsStatement = $db->prepare('SELECT COALESCE(SUM(f.download_count), 0) AS total FROM product_files f JOIN products p ON p.id = f.product_id WHERE p.created_by = :id');
  39. $downloadsStatement->execute(['id' => $currentUser['id']]);
  40. $totalDownloads = (int) $downloadsStatement->fetch()['total'];
  41. }
  42. ​
  43. $isManager = Auth::hasRoleAtLeast(Auth::ROLE_STORE_MANAGER);
  44. $revenueByDay = [];
  45. if ($isManager) {
  46. $usersDb = Database::users();
  47. $revenueByDay = $usersDb->query(
  48. "SELECT DATE(created_at) AS day, COALESCE(SUM(total_cents), 0) AS total
  49. FROM orders WHERE status IN ('paid','processing','fulfilled','shipped','completed') AND created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)
  50. GROUP BY DATE(created_at) ORDER BY day ASC"
  51. )->fetchAll();
  52. }
  53. ​
  54. ?>
  55. <h1 class="dash-title"><?= Icons::icon("stats", "icon icon-lg") ?>Statistics</h1>
  56. ​
  57. <div class="dash-cards">
  58. <div class="dash-card"><?= Icons::icon('eye', 'icon icon-lg') ?><div class="dash-card-value"><?= number_format($totalViews) ?></div><div class="dash-card-label">Total views</div></div>
  59. <div class="dash-card"><?= Icons::icon('cart', 'icon icon-lg') ?><div class="dash-card-value"><?= number_format($totalSales) ?></div><div class="dash-card-label">Total sales</div></div>
  60. <div class="dash-card"><?= Icons::icon('download', 'icon icon-lg') ?><div class="dash-card-value"><?= number_format($totalDownloads) ?></div><div class="dash-card-label">Total downloads</div></div>
  61. </div>
  62. ​
  63. <?php if ($isManager && !empty($revenueByDay)): ?>
  64. <h2 class="dash-subtitle"><?= Icons::icon('dollar', 'icon icon-sm') ?>Revenue (last 30 days)</h2>
  65. <table class="dash-table">
  66. <thead><tr><th><?= Icons::icon('clock', 'icon icon-sm') ?>Day</th><th><?= Icons::icon('dollar', 'icon icon-sm') ?>Revenue</th></tr></thead>
  67. <tbody>
  68. <?php foreach ($revenueByDay as $day): ?>
  69. <tr>
  70. <td><?= htmlspecialchars($day['day']) ?></td>
  71. <td><?= htmlspecialchars(Currency::format((int) $day['total'], $storeCurrency)) ?></td>
  72. </tr>
  73. <?php endforeach; ?>
  74. </tbody>
  75. </table>
  76. <?php endif; ?>
  77. ​
  78. <h2 class="dash-subtitle"><?= Icons::icon('star', 'icon icon-sm') ?>Top products</h2>
  79. <table class="dash-table">
  80. <thead><tr><th><?= Icons::icon('heading', 'icon icon-sm') ?>Title</th><th><?= Icons::icon('eye', 'icon icon-sm') ?>Views</th><th><?= Icons::icon('cart', 'icon icon-sm') ?>Sales</th><th><?= Icons::icon('download', 'icon icon-sm') ?>Downloads</th><th><?= Icons::icon('flag', 'icon icon-sm') ?>Status</th></tr></thead>
  81. <tbody>
  82. <?php foreach ($topProducts as $product): ?>
  83. <tr>
  84. <td><?= htmlspecialchars($product['title']) ?></td>
  85. <td><?= number_format((int) $product['views_count']) ?></td>
  86. <td><?= number_format((int) $product['sales_count']) ?></td>
  87. <td><?= number_format((int) ($product['downloads_count'] ?? 0)) ?></td>
  88. <td><span class="status-pill status-<?= htmlspecialchars($product['status']) ?>"><?= htmlspecialchars($product['status']) ?></span></td>
  89. </tr>
  90. <?php endforeach; ?>
  91. <?php if (empty($topProducts)): ?>
  92. <tr><td colspan="5">No data yet.</td></tr>
  93. <?php endif; ?>
  94. </tbody>
  95. </table>
  96. ​