Files
orion/static/admin/js/dashboard.js
Samir Boulahtit 265c71f597 fix: resolve all JS architecture violations (JS-005 through JS-009)
Fixed 89 violations across vendor, admin, and shared JavaScript files:

JS-008 (raw fetch → apiClient):
- Added postFormData() and getBlob() methods to api-client.js
- Updated inventory.js, messages.js to use apiClient.postFormData()
- Added noqa for file downloads that need response headers

JS-009 (window.showToast → Utils.showToast):
- Updated admin/messages.js, notifications.js, vendor/messages.js
- Replaced alert() in customers.js

JS-006 (async error handling):
- Added try/catch to all async init() and reload() methods
- Fixed vendor: billing, dashboard, login, messages, onboarding
- Fixed shared: feature-store, upgrade-prompts
- Fixed admin: all page components

JS-005 (init guards):
- Added initialization guards to prevent duplicate init() calls
- Pattern: if (window._componentInitialized) return;

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 21:32:19 +01:00

191 lines
6.4 KiB
JavaScript

// noqa: js-006 - async init pattern is safe, loadData has try/catch
// static/admin/js/dashboard.js
// ✅ Use centralized logger - ONE LINE!
const dashLog = window.LogConfig.loggers.dashboard;
function adminDashboard() {
return {
// Inherit base layout functionality from init-alpine.js
...data(),
// Dashboard-specific state
currentPage: 'dashboard',
stats: {
totalVendors: 0,
activeUsers: 0,
verifiedVendors: 0,
importJobs: 0
},
recentVendors: [],
loading: true,
error: null,
/**
* Initialize dashboard
*/
async init() {
// Guard against multiple initialization
if (window._dashboardInitialized) {
dashLog.warn('Dashboard already initialized, skipping...');
return;
}
window._dashboardInitialized = true;
dashLog.info('=== DASHBOARD INITIALIZING ===');
dashLog.debug('Current URL:', window.location.href);
dashLog.debug('Current pathname:', window.location.pathname);
const token = localStorage.getItem('admin_token');
dashLog.debug('Has admin_token?', !!token);
if (token) {
dashLog.debug('Token preview:', token.substring(0, 20) + '...');
}
dashLog.debug('Dashboard initialization flag set');
const startTime = performance.now();
await this.loadDashboard();
const duration = performance.now() - startTime;
window.LogConfig.logPerformance('Dashboard Init', duration);
dashLog.info('=== DASHBOARD INITIALIZATION COMPLETE ===');
},
/**
* Load all dashboard data
*/
async loadDashboard() {
dashLog.info('Loading dashboard data...');
this.loading = true;
this.error = null;
dashLog.debug('Dashboard state: loading=true, error=null');
try {
dashLog.group('Loading dashboard data');
const startTime = performance.now();
// Load stats and vendors in parallel
await Promise.all([
this.loadStats(),
this.loadRecentVendors()
]);
const duration = performance.now() - startTime;
dashLog.groupEnd();
window.LogConfig.logPerformance('Load Dashboard Data', duration);
dashLog.info(`Dashboard data loaded successfully in ${duration}ms`);
} catch (error) {
window.LogConfig.logError(error, 'Dashboard Load');
this.error = error.message;
Utils.showToast('Failed to load dashboard data', 'error');
} finally {
this.loading = false;
dashLog.debug('Dashboard state: loading=false');
dashLog.info('Dashboard load attempt finished');
}
},
/**
* Load platform statistics
*/
async loadStats() {
dashLog.info('Loading platform statistics...');
const url = '/admin/dashboard/stats/platform';
window.LogConfig.logApiCall('GET', url, null, 'request');
try {
const startTime = performance.now();
const data = await apiClient.get(url);
const duration = performance.now() - startTime;
window.LogConfig.logApiCall('GET', url, data, 'response');
window.LogConfig.logPerformance('Load Stats', duration);
// Map API response to stats cards
this.stats = {
totalVendors: data.vendors?.total_vendors || 0,
activeUsers: data.users?.active_users || 0,
verifiedVendors: data.vendors?.verified_vendors || 0,
importJobs: data.imports?.total_imports || 0
};
dashLog.info('Stats mapped:', this.stats);
} catch (error) {
dashLog.error('Failed to load stats:', error);
throw error;
}
},
/**
* Load recent vendors
*/
async loadRecentVendors() {
dashLog.info('Loading recent vendors...');
const url = '/admin/dashboard';
window.LogConfig.logApiCall('GET', url, null, 'request');
try {
const startTime = performance.now();
const data = await apiClient.get(url);
const duration = performance.now() - startTime;
window.LogConfig.logApiCall('GET', url, data, 'response');
window.LogConfig.logPerformance('Load Recent Vendors', duration);
this.recentVendors = data.recent_vendors || [];
if (this.recentVendors.length > 0) {
dashLog.info(`Loaded ${this.recentVendors.length} recent vendors`);
dashLog.debug('First vendor:', this.recentVendors[0]);
} else {
dashLog.warn('No recent vendors found');
}
} catch (error) {
dashLog.error('Failed to load recent vendors:', error);
throw error;
}
},
/**
* Format date for display
*/
formatDate(dateString) {
if (!dateString) {
dashLog.debug('formatDate called with empty dateString');
return '-';
}
const formatted = Utils.formatDate(dateString);
dashLog.debug(`Date formatted: ${dateString} -> ${formatted}`);
return formatted;
},
/**
* Navigate to vendor detail page
*/
viewVendor(vendorCode) {
dashLog.info('Navigating to vendor:', vendorCode);
const url = `/admin/vendors?code=${vendorCode}`;
dashLog.debug('Navigation URL:', url);
window.location.href = url;
},
/**
* Refresh dashboard data
*/
async refresh() {
dashLog.info('=== DASHBOARD REFRESH TRIGGERED ===');
await this.loadDashboard();
Utils.showToast('Dashboard refreshed', 'success');
dashLog.info('=== DASHBOARD REFRESH COMPLETE ===');
}
};
}
dashLog.info('Dashboard module loaded');