GST Invoice Pro

GST Invoice Pro

Professional GST Billing

Dashboard

Total Invoices

0

Total Revenue

₹0

GST Collected

₹0

Pending

0

Recent Invoices

No invoices yet. Create your first one!
`); printWindow.document.close(); setTimeout(() => { printWindow.focus(); printWindow.print(); }, 250); }function downloadPDF() { const inv = allInvoices.find(i => i.__backendId === currentPreviewId); if (!inv) { showToast('Invoice not found', 'error'); return; } showToast('📄 Click Print button above, then choose "Save as PDF" from your printer options', 'info'); }// ============ TOAST ============ function showToast(msg, type = 'info') { const c = document.getElementById('toastContainer'); const colors = { success: 'bg-emerald-500', error: 'bg-rose-500', warning: 'bg-amber-500', info: 'bg-slate-700' }; const t = document.createElement('div'); t.className = `toast-enter ${colors[type]} text-white px-4 py-2.5 rounded-lg text-sm font-medium shadow-lg flex items-center gap-2 max-w-xs`; const icons = { success: 'check-circle', error: 'x-circle', warning: 'alert-triangle', info: 'info' }; t.innerHTML = `${escHtml(msg)}`; c.appendChild(t); lucide.createIcons(); setTimeout(() => { t.style.opacity = '0'; t.style.transition = 'opacity 0.3s'; setTimeout(() => t.remove(), 300); }, 3000); }function escHtml(s) { const d = document.createElement('div'); d.textContent = s || ''; return d.innerHTML; }// ============ DATA SDK ============ const dataHandler = { onDataChanged(data) { allInvoices = data.filter(d => d.type === 'invoice'); const currentView = document.querySelector('.view-panel:not(.hidden)'); if (currentView) { if (currentView.id === 'view-invoices') filterInvoices(); if (currentView.id === 'view-dashboard') updateDashboard(); } } };// ============ ELEMENT SDK ============ const defaultConfig = { app_title: 'GST Invoice Pro', company_tagline: 'Professional GST Billing', background_color: '#020617', surface_color: '#0f172a', text_color: '#e2e8f0', primary_action_color: '#10b981', secondary_action_color: '#64748b', font_family: 'DM Sans', font_size: 14 };function applyConfig(config) { const c = { ...defaultConfig, ...config }; document.getElementById('appTitle').textContent = c.app_title; document.getElementById('appTagline').textContent = c.company_tagline;const shell = document.getElementById('appShell'); shell.style.backgroundColor = c.background_color; shell.style.color = c.text_color; shell.style.fontFamily = `${c.font_family}, DM Sans, sans-serif`;// Apply colors via CSS custom properties on the shell document.querySelectorAll('.bg-slate-900').forEach(el => el.style.backgroundColor = c.surface_color); document.querySelectorAll('.bg-emerald-500').forEach(el => { el.style.backgroundColor = c.primary_action_color; }); document.querySelectorAll('.text-emerald-400, .text-emerald-500').forEach(el => el.style.color = c.primary_action_color); }(async () => { populateStateDropdowns(); renderLineItems();if (window.elementSdk) { window.elementSdk.init({ defaultConfig, onConfigChange: async (config) => applyConfig(config), mapToCapabilities: (config) => ({ recolorables: [ { get: () => config.background_color || defaultConfig.background_color, set: (v) => { config.background_color = v; window.elementSdk.setConfig({ background_color: v }); } }, { get: () => config.surface_color || defaultConfig.surface_color, set: (v) => { config.surface_color = v; window.elementSdk.setConfig({ surface_color: v }); } }, { get: () => config.text_color || defaultConfig.text_color, set: (v) => { config.text_color = v; window.elementSdk.setConfig({ text_color: v }); } }, { get: () => config.primary_action_color || defaultConfig.primary_action_color, set: (v) => { config.primary_action_color = v; window.elementSdk.setConfig({ primary_action_color: v }); } }, { get: () => config.secondary_action_color || defaultConfig.secondary_action_color, set: (v) => { config.secondary_action_color = v; window.elementSdk.setConfig({ secondary_action_color: v }); } } ], borderables: [], fontEditable: { get: () => config.font_family || defaultConfig.font_family, set: (v) => { config.font_family = v; window.elementSdk.setConfig({ font_family: v }); } }, fontSizeable: { get: () => config.font_size || defaultConfig.font_size, set: (v) => { config.font_size = v; window.elementSdk.setConfig({ font_size: v }); } } }), mapToEditPanelValues: (config) => new Map([ ['app_title', config.app_title || defaultConfig.app_title], ['company_tagline', config.company_tagline || defaultConfig.company_tagline] ]) }); }if (window.dataSdk) { const result = await window.dataSdk.init(dataHandler); if (!result.isOk) console.error('Data SDK init failed'); }lucide.createIcons(); showView('dashboard'); })();