38682-vm/admin/loyalty.php
2026-02-25 18:31:31 +00:00

212 lines
9.6 KiB
PHP

<?php
require_once __DIR__ . "/../includes/functions.php";
require_permission("loyalty_view");
require_once __DIR__ . '/../db/config.php';
$pdo = db();
$message = '';
// Handle Settings Update
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_settings'])) {
if (!has_permission('loyalty_add')) {
$message = '<div class="alert alert-danger">Access Denied: You do not have permission to update loyalty settings.</div>';
} else {
$points_per_order = intval($_POST['points_per_order']);
$points_for_free_meal = intval($_POST['points_for_free_meal']);
$is_enabled = isset($_POST['is_enabled']) ? 1 : 0;
$stmt = $pdo->prepare("UPDATE loyalty_settings SET points_per_order = ?, points_for_free_meal = ?, is_enabled = ? WHERE id = 1");
$stmt->execute([$points_per_order, $points_for_free_meal, $is_enabled]);
$message = '<div class="alert alert-success">Loyalty settings updated successfully!</div>';
}
}
// Fetch Settings
$stmt = $pdo->query("SELECT * FROM loyalty_settings WHERE id = 1");
$settings = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$settings) {
// Default fallback if migration failed or empty
$settings = ['points_per_order' => 10, 'points_for_free_meal' => 70, 'is_enabled' => 1];
}
// Fetch Customers with Points
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$limit = 20;
$offset = ($page - 1) * $limit;
$count_stmt = $pdo->query("SELECT COUNT(*) FROM customers WHERE points > 0");
$total_customers = $count_stmt->fetchColumn();
$total_pages = ceil($total_customers / $limit);
$query = "SELECT * FROM customers WHERE points > 0 ORDER BY points DESC LIMIT $limit OFFSET $offset";
$stmt = $pdo->query($query);
$customers = $stmt->fetchAll(PDO::FETCH_ASSOC);
include 'includes/header.php';
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="d-flex align-items-center gap-3">
<h2 class="fw-bold mb-0">Loyalty Program</h2>
<?php if ($settings['is_enabled']): ?>
<span class="badge bg-success-subtle text-success border border-success-subtle px-3">Active</span>
<?php else: ?>
<span class="badge bg-danger-subtle text-danger border border-danger-subtle px-3">Disabled</span>
<?php endif; ?>
</div>
<?php if (has_permission('loyalty_add')): ?>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#settingsModal">
<i class="bi bi-gear-fill me-2"></i> Configure Settings
</button>
<?php endif; ?>
</div>
<?= $message ?>
<div class="row mb-4">
<div class="col-md-6 col-lg-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-body">
<h6 class="card-subtitle mb-2 text-muted text-uppercase small">Current Configuration</h6>
<div class="d-flex justify-content-between align-items-center mt-3">
<div>
<span class="d-block text-muted small">Points per Loyalty Product</span>
<span class="fs-4 fw-bold text-primary"><?= $settings['points_per_order'] ?> pts</span>
</div>
<div class="border-start ps-3">
<span class="d-block text-muted small">Free Product Threshold</span>
<span class="fs-4 fw-bold text-success"><?= $settings['points_for_free_meal'] ?> pts</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card border-0 shadow-sm">
<div class="card-header bg-white py-3">
<h5 class="mb-0">Loyalty Members</h5>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="bg-light">
<tr>
<th class="ps-4">Customer</th>
<th>Contact</th>
<th>Points Balance</th>
<th>Status</th>
<th>Joined</th>
</tr>
</thead>
<tbody>
<?php foreach ($customers as $customer): ?>
<?php
$progress = min(100, ($customer['points'] / $settings['points_for_free_meal']) * 100);
$eligible = $customer['points'] >= $settings['points_for_free_meal'];
?>
<tr>
<td class="ps-4">
<div class="fw-bold"><?= htmlspecialchars($customer['name']) ?></div>
</td>
<td>
<div class="small"><?= htmlspecialchars($customer['phone'] ?? '-') ?></div>
<div class="small text-muted"><?= htmlspecialchars($customer['email'] ?? '') ?></div>
</td>
<td>
<div class="d-flex align-items-center">
<span class="badge bg-warning text-dark border border-warning me-2" style="width: 60px;">
<?= $customer['points'] ?> pts
</span>
<div class="progress flex-grow-1" style="height: 6px; max-width: 100px;">
<div class="progress-bar bg-success" role="progressbar" style="width: <?= $progress ?>%"></div>
</div>
</div>
</td>
<td>
<?php if ($eligible): ?>
<span class="badge bg-success-subtle text-success border border-success-subtle">
<i class="bi bi-gift-fill me-1"></i> Eligible for Free Product
</span>
<?php else: ?>
<span class="text-muted small">
<?= $settings['points_for_free_meal'] - $customer['points'] ?> pts to go
</span>
<?php endif; ?>
</td>
<td class="text-muted small"><?= date('M d, Y', strtotime($customer['created_at'])) ?></td>
</tr>
<?php endforeach; ?>
<?php if (empty($customers)): ?>
<tr>
<td colspan="5" class="text-center py-5 text-muted">No active loyalty members found.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<!-- Pagination -->
<?php if ($total_pages > 1): ?>
<div class="card-footer bg-white py-3">
<nav>
<ul class="pagination justify-content-center mb-0">
<li class="page-item <?= $page <= 1 ? 'disabled' : '' ?>">
<a class="page-link" href="?page=<?= $page - 1 ?>">Previous</a>
</li>
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
<li class="page-item <?= $page == $i ? 'active' : '' ?>">
<a class="page-link" href="?page=<?= $i ?>"><?= $i ?></a>
</li>
<?php endfor; ?>
<li class="page-item <?= $page >= $total_pages ? 'disabled' : '' ?>">
<a class="page-link" href="?page=<?= $page + 1 ?>">Next</a>
</li>
</ul>
</nav>
</div>
<?php endif; ?>
</div>
<!-- Settings Modal -->
<?php if (has_permission('loyalty_add')): ?>
<div class="modal fade" id="settingsModal" tabindex="-1">
<div class="modal-dialog">
<form method="POST" class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Configure Loyalty Program</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<input type="hidden" name="update_settings" value="1">
<div class="mb-4">
<div class="form-check form-switch p-0 d-flex justify-content-between align-items-center">
<label class="form-check-label fw-bold" for="is_enabled">Enable Loyalty Program</label>
<input class="form-check-input ms-0" type="checkbox" id="is_enabled" name="is_enabled" <?= $settings['is_enabled'] ? 'checked' : '' ?> style="width: 3em; height: 1.5em; cursor: pointer;">
</div>
<div class="form-text mt-1">When disabled, loyalty features will be hidden from the POS.</div>
</div>
<div class="mb-3">
<label class="form-label">Points per Loyalty Product</label>
<input type="number" name="points_per_order" class="form-control" value="<?= $settings['points_per_order'] ?>" min="0" required>
<div class="form-text">Points awarded for every loyalty-participating product in the order.</div>
</div>
<div class="mb-3">
<label class="form-label">Points for Free Product</label>
<input type="number" name="points_for_free_meal" class="form-control" value="<?= $settings['points_for_free_meal'] ?>" min="0" required>
<div class="form-text">Threshold points required to redeem a free product.</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
<?php endif; ?>
<?php include 'includes/footer.php'; ?>