This commit is contained in:
@@ -6,16 +6,6 @@
|
||||
<div class="content"></div>
|
||||
<h2 class="text-center mt-4 mb-3">Invoice Management</h2>
|
||||
|
||||
<!-- Controls -->
|
||||
<div class="row g-2 align-items-center justify-content-center mb-3">
|
||||
<div class="col-auto">
|
||||
<label for="schoolYearSelect" class="col-form-label">School year</label>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select id="schoolYearSelect" class="form-select form-select-sm" style="min-width: 180px;"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Table for displaying invoices (client-hydrated) -->
|
||||
<table id="invoicesTable" class="table table-striped table-hover table-bordered w-100">
|
||||
<thead class="thead-dark">
|
||||
@@ -155,16 +145,20 @@
|
||||
const $tbl = $('#invoicesTable');
|
||||
let dt = null;
|
||||
const $year = document.getElementById('schoolYearSelect');
|
||||
const selectedSchoolYear = () => $year ? $year.value : '';
|
||||
const syncSchoolYearSelect = (resp) => {
|
||||
if (!$year) return;
|
||||
const years = Array.isArray(resp.schoolYears) ? resp.schoolYears : [];
|
||||
const selected = resp.schoolYear || (years[0] || '');
|
||||
$year.innerHTML = years.map(y => `<option value="${esc(y)}" ${y===selected?'selected':''}>${esc(y)}</option>`).join('');
|
||||
};
|
||||
// Global fallback handler for inline onclick
|
||||
window.__genInvoice = async function(btn){
|
||||
try {
|
||||
btn.disabled = true;
|
||||
await generateInvoice(btn.getAttribute('data-parent-id'));
|
||||
const resp = await loadInvoices();
|
||||
// Populate year select
|
||||
const years = Array.isArray(resp.schoolYears) ? resp.schoolYears : [];
|
||||
const selected = resp.schoolYear || (years[0] || '');
|
||||
$year.innerHTML = years.map(y => `<option value="${esc(y)}" ${y===selected?'selected':''}>${esc(y)}</option>`).join('');
|
||||
const resp = await loadInvoices(selectedSchoolYear());
|
||||
syncSchoolYearSelect(resp);
|
||||
|
||||
const data = (resp.invoices || []).map(r => {
|
||||
const ts = Date.parse(r.invoice_date || new Date().toISOString());
|
||||
@@ -194,10 +188,7 @@
|
||||
}
|
||||
try {
|
||||
const resp = await loadInvoices();
|
||||
// Populate year select on first load
|
||||
const years = Array.isArray(resp.schoolYears) ? resp.schoolYears : [];
|
||||
const selected = resp.schoolYear || (years[0] || '');
|
||||
$year.innerHTML = years.map(y => `<option value="${esc(y)}" ${y===selected?'selected':''}>${esc(y)}</option>`).join('');
|
||||
syncSchoolYearSelect(resp);
|
||||
|
||||
const data = (resp.invoices || []).map(r => {
|
||||
const ts = Date.parse(r.invoice_date || new Date().toISOString());
|
||||
@@ -240,7 +231,7 @@
|
||||
try {
|
||||
await generateInvoice(btn.getAttribute('data-parent-id'));
|
||||
// Refresh table minimally: reload data
|
||||
const resp = await loadInvoices($year.value);
|
||||
const resp = await loadInvoices(selectedSchoolYear());
|
||||
const data = (resp.invoices || []).map(r => {
|
||||
const ts = Date.parse(r.invoice_date || new Date().toISOString());
|
||||
const genBtn = `<button type=\"button\" class=\"btn btn-primary btn-sm gen-invoice\" data-parent-id=\"${esc(r.parent_id)}\" onclick=\"return window.__genInvoice && window.__genInvoice(this)\">Generate Invoice</button>`;
|
||||
@@ -273,7 +264,7 @@
|
||||
try {
|
||||
this.disabled = true;
|
||||
await generateInvoice(this.getAttribute('data-parent-id'));
|
||||
const resp = await loadInvoices($year.value);
|
||||
const resp = await loadInvoices(selectedSchoolYear());
|
||||
const data = (resp.invoices || []).map(r => {
|
||||
const ts = Date.parse(r.invoice_date || new Date().toISOString());
|
||||
const genBtn = `<button type=\"button\" class=\"btn btn-primary btn-sm gen-invoice\" data-parent-id=\"${esc(r.parent_id)}\" onclick=\"return window.__genInvoice && window.__genInvoice(this)\">Generate Invoice</button>`;
|
||||
@@ -312,34 +303,36 @@
|
||||
});
|
||||
|
||||
// Year change
|
||||
$year.addEventListener('change', async () => {
|
||||
try {
|
||||
const resp = await loadInvoices($year.value);
|
||||
const data = (resp.invoices || []).map(r => {
|
||||
const ts = Date.parse(r.invoice_date || new Date().toISOString());
|
||||
const genBtn = `<button type=\"button\" class=\"btn btn-primary btn-sm gen-invoice\" data-parent-id=\"${esc(r.parent_id)}\" onclick=\"return window.__genInvoice && window.__genInvoice(this)\">Generate Invoice</button>`;
|
||||
const pdf = r.invoice_id ? `<a href=\"<?= base_url('invoice/pdf') ?>/${esc(r.invoice_id)}\" target=\"_blank\" class=\"btn btn-info btn-sm external-link\">View/Print PDF</a>` : '<span class=\"text-muted\">No invoice yet</span>';
|
||||
return [
|
||||
esc(r.parent_name || ''),
|
||||
renderStudents(r.enrolledKids || []),
|
||||
genBtn,
|
||||
fmtMoney(r.invoice_amount),
|
||||
fmtMoney(r.refund_amount),
|
||||
`<span data-order=\"${ts}\">${formatDateTime(ts)}</span>`,
|
||||
pdf,
|
||||
];
|
||||
});
|
||||
if ($.fn.DataTable.isDataTable($tbl)) {
|
||||
const dti = $tbl.DataTable();
|
||||
dti.clear();
|
||||
dti.rows.add(data).draw(false);
|
||||
if ($year) {
|
||||
$year.addEventListener('change', async () => {
|
||||
try {
|
||||
const resp = await loadInvoices($year.value);
|
||||
const data = (resp.invoices || []).map(r => {
|
||||
const ts = Date.parse(r.invoice_date || new Date().toISOString());
|
||||
const genBtn = `<button type=\"button\" class=\"btn btn-primary btn-sm gen-invoice\" data-parent-id=\"${esc(r.parent_id)}\" onclick=\"return window.__genInvoice && window.__genInvoice(this)\">Generate Invoice</button>`;
|
||||
const pdf = r.invoice_id ? `<a href=\"<?= base_url('invoice/pdf') ?>/${esc(r.invoice_id)}\" target=\"_blank\" class=\"btn btn-info btn-sm external-link\">View/Print PDF</a>` : '<span class=\"text-muted\">No invoice yet</span>';
|
||||
return [
|
||||
esc(r.parent_name || ''),
|
||||
renderStudents(r.enrolledKids || []),
|
||||
genBtn,
|
||||
fmtMoney(r.invoice_amount),
|
||||
fmtMoney(r.refund_amount),
|
||||
`<span data-order=\"${ts}\">${formatDateTime(ts)}</span>`,
|
||||
pdf,
|
||||
];
|
||||
});
|
||||
if ($.fn.DataTable.isDataTable($tbl)) {
|
||||
const dti = $tbl.DataTable();
|
||||
dti.clear();
|
||||
dti.rows.add(data).draw(false);
|
||||
}
|
||||
showToast('Loaded ' + $year.value);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
showToast('Failed to load ' + $year.value, false);
|
||||
}
|
||||
showToast('Loaded ' + $year.value);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
showToast('Failed to load ' + $year.value, false);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
Reference in New Issue
Block a user