views(admin): add product management pages

This commit is contained in:
dualfroz committed 2026-08-27 16:28:15 +02:00
1 parent c200aa2996
commit 244e502bad
2 files changed
+133

No files matched your search

+74
View File
@@ -0,0 +1,74 @@
<?php
$editing = $product !== null && !empty($product['id']);
$action = $editing ? '/admin/products/' . (int) $product['id'] : '/admin/products';
$priceValue = $product !== null ? number_format((int) ($product['priceCents'] ?? 0) / 100, 2, '.', '') : '';
$field = static fn (string $key, $fallback = '') => $product[$key] ?? $fallback;
?>
<div class="admin__head">
<div>
<p class="small muted"><a href="/admin/products">Products</a> / <?= $editing ? 'Edit' : 'New' ?></p>
<h1 style="margin:0"><?= $editing ? e($product['name']) : 'New product' ?></h1>
</div>
</div>
<form method="post" action="<?= e($action) ?>" style="max-width:720px">
<input type="hidden" name="csrfToken" value="<?= e($csrfToken) ?>">
<div class="panel panel--pad">
<div class="field <?= isset($errors['name']) ? 'field--error' : '' ?>">
<label for="name">Name</label>
<input class="input" type="text" id="name" name="name" value="<?= e((string) $field('name')) ?>" required>
<?php if (isset($errors['name'])): ?><span class="field__error"><?= e($errors['name']) ?></span><?php endif; ?>
</div>
<div class="row gap-lg" style="align-items:flex-start">
<div class="field" style="flex:1">
<label for="slug">Slug</label>
<input class="input" type="text" id="slug" name="slug" value="<?= e((string) $field('slug')) ?>" placeholder="auto-generated from name">
</div>
<div class="field <?= isset($errors['categoryId']) ? 'field--error' : '' ?>" style="flex:1">
<label for="categoryId">Category</label>
<select class="select" id="categoryId" name="categoryId">
<option value="">Select a category</option>
<?php foreach ($categories as $category): ?>
<option value="<?= (int) $category['id'] ?>" <?= (int) $field('categoryId') === (int) $category['id'] ? 'selected' : '' ?>><?= e($category['name']) ?></option>
<?php endforeach; ?>
</select>
<?php if (isset($errors['categoryId'])): ?><span class="field__error"><?= e($errors['categoryId']) ?></span><?php endif; ?>
</div>
</div>
<div class="field">
<label for="description">Description</label>
<textarea class="textarea" id="description" name="description"><?= e((string) $field('description')) ?></textarea>
</div>
<div class="row gap-lg" style="align-items:flex-start">
<div class="field <?= isset($errors['price']) ? 'field--error' : '' ?>" style="flex:1">
<label for="price">Price (<?= e(strtoupper($currency)) ?>)</label>
<input class="input mono" type="number" step="0.01" min="0" id="price" name="price" value="<?= e($priceValue) ?>" required>
<?php if (isset($errors['price'])): ?><span class="field__error"><?= e($errors['price']) ?></span><?php endif; ?>
</div>
<div class="field <?= isset($errors['stockQuantity']) ? 'field--error' : '' ?>" style="flex:1">
<label for="stockQuantity">Stock quantity</label>
<input class="input mono" type="number" min="0" id="stockQuantity" name="stockQuantity" value="<?= e((string) $field('stockQuantity', '0')) ?>">
<?php if (isset($errors['stockQuantity'])): ?><span class="field__error"><?= e($errors['stockQuantity']) ?></span><?php endif; ?>
</div>
</div>
<div class="field">
<label for="imageUrl">Image URL</label>
<input class="input" type="url" id="imageUrl" name="imageUrl" value="<?= e((string) $field('imageUrl')) ?>" placeholder="https://...">
</div>
<label class="checkbox">
<input type="checkbox" name="isActive" value="1" <?= ($product === null || (int) $field('isActive', 1) === 1) ? 'checked' : '' ?>>
Visible in the storefront
</label>
</div>
<div class="row mt-lg" style="gap:12px">
<button class="btn btn--primary" type="submit"><?= $editing ? 'Save changes' : 'Create product' ?></button>
<a class="btn" href="/admin/products">Cancel</a>
</div>
</form>
+59
View File
@@ -0,0 +1,59 @@
<div class="admin__head">
<div>
<h1 style="margin:0">Products</h1>
<p class="muted" style="margin:0"><?= count($products) ?> products in the catalog.</p>
</div>
<a class="btn btn--primary" href="/admin/products/create">New product</a>
</div>
<?php if (empty($products)): ?>
<div class="empty">
<h3>No products yet</h3>
<p class="muted">Create your first product to start selling.</p>
<a class="btn btn--primary mt" href="/admin/products/create">New product</a>
</div>
<?php else: ?>
<div class="table-wrap">
<table class="table">
<thead>
<tr><th colspan="2">Product</th><th>Category</th><th class="num">Price</th><th class="num">Stock</th><th>Status</th><th></th></tr>
</thead>
<tbody>
<?php foreach ($products as $product): $stock = (int) $product['stockQuantity']; ?>
<tr>
<td style="width:60px">
<?php if (!empty($product['imageUrl'])): ?>
<img class="cart-thumb" src="<?= e($product['imageUrl']) ?>" alt="">
<?php else: ?>
<span class="cart-thumb"><?= e(strtoupper(substr($product['name'], 0, 1))) ?></span>
<?php endif; ?>
</td>
<td style="font-weight:600"><?= e($product['name']) ?><div class="small muted mono">/<?= e($product['slug']) ?></div></td>
<td class="muted"><?= e($product['categoryName'] ?? 'Uncategorized') ?></td>
<td class="num mono"><?= e(formatMoney((int) $product['priceCents'], $currency)) ?></td>
<td class="num">
<span class="badge badge--<?= $stock <= 0 ? 'out' : ($stock <= 5 ? 'low' : 'stock') ?>"><?= $stock ?></span>
</td>
<td>
<?php if ((int) $product['isActive'] === 1): ?>
<span class="badge badge--fulfilled">Active</span>
<?php else: ?>
<span class="badge badge--cancelled">Hidden</span>
<?php endif; ?>
</td>
<td>
<div class="row" style="gap:6px;justify-content:flex-end">
<a class="btn btn--sm" href="/admin/products/<?= (int) $product['id'] ?>/variants">Variants</a>
<a class="btn btn--sm" href="/admin/products/<?= (int) $product['id'] ?>/edit">Edit</a>
<form method="post" action="/admin/products/<?= (int) $product['id'] ?>/delete" onsubmit="return confirm('Delete this product? This cannot be undone.')">
<input type="hidden" name="csrfToken" value="<?= e($csrfToken) ?>">
<button class="btn btn--danger btn--sm" type="submit">Delete</button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>