mirror of
https://github.com/myronblair/tomsjavajive
synced 2026-06-30 17:50:32 -05:00
261 lines
12 KiB
PHP
261 lines
12 KiB
PHP
<?php
|
|
ob_start();
|
|
/**
|
|
* Tom's Java Jive - Admin Coupons
|
|
*/
|
|
|
|
$pageTitle = 'Coupons';
|
|
require_once __DIR__ . '/includes/header.php';
|
|
|
|
// Handle actions
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$action = $_POST['action'] ?? '';
|
|
|
|
if ($action === 'create' || $action === 'update') {
|
|
$couponId = $_POST['coupon_id'] ?? '';
|
|
$code = strtoupper(trim($_POST['code'] ?? ''));
|
|
$discountType = $_POST['discount_type'] ?? 'percentage';
|
|
$discountValue = floatval($_POST['discount_value'] ?? 0);
|
|
$minOrderAmount = floatval($_POST['min_order_amount'] ?? 0);
|
|
$maxUses = intval($_POST['max_uses'] ?? 0);
|
|
$expiresAt = $_POST['expires_at'] ?: null;
|
|
$isActive = isset($_POST['is_active']) ? 1 : 0;
|
|
|
|
if (empty($code) || $discountValue <= 0) {
|
|
setFlash('error', 'Code and discount value are required');
|
|
} else {
|
|
$data = [
|
|
'code' => $code,
|
|
'discount_type' => $discountType,
|
|
'discount_value' => $discountValue,
|
|
'min_order_amount' => $minOrderAmount ?: null,
|
|
'max_uses' => $maxUses ?: null,
|
|
'expires_at' => $expiresAt,
|
|
'is_active' => $isActive
|
|
];
|
|
|
|
if ($action === 'update' && $couponId) {
|
|
db()->update('coupons', $data, 'coupon_id = :id', ['id' => $couponId]);
|
|
setFlash('success', 'Coupon updated');
|
|
} else {
|
|
// Check for duplicate code
|
|
$existing = db()->fetch("SELECT id FROM coupons WHERE code = :code", ['code' => $code]);
|
|
if ($existing) {
|
|
setFlash('error', 'Coupon code already exists');
|
|
} else {
|
|
$data['coupon_id'] = generateId('coup_');
|
|
$data['times_used'] = 0;
|
|
db()->insert('coupons', $data);
|
|
setFlash('success', 'Coupon created');
|
|
}
|
|
}
|
|
}
|
|
|
|
header('Location: /admin/coupons.php');
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'delete' && !empty($_POST['coupon_id'])) {
|
|
db()->delete('coupons', 'coupon_id = :id', ['id' => $_POST['coupon_id']]);
|
|
setFlash('success', 'Coupon deleted');
|
|
header('Location: /admin/coupons.php');
|
|
exit;
|
|
}
|
|
|
|
if ($action === 'toggle' && !empty($_POST['coupon_id'])) {
|
|
$coupon = db()->fetch("SELECT is_active FROM coupons WHERE coupon_id = :id", ['id' => $_POST['coupon_id']]);
|
|
if ($coupon) {
|
|
db()->update('coupons', ['is_active' => !$coupon['is_active']], 'coupon_id = :id', ['id' => $_POST['coupon_id']]);
|
|
setFlash('success', 'Coupon status updated');
|
|
}
|
|
header('Location: /admin/coupons.php');
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Get coupons
|
|
$coupons = db()->fetchAll("SELECT * FROM coupons ORDER BY created_at DESC");
|
|
?>
|
|
|
|
<div class="page-header">
|
|
<h1 class="page-title">Coupons & Discounts</h1>
|
|
<button class="btn btn-primary" onclick="openCouponModal()">
|
|
<i class="fas fa-plus"></i> Create Coupon
|
|
</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>Code</th>
|
|
<th>Discount</th>
|
|
<th>Min Order</th>
|
|
<th>Usage</th>
|
|
<th>Expires</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (empty($coupons)): ?>
|
|
<tr><td colspan="7" class="text-muted" style="text-align: center; padding: 2rem;">No coupons created yet</td></tr>
|
|
<?php else: ?>
|
|
<?php foreach ($coupons as $coupon):
|
|
$isExpired = $coupon['expires_at'] && strtotime($coupon['expires_at']) < time();
|
|
$isMaxed = $coupon['max_uses'] && $coupon['times_used'] >= $coupon['max_uses'];
|
|
?>
|
|
<tr>
|
|
<td><strong style="font-family: monospace;"><?= htmlspecialchars($coupon['code']) ?></strong></td>
|
|
<td>
|
|
<?php if ($coupon['discount_type'] === 'percentage'): ?>
|
|
<?= $coupon['discount_value'] ?>% off
|
|
<?php else: ?>
|
|
<?= formatCurrency($coupon['discount_value']) ?> off
|
|
<?php endif; ?>
|
|
</td>
|
|
<td><?= $coupon['min_order_amount'] ? formatCurrency($coupon['min_order_amount']) : '-' ?></td>
|
|
<td>
|
|
<?= $coupon['times_used'] ?><?= $coupon['max_uses'] ? '/' . $coupon['max_uses'] : '' ?>
|
|
</td>
|
|
<td>
|
|
<?php if ($coupon['expires_at']): ?>
|
|
<?php if ($isExpired): ?>
|
|
<span class="text-error"><?= formatDate($coupon['expires_at']) ?></span>
|
|
<?php else: ?>
|
|
<?= formatDate($coupon['expires_at']) ?>
|
|
<?php endif; ?>
|
|
<?php else: ?>
|
|
<span class="text-muted">Never</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<?php if (!$coupon['is_active']): ?>
|
|
<span class="badge badge-error">Disabled</span>
|
|
<?php elseif ($isExpired): ?>
|
|
<span class="badge badge-warning">Expired</span>
|
|
<?php elseif ($isMaxed): ?>
|
|
<span class="badge badge-warning">Maxed Out</span>
|
|
<?php else: ?>
|
|
<span class="badge badge-success">Active</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<button class="btn btn-sm btn-secondary" onclick='openCouponModal(<?= json_encode($coupon) ?>)'>
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<form method="POST" style="display: inline;">
|
|
<input type="hidden" name="action" value="toggle">
|
|
<input type="hidden" name="coupon_id" value="<?= $coupon['coupon_id'] ?>">
|
|
<button type="submit" class="btn btn-sm btn-secondary">
|
|
<i class="fas fa-<?= $coupon['is_active'] ? 'ban' : 'check' ?>"></i>
|
|
</button>
|
|
</form>
|
|
<form method="POST" style="display: inline;">
|
|
<input type="hidden" name="action" value="delete">
|
|
<input type="hidden" name="coupon_id" value="<?= $coupon['coupon_id'] ?>">
|
|
<button type="submit" class="btn btn-sm btn-danger" data-confirm="Delete this coupon?">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Coupon Modal -->
|
|
<div class="modal-overlay" id="couponModal">
|
|
<div class="modal">
|
|
<div class="modal-header">
|
|
<h3 class="modal-title" id="couponModalTitle">Create Coupon</h3>
|
|
<button type="button" class="modal-close" onclick="Modal.close('couponModal')">×</button>
|
|
</div>
|
|
<form method="POST" id="couponForm">
|
|
<div class="modal-body">
|
|
<input type="hidden" name="action" id="couponAction" value="create">
|
|
<input type="hidden" name="coupon_id" id="couponId">
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Coupon Code *</label>
|
|
<input type="text" name="code" id="couponCode" class="form-input" required style="text-transform: uppercase;">
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label class="form-label">Discount Type</label>
|
|
<select name="discount_type" id="couponType" class="form-select">
|
|
<option value="percentage">Percentage (%)</option>
|
|
<option value="fixed">Fixed Amount ($)</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">Discount Value *</label>
|
|
<input type="number" name="discount_value" id="couponValue" class="form-input" step="0.01" min="0" required>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label class="form-label">Min Order Amount</label>
|
|
<input type="number" name="min_order_amount" id="couponMinOrder" class="form-input" step="0.01" min="0">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">Max Uses (0 = unlimited)</label>
|
|
<input type="number" name="max_uses" id="couponMaxUses" class="form-input" min="0">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">Expiration Date</label>
|
|
<input type="date" name="expires_at" id="couponExpires" class="form-input">
|
|
</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="couponActive" value="1" checked>
|
|
Active
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" onclick="Modal.close('couponModal')">Cancel</button>
|
|
<button type="submit" class="btn btn-primary" id="couponSubmitBtn">Create Coupon</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function openCouponModal(coupon = null) {
|
|
const isEdit = !!coupon;
|
|
|
|
document.getElementById('couponModalTitle').textContent = isEdit ? 'Edit Coupon' : 'Create Coupon';
|
|
document.getElementById('couponSubmitBtn').textContent = isEdit ? 'Update Coupon' : 'Create Coupon';
|
|
document.getElementById('couponAction').value = isEdit ? 'update' : 'create';
|
|
document.getElementById('couponId').value = isEdit ? coupon.coupon_id : '';
|
|
document.getElementById('couponCode').value = isEdit ? coupon.code : '';
|
|
document.getElementById('couponType').value = isEdit ? coupon.discount_type : 'percentage';
|
|
document.getElementById('couponValue').value = isEdit ? coupon.discount_value : '';
|
|
document.getElementById('couponMinOrder').value = isEdit && coupon.min_order_amount ? coupon.min_order_amount : '';
|
|
document.getElementById('couponMaxUses').value = isEdit && coupon.max_uses ? coupon.max_uses : '';
|
|
document.getElementById('couponExpires').value = isEdit && coupon.expires_at ? coupon.expires_at.split(' ')[0] : '';
|
|
document.getElementById('couponActive').checked = isEdit ? coupon.is_active : true;
|
|
|
|
Modal.open('couponModal');
|
|
}
|
|
</script>
|
|
|
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|