Files
2026-05-22 12:52:44 +00:00

453 lines
15 KiB
PHP

<?php
/**
* Tom's Java Jive - Customer Loyalty Rewards Page
*/
$pageTitle = "My Rewards - Tom's Java Jive";
require_once __DIR__ . '/../includes/functions.php';
require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/loyalty.php';
CustomerAuth::require();
$customer = CustomerAuth::getFullUser();
$currentPage = 'rewards';
// Get loyalty status
$loyaltyStatus = loyalty()->getCustomerTier($customer['customer_id']);
$tiers = loyalty()->getTiers();
$conversion = loyalty()->getConversionInfo();
$history = loyalty()->getHistory($customer['customer_id'], 20);
// Handle redemption
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['redeem_points'])) {
$points = intval($_POST['points'] ?? 0);
if ($points >= 100) {
$result = loyalty()->redeemPoints($customer['customer_id'], $points);
if ($result['success']) {
setFlash('success', "Successfully redeemed {$points} points for " . formatCurrency($result['credit_value']) . " wallet credit!");
} else {
setFlash('error', $result['error']);
}
} else {
setFlash('error', 'Minimum 100 points required for redemption');
}
redirect('/account/rewards.php');
}
require_once __DIR__ . '/../includes/header.php';
require_once __DIR__ . '/includes/sidebar.php';
?>
<style>
.tier-card {
background: linear-gradient(135deg, <?= $loyaltyStatus['info']['color'] ?>22, <?= $loyaltyStatus['info']['color'] ?>44);
border: 2px solid <?= $loyaltyStatus['info']['color'] ?>;
border-radius: var(--radius-lg);
padding: 2rem;
margin-bottom: 2rem;
position: relative;
overflow: hidden;
}
.tier-card::before {
content: '';
position: absolute;
top: -50%;
right: -20%;
width: 300px;
height: 300px;
background: <?= $loyaltyStatus['info']['color'] ?>;
opacity: 0.1;
border-radius: 50%;
}
.tier-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: <?= $loyaltyStatus['info']['color'] ?>;
color: <?= in_array($loyaltyStatus['tier'], ['silver', 'platinum']) ? '#333' : 'white' ?>;
padding: 0.5rem 1rem;
border-radius: 20px;
font-weight: 600;
font-size: 0.875rem;
margin-bottom: 1rem;
}
.points-display {
display: flex;
gap: 3rem;
margin: 1.5rem 0;
}
.points-item {
text-align: center;
}
.points-value {
font-size: 2.5rem;
font-weight: 700;
color: var(--color-text);
}
.points-label {
color: var(--color-text-muted);
font-size: 0.875rem;
}
.progress-to-next {
background: var(--color-surface);
border-radius: var(--radius-lg);
padding: 1.5rem;
margin-top: 1rem;
}
.progress-bar-wrapper {
background: var(--color-border);
border-radius: 10px;
height: 12px;
overflow: hidden;
margin: 0.75rem 0;
}
.progress-bar-fill {
height: 100%;
background: linear-gradient(90deg, <?= $loyaltyStatus['info']['color'] ?>, <?= $loyaltyStatus['next_tier_info']['color'] ?? $loyaltyStatus['info']['color'] ?>);
border-radius: 10px;
transition: width 0.5s ease;
}
.tier-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
margin: 2rem 0;
}
.tier-item {
background: var(--color-surface);
border-radius: var(--radius-lg);
padding: 1.25rem;
text-align: center;
border: 2px solid transparent;
transition: all 0.2s;
}
.tier-item.current {
border-color: var(--color-primary);
box-shadow: 0 4px 12px rgba(255, 94, 26, 0.2);
}
.tier-item-icon {
width: 50px;
height: 50px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 0.75rem;
font-size: 1.25rem;
}
.tier-item h4 {
margin: 0 0 0.25rem;
font-size: 0.9rem;
}
.tier-item .points {
font-size: 0.75rem;
color: var(--color-text-muted);
}
.redeem-card {
background: var(--color-surface);
border-radius: var(--radius-lg);
padding: 1.5rem;
margin-bottom: 1.5rem;
}
.redeem-options {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
margin-top: 1rem;
}
.redeem-option {
background: var(--color-background);
border: 2px solid var(--color-border);
border-radius: var(--radius-md);
padding: 1rem;
text-align: center;
cursor: pointer;
transition: all 0.2s;
}
.redeem-option:hover {
border-color: var(--color-primary);
}
.redeem-option.selected {
border-color: var(--color-primary);
background: rgba(255, 94, 26, 0.05);
}
.redeem-option .points {
font-size: 1.5rem;
font-weight: 700;
color: var(--color-primary);
}
.redeem-option .value {
color: var(--color-success);
font-weight: 600;
}
@media (max-width: 768px) {
.points-display {
gap: 1.5rem;
}
.tier-grid {
grid-template-columns: repeat(2, 1fr);
}
.redeem-options {
grid-template-columns: 1fr;
}
}
</style>
<div class="account-header">
<h1>My Rewards</h1>
<p class="text-muted">Earn points and unlock exclusive benefits</p>
</div>
<?php if (hasFlash('success')): ?>
<div class="alert alert-success mb-2">
<i class="fas fa-check-circle"></i> <?= getFlash('success') ?>
</div>
<?php endif; ?>
<?php if (hasFlash('error')): ?>
<div class="alert alert-error mb-2">
<i class="fas fa-exclamation-circle"></i> <?= getFlash('error') ?>
</div>
<?php endif; ?>
<!-- Current Tier Card -->
<div class="tier-card">
<div class="tier-badge">
<i class="fas <?= $loyaltyStatus['info']['icon'] ?>"></i>
<?= $loyaltyStatus['info']['name'] ?>
</div>
<div class="points-display">
<div class="points-item">
<div class="points-value"><?= number_format($loyaltyStatus['points']) ?></div>
<div class="points-label">Available Points</div>
</div>
<div class="points-item">
<div class="points-value"><?= formatCurrency($loyaltyStatus['points'] * $conversion['points_value']) ?></div>
<div class="points-label">Points Value</div>
</div>
<div class="points-item">
<div class="points-value"><?= $loyaltyStatus['info']['multiplier'] ?>x</div>
<div class="points-label">Earning Rate</div>
</div>
</div>
<?php if ($loyaltyStatus['next_tier']): ?>
<div class="progress-to-next">
<div style="display: flex; justify-content: space-between; align-items: center;">
<span>Progress to <?= $loyaltyStatus['next_tier_info']['name'] ?></span>
<span style="font-weight: 600;"><?= number_format($loyaltyStatus['points_to_next']) ?> points to go</span>
</div>
<div class="progress-bar-wrapper">
<div class="progress-bar-fill" style="width: <?= $loyaltyStatus['progress_percent'] ?>%;"></div>
</div>
</div>
<?php else: ?>
<div class="progress-to-next" style="text-align: center;">
<i class="fas fa-crown" style="font-size: 2rem; color: <?= $loyaltyStatus['info']['color'] ?>; margin-bottom: 0.5rem;"></i>
<p style="margin: 0; font-weight: 600;">You've reached the highest tier!</p>
<p class="text-muted" style="margin: 0.25rem 0 0;">Enjoy all the exclusive benefits of <?= $loyaltyStatus['info']['name'] ?></p>
</div>
<?php endif; ?>
</div>
<!-- All Tiers -->
<div class="section-card">
<div class="section-card-header">
<h3><i class="fas fa-layer-group"></i> Loyalty Tiers</h3>
</div>
<div class="section-card-body">
<div class="tier-grid">
<?php foreach ($tiers as $key => $tier): ?>
<div class="tier-item <?= $key === $loyaltyStatus['tier'] ? 'current' : '' ?>">
<div class="tier-item-icon" style="background: <?= $tier['color'] ?>22; color: <?= $tier['color'] ?>;">
<i class="fas <?= $tier['icon'] ?>"></i>
</div>
<h4><?= $tier['name'] ?></h4>
<div class="points"><?= number_format($tier['min_points']) ?>+ pts</div>
<div style="margin-top: 0.5rem; font-weight: 600;"><?= $tier['multiplier'] ?>x points</div>
</div>
<?php endforeach; ?>
</div>
<details style="margin-top: 1rem;">
<summary style="cursor: pointer; font-weight: 600; color: var(--color-primary);">View All Benefits</summary>
<div style="margin-top: 1rem;">
<?php foreach ($tiers as $key => $tier): ?>
<div style="margin-bottom: 1rem; padding: 1rem; background: var(--color-background); border-radius: var(--radius-md);">
<h4 style="margin: 0 0 0.5rem; display: flex; align-items: center; gap: 0.5rem;">
<i class="fas <?= $tier['icon'] ?>" style="color: <?= $tier['color'] ?>;"></i>
<?= $tier['name'] ?>
</h4>
<ul style="margin: 0; padding-left: 1.5rem; color: var(--color-text-muted);">
<?php foreach ($tier['benefits'] as $benefit): ?>
<li><?= htmlspecialchars($benefit) ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endforeach; ?>
</div>
</details>
</div>
</div>
<!-- Redeem Points -->
<div class="redeem-card">
<h3 style="margin: 0 0 0.5rem;"><i class="fas fa-gift"></i> Redeem Points</h3>
<p class="text-muted" style="margin: 0 0 1rem;">Convert your points to wallet credit. <?= $conversion['points_for_one_dollar'] ?> points = $1</p>
<?php if ($loyaltyStatus['points'] >= 100): ?>
<form method="POST">
<div class="redeem-options">
<?php
$redeemOptions = [100, 500, 1000];
foreach ($redeemOptions as $pts):
if ($pts <= $loyaltyStatus['points']):
?>
<label class="redeem-option">
<input type="radio" name="points" value="<?= $pts ?>" style="display: none;">
<div class="points"><?= number_format($pts) ?></div>
<div>points</div>
<div class="value" style="margin-top: 0.5rem;"><?= formatCurrency($pts * $conversion['points_value']) ?> credit</div>
</label>
<?php
endif;
endforeach;
?>
</div>
<div style="margin-top: 1rem; display: flex; gap: 1rem; align-items: center;">
<div class="form-group" style="margin: 0; flex: 1;">
<input type="number" name="custom_points" class="form-input" placeholder="Or enter custom amount" min="100" max="<?= $loyaltyStatus['points'] ?>" step="50">
</div>
<button type="submit" name="redeem_points" class="btn btn-primary">
<i class="fas fa-exchange-alt"></i> Redeem
</button>
</div>
</form>
<?php else: ?>
<p class="text-muted" style="text-align: center; padding: 2rem;">
You need at least 100 points to redeem. Keep shopping to earn more!
</p>
<?php endif; ?>
</div>
<!-- Points History -->
<div class="section-card">
<div class="section-card-header">
<h3><i class="fas fa-history"></i> Points History</h3>
</div>
<div class="section-card-body" style="padding: 0;">
<?php if (empty($history)): ?>
<p class="text-muted text-center" style="padding: 2rem;">No points activity yet</p>
<?php else: ?>
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Activity</th>
<th style="text-align: right;">Points</th>
</tr>
</thead>
<tbody>
<?php foreach ($history as $tx): ?>
<tr>
<td><?= formatDate($tx['created_at']) ?></td>
<td>
<?php
$icon = match($tx['type']) {
'earn' => 'fa-plus-circle',
'redeem' => 'fa-gift',
'tier_upgrade' => 'fa-arrow-up',
'birthday_bonus' => 'fa-birthday-cake',
'referral_bonus', 'referral_welcome' => 'fa-user-plus',
default => 'fa-circle'
};
?>
<i class="fas <?= $icon ?>" style="color: <?= $tx['points'] > 0 ? 'var(--color-success)' : 'var(--color-primary)' ?>;"></i>
<?= htmlspecialchars($tx['description'] ?? ucfirst(str_replace('_', ' ', $tx['type']))) ?>
</td>
<td style="text-align: right; font-weight: 600; color: <?= $tx['points'] > 0 ? 'var(--color-success)' : 'var(--color-text)' ?>;">
<?= $tx['points'] > 0 ? '+' : '' ?><?= number_format($tx['points']) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>
</div>
<script>
// Handle redeem option selection
document.querySelectorAll('.redeem-option').forEach(opt => {
opt.addEventListener('click', function() {
document.querySelectorAll('.redeem-option').forEach(o => o.classList.remove('selected'));
this.classList.add('selected');
this.querySelector('input[type="radio"]').checked = true;
document.querySelector('input[name="custom_points"]').value = '';
});
});
// Custom points input clears radio selection
document.querySelector('input[name="custom_points"]')?.addEventListener('input', function() {
if (this.value) {
document.querySelectorAll('.redeem-option').forEach(o => {
o.classList.remove('selected');
o.querySelector('input[type="radio"]').checked = false;
});
}
});
// Form submission - use custom or selected
document.querySelector('form')?.addEventListener('submit', function(e) {
const customPoints = document.querySelector('input[name="custom_points"]').value;
const selectedRadio = document.querySelector('input[name="points"]:checked');
if (!customPoints && !selectedRadio) {
e.preventDefault();
alert('Please select or enter the number of points to redeem');
return;
}
if (customPoints) {
// Create hidden input with custom points as 'points'
const hidden = document.createElement('input');
hidden.type = 'hidden';
hidden.name = 'points';
hidden.value = customPoints;
this.appendChild(hidden);
}
});
</script>
<?php require_once __DIR__ . '/includes/footer.php'; ?>