v1.0.0.0
StocketBase
- <?php
-
- declare(strict_types=1);
-
- if (count(get_included_files()) === 1) {
- http_response_code(403);
- exit;
- }
-
- require_once __DIR__ . '/../includes/currency.php';
-
- $db = Database::site();
- $usersDb = Database::users();
- $storeCurrency = SiteFront::settings()['store_currency'] ?? 'USD';
-
- $myProductCount = 0;
- $pendingCount = 0;
- $publishedCount = 0;
-
- if (Auth::isAdministrative()) {
- $publishedCount = (int) $db->query("SELECT COUNT(*) AS c FROM products WHERE status = 'published'")->fetch()['c'];
- $pendingCount = (int) $db->query("SELECT COUNT(*) AS c FROM products WHERE status = 'pending_review'")->fetch()['c'];
- } else {
- $statement = $db->prepare("SELECT COUNT(*) AS c FROM products WHERE created_by = :id AND deleted_at IS NULL");
- $statement->execute(['id' => $currentUser['id']]);
- $myProductCount = (int) $statement->fetch()['c'];
-
- $statement = $db->prepare("SELECT COUNT(*) AS c FROM products WHERE created_by = :id AND status = 'published'");
- $statement->execute(['id' => $currentUser['id']]);
- $publishedCount = (int) $statement->fetch()['c'];
- }
-
- $recentStatement = $db->prepare(
- Auth::isAdministrative()
- ? 'SELECT p.*, t.display_name FROM products p JOIN team_accounts t ON t.id = p.created_by WHERE p.deleted_at IS NULL ORDER BY p.updated_at DESC LIMIT 8'
- : 'SELECT p.*, t.display_name FROM products p JOIN team_accounts t ON t.id = p.created_by WHERE p.created_by = :id AND p.deleted_at IS NULL ORDER BY p.updated_at DESC LIMIT 8'
- );
- if (!Auth::isAdministrative()) {
- $recentStatement->execute(['id' => $currentUser['id']]);
- } else {
- $recentStatement->execute();
- }
- $recentProducts = $recentStatement->fetchAll();
-
- $isManager = Auth::hasRoleAtLeast(Auth::ROLE_STORE_MANAGER);
- $revenueToday = 0;
- $revenue7d = 0;
- $revenue30d = 0;
- $ordersPending = 0;
- $recentOrders = [];
- $lowStockProducts = [];
-
- if ($isManager) {
- $paidStatuses = "('paid','processing','fulfilled','shipped','completed')";
- $revenueToday = (int) $usersDb->query("SELECT COALESCE(SUM(total_cents), 0) AS c FROM orders WHERE status IN $paidStatuses AND created_at >= CURDATE()")->fetch()['c'];
- $revenue7d = (int) $usersDb->query("SELECT COALESCE(SUM(total_cents), 0) AS c FROM orders WHERE status IN $paidStatuses AND created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)")->fetch()['c'];
- $revenue30d = (int) $usersDb->query("SELECT COALESCE(SUM(total_cents), 0) AS c FROM orders WHERE status IN $paidStatuses AND created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)")->fetch()['c'];
- $ordersPending = (int) $usersDb->query("SELECT COUNT(*) AS c FROM orders WHERE status = 'pending'")->fetch()['c'];
- $recentOrders = $usersDb->query('SELECT * FROM orders ORDER BY created_at DESC LIMIT 8')->fetchAll();
- $lowStockProducts = $db->query(
- "SELECT id, title, stock_quantity FROM products WHERE deleted_at IS NULL AND track_inventory = 1 AND stock_quantity IS NOT NULL AND stock_quantity <= 5 ORDER BY stock_quantity ASC LIMIT 8"
- )->fetchAll();
- }
-
- ?>
- <h1 class="dash-title"><?= Icons::icon("overview", "icon icon-lg") ?>Overview</h1>
-
- <div class="dash-cards">
- <?php if ($isManager): ?>
- <div class="dash-card"><?= Icons::icon('dollar', 'icon icon-lg') ?><div class="dash-card-value"><?= htmlspecialchars(Currency::format($revenueToday, $storeCurrency)) ?></div><div class="dash-card-label">Revenue today</div></div>
- <div class="dash-card"><?= Icons::icon('credit-card', 'icon icon-lg') ?><div class="dash-card-value"><?= htmlspecialchars(Currency::format($revenue7d, $storeCurrency)) ?></div><div class="dash-card-label">Revenue (7 days)</div></div>
- <div class="dash-card"><?= Icons::icon('stats', 'icon icon-lg') ?><div class="dash-card-value"><?= htmlspecialchars(Currency::format($revenue30d, $storeCurrency)) ?></div><div class="dash-card-label">Revenue (30 days)</div></div>
- <div class="dash-card"><?= Icons::icon('checklist', 'icon icon-lg') ?><div class="dash-card-value"><?= $ordersPending ?></div><div class="dash-card-label">Orders awaiting payment</div></div>
- <?php endif; ?>
- <?php if (Auth::isAdministrative()): ?>
- <div class="dash-card"><div class="dash-card-value"><?= $publishedCount ?></div><div class="dash-card-label">Published products</div></div>
- <div class="dash-card"><div class="dash-card-value"><?= $pendingCount ?></div><div class="dash-card-label">Pending review</div></div>
- <?php else: ?>
- <div class="dash-card"><div class="dash-card-value"><?= $myProductCount ?></div><div class="dash-card-label">Your products</div></div>
- <div class="dash-card"><div class="dash-card-value"><?= $publishedCount ?></div><div class="dash-card-label">Published</div></div>
- <?php endif; ?>
- </div>
-
- <?php if ($isManager): ?>
- <h2 class="dash-subtitle"><?= Icons::icon('checklist', 'icon icon-sm') ?>Recent orders</h2>
- <table class="dash-table">
- <thead><tr><th><?= Icons::icon('hash', 'icon icon-sm') ?>Order</th><th><?= Icons::icon('dollar', 'icon icon-sm') ?>Total</th><th><?= Icons::icon('flag', 'icon icon-sm') ?>Status</th><th><?= Icons::icon('clock', 'icon icon-sm') ?>Placed</th><th></th></tr></thead>
- <tbody>
- <?php foreach ($recentOrders as $order): ?>
- <tr>
- <td><?= htmlspecialchars($order['order_number']) ?></td>
- <td><?= htmlspecialchars(Currency::format((int) $order['total_cents'], $order['currency'])) ?></td>
- <td><span class="status-pill status-<?= htmlspecialchars($order['status']) ?>"><?= htmlspecialchars($order['status']) ?></span></td>
- <td><?= htmlspecialchars($order['created_at']) ?></td>
- <td><a href="dashboard.php?view=order-detail&id=<?= (int) $order['id'] ?>" class="dash-btn-small"><?= Icons::icon('eye', 'icon icon-sm') ?>View</a></td>
- </tr>
- <?php endforeach; ?>
- <?php if (empty($recentOrders)): ?>
- <tr><td colspan="5">No orders yet.</td></tr>
- <?php endif; ?>
- </tbody>
- </table>
-
- <?php if (!empty($lowStockProducts)): ?>
- <h2 class="dash-subtitle"><?= Icons::icon('flag', 'icon icon-sm') ?>Low stock</h2>
- <table class="dash-table">
- <thead><tr><th><?= Icons::icon('heading', 'icon icon-sm') ?>Product</th><th><?= Icons::icon('grid', 'icon icon-sm') ?>Stock left</th><th></th></tr></thead>
- <tbody>
- <?php foreach ($lowStockProducts as $lowStock): ?>
- <tr>
- <td><?= htmlspecialchars($lowStock['title']) ?></td>
- <td><?= (int) $lowStock['stock_quantity'] ?></td>
- <td><a href="dashboard.php?view=product-edit&id=<?= (int) $lowStock['id'] ?>" class="dash-btn-small"><?= Icons::icon('edit', 'icon icon-sm') ?>Edit</a></td>
- </tr>
- <?php endforeach; ?>
- </tbody>
- </table>
- <?php endif; ?>
- <?php endif; ?>
-
- <h2 class="dash-subtitle"><?= Icons::icon('activity', 'icon icon-sm') ?>Recent products</h2>
- <table class="dash-table">
- <thead><tr><th><?= Icons::icon('heading', 'icon icon-sm') ?>Title</th><th><?= Icons::icon('user', 'icon icon-sm') ?>Created by</th><th><?= Icons::icon('flag', 'icon icon-sm') ?>Status</th><th><?= Icons::icon('clock', 'icon icon-sm') ?>Updated</th></tr></thead>
- <tbody>
- <?php foreach ($recentProducts as $product): ?>
- <tr>
- <td><a href="dashboard.php?view=product-edit&id=<?= (int) $product['id'] ?>"><?= htmlspecialchars($product['title']) ?></a></td>
- <td><?= htmlspecialchars($product['display_name']) ?></td>
- <td><span class="status-pill status-<?= htmlspecialchars($product['status']) ?>"><?= htmlspecialchars($product['status']) ?></span></td>
- <td><?= htmlspecialchars($product['updated_at']) ?></td>
- </tr>
- <?php endforeach; ?>
- <?php if (empty($recentProducts)): ?>
- <tr><td colspan="4">No products yet.</td></tr>
- <?php endif; ?>
- </tbody>
- </table>
-