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>
This commit is contained in:
2025-12-31 21:32:19 +01:00
parent c8fd09d16f
commit 265c71f597
48 changed files with 410 additions and 196 deletions

View File

@@ -71,12 +71,21 @@ function adminNotifications() {
* Initialize component
*/
async init() {
notificationsLog.debug('Initializing notifications page');
await Promise.all([
this.loadNotifications(),
this.loadAlertStats()
]);
this.loading = false;
// Guard against multiple initialization
if (window._adminNotificationsInitialized) return;
window._adminNotificationsInitialized = true;
try {
notificationsLog.debug('Initializing notifications page');
await Promise.all([
this.loadNotifications(),
this.loadAlertStats()
]);
} catch (error) {
notificationsLog.error('Failed to initialize notifications page:', error);
} finally {
this.loading = false;
}
},
// ============================================================================
@@ -105,7 +114,7 @@ function adminNotifications() {
notificationsLog.debug(`Loaded ${this.notifications.length} notifications`);
} catch (error) {
notificationsLog.error('Failed to load notifications:', error);
window.showToast?.('Failed to load notifications', 'error');
Utils.showToast('Failed to load notifications', 'error');
} finally {
this.loadingNotifications = false;
}
@@ -122,10 +131,10 @@ function adminNotifications() {
notification.is_read = true;
this.stats.unread_count = Math.max(0, this.stats.unread_count - 1);
window.showToast?.('Notification marked as read', 'success');
Utils.showToast('Notification marked as read', 'success');
} catch (error) {
notificationsLog.error('Failed to mark as read:', error);
window.showToast?.('Failed to mark notification as read', 'error');
Utils.showToast('Failed to mark notification as read', 'error');
}
},
@@ -140,10 +149,10 @@ function adminNotifications() {
this.notifications.forEach(n => n.is_read = true);
this.stats.unread_count = 0;
window.showToast?.('All notifications marked as read', 'success');
Utils.showToast('All notifications marked as read', 'success');
} catch (error) {
notificationsLog.error('Failed to mark all as read:', error);
window.showToast?.('Failed to mark all as read', 'error');
Utils.showToast('Failed to mark all as read', 'error');
}
},
@@ -166,10 +175,10 @@ function adminNotifications() {
this.stats.unread_count = Math.max(0, this.stats.unread_count - 1);
}
window.showToast?.('Notification deleted', 'success');
Utils.showToast('Notification deleted', 'success');
} catch (error) {
notificationsLog.error('Failed to delete notification:', error);
window.showToast?.('Failed to delete notification', 'error');
Utils.showToast('Failed to delete notification', 'error');
}
},
@@ -216,7 +225,7 @@ function adminNotifications() {
notificationsLog.debug(`Loaded ${this.alerts.length} alerts`);
} catch (error) {
notificationsLog.error('Failed to load alerts:', error);
window.showToast?.('Failed to load alerts', 'error');
Utils.showToast('Failed to load alerts', 'error');
} finally {
this.loadingAlerts = false;
}
@@ -263,10 +272,10 @@ function adminNotifications() {
}
this.alertStats.resolved_today++;
window.showToast?.('Alert resolved successfully', 'success');
Utils.showToast('Alert resolved successfully', 'success');
} catch (error) {
notificationsLog.error('Failed to resolve alert:', error);
window.showToast?.('Failed to resolve alert', 'error');
Utils.showToast('Failed to resolve alert', 'error');
}
},