38682-vm/admin/product_variants.php
2026-02-25 18:22:13 +00:00

295 lines
13 KiB
PHP

<?php
require_once __DIR__ . '/../db/config.php';
require_once __DIR__ . '/../includes/functions.php';
$pdo = db();
if (!isset($_GET['product_id'])) {
header("Location: products.php");
exit;
}
$product_id = $_GET['product_id'];
// Fetch Product Details
$stmt = $pdo->prepare("SELECT * FROM products WHERE id = ?");
$stmt->execute([$product_id]);
$product = $stmt->fetch();
if (!$product) {
header("Location: products.php");
exit;
}
$message = '';
// Handle Add Variant
if (isset($_POST['action']) && $_POST['action'] === 'add_variant') {
$name = $_POST['name'];
$name_ar = $_POST['name_ar'] ?? '';
$price_adj = $_POST['price_adjustment'];
try {
$stmt = $pdo->prepare("INSERT INTO product_variants (product_id, name, name_ar, price_adjustment) VALUES (?, ?, ?, ?)");
$stmt->execute([$product_id, $name, $name_ar, $price_adj]);
header("Location: product_variants.php?product_id=$product_id&added=1");
exit;
} catch (PDOException $e) {
$message = '<div class="alert alert-danger">Error adding variant: ' . $e->getMessage() . '</div>';
}
}
// Handle Edit Variant
if (isset($_POST['action']) && $_POST['action'] === 'edit_variant') {
$id = $_POST['variant_id'];
$name = $_POST['name'];
$name_ar = $_POST['name_ar'] ?? '';
$price_adj = $_POST['price_adjustment'];
try {
$stmt = $pdo->prepare("UPDATE product_variants SET name = ?, name_ar = ?, price_adjustment = ? WHERE id = ?");
$stmt->execute([$name, $name_ar, $price_adj, $id]);
header("Location: product_variants.php?product_id=$product_id&updated=1");
exit;
} catch (PDOException $e) {
$message = '<div class="alert alert-danger">Error updating variant: ' . $e->getMessage() . '</div>';
}
}
// Handle Delete (Soft Delete)
if (isset($_GET['delete'])) {
try {
$id = (int)$_GET['delete'];
$pdo->prepare("UPDATE product_variants SET is_deleted = 1 WHERE id = ?")->execute([$id]);
header("Location: product_variants.php?product_id=$product_id&deleted=1");
exit;
} catch (PDOException $e) {
$message = '<div class="alert alert-danger">Error deleting variant: ' . $e->getMessage() . '</div>';
}
}
if (isset($_GET['added'])) {
$message = '<div class="alert alert-success">Variant added successfully!</div>';
} elseif (isset($_GET['updated'])) {
$message = '<div class="alert alert-success">Variant updated successfully!</div>';
} elseif (isset($_GET['deleted'])) {
$message = '<div class="alert alert-success">Variant removed successfully!</div>';
}
$query = "SELECT * FROM product_variants WHERE product_id = ? AND is_deleted = 0 ORDER BY price_adjustment ASC";
$variants_pagination = paginate_query($pdo, $query, [$product_id]);
$variants = $variants_pagination['data'];
include 'includes/header.php';
$effective_base_price = get_product_price($product);
?>
<div class="mb-4">
<a href="products.php" class="text-decoration-none text-muted mb-2 d-inline-block"><i class="bi bi-arrow-left"></i> Back to Products</a>
<div class="d-flex justify-content-between align-items-center">
<div>
<h2 class="fw-bold mb-0">Variants: <?= htmlspecialchars($product['name']) ?></h2>
<p class="text-muted mb-0">Manage sizes, extras, or options.</p>
</div>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addVariantModal">
<i class="bi bi-plus-lg"></i> Add Variant
</button>
</div>
</div>
<?= $message ?>
<div class="card border-0 shadow-sm">
<div class="card-body p-0">
<!-- Pagination Controls -->
<div class="p-3 border-bottom bg-light">
<?php render_pagination_controls($variants_pagination, ['product_id' => $product_id]); ?>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="bg-light">
<tr>
<th class="ps-4">Variant Name</th>
<th>Arabic Name</th>
<th>Price Adjustment</th>
<th>Final Price (Est.)</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($variants as $variant): ?>
<tr>
<td class="ps-4 fw-medium"><?= htmlspecialchars($variant['name']) ?></td>
<td><div class="text-primary small fw-semibold" dir="rtl"><?= htmlspecialchars($variant['name_ar'] ?? '-') ?></div></td>
<td>
<?php if ($variant['price_adjustment'] > 0): ?>
<span class="text-danger">+ <?= format_currency($variant['price_adjustment']) ?></span>
<?php elseif ($variant['price_adjustment'] < 0): ?>
<span class="text-success">- <?= format_currency(abs((float)$variant['price_adjustment'])) ?></span>
<?php else: ?>
<span class="text-muted">No change</span>
<?php endif; ?>
</td>
<td>
<div class="fw-bold"><?= format_currency($effective_base_price + $variant['price_adjustment']) ?></div>
<?php if ($effective_base_price < $product['price']): ?>
<small class="text-muted text-decoration-line-through"><?= format_currency($product['price'] + $variant['price_adjustment']) ?></small>
<?php endif; ?>
</td>
<td>
<button class="btn btn-sm btn-outline-primary me-1"
data-bs-toggle="modal"
data-bs-target="#editVariantModal"
data-id="<?= $variant['id'] ?>"
data-name="<?= htmlspecialchars($variant['name']) ?>"
data-name-ar="<?= htmlspecialchars($variant['name_ar'] ?? '') ?>"
data-price="<?= $variant['price_adjustment'] ?>">
<i class="bi bi-pencil"></i>
</button>
<a href="?product_id=<?= $product_id ?>&delete=<?= $variant['id'] ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Delete this variant?')"><i class="bi bi-trash"></i></a>
</td>
</tr>
<?php endforeach; ?>
<?php if (empty($variants)): ?>
<tr>
<td colspan="5" class="text-center py-5 text-muted">No variants defined (e.g., Small, Large, Spicy).</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<!-- Bottom Pagination -->
<div class="p-3 border-top bg-light">
<?php render_pagination_controls($variants_pagination, ['product_id' => $product_id]); ?>
</div>
</div>
</div>
<!-- Add Variant Modal -->
<div class="modal fade" id="addVariantModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Variant</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="POST">
<div class="modal-body">
<input type="hidden" name="action" value="add_variant">
<div class="mb-3">
<label class="form-label">Variant Name (EN)</label>
<div class="input-group">
<input type="text" name="name" id="add_name" class="form-control" required>
<button class="btn btn-outline-secondary" type="button" onclick="translateField('add_name', 'add_name_ar')">
<i class="bi bi-translate"></i>
</button>
</div>
</div>
<div class="mb-3">
<label class="form-label">Variant Name (AR)</label>
<input type="text" name="name_ar" id="add_name_ar" class="form-control text-end" dir="rtl">
</div>
<div class="mb-3">
<label class="form-label">Price Adjustment (+/-)</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" step="0.01" name="price_adjustment" class="form-control" value="0.00" required>
</div>
<div class="form-text">Enter positive value for extra cost, negative for discount.</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save Variant</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Variant Modal -->
<div class="modal fade" id="editVariantModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Edit Variant</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="POST">
<div class="modal-body">
<input type="hidden" name="action" value="edit_variant">
<input type="hidden" name="variant_id" id="edit_variant_id">
<div class="mb-3">
<label class="form-label">Variant Name (EN)</label>
<div class="input-group">
<input type="text" name="name" id="edit_variant_name" class="form-control" required>
<button class="btn btn-outline-secondary" type="button" onclick="translateField('edit_variant_name', 'edit_variant_name_ar')">
<i class="bi bi-translate"></i>
</button>
</div>
</div>
<div class="mb-3">
<label class="form-label">Variant Name (AR)</label>
<input type="text" name="name_ar" id="edit_variant_name_ar" class="form-control text-end" dir="rtl">
</div>
<div class="mb-3">
<label class="form-label">Price Adjustment (+/-)</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" step="0.01" name="price_adjustment" id="edit_variant_price" class="form-control" required>
</div>
<div class="form-text">Enter positive value for extra cost, negative for discount.</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Update Variant</button>
</div>
</form>
</div>
</div>
</div>
<script>
var editVariantModal = document.getElementById('editVariantModal');
if (editVariantModal) {
editVariantModal.addEventListener('show.bs.modal', function (event) {
var button = event.relatedTarget;
var id = button.getAttribute('data-id');
var name = button.getAttribute('data-name');
var nameAr = button.getAttribute('data-name-ar');
var price = button.getAttribute('data-price');
var modalIdInput = editVariantModal.querySelector('#edit_variant_id');
var modalNameInput = editVariantModal.querySelector('#edit_variant_name');
var modalNameArInput = editVariantModal.querySelector('#edit_variant_name_ar');
var modalPriceInput = editVariantModal.querySelector('#edit_variant_price');
modalIdInput.value = id;
modalNameInput.value = name;
modalNameArInput.value = nameAr;
modalPriceInput.value = price;
});
}
async function translateField(sourceId, targetId) {
const text = document.getElementById(sourceId).value;
if (!text) return;
try {
const response = await fetch('../api/translate.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: text, target_lang: 'Arabic' })
});
const data = await response.json();
if (data.success) {
document.getElementById(targetId).value = data.translated_text;
}
} catch (e) {
console.error(e);
}
}
</script>
<?php include 'includes/footer.php'; ?>