Files
AudioCore/plugins/store/views/admin/customers.php
2026-03-04 20:46:11 +00:00

225 lines
6.9 KiB
PHP

<?php
$pageTitle = $title ?? 'Store Customers';
$customers = $customers ?? [];
$currency = (string)($currency ?? 'GBP');
$q = (string)($q ?? '');
ob_start();
?>
<section class="admin-card customers-page">
<div class="badge">Store</div>
<div class="customers-header">
<div>
<h1 class="customers-title">Customers</h1>
<p class="customers-sub">Customer activity, value, and latest order access.</p>
</div>
<a href="/admin/store" class="btn outline">Back</a>
</div>
<div class="customers-tabs">
<a href="/admin/store" class="btn outline small">Overview</a>
<a href="/admin/store/settings" class="btn outline small">Settings</a>
<a href="/admin/store/orders" class="btn outline small">Orders</a>
<a href="/admin/store/customers" class="btn outline small">Customers</a>
</div>
<form method="get" action="/admin/store/customers" class="customers-search">
<input type="text" name="q" value="<?= htmlspecialchars($q, ENT_QUOTES, 'UTF-8') ?>" placeholder="Search by email, name, or order number">
<button type="submit" class="btn small">Search</button>
<?php if ($q !== ''): ?>
<a href="/admin/store/customers" class="btn outline small">Clear</a>
<?php endif; ?>
</form>
<?php if (!$customers): ?>
<div class="customers-empty">No customers yet.</div>
<?php else: ?>
<div class="customers-table-wrap">
<table class="customers-table">
<thead>
<tr>
<th>Customer</th>
<th>Orders</th>
<th>Revenue</th>
<th>Latest Order</th>
<th>Last Seen</th>
</tr>
</thead>
<tbody>
<?php foreach ($customers as $customer): ?>
<?php
$ips = is_array($customer['ips'] ?? null) ? $customer['ips'] : [];
$email = (string)($customer['email'] ?? '');
$lastOrderNo = (string)($customer['last_order_no'] ?? '');
$lastOrderId = (int)($customer['last_order_id'] ?? 0);
$lastSeen = (string)($customer['last_order_at'] ?? $customer['created_at'] ?? '');
?>
<tr>
<td>
<div class="customer-email"><?= htmlspecialchars($email, ENT_QUOTES, 'UTF-8') ?></div>
<?php if ($ips): ?>
<div class="customer-ips">
<?php foreach ($ips as $entry): ?>
<?php
$ip = (string)($entry['ip'] ?? '');
$ipLastSeen = (string)($entry['last_seen'] ?? '');
if ($ip === '') { continue; }
?>
<span class="ip-chip" title="<?= htmlspecialchars($ipLastSeen, ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($ip, ENT_QUOTES, 'UTF-8') ?></span>
<?php endforeach; ?>
</div>
<?php endif; ?>
</td>
<td class="num"><?= (int)($customer['order_count'] ?? 0) ?></td>
<td class="num"><?= htmlspecialchars($currency, ENT_QUOTES, 'UTF-8') ?> <?= number_format((float)($customer['revenue'] ?? 0), 2) ?></td>
<td>
<?php if ($lastOrderId > 0): ?>
<a href="/admin/store/order?id=<?= $lastOrderId ?>" class="order-link">
<?= htmlspecialchars($lastOrderNo !== '' ? $lastOrderNo : ('#' . $lastOrderId), ENT_QUOTES, 'UTF-8') ?>
</a>
<?php else: ?>
<span class="muted">No orders</span>
<?php endif; ?>
</td>
<td class="muted"><?= htmlspecialchars($lastSeen, ENT_QUOTES, 'UTF-8') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</section>
<style>
.customers-page { display:grid; gap:14px; }
.customers-header { display:flex; align-items:flex-start; justify-content:space-between; gap:16px; margin-top:14px; }
.customers-title { margin:0; font-size:28px; line-height:1.1; }
.customers-sub { margin:6px 0 0; color:var(--muted); font-size:14px; }
.customers-tabs { display:flex; flex-wrap:wrap; gap:8px; }
.customers-search { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.customers-search input {
height:36px;
min-width:280px;
border-radius:10px;
border:1px solid rgba(255,255,255,.15);
background:rgba(255,255,255,.04);
color:#fff;
padding:0 12px;
}
.customers-empty {
padding:16px;
border-radius:12px;
border:1px solid rgba(255,255,255,.08);
background:rgba(0,0,0,.15);
color:var(--muted);
font-size:14px;
}
.customers-table-wrap {
border:1px solid rgba(255,255,255,.1);
border-radius:14px;
overflow:hidden;
background:rgba(0,0,0,.2);
}
.customers-table {
width:100%;
border-collapse:separate;
border-spacing:0;
table-layout:fixed;
}
.customers-table th {
text-align:left;
font-size:11px;
letter-spacing:.16em;
text-transform:uppercase;
color:var(--muted);
padding:14px 16px;
background:rgba(255,255,255,.03);
border-bottom:1px solid rgba(255,255,255,.1);
}
.customers-table td {
padding:14px 16px;
vertical-align:top;
border-bottom:1px solid rgba(255,255,255,.06);
font-size:14px;
}
.customers-table tbody tr:last-child td { border-bottom:none; }
.customers-table tbody tr:hover { background:rgba(255,255,255,.03); }
.customer-email {
font-size:16px;
font-weight:600;
line-height:1.25;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.customer-name {
margin-top:4px;
color:var(--muted);
font-size:13px;
}
.customer-ips {
display:flex;
flex-wrap:wrap;
gap:6px;
margin-top:8px;
}
.ip-chip {
display:inline-flex;
align-items:center;
padding:3px 8px;
border-radius:999px;
border:1px solid rgba(255,255,255,.14);
background:rgba(255,255,255,.04);
color:#d8def1;
font-size:11px;
line-height:1;
}
.num {
font-weight:600;
white-space:nowrap;
}
.order-link {
display:inline-flex;
max-width:100%;
color:#dce8ff;
text-decoration:none;
border-bottom:1px dashed rgba(220,232,255,.4);
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.order-link:hover { color:#fff; border-bottom-color:rgba(255,255,255,.8); }
.muted { color:var(--muted); }
@media (max-width: 980px) {
.customers-table th:nth-child(3),
.customers-table td:nth-child(3),
.customers-table th:nth-child(5),
.customers-table td:nth-child(5) { display:none; }
}
@media (max-width: 700px) {
.customers-header { flex-direction:column; }
.customers-table { table-layout:auto; }
.customers-table th:nth-child(2),
.customers-table td:nth-child(2) { display:none; }
.customer-email { font-size:15px; }
.customers-search input { min-width:100%; width:100%; }
}
</style>
<?php
$content = ob_get_clean();
require __DIR__ . '/../../../../modules/admin/views/layout.php';