views(admin): add coupon and review management pages

This commit is contained in:
dualfroz committed 2026-08-27 17:45:06 +02:00
1 parent 244e502bad
commit f9741f89ef
3 files changed
+174

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
<div class="admin__head">
<div>
<h1 style="margin:0">New coupon</h1>
<p class="muted" style="margin:0">Create a discount code.</p>
</div>
<a class="btn btn--ghost" href="/admin/coupons">Back</a>
</div>
<form method="post" action="/admin/coupons" class="panel panel--pad" style="max-width:640px">
<input type="hidden" name="csrfToken" value="<?= e($csrfToken) ?>">
<label class="field">
<span class="field__label">Code</span>
<input class="input" type="text" name="code" value="<?= e($_POST['code'] ?? '') ?>" placeholder="SAVE10" required>
<?php if (!empty($errors['code'])): ?><span class="field__error"><?= e($errors['code']) ?></span><?php endif; ?>
</label>
<div class="row" style="gap:16px">
<label class="field" style="flex:1">
<span class="field__label">Type</span>
<select class="select" name="type">
<option value="percent">Percent</option>
<option value="fixed">Fixed amount</option>
</select>
</label>
<label class="field" style="flex:1">
<span class="field__label">Value (percent, or amount)</span>
<input class="input" type="number" name="value" step="0.01" min="0" value="<?= e($_POST['value'] ?? '') ?>" required>
<?php if (!empty($errors['value'])): ?><span class="field__error"><?= e($errors['value']) ?></span><?php endif; ?>
</label>
</div>
<div class="row" style="gap:16px">
<label class="field" style="flex:1">
<span class="field__label">Minimum cart</span>
<input class="input" type="number" name="minSubtotal" step="0.01" min="0" value="<?= e($_POST['minSubtotal'] ?? '0') ?>">
</label>
<label class="field" style="flex:1">
<span class="field__label">Max redemptions (blank = unlimited)</span>
<input class="input" type="number" name="maxRedemptions" min="1" value="<?= e($_POST['maxRedemptions'] ?? '') ?>">
</label>
</div>
<div class="row" style="gap:16px">
<label class="field" style="flex:1">
<span class="field__label">Starts at</span>
<input class="input" type="date" name="startsAt" value="<?= e($_POST['startsAt'] ?? '') ?>">
</label>
<label class="field" style="flex:1">
<span class="field__label">Expires at</span>
<input class="input" type="date" name="expiresAt" value="<?= e($_POST['expiresAt'] ?? '') ?>">
</label>
</div>
<label class="checkbox">
<input type="checkbox" name="isActive" checked> Active
</label>
<div class="mt-lg">
<button class="btn btn--primary" type="submit">Create coupon</button>
</div>
</form>
+49
View File
@@ -0,0 +1,49 @@
<div class="admin__head">
<div>
<h1 style="margin:0">Coupons</h1>
<p class="muted" style="margin:0">Percentage or fixed discounts with limits and windows.</p>
</div>
<a class="btn btn--primary" href="/admin/coupons/create">New coupon</a>
</div>
<?php if (empty($coupons)): ?>
<div class="empty"><p class="muted" style="margin:0">No coupons yet.</p></div>
<?php else: ?>
<div class="table-wrap">
<table class="table">
<thead>
<tr><th>Code</th><th>Discount</th><th class="num">Min cart</th><th>Redemptions</th><th>Window</th><th>Status</th><th></th></tr>
</thead>
<tbody>
<?php foreach ($coupons as $coupon): ?>
<tr>
<td class="mono" style="font-weight:600"><?= e($coupon['code']) ?></td>
<td>
<?php if ($coupon['type'] === 'percent'): ?>
<?= (int) $coupon['value'] ?>%
<?php else: ?>
<?= e(formatMoney((int) $coupon['value'], $currency)) ?>
<?php endif; ?>
</td>
<td class="num mono"><?= e(formatMoney((int) $coupon['minSubtotalCents'], $currency)) ?></td>
<td>
<?= (int) $coupon['redeemedCount'] ?><?= $coupon['maxRedemptions'] !== null ? ' / ' . (int) $coupon['maxRedemptions'] : '' ?>
</td>
<td class="small muted">
<?= $coupon['startsAt'] ? e(substr($coupon['startsAt'], 0, 10)) : '-' ?>
&rarr;
<?= $coupon['expiresAt'] ? e(substr($coupon['expiresAt'], 0, 10)) : '-' ?>
</td>
<td><span class="badge badge--<?= (int) $coupon['isActive'] === 1 ? 'stock' : 'out' ?>"><?= (int) $coupon['isActive'] === 1 ? 'active' : 'off' ?></span></td>
<td>
<form method="post" action="/admin/coupons/<?= (int) $coupon['id'] ?>/delete" onsubmit="return confirm('Delete this coupon?')">
<input type="hidden" name="csrfToken" value="<?= e($csrfToken) ?>">
<button class="btn btn--danger btn--sm" type="submit">Delete</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
+63
View File
@@ -0,0 +1,63 @@
<div class="admin__head">
<div>
<h1 style="margin:0">Reviews</h1>
<p class="muted" style="margin:0"><?= count($pending) ?> awaiting moderation.</p>
</div>
</div>
<div class="section-head"><h3 style="margin:0">Pending</h3></div>
<?php if (empty($pending)): ?>
<div class="empty"><p class="muted" style="margin:0">Nothing to moderate.</p></div>
<?php else: ?>
<div class="stack" style="gap:12px">
<?php foreach ($pending as $review): ?>
<div class="panel panel--pad review-card">
<div class="row" style="justify-content:space-between;align-items:flex-start">
<div>
<span class="rating__stars"><?= str_repeat('*', (int) $review['rating']) ?><span class="rating__off"><?= str_repeat('*', 5 - (int) $review['rating']) ?></span></span>
<strong style="margin-left:8px"><?= e($review['title'] !== '' ? $review['title'] : 'Review') ?></strong>
<div class="small muted">
<a href="/products/<?= e($review['productSlug']) ?>"><?= e($review['productName']) ?></a>
&middot; <?= e($review['authorName']) ?> (<?= e($review['authorEmail']) ?>)
&middot; <?= e(substr((string) $review['createdAt'], 0, 10)) ?>
</div>
</div>
<div class="row" style="gap:8px">
<form method="post" action="/admin/reviews/<?= (int) $review['id'] ?>/approve">
<input type="hidden" name="csrfToken" value="<?= e($csrfToken) ?>">
<button class="btn btn--primary btn--sm" type="submit">Approve</button>
</form>
<form method="post" action="/admin/reviews/<?= (int) $review['id'] ?>/reject">
<input type="hidden" name="csrfToken" value="<?= e($csrfToken) ?>">
<button class="btn btn--danger btn--sm" type="submit">Reject</button>
</form>
</div>
</div>
<?php if ($review['body'] !== ''): ?>
<p style="margin:10px 0 0"><?= nl2br(e($review['body'])) ?></p>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<div class="section-head mt-lg"><h3 style="margin:0">Approved (<?= count($approved) ?>)</h3></div>
<?php if (empty($approved)): ?>
<div class="empty"><p class="muted" style="margin:0">None yet.</p></div>
<?php else: ?>
<div class="table-wrap">
<table class="table">
<thead><tr><th>Product</th><th>Rating</th><th>Title</th><th>Author</th></tr></thead>
<tbody>
<?php foreach ($approved as $review): ?>
<tr>
<td><a href="/products/<?= e($review['productSlug']) ?>"><?= e($review['productName']) ?></a></td>
<td><?= str_repeat('*', (int) $review['rating']) ?></td>
<td><?= e($review['title']) ?></td>
<td class="muted"><?= e($review['authorName']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>