registerPage('clients', async (content, params = {}) => {
document.getElementById('topbar-title').textContent = 'Clients';
let provinces = [];
async function loadProvinces() {
if (provinces.length) return;
const r = await api('clients.php', { action: 'provinces' });
if (r.success) provinces = r.provinces;
}
async function render(search = '') {
const r = await api('clients.php', { action: 'list', search });
if (!r.success) { content.innerHTML = emptyHTML('Failed to load clients'); return; }
const rows = r.clients;
const tableHtml = rows.length === 0 ? emptyHTML('No clients found') : `
| Code | Name | Province | Email | Phone | Actions |
${rows.map(c => `
| ${c.client_code || '—'} |
${c.clients_name} |
${c.provinces_name || '—'} |
${c.email || '—'} |
${c.phone || '—'} |
|
`).join('')}
`;
document.getElementById('clients-table').innerHTML = tableHtml;
}
content.innerHTML = `
`;
await loadProvinces();
const sel = document.getElementById('cf-province');
provinces.forEach(p => sel.innerHTML += ``);
document.getElementById('client-search').addEventListener('input', e => render(e.target.value));
render();
window.clientAdd = async () => {
document.getElementById('client-modal-title').textContent = 'Add Client';
document.getElementById('client-form').reset();
document.getElementById('cf-id').value = '';
openModal('client-modal');
};
window.clientEdit = async (id) => {
const r = await api('clients.php', { action: 'get', id });
if (!r.success) { toast('Failed to load client', 'error'); return; }
const c = r.client;
document.getElementById('client-modal-title').textContent = 'Edit Client';
document.getElementById('cf-id').value = c.record_id;
document.getElementById('cf-name').value = c.clients_name;
document.getElementById('cf-code').value = c.client_code || '';
document.getElementById('cf-province').value = c.provinces_id || 0;
document.getElementById('cf-email').value = c.email || '';
document.getElementById('cf-phone').value = c.phone || '';
document.getElementById('cf-address').value = c.address || '';
openModal('client-modal');
};
window.clientSave = async () => {
const id = document.getElementById('cf-id').value;
const params = {
action: id ? 'update' : 'create',
id,
clients_name: document.getElementById('cf-name').value,
client_code: document.getElementById('cf-code').value,
provinces_id: document.getElementById('cf-province').value,
email: document.getElementById('cf-email').value,
phone: document.getElementById('cf-phone').value,
address: document.getElementById('cf-address').value,
};
const r = await api('clients.php', params, 'POST');
if (r.success) { toast(r.message, 'success'); closeModal('client-modal'); render(); }
else toast(r.error, 'error');
};
window.clientDelete = async (id, name) => {
if (!confirm(`Delete client "${name}"? This cannot be undone.`)) return;
const r = await api('clients.php', { action: 'delete', id }, 'POST');
if (r.success) { toast('Client deleted', 'success'); render(); }
else toast(r.error, 'error');
};
// ── Export ─────────────────────────────────────────────────────────────────
const _getExportRows = async (filter) => {
const r = await api('clients.php', { action: 'list', search: '' });
if (!r.success) { toast('Export failed', 'error'); return null; }
return r.clients.map(c => [c.client_code || '', c.clients_name || '', c.provinces_name || '', c.email || '', c.phone || '', c.address || '']);
};
const _exportHeaders = ['Code', 'Name', 'Province', 'Email', 'Phone', 'Address'];
const _exportTitle = 'Clients';
function printExport(title, headers, rows) {
const headHtml = headers.map(h => '' + h + ' | ').join('');
const bodyHtml = rows.map((row, i) =>
'' + row.map(v => '| ' + (v ?? '') + ' | ').join('') + '
'
).join('');
const date = new Date().toLocaleDateString('en-ZA', { day: 'numeric', month: 'short', year: 'numeric' });
const html = '' + title + '' +
'' +
'' + headHtml + '
' + bodyHtml + '
' +
'' +
'window.onload=function(){window.print();}' + 'script>' +
'';
const w = window.open('', '_blank');
w.document.write(html);
w.document.close();
}
window.doExportPDF = async () => {
const rows = await _getExportRows();
if (rows) printExport(_exportTitle, _exportHeaders, rows);
};
window.doExportCSV = async () => {
const rows = await _getExportRows();
if (!rows) return;
const wb = XLSX.utils.book_new();
const ws = XLSX.utils.aoa_to_sheet([_exportHeaders, ...rows]);
XLSX.utils.book_append_sheet(wb, ws, 'Clients');
XLSX.writeFile(wb, _exportTitle.toLowerCase().replace(/ /g, '_') + '_' + new Date().toISOString().slice(0, 10) + '.xlsx');
};
});