16235369cb
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.
102 lines
5.4 KiB
PHP
102 lines
5.4 KiB
PHP
<div class="detail-heading">
|
|
<div>
|
|
<a class="back-link" href="/admin/orders">← Back to orders</a>
|
|
<div class="detail-title-row">
|
|
<h2><?= e($order['order_number']) ?></h2>
|
|
<span class="status-pill status-<?= e($order['status']) ?>"><?= e(ucfirst((string) $order['status'])) ?></span>
|
|
</div>
|
|
<p>Placed <?= e(store_datetime((string) $order['placed_at'], 'F j, Y \a\t g:i A')) ?></p>
|
|
</div>
|
|
<strong class="detail-total"><?= money($order['total_cents']) ?></strong>
|
|
</div>
|
|
|
|
<div class="admin-detail-grid">
|
|
<div>
|
|
<section class="admin-panel">
|
|
<div class="admin-panel-heading"><h2>Order Items</h2></div>
|
|
<div class="order-item-list">
|
|
<?php foreach ($items as $item): ?>
|
|
<div>
|
|
<span class="item-quantity"><?= (int) $item['quantity'] ?>x</span>
|
|
<span><strong><?= e($item['item_name']) ?></strong><?php if ($item['notes']): ?><small><?= e($item['notes']) ?></small><?php endif; ?></span>
|
|
<strong><?= money($item['line_total_cents']) ?></strong>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<dl class="admin-totals">
|
|
<div><dt>Subtotal</dt><dd><?= money($order['subtotal_cents']) ?></dd></div>
|
|
<div><dt>Tax</dt><dd><?= money($order['tax_cents']) ?></dd></div>
|
|
<div><dt>Total</dt><dd><?= money($order['total_cents']) ?></dd></div>
|
|
</dl>
|
|
<?php if ($order['special_instructions']): ?>
|
|
<div class="notice"><strong>Customer note:</strong> <?= e($order['special_instructions']) ?></div>
|
|
<?php endif; ?>
|
|
</section>
|
|
<section class="admin-panel">
|
|
<div class="admin-panel-heading"><h2>Activity</h2></div>
|
|
<div class="timeline">
|
|
<?php foreach ($events as $event): ?>
|
|
<div>
|
|
<i></i>
|
|
<span>
|
|
<strong><?= e(ucwords(str_replace('_', ' ', (string) $event['event_type']))) ?></strong>
|
|
<p><?= e($event['details']) ?></p>
|
|
<small><?= e($event['staff_name'] ?: 'System') ?> · <?= e(store_datetime((string) $event['created_at'], 'M j, g:i A')) ?></small>
|
|
</span>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
<aside>
|
|
<section class="admin-panel">
|
|
<div class="admin-panel-heading"><h2>Update Order</h2></div>
|
|
<form class="form-stack" action="/admin/order" method="post">
|
|
<?= csrf_field() ?>
|
|
<input type="hidden" name="order_id" value="<?= (int) $order['id'] ?>">
|
|
<label>Status
|
|
<select name="status">
|
|
<?php foreach (['paid', 'preparing', 'ready', 'completed', 'cancelled'] as $status): ?>
|
|
<option value="<?= $status ?>" <?= selected($order['status'], $status) ?>><?= e(ucfirst($status)) ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
<label>Staff note
|
|
<textarea name="staff_note" rows="3" placeholder="Optional internal note"></textarea>
|
|
</label>
|
|
<button class="button button-block" type="submit">Update Status</button>
|
|
</form>
|
|
</section>
|
|
<section class="admin-panel">
|
|
<div class="admin-panel-heading"><h2>Customer</h2></div>
|
|
<div class="customer-card">
|
|
<strong><?= e($order['customer_name']) ?></strong>
|
|
<a href="mailto:<?= e($order['customer_email']) ?>"><?= e($order['customer_email']) ?></a>
|
|
<a href="tel:<?= e(preg_replace('/[^0-9+]/', '', (string) $order['customer_phone'])) ?>"><?= e($order['customer_phone']) ?></a>
|
|
<span>Pickup<?= $order['pickup_time'] ? ' at ' . e($order['pickup_time']) : '' ?></span>
|
|
</div>
|
|
</section>
|
|
<section class="admin-panel">
|
|
<div class="admin-panel-heading"><h2>Issue Refund</h2></div>
|
|
<form class="form-stack" action="/admin/order/refund" method="post">
|
|
<?= csrf_field() ?>
|
|
<input type="hidden" name="order_id" value="<?= (int) $order['id'] ?>">
|
|
<label>Amount
|
|
<input type="number" name="amount" min="0.01" max="<?= number_format((int) $order['total_cents'] / 100, 2, '.', '') ?>" step="0.01" required>
|
|
</label>
|
|
<label>Reason
|
|
<input type="text" name="reason" required placeholder="Customer request, unavailable item...">
|
|
</label>
|
|
<button class="button button-danger button-block" type="submit" data-confirm="Issue this refund? This action sends money back through the payment provider.">Issue Refund</button>
|
|
</form>
|
|
<?php if ($refunds): ?>
|
|
<div class="refund-list">
|
|
<?php foreach ($refunds as $refund): ?>
|
|
<div><strong>-<?= money($refund['amount_cents']) ?></strong><span><?= e($refund['reason']) ?></span><small><?= e($refund['staff_name'] ?? 'Staff') ?></small></div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</section>
|
|
</aside>
|
|
</div>
|