288 lines
13 KiB
PHP
288 lines
13 KiB
PHP
{{-- Admin: Manage Subscription Plans --}}
|
|
<div class="card" id="main-card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">Subscription Plans</h3>
|
|
<div class="card-tools">
|
|
<button class="btn btn-sm btn-primary" onclick="SubAdmin_showCreateForm()">
|
|
<i class="fas fa-plus"></i> New Plan
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="sub-admin-plans-loading" class="text-center" style="padding:20px;">
|
|
<i class="fas fa-spinner fa-spin fa-2x"></i>
|
|
</div>
|
|
<table class="table table-bordered table-hover" id="sub-admin-plans-table" style="display:none;">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Price</th>
|
|
<th>Duration</th>
|
|
<th>Expiry Action</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="sub-admin-plans-body"></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Create / Edit Plan Form --}}
|
|
<div class="card" id="sub-admin-plan-form-card" style="display:none;">
|
|
<div class="card-header">
|
|
<h3 class="card-title" id="sub-admin-form-title">New Plan</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
<input type="hidden" id="sub-plan-hashkey">
|
|
<div class="form-group">
|
|
<label>Name</label>
|
|
<input type="text" class="form-control" id="sub-plan-name-field" placeholder="e.g. Monthly Basic">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Description</label>
|
|
<textarea class="form-control" id="sub-plan-desc-field" rows="2" placeholder="Optional description"></textarea>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<div class="form-group">
|
|
<label>Price (₱)</label>
|
|
<input type="number" class="form-control" id="sub-plan-price-field" min="0" step="0.01" placeholder="299.00">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-group">
|
|
<label>Duration (days)</label>
|
|
<input type="number" class="form-control" id="sub-plan-duration-field" min="1" placeholder="30">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="form-group">
|
|
<label>On Expiry</label>
|
|
<select class="form-control" id="sub-plan-expiry-field">
|
|
<option value="warn">Warn user (show notice)</option>
|
|
<option value="restrict">Restrict access</option>
|
|
<option value="auto_deduct">Auto-deduct & renew</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<button class="btn btn-success" onclick="SubAdmin_savePlan()">
|
|
<i class="fas fa-save"></i> Save Plan
|
|
</button>
|
|
<button class="btn btn-secondary ml-2" onclick="SubAdmin_cancelForm()">Cancel</button>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- All User Subscriptions --}}
|
|
<div class="card" id="secondary-card">
|
|
<div class="card-header ui-sortable-handle" style="cursor:move;">
|
|
<h3 class="card-title">All User Subscriptions</h3>
|
|
<div class="card-tools">
|
|
<select class="form-control form-control-sm" id="sub-admin-status-filter" onchange="SubAdmin_loadSubscriptions()">
|
|
<option value="">All Statuses</option>
|
|
<option value="active">Active</option>
|
|
<option value="expired">Expired</option>
|
|
<option value="cancelled">Cancelled</option>
|
|
<option value="pending">Pending</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="sub-admin-subs-loading" class="text-center" style="padding:20px; display:none;">
|
|
<i class="fas fa-spinner fa-spin"></i> Loading...
|
|
</div>
|
|
<table class="table table-sm table-striped" id="sub-admin-subs-table" style="display:none;">
|
|
<thead>
|
|
<tr>
|
|
<th>User</th>
|
|
<th>Mobile</th>
|
|
<th>Plan</th>
|
|
<th>Status</th>
|
|
<th>Starts</th>
|
|
<th>Expires</th>
|
|
<th>Method</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="sub-admin-subs-body"></tbody>
|
|
</table>
|
|
<div id="sub-admin-subs-empty" class="text-muted" style="display:none;">No subscriptions found.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
|
|
SubAdmin_loadPlans();
|
|
SubAdmin_loadSubscriptions();
|
|
|
|
// ── Load plans list ──────────────────────────────────────────────────
|
|
function SubAdmin_loadPlans() {
|
|
$('#sub-admin-plans-loading').show();
|
|
$('#sub-admin-plans-table').hide();
|
|
$('#sub-admin-plans-body').empty();
|
|
|
|
$.get('/admin/subscription/plans', function (plans) {
|
|
$('#sub-admin-plans-loading').hide();
|
|
|
|
if (!plans || plans.length === 0) {
|
|
$('#sub-admin-plans-body').append('<tr><td colspan="6" class="text-center text-muted">No plans yet.</td></tr>');
|
|
$('#sub-admin-plans-table').show();
|
|
return;
|
|
}
|
|
|
|
plans.forEach(function (plan) {
|
|
const activeBadge = plan.active
|
|
? '<span class="badge badge-success">Active</span>'
|
|
: '<span class="badge badge-secondary">Inactive</span>';
|
|
|
|
const expiryLabels = {
|
|
'warn': '<span class="badge badge-warning">Warn</span>',
|
|
'restrict': '<span class="badge badge-danger">Restrict</span>',
|
|
'auto_deduct': '<span class="badge badge-info">Auto-Renew</span>',
|
|
};
|
|
|
|
const row = `<tr>
|
|
<td>${escHtml(plan.name)}</td>
|
|
<td>₱${parseFloat(plan.price).toFixed(2)}</td>
|
|
<td>${parseInt(plan.duration_days)} days</td>
|
|
<td>${expiryLabels[plan.expiry_action] || plan.expiry_action}</td>
|
|
<td>${activeBadge}</td>
|
|
<td>
|
|
<button class="btn btn-xs btn-info mr-1" onclick="SubAdmin_editPlan(${JSON.stringify(plan)})">
|
|
<i class="fas fa-edit"></i> Edit
|
|
</button>
|
|
<button class="btn btn-xs ${plan.active ? 'btn-secondary' : 'btn-success'}"
|
|
onclick="SubAdmin_togglePlan('${escHtml(plan.hashkey)}', this)">
|
|
<i class="fas fa-power-off"></i> ${plan.active ? 'Disable' : 'Enable'}
|
|
</button>
|
|
</td>
|
|
</tr>`;
|
|
$('#sub-admin-plans-body').append(row);
|
|
});
|
|
|
|
$('#sub-admin-plans-table').show();
|
|
}).fail(function () {
|
|
$('#sub-admin-plans-loading').html('<span class="text-danger">Failed to load plans.</span>');
|
|
});
|
|
}
|
|
|
|
// ── Create form ──────────────────────────────────────────────────────
|
|
window.SubAdmin_showCreateForm = function () {
|
|
$('#sub-plan-hashkey').val('');
|
|
$('#sub-plan-name-field').val('');
|
|
$('#sub-plan-desc-field').val('');
|
|
$('#sub-plan-price-field').val('');
|
|
$('#sub-plan-duration-field').val('30');
|
|
$('#sub-plan-expiry-field').val('warn');
|
|
$('#sub-admin-form-title').text('New Plan');
|
|
$('#sub-admin-plan-form-card').show();
|
|
$('html, body').animate({ scrollTop: $('#sub-admin-plan-form-card').offset().top - 20 }, 300);
|
|
};
|
|
|
|
// ── Edit form ────────────────────────────────────────────────────────
|
|
window.SubAdmin_editPlan = function (plan) {
|
|
$('#sub-plan-hashkey').val(plan.hashkey);
|
|
$('#sub-plan-name-field').val(plan.name);
|
|
$('#sub-plan-desc-field').val(plan.description || '');
|
|
$('#sub-plan-price-field').val(parseFloat(plan.price).toFixed(2));
|
|
$('#sub-plan-duration-field').val(parseInt(plan.duration_days));
|
|
$('#sub-plan-expiry-field').val(plan.expiry_action);
|
|
$('#sub-admin-form-title').text('Edit Plan: ' + escHtml(plan.name));
|
|
$('#sub-admin-plan-form-card').show();
|
|
$('html, body').animate({ scrollTop: $('#sub-admin-plan-form-card').offset().top - 20 }, 300);
|
|
};
|
|
|
|
window.SubAdmin_cancelForm = function () {
|
|
$('#sub-admin-plan-form-card').hide();
|
|
};
|
|
|
|
// ── Save (create or update) ──────────────────────────────────────────
|
|
window.SubAdmin_savePlan = function () {
|
|
const hashkey = $('#sub-plan-hashkey').val();
|
|
const isEdit = !!hashkey;
|
|
const payload = {
|
|
name: $('#sub-plan-name-field').val().trim(),
|
|
description: $('#sub-plan-desc-field').val().trim(),
|
|
price: $('#sub-plan-price-field').val(),
|
|
duration_days: $('#sub-plan-duration-field').val(),
|
|
expiry_action: $('#sub-plan-expiry-field').val(),
|
|
};
|
|
|
|
if (!payload.name || !payload.price || !payload.duration_days) {
|
|
ModalQuickDismiss('Validation', 'Please fill in Name, Price, and Duration.');
|
|
return;
|
|
}
|
|
|
|
if (isEdit) payload.hashkey = hashkey;
|
|
|
|
const url = isEdit ? '/admin/subscription/plan/update' : '/admin/subscription/plan/create';
|
|
|
|
$.post(url, payload, function (data) {
|
|
ModalQuickDismiss('Saved', 'Plan saved successfully.');
|
|
$('#sub-admin-plan-form-card').hide();
|
|
SubAdmin_loadPlans();
|
|
}).fail(function (xhr) {
|
|
ModalQuickDismiss('Error', xhr.responseJSON || xhr.responseText || 'Save failed.');
|
|
});
|
|
};
|
|
|
|
// ── Toggle active/inactive ───────────────────────────────────────────
|
|
window.SubAdmin_togglePlan = function (hashkey, btn) {
|
|
$.post('/admin/subscription/plan/toggle', { hashkey: hashkey }, function (data) {
|
|
SubAdmin_loadPlans();
|
|
}).fail(function (xhr) {
|
|
ModalQuickDismiss('Error', xhr.responseJSON || xhr.responseText || 'Toggle failed.');
|
|
});
|
|
};
|
|
|
|
// ── Load all user subscriptions ──────────────────────────────────────
|
|
window.SubAdmin_loadSubscriptions = function () {
|
|
const status = $('#sub-admin-status-filter').val();
|
|
$('#sub-admin-subs-loading').show();
|
|
$('#sub-admin-subs-table').hide();
|
|
$('#sub-admin-subs-empty').hide();
|
|
$('#sub-admin-subs-body').empty();
|
|
|
|
$.post('/admin/subscription/list', { status: status }, function (subs) {
|
|
$('#sub-admin-subs-loading').hide();
|
|
|
|
if (!subs || subs.length === 0) {
|
|
$('#sub-admin-subs-empty').show();
|
|
return;
|
|
}
|
|
|
|
subs.forEach(function (sub) {
|
|
const statusBadges = {
|
|
'active': '<span class="badge badge-success">Active</span>',
|
|
'expired': '<span class="badge badge-danger">Expired</span>',
|
|
'cancelled': '<span class="badge badge-secondary">Cancelled</span>',
|
|
'pending': '<span class="badge badge-warning">Pending</span>',
|
|
};
|
|
const row = `<tr>
|
|
<td>${escHtml(sub.user?.name || '—')}</td>
|
|
<td>${escHtml(sub.user?.mobile || '—')}</td>
|
|
<td>${escHtml(sub.plan?.name || '—')}</td>
|
|
<td>${statusBadges[sub.status] || sub.status}</td>
|
|
<td>${sub.starts_at ? sub.starts_at.substring(0, 10) : '—'}</td>
|
|
<td>${sub.expires_at ? sub.expires_at.substring(0, 10) : '—'}</td>
|
|
<td>${escHtml(sub.payment_method)}</td>
|
|
</tr>`;
|
|
$('#sub-admin-subs-body').append(row);
|
|
});
|
|
|
|
$('#sub-admin-subs-table').show();
|
|
}).fail(function () {
|
|
$('#sub-admin-subs-loading').html('<span class="text-danger">Failed to load subscriptions.</span>');
|
|
});
|
|
};
|
|
|
|
function escHtml(str) {
|
|
const d = document.createElement('div');
|
|
d.appendChild(document.createTextNode(str ?? ''));
|
|
return d.innerHTML;
|
|
}
|
|
|
|
})();
|
|
</script>
|