/** * Billing & Subscription Logic */ const billing = { state: { subscription: null, invoices: [] }, init: async () => { console.log('💳 Initializing Billing...'); await billing.fetchSubscription(); await billing.fetchInvoices(); billing.renderUI(); }, fetchSubscription: async () => { try { const headers = auth.getAuthHeader(); const res = await fetch('/api/billing/subscription', { headers }); if (res.ok) { billing.state.subscription = await res.json(); } } catch (error) { console.error('Failed to fetch subscription', error); } }, fetchInvoices: async () => { try { const headers = auth.getAuthHeader(); const res = await fetch('/api/billing/invoices', { headers }); if (res.ok) { billing.state.invoices = await res.json(); } } catch (error) { console.error('Failed to fetch invoices', error); } }, renderUI: () => { const sub = billing.state.subscription; if (!sub) return; // 1. Update Current Plan Badges document.querySelectorAll('.current-plan-name').forEach(el => el.textContent = sub.plan); // 2. Render Plan Cards logic const plans = ['FREE', 'STARTER', 'PRO', 'ENTERPRISE']; plans.forEach(p => { const card = document.getElementById(`plan-card-${p.toLowerCase()}`); if (card) { const btn = card.querySelector('.plan-btn'); if (p === sub.plan) { card.classList.add('border-blue-500/50'); if (btn) { btn.textContent = 'Current Plan'; btn.disabled = true; btn.classList.add('opacity-50'); } } else { card.classList.remove('border-blue-500/50'); if (btn) { btn.textContent = p === 'ENTERPRISE' ? 'Contact Sales' : 'Upgrade Now'; btn.disabled = false; btn.classList.remove('opacity-50'); } } } }); // 3. Render Invoice History const tbody = document.getElementById('invoice-table-body'); if (tbody) { if (billing.state.invoices.length === 0) { tbody.innerHTML = `No transactions yet.`; } else { tbody.innerHTML = billing.state.invoices.map(inv => ` ${new Date(inv.createdAt).toLocaleDateString()} $${inv.amount} ${inv.provider} ${inv.status} `).join(''); } } }, startCheckout: async (plan, provider) => { try { const btn = event.target; const originalText = btn.textContent; btn.textContent = 'Processing...'; btn.disabled = true; const headers = { 'Content-Type': 'application/json', ...auth.getAuthHeader() }; const res = await fetch('/api/billing/checkout', { method: 'POST', headers, body: JSON.stringify({ plan, provider }) }); if (res.ok) { const data = await res.json(); if (data.checkoutUrl) { window.location.href = data.checkoutUrl; } } else { alert('Checkout failed. Please try again.'); } btn.textContent = originalText; btn.disabled = false; } catch (error) { console.error('Checkout error', error); alert('An error occurred during checkout.'); } } };