/**
* Main App Logic for Intaleq Dashboard (Vanilla Version)
*/
const app = {
state: {
tenant: null,
keys: [],
showKeys: {}, // { id: boolean }
activePage: 'home'
},
init: async () => {
try {
console.log('🚀 Intaleq Dashboard Initializing Core UI...');
app.updateHeader();
app.bindEvents();
// Check for payment success/fail status earlier
app.checkPaymentStatus();
// Trigger initial routing based on URL hash
app.handleRouting();
if (window.lucide) lucide.createIcons();
} catch (e) {
console.error('Core UI Init failed', e);
}
},
checkPaymentStatus: () => {
const params = new URLSearchParams(window.location.search);
const status = params.get('payment_status');
const txId = params.get('id');
if (status === 'success') {
console.log('🏁 Payment Success Detected! Updating UI...');
app.showSuccessModal(txId);
// Force refresh stats to show PRO plan
app.fetchStats();
// Clean URL without refresh
const newUrl = window.location.pathname + window.location.hash;
window.history.replaceState({}, document.title, newUrl);
}
},
showSuccessModal: (id) => {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 z-[100] flex items-center justify-center p-6 bg-slate-950/90 backdrop-blur-xl animate-in fade-in duration-500';
modal.innerHTML = `
Upgrade Successful!
Your account has been upgraded to PRO Plan. Enjoy 50,000 monthly requests!
Transaction ID
${id || 'N/A'}
PRO ACTIVE
`;
document.body.appendChild(modal);
if (window.lucide) lucide.createIcons();
document.getElementById('close-success-modal').onclick = () => {
modal.classList.add('animate-out', 'fade-out', 'zoom-out-95');
setTimeout(() => modal.remove(), 400);
};
},
onAuthenticated: async () => {
console.log('🔑 User Authenticated. Initializing Data Flow...');
await app.init(); // Setup UI first
await app.fetchData();
app.updateStats();
},
bindEvents: () => {
window.addEventListener('hashchange', app.handleRouting);
// Form submission for new key
const createKeyForm = document.getElementById('create-key-form');
if (createKeyForm) {
createKeyForm.addEventListener('submit', async (e) => {
e.preventDefault();
await app.createKey();
});
}
},
handleRouting: () => {
const hash = window.location.hash.replace('#', '') || 'home';
app.state.activePage = hash;
// Update UI
document.querySelectorAll('.page-section').forEach(s => s.classList.remove('active'));
const activeSection = document.getElementById(hash);
if (activeSection) activeSection.classList.add('active');
// Update Nav
document.querySelectorAll('.nav-link').forEach(l => l.classList.remove('active'));
const activeLink = document.getElementById(`nav-${hash}`);
if (activeLink) activeLink.classList.add('active');
// Specialized page logic
if (hash === 'playground') {
playground.init(app.state.keys);
} else if (hash === 'analytics') {
analytics.init();
} else if (hash === 'billing') {
billing.init();
} else if (hash === 'refinement') {
refinement.init();
} else if (hash === 'docs') {
docs.init();
}
},
fetchData: async () => {
const headers = auth.getAuthHeader();
try {
// Fetch Tenant
const tenantRes = await fetch('/api/auth/management/me', { headers });
if (tenantRes.ok) {
app.state.tenant = await tenantRes.json();
app.updateHeader();
}
// Fetch Keys
if (app.state.tenant) {
const keysRes = await fetch('/api/auth/management/keys', { headers });
if (keysRes.ok) {
app.state.keys = await keysRes.json();
app.renderKeysTable();
}
}
// Update Quota Widget
const summaryRes = await fetch('/api/usage/summary', { headers });
if (summaryRes.ok) {
const summary = await summaryRes.json();
app.updateQuotaWidget(summary);
}
} catch (error) {
console.warn('Dashboard data fetch partially failed', error);
}
},
updateQuotaWidget: (summary) => {
const percent = parseFloat(summary.percentage) || 0;
const used = summary.monthlyUsage || 0;
const total = summary.limit || 8000;
const left = Math.max(total - used, 0);
// Sidebar Widget
const bar = document.getElementById('quota-bar');
const pctText = document.getElementById('quota-percent');
const leftText = document.getElementById('quota-text');
if (bar) {
bar.style.width = `${percent}%`;
// Color shift based on usage
bar.classList.remove('from-blue-600', 'to-blue-400', 'from-orange-500', 'to-orange-400', 'from-red-600', 'to-red-400');
if (percent > 90) {
bar.classList.add('from-red-600', 'to-red-400');
} else if (percent > 70) {
bar.classList.add('from-orange-500', 'to-orange-400');
} else {
bar.classList.add('from-blue-600', 'to-blue-400');
}
}
if (pctText) pctText.textContent = `${percent}%`;
if (leftText) leftText.textContent = `${left.toLocaleString()} requests left`;
// Billing Section Widget (if present)
const bBar = document.getElementById('billing-quota-bar');
const bPct = document.getElementById('billing-quota-percent');
const bUsed = document.getElementById('billing-quota-used');
const bTotal = document.getElementById('billing-quota-total');
if (bBar) bBar.style.width = `${percent}%`;
if (bPct) bPct.textContent = `${percent}%`;
if (bUsed) bUsed.textContent = `${used.toLocaleString()} used`;
if (bTotal) bTotal.textContent = `${total.toLocaleString()} limit`;
},
updateHeader: () => {
if (!app.state.tenant) return;
document.getElementById('tenant-name').textContent = app.state.tenant.name;
document.getElementById('tenant-email').textContent = app.state.tenant.email;
document.getElementById('welcome-msg').textContent = `Welcome back, ${app.state.tenant.name.split(' ')[0]}`;
// Role-based UI visibility
if (app.state.tenant.role === 'ADMIN') {
const auditLink = document.getElementById('nav-refinement');
if (auditLink) auditLink.classList.remove('hidden');
}
// Update user avatar if photoUrl exists
if (app.state.tenant.photoUrl) {
const avatarContainer = document.querySelector('.w-10.h-10.rounded-full.bg-slate-900');
if (avatarContainer) {
avatarContainer.innerHTML = `