mirror of
https://github.com/myronblair/tomsjavajive-app
synced 2026-06-30 17:50:56 -05:00
v1.0.0 - Initial backup
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
ob_start();
|
||||
/**
|
||||
* Tom's Java Jive - Admin Categories
|
||||
*/
|
||||
|
||||
$pageTitle = 'Categories';
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
|
||||
// Handle actions
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$action = $_POST['action'] ?? '';
|
||||
|
||||
if ($action === 'create' || $action === 'update') {
|
||||
$categoryId = $_POST['category_id'] ?? '';
|
||||
$name = trim($_POST['name'] ?? '');
|
||||
$slug = trim($_POST['slug'] ?? '') ?: slugify($name);
|
||||
$description = trim($_POST['description'] ?? '');
|
||||
$isActive = isset($_POST['is_active']) ? 1 : 0;
|
||||
|
||||
if (empty($name)) {
|
||||
setFlash('error', 'Category name is required');
|
||||
} else {
|
||||
$data = [
|
||||
'name' => $name,
|
||||
'slug' => $slug,
|
||||
'description' => $description,
|
||||
'is_active' => $isActive
|
||||
];
|
||||
|
||||
if ($action === 'update' && $categoryId) {
|
||||
db()->update('categories', $data, 'category_id = :id', ['id' => $categoryId]);
|
||||
setFlash('success', 'Category updated');
|
||||
} else {
|
||||
$data['category_id'] = generateId('cat_');
|
||||
db()->insert('categories', $data);
|
||||
setFlash('success', 'Category created');
|
||||
}
|
||||
}
|
||||
|
||||
header('Location: /admin/categories.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($action === 'delete' && !empty($_POST['category_id'])) {
|
||||
db()->delete('categories', 'category_id = :id', ['id' => $_POST['category_id']]);
|
||||
setFlash('success', 'Category deleted');
|
||||
header('Location: /admin/categories.php');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Get categories with product counts
|
||||
$categories = db()->fetchAll(
|
||||
"SELECT c.*,
|
||||
(SELECT COUNT(*) FROM products p WHERE p.category = c.slug OR p.category = c.name) as product_count
|
||||
FROM categories c
|
||||
ORDER BY c.name ASC"
|
||||
);
|
||||
|
||||
// Also get uncategorized products
|
||||
$uncategorizedCount = db()->count('products', "category IS NULL OR category = ''");
|
||||
?>
|
||||
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">Categories</h1>
|
||||
<button class="btn btn-primary" onclick="openCategoryModal()">
|
||||
<i class="fas fa-plus"></i> Add Category
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<?php if (hasFlash('success')): ?>
|
||||
<div class="alert alert-success"><i class="fas fa-check-circle"></i> <?= getFlash('success') ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if (hasFlash('error')): ?>
|
||||
<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> <?= getFlash('error') ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="admin-card">
|
||||
<div class="admin-card-body" style="padding: 0;">
|
||||
<table class="admin-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Slug</th>
|
||||
<th>Products</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($categories)): ?>
|
||||
<tr><td colspan="5" class="text-muted" style="text-align: center; padding: 2rem;">No categories yet. Create one above.</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($categories as $cat): ?>
|
||||
<tr>
|
||||
<td><strong><?= htmlspecialchars($cat['name']) ?></strong></td>
|
||||
<td class="text-muted"><?= htmlspecialchars($cat['slug']) ?></td>
|
||||
<td>
|
||||
<?php if ($cat['product_count'] > 0): ?>
|
||||
<a href="/admin/products.php?category=<?= urlencode($cat['slug']) ?>">
|
||||
<?= $cat['product_count'] ?> products
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<span class="text-muted">0 products</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if ($cat['is_active']): ?>
|
||||
<span class="badge badge-success">Active</span>
|
||||
<?php else: ?>
|
||||
<span class="badge badge-error">Hidden</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-secondary" onclick='openCategoryModal(<?= json_encode($cat) ?>)'>
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
<form method="POST" style="display: inline;">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="category_id" value="<?= $cat['category_id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-danger" data-confirm="Delete this category? Products won't be deleted.">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($uncategorizedCount > 0): ?>
|
||||
<tr style="background: var(--admin-bg);">
|
||||
<td><em>Uncategorized</em></td>
|
||||
<td class="text-muted">-</td>
|
||||
<td>
|
||||
<a href="/admin/products.php?category=uncategorized"><?= $uncategorizedCount ?> products</a>
|
||||
</td>
|
||||
<td><span class="badge badge-warning">Default</span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Category Modal -->
|
||||
<div class="modal-overlay" id="categoryModal">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" id="categoryModalTitle">Add Category</h3>
|
||||
<button type="button" class="modal-close" onclick="Modal.close('categoryModal')">×</button>
|
||||
</div>
|
||||
<form method="POST">
|
||||
<div class="modal-body">
|
||||
<input type="hidden" name="action" id="categoryAction" value="create">
|
||||
<input type="hidden" name="category_id" id="categoryId">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Category Name *</label>
|
||||
<input type="text" name="name" id="categoryName" class="form-input" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Slug</label>
|
||||
<input type="text" name="slug" id="categorySlug" class="form-input" placeholder="auto-generated if empty">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Description</label>
|
||||
<textarea name="description" id="categoryDesc" class="form-textarea" rows="2"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-0">
|
||||
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
||||
<input type="checkbox" name="is_active" id="categoryActive" checked>
|
||||
Active (visible on store)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" onclick="Modal.close('categoryModal')">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary" id="categorySubmitBtn">Add Category</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function openCategoryModal(category = null) {
|
||||
const isEdit = !!category;
|
||||
|
||||
document.getElementById('categoryModalTitle').textContent = isEdit ? 'Edit Category' : 'Add Category';
|
||||
document.getElementById('categorySubmitBtn').textContent = isEdit ? 'Update Category' : 'Add Category';
|
||||
document.getElementById('categoryAction').value = isEdit ? 'update' : 'create';
|
||||
document.getElementById('categoryId').value = isEdit ? category.category_id : '';
|
||||
document.getElementById('categoryName').value = isEdit ? category.name : '';
|
||||
document.getElementById('categorySlug').value = isEdit ? category.slug : '';
|
||||
document.getElementById('categoryDesc').value = isEdit ? (category.description || '') : '';
|
||||
document.getElementById('categoryActive').checked = isEdit ? category.is_active : true;
|
||||
|
||||
Modal.open('categoryModal');
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||
Reference in New Issue
Block a user