mirror of
https://github.com/myronblair/tomsjavajive-app
synced 2026-06-30 17:50:56 -05:00
300 lines
13 KiB
PHP
300 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* Tom's Java Jive - Admin Order Detail
|
|
*/
|
|
|
|
$pageTitle = 'Order Details';
|
|
require_once __DIR__ . '/includes/header.php';
|
|
|
|
$orderId = $_GET['id'] ?? '';
|
|
|
|
if (empty($orderId)) {
|
|
header('Location: /admin/orders.php');
|
|
exit;
|
|
}
|
|
|
|
$order = db()->fetch("SELECT * FROM orders WHERE order_id = :id", ['id' => $orderId]);
|
|
|
|
if (!$order) {
|
|
setFlash('error', 'Order not found');
|
|
header('Location: /admin/orders.php');
|
|
exit;
|
|
}
|
|
|
|
// Handle status update
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$action = $_POST['action'] ?? '';
|
|
|
|
if ($action === 'update_status') {
|
|
$status = $_POST['status'] ?? '';
|
|
$trackingNumber = $_POST['tracking_number'] ?? '';
|
|
|
|
$updateData = ['order_status' => $status];
|
|
if ($trackingNumber) {
|
|
$updateData['tracking_number'] = $trackingNumber;
|
|
}
|
|
|
|
db()->update('orders', $updateData, 'order_id = :id', ['id' => $orderId]);
|
|
setFlash('success', 'Order status updated');
|
|
header('Location: /admin/order.php?id=' . $orderId);
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'add_note') {
|
|
$note = trim($_POST['note'] ?? '');
|
|
if ($note) {
|
|
$existingNotes = $order['notes'] ?? '';
|
|
$newNote = '[' . date('M j, Y g:i A') . '] ' . $note;
|
|
$allNotes = $existingNotes ? $existingNotes . "\n" . $newNote : $newNote;
|
|
|
|
db()->update('orders', ['notes' => $allNotes], 'order_id = :id', ['id' => $orderId]);
|
|
setFlash('success', 'Note added');
|
|
header('Location: /admin/order.php?id=' . $orderId);
|
|
exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
$items = json_decode($order['items'], true) ?? [];
|
|
$shippingAddress = json_decode($order['shipping_address'], true) ?? [];
|
|
|
|
$statuses = ['pending', 'confirmed', 'processing', 'shipped', 'delivered', 'cancelled', 'refunded'];
|
|
?>
|
|
|
|
<div class="page-header">
|
|
<div style="display: flex; align-items: center; gap: 1rem;">
|
|
<a href="/admin/orders.php" class="btn btn-secondary">
|
|
<i class="fas fa-arrow-left"></i>
|
|
</a>
|
|
<h1 class="page-title">Order #<?= htmlspecialchars($order['order_number']) ?></h1>
|
|
<?php if ($order['is_pos_order']): ?>
|
|
<span class="badge badge-primary">POS Order</span>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div style="display: flex; gap: 0.5rem;">
|
|
<button class="btn btn-secondary" onclick="window.print()">
|
|
<i class="fas fa-print"></i> Print
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if (hasFlash('success')): ?>
|
|
<div class="alert alert-success"><i class="fas fa-check-circle"></i> <?= getFlash('success') ?></div>
|
|
<?php endif; ?>
|
|
|
|
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 1.5rem;">
|
|
<!-- Main Column -->
|
|
<div>
|
|
<!-- Order Items -->
|
|
<div class="admin-card">
|
|
<div class="admin-card-header">
|
|
<h3 class="admin-card-title">Order Items</h3>
|
|
</div>
|
|
<div class="admin-card-body" style="padding: 0;">
|
|
<table class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Product</th>
|
|
<th>Price</th>
|
|
<th>Qty</th>
|
|
<th style="text-align: right;">Total</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($items as $item): ?>
|
|
<tr>
|
|
<td>
|
|
<?php if (isset($item['product_id'])): ?>
|
|
<a href="/admin/product-edit.php?id=<?= $item['product_id'] ?>">
|
|
<?= htmlspecialchars($item['name']) ?>
|
|
</a>
|
|
<?php else: ?>
|
|
<?= htmlspecialchars($item['name']) ?>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= formatCurrency($item['price']) ?></td>
|
|
<td><?= $item['quantity'] ?></td>
|
|
<td style="text-align: right;"><?= formatCurrency($item['total']) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td colspan="3" style="text-align: right;">Subtotal</td>
|
|
<td style="text-align: right;"><?= formatCurrency($order['subtotal']) ?></td>
|
|
</tr>
|
|
<?php if ($order['shipping_cost'] > 0): ?>
|
|
<tr>
|
|
<td colspan="3" style="text-align: right;">Shipping</td>
|
|
<td style="text-align: right;"><?= formatCurrency($order['shipping_cost']) ?></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
<?php if (($order['tax'] ?? 0) > 0): ?>
|
|
<tr>
|
|
<td colspan="3" style="text-align: right;">Tax</td>
|
|
<td style="text-align: right;"><?= formatCurrency($order['tax']) ?></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
<?php if (($order['discount'] ?? 0) > 0): ?>
|
|
<tr>
|
|
<td colspan="3" style="text-align: right;">Discount</td>
|
|
<td style="text-align: right; color: var(--admin-success);">-<?= formatCurrency($order['discount']) ?></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
<tr style="font-size: 1.125rem; font-weight: 600;">
|
|
<td colspan="3" style="text-align: right;">Total</td>
|
|
<td style="text-align: right;"><?= formatCurrency($order['total']) ?></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Notes -->
|
|
<div class="admin-card">
|
|
<div class="admin-card-header">
|
|
<h3 class="admin-card-title">Order Notes</h3>
|
|
</div>
|
|
<div class="admin-card-body">
|
|
<?php if ($order['notes']): ?>
|
|
<pre style="white-space: pre-wrap; font-family: inherit; margin-bottom: 1rem; padding: 1rem; background: var(--admin-bg); border-radius: var(--admin-radius);"><?= htmlspecialchars($order['notes']) ?></pre>
|
|
<?php else: ?>
|
|
<p class="text-muted" style="margin-bottom: 1rem;">No notes yet.</p>
|
|
<?php endif; ?>
|
|
|
|
<form method="POST">
|
|
<input type="hidden" name="action" value="add_note">
|
|
<div class="form-group mb-0">
|
|
<div style="display: flex; gap: 0.5rem;">
|
|
<input type="text" name="note" class="form-input" placeholder="Add a note...">
|
|
<button type="submit" class="btn btn-secondary">Add Note</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sidebar -->
|
|
<div>
|
|
<!-- Status -->
|
|
<div class="admin-card">
|
|
<div class="admin-card-header">
|
|
<h3 class="admin-card-title">Order Status</h3>
|
|
</div>
|
|
<div class="admin-card-body">
|
|
<form method="POST">
|
|
<input type="hidden" name="action" value="update_status">
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Status</label>
|
|
<select name="status" class="form-select">
|
|
<?php foreach ($statuses as $s): ?>
|
|
<option value="<?= $s ?>" <?= $order['order_status'] === $s ? 'selected' : '' ?>>
|
|
<?= ucfirst($s) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Tracking Number</label>
|
|
<input type="text" name="tracking_number" class="form-input" value="<?= htmlspecialchars($order['tracking_number'] ?? '') ?>">
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary btn-block">Update Status</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Customer -->
|
|
<div class="admin-card">
|
|
<div class="admin-card-header">
|
|
<h3 class="admin-card-title">Customer</h3>
|
|
</div>
|
|
<div class="admin-card-body">
|
|
<p><strong><?= htmlspecialchars($order['customer_name']) ?></strong></p>
|
|
<p><?= htmlspecialchars($order['customer_email']) ?></p>
|
|
<?php if ($order['customer_phone']): ?>
|
|
<p><?= htmlspecialchars($order['customer_phone']) ?></p>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($order['customer_id']): ?>
|
|
<a href="/admin/customers.php?id=<?= $order['customer_id'] ?>" class="btn btn-sm btn-secondary mt-1">
|
|
View Customer
|
|
</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Shipping Address -->
|
|
<?php if (!empty($shippingAddress) && ($shippingAddress['type'] ?? '') !== 'pickup'): ?>
|
|
<div class="admin-card">
|
|
<div class="admin-card-header">
|
|
<h3 class="admin-card-title">Shipping Address</h3>
|
|
</div>
|
|
<div class="admin-card-body">
|
|
<p>
|
|
<?= htmlspecialchars($shippingAddress['address'] ?? '') ?><br>
|
|
<?= htmlspecialchars($shippingAddress['city'] ?? '') ?>,
|
|
<?= htmlspecialchars($shippingAddress['state'] ?? '') ?>
|
|
<?= htmlspecialchars($shippingAddress['zip'] ?? '') ?>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<!-- Payment -->
|
|
<div class="admin-card">
|
|
<div class="admin-card-header">
|
|
<h3 class="admin-card-title">Payment</h3>
|
|
</div>
|
|
<div class="admin-card-body">
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 0.5rem;">
|
|
<span>Method</span>
|
|
<span><?= ucfirst($order['payment_method'] ?? 'N/A') ?></span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 0.5rem;">
|
|
<span>Status</span>
|
|
<?php
|
|
$paymentClass = match($order['payment_status']) {
|
|
'paid' => 'success',
|
|
'failed' => 'error',
|
|
'refunded' => 'warning',
|
|
default => 'primary'
|
|
};
|
|
?>
|
|
<span class="badge badge-<?= $paymentClass ?>"><?= ucfirst($order['payment_status']) ?></span>
|
|
</div>
|
|
<?php if ($order['stripe_payment_intent']): ?>
|
|
<div style="display: flex; justify-content: space-between;">
|
|
<span>Stripe ID</span>
|
|
<span class="text-muted" style="font-size: 0.8rem;"><?= htmlspecialchars(substr($order['stripe_payment_intent'], 0, 20)) ?>...</span>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Timeline -->
|
|
<div class="admin-card">
|
|
<div class="admin-card-header">
|
|
<h3 class="admin-card-title">Timeline</h3>
|
|
</div>
|
|
<div class="admin-card-body">
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 0.5rem;">
|
|
<span class="text-muted">Created</span>
|
|
<span><?= formatDateTime($order['created_at']) ?></span>
|
|
</div>
|
|
<?php if ($order['updated_at'] && $order['updated_at'] !== $order['created_at']): ?>
|
|
<div style="display: flex; justify-content: space-between;">
|
|
<span class="text-muted">Updated</span>
|
|
<span><?= formatDateTime($order['updated_at']) ?></span>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|