Files
order/views/admin/order-detail.php
T
Ty Clifford 03348cad79 - Implemented the full order lifecycle, secure customer tracker, automatic acceptance emails, configurable status templates, and guest/account CRM management.
Key areas: 
[OrderStatusService.php](/Users/tyemeclifford/Documents/GH/fatbottomgrille/app/Services/OrderStatusService.php), 
[AdminController.php](/Users/tyemeclifford/Documents/GH/fatbottomgrille/app/Controllers/AdminController.php), 
and 
[Database.php](/Users/tyemeclifford/Documents/GH/fatbottomgrille/app/Core/Database.php).
SQLite migration applied successfully. PHP/JS syntax, integration 
workflows, rendered pages, database integrity, and tracker authorization 
all passed. Invalid tracker tokens correctly return 403.
2026-06-14 13:35:31 -04:00

115 lines
6.8 KiB
PHP

<div class="detail-heading">
<div>
<a class="back-link" href="<?= e(url('/admin/orders')) ?>">&larr; Back to orders</a>
<div class="detail-title-row">
<h2><?= e($order['order_number']) ?></h2>
<span class="status-pill status-<?= e($order['status']) ?>"><?= e(order_status_label((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($event['status'] ? order_status_label((string) $event['status']) : ucwords(str_replace('_', ' ', (string) $event['event_type']))) ?></strong>
<p><?= e($event['details']) ?></p>
<?php if ($event['note']): ?>
<small><?= $event['customer_visible'] ? 'Customer-visible note' : 'Internal note' ?><?= $event['email_sent'] ? ' · Emailed' : '' ?></small>
<?php endif; ?>
<small><?= e($event['staff_name'] ?: 'System') ?> &middot; <?= 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>Order Actions</h2></div>
<form class="form-stack" action="<?= e(url('/admin/order')) ?>" method="post">
<?= csrf_field() ?>
<input type="hidden" name="order_id" value="<?= (int) $order['id'] ?>">
<label>Reason or note
<textarea name="status_note" rows="3" placeholder="Optional. A blank rejection reason will not appear to the customer."></textarea>
</label>
<label class="check-control compact">
<input type="checkbox" name="customer_visible" value="1">
<span><strong>Show this note to the customer</strong><small>The status itself is always visible.</small></span>
</label>
<label class="check-control compact">
<input type="checkbox" name="send_email" value="1">
<span><strong>Email this update</strong><small>Acceptance emails are always sent.</small></span>
</label>
<div class="order-action-grid">
<button class="button" type="submit" name="status" value="accepted">Accept</button>
<button class="button button-danger" type="submit" name="status" value="declined">Reject</button>
<button class="button button-outline" type="submit" name="status" value="processing">Start Order</button>
<button class="button" type="submit" name="status" value="ready">Complete / Ready</button>
<button class="button button-ghost" type="submit" name="status" value="completed">Picked Up</button>
</div>
</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>
<?php if ($customer): ?>
<a class="button button-small button-ghost" href="<?= e(url('/admin/customer')) ?>?id=<?= (int) $customer['id'] ?>">Open CRM Profile</a>
<?php endif; ?>
</div>
</section>
<section class="admin-panel">
<div class="admin-panel-heading"><h2>Issue Refund</h2></div>
<form class="form-stack" action="<?= e(url('/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>