Files
order/views/admin/dashboard.php
T
Ty Clifford 16235369cb - Implemented the full Fat Bottom Grille storefront and staff dashboard.
Highlights include configurable menus, specials, cart/checkout, taxes, 
customer accounts with email 2FA, newsletters, analytics, refunds, 
PDF/CSV exports, Square/Mailgun adapters, and optional MySQL migration.

See README.md for setup and production configuration. Verified 
PHP/JavaScript syntax, responsive layouts, registration, 2FA, checkout, 
dashboard workflows, settings persistence, and PDF generation.
Real Square, Mailgun, and MySQL connections require credentials/server 
access. Square implementation follows the official Payments API and 
Refunds API.
2026-06-10 13:27:42 -04:00

99 lines
4.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div class="stat-grid">
<article class="stat-card stat-primary">
<span>Todays sales</span>
<strong><?= money($stats['today_sales']) ?></strong>
<small><?= (int) $stats['today_orders'] ?> paid orders</small>
</article>
<article class="stat-card">
<span>Open orders</span>
<strong><?= (int) $stats['open_orders'] ?></strong>
<small>Paid through ready</small>
</article>
<article class="stat-card">
<span>Abandoned carts</span>
<strong><?= (int) $stats['abandoned_carts'] ?></strong>
<small>Inactive for 30+ minutes</small>
</article>
<article class="stat-card">
<span>Todays visitors</span>
<strong><?= (int) $stats['today_visitors'] ?></strong>
<small><?= (int) $stats['newsletter_members'] ?> news subscribers</small>
</article>
</div>
<?php if (password_verify('ChangeMe123!', (string) $currentUser['password_hash'])): ?>
<div class="notice admin-security-notice">
<strong>Security reminder:</strong> the initial administrator password is still active.
Change it from <a href="/account">My Account</a> before deployment.
</div>
<?php endif; ?>
<div class="admin-dashboard-grid">
<section class="admin-panel admin-panel-wide">
<div class="admin-panel-heading">
<div>
<span class="eyebrow">Live queue</span>
<h2>Recent Orders</h2>
</div>
<a class="button button-small" href="/admin/orders">View All Orders</a>
</div>
<div class="table-wrap">
<table>
<thead><tr><th>Order</th><th>Customer</th><th>Placed</th><th>Status</th><th>Total</th></tr></thead>
<tbody>
<?php if (!$recentOrders): ?>
<tr><td colspan="5" class="empty-cell">No orders yet. The kitchen is standing by.</td></tr>
<?php endif; ?>
<?php foreach ($recentOrders as $order): ?>
<tr>
<td><a href="/admin/order?id=<?= (int) $order['id'] ?>"><?= e($order['order_number']) ?></a></td>
<td><?= e($order['customer_name']) ?><small><?= e($order['customer_phone']) ?></small></td>
<td><?= e(store_datetime((string) $order['placed_at'], 'g:i A')) ?></td>
<td><span class="status-pill status-<?= e($order['status']) ?>"><?= e(ucfirst((string) $order['status'])) ?></span></td>
<td><?= money($order['total_cents']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</section>
<section class="admin-panel">
<div class="admin-panel-heading">
<div>
<span class="eyebrow">Last 7 days</span>
<h2>Store Traffic</h2>
</div>
</div>
<?php $maxTraffic = max(1, ...array_map(static fn (array $row): int => (int) $row['visitors'], $traffic)); ?>
<div class="bar-chart">
<?php if (!$traffic): ?><p class="muted">Traffic data will appear as visitors arrive.</p><?php endif; ?>
<?php foreach ($traffic as $day): ?>
<div>
<span class="bar-value"><?= (int) $day['visitors'] ?></span>
<i style="height:<?= max(8, round(((int) $day['visitors'] / $maxTraffic) * 120)) ?>px"></i>
<small><?= e((new DateTimeImmutable((string) $day['day']))->format('D')) ?></small>
</div>
<?php endforeach; ?>
</div>
</section>
<section class="admin-panel">
<div class="admin-panel-heading">
<div>
<span class="eyebrow">Whats moving</span>
<h2>Popular Items</h2>
</div>
</div>
<div class="rank-list">
<?php if (!$popularItems): ?><p class="muted">Item sales will appear after the first order.</p><?php endif; ?>
<?php foreach ($popularItems as $index => $item): ?>
<div>
<span><?= $index + 1 ?></span>
<strong><?= e($item['item_name']) ?></strong>
<small><?= (int) $item['quantity'] ?> sold</small>
<b><?= money($item['sales_cents']) ?></b>
</div>
<?php endforeach; ?>
</div>
</section>
</div>