class AdminBilling extends HTMLElement { constructor() { super(); this.pricingConfig = []; this.stats = null; this.boundHandleClick = this.handleClick.bind(this); this.loading = true; this.error = null; } async connectedCallback() { this.addEventListener('click', this.boundHandleClick); await this.loadData(); this.render(); this.attachEventListeners(); } disconnectedCallback() { this.removeEventListener('click', this.boundHandleClick); } async loadData() { this.loading = true; this.error = null; try { const [pricing, stats] = await Promise.all([ this.fetchPricing(), this.fetchStats() ]); this.pricingConfig = pricing; this.stats = stats; this.loading = false; } catch (error) { console.error('Failed to load admin billing data:', error); this.error = error.message || 'Failed to load admin billing data'; this.loading = false; } } async fetchPricing() { const response = await fetch('/api/admin/billing/pricing', { headers: {'Authorization': `Bearer ${localStorage.getItem('token')}`} }); return await response.json(); } async fetchStats() { const response = await fetch('/api/admin/billing/stats', { headers: {'Authorization': `Bearer ${localStorage.getItem('token')}`} }); return await response.json(); } formatCurrency(amount) { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(amount); } render() { if (this.loading) { this.innerHTML = '
Loading admin billing data...
'; return; } if (this.error) { this.innerHTML = `
Error: ${this.error}
`; return; } this.innerHTML = `

Billing Administration

Total Revenue

${this.formatCurrency(this.stats?.total_revenue || 0)}

Total Invoices

${this.stats?.total_invoices || 0}

Pending Invoices

${this.stats?.pending_invoices || 0}

Pricing Configuration

${this.pricingConfig.map(config => ` `).join('')}
Configuration Current Value Unit Actions
${config.description || config.config_key} ${config.config_value} ${config.unit || '-'}

Generate Invoices

`; } handleClick(e) { const target = e.target; if (target.classList.contains('btn-edit')) { const configId = target.dataset.configId; this.editPricing(configId); return; } if (target.id === 'generateInvoices') { this.generateInvoices(); } } attachEventListeners() { } async editPricing(configId) { const config = this.pricingConfig.find(c => c.id === parseInt(configId)); if (!config) return; const newValue = prompt(`Enter new value for ${config.config_key}:`, config.config_value); if (newValue === null) return; try { const response = await fetch(`/api/admin/billing/pricing/${configId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, body: JSON.stringify({ config_key: config.config_key, config_value: parseFloat(newValue) }) }); if (response.ok) { alert('Pricing updated successfully'); await this.loadData(); this.render(); this.attachEventListeners(); } else { alert('Failed to update pricing'); } } catch (error) { console.error('Error updating pricing:', error); alert('Error updating pricing'); } } async generateInvoices() { const year = parseInt(this.querySelector('#invoiceYear').value); const month = parseInt(this.querySelector('#invoiceMonth').value); if (!confirm(`Generate invoices for ${month}/${year}?`)) return; try { const response = await fetch(`/api/admin/billing/generate-invoices/${year}/${month}`, { method: 'POST', headers: {'Authorization': `Bearer ${localStorage.getItem('token')}`} }); const result = await response.json(); alert(`Generated ${result.generated} invoices, skipped ${result.skipped} users`); } catch (error) { console.error('Error generating invoices:', error); alert('Failed to generate invoices'); } } } customElements.define('admin-billing', AdminBilling); export default AdminBilling;