From cd5097fc04cfdcc871136e9dc6ebef3be4a2c001 Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Tue, 28 Oct 2025 22:58:55 +0100 Subject: [PATCH] migrating vendor frontend to new architecture --- app/templates/admin/login.html | 2 +- app/templates/admin/vendors.html | 4 +- .../templates}/vendor/admin/customers.html | 0 .../templates}/vendor/admin/inventory.html | 0 .../vendor/admin/marketplace/browse.html | 0 .../vendor/admin/marketplace/config.html | 0 .../vendor/admin/marketplace/imports.html | 0 .../vendor/admin/marketplace/selected.html | 0 .../templates}/vendor/admin/media.html | 0 .../vendor/admin/notifications.html | 0 .../templates}/vendor/admin/orders.html | 0 .../templates}/vendor/admin/payments.html | 0 .../templates}/vendor/admin/products.html | 0 .../templates}/vendor/admin/settings.html | 0 .../templates}/vendor/admin/teams.html | 0 .../templates}/vendor/dashboard.html | 0 {static => app/templates}/vendor/login.html | 0 .../FRONTEND_ARCHITECTURE_OVERVIEW.txt | 26 ++-- static/admin/js/components.js | 20 ++- static/admin/js/dashboard.js | 63 ++++----- static/admin/js/icons-page.js | 21 ++- static/admin/js/login.js | 127 +++++++++--------- static/admin/js/testing-hub.js | 12 +- static/admin/js/users.js | 104 +++++++++++--- static/admin/js/vendor-detail.js | 35 ++--- static/admin/js/vendor-edit.js | 71 +++++----- static/admin/js/vendors.js | 54 +++++--- static/shared/js/icons.js | 1 + 28 files changed, 312 insertions(+), 228 deletions(-) rename {static => app/templates}/vendor/admin/customers.html (100%) rename {static => app/templates}/vendor/admin/inventory.html (100%) rename {static => app/templates}/vendor/admin/marketplace/browse.html (100%) rename {static => app/templates}/vendor/admin/marketplace/config.html (100%) rename {static => app/templates}/vendor/admin/marketplace/imports.html (100%) rename {static => app/templates}/vendor/admin/marketplace/selected.html (100%) rename {static => app/templates}/vendor/admin/media.html (100%) rename {static => app/templates}/vendor/admin/notifications.html (100%) rename {static => app/templates}/vendor/admin/orders.html (100%) rename {static => app/templates}/vendor/admin/payments.html (100%) rename {static => app/templates}/vendor/admin/products.html (100%) rename {static => app/templates}/vendor/admin/settings.html (100%) rename {static => app/templates}/vendor/admin/teams.html (100%) rename {static => app/templates}/vendor/dashboard.html (100%) rename {static => app/templates}/vendor/login.html (100%) diff --git a/app/templates/admin/login.html b/app/templates/admin/login.html index f5ca948b..621d4742 100644 --- a/app/templates/admin/login.html +++ b/app/templates/admin/login.html @@ -103,7 +103,7 @@ - + diff --git a/app/templates/admin/vendors.html b/app/templates/admin/vendors.html index 21c95568..3744ef13 100644 --- a/app/templates/admin/vendors.html +++ b/app/templates/admin/vendors.html @@ -69,7 +69,7 @@
-
+
@@ -84,7 +84,7 @@
-
+
diff --git a/static/vendor/admin/customers.html b/app/templates/vendor/admin/customers.html similarity index 100% rename from static/vendor/admin/customers.html rename to app/templates/vendor/admin/customers.html diff --git a/static/vendor/admin/inventory.html b/app/templates/vendor/admin/inventory.html similarity index 100% rename from static/vendor/admin/inventory.html rename to app/templates/vendor/admin/inventory.html diff --git a/static/vendor/admin/marketplace/browse.html b/app/templates/vendor/admin/marketplace/browse.html similarity index 100% rename from static/vendor/admin/marketplace/browse.html rename to app/templates/vendor/admin/marketplace/browse.html diff --git a/static/vendor/admin/marketplace/config.html b/app/templates/vendor/admin/marketplace/config.html similarity index 100% rename from static/vendor/admin/marketplace/config.html rename to app/templates/vendor/admin/marketplace/config.html diff --git a/static/vendor/admin/marketplace/imports.html b/app/templates/vendor/admin/marketplace/imports.html similarity index 100% rename from static/vendor/admin/marketplace/imports.html rename to app/templates/vendor/admin/marketplace/imports.html diff --git a/static/vendor/admin/marketplace/selected.html b/app/templates/vendor/admin/marketplace/selected.html similarity index 100% rename from static/vendor/admin/marketplace/selected.html rename to app/templates/vendor/admin/marketplace/selected.html diff --git a/static/vendor/admin/media.html b/app/templates/vendor/admin/media.html similarity index 100% rename from static/vendor/admin/media.html rename to app/templates/vendor/admin/media.html diff --git a/static/vendor/admin/notifications.html b/app/templates/vendor/admin/notifications.html similarity index 100% rename from static/vendor/admin/notifications.html rename to app/templates/vendor/admin/notifications.html diff --git a/static/vendor/admin/orders.html b/app/templates/vendor/admin/orders.html similarity index 100% rename from static/vendor/admin/orders.html rename to app/templates/vendor/admin/orders.html diff --git a/static/vendor/admin/payments.html b/app/templates/vendor/admin/payments.html similarity index 100% rename from static/vendor/admin/payments.html rename to app/templates/vendor/admin/payments.html diff --git a/static/vendor/admin/products.html b/app/templates/vendor/admin/products.html similarity index 100% rename from static/vendor/admin/products.html rename to app/templates/vendor/admin/products.html diff --git a/static/vendor/admin/settings.html b/app/templates/vendor/admin/settings.html similarity index 100% rename from static/vendor/admin/settings.html rename to app/templates/vendor/admin/settings.html diff --git a/static/vendor/admin/teams.html b/app/templates/vendor/admin/teams.html similarity index 100% rename from static/vendor/admin/teams.html rename to app/templates/vendor/admin/teams.html diff --git a/static/vendor/dashboard.html b/app/templates/vendor/dashboard.html similarity index 100% rename from static/vendor/dashboard.html rename to app/templates/vendor/dashboard.html diff --git a/static/vendor/login.html b/app/templates/vendor/login.html similarity index 100% rename from static/vendor/login.html rename to app/templates/vendor/login.html diff --git a/docs/__REVAMPING/FRONTEND/FRONTEND_ARCHITECTURE_OVERVIEW.txt b/docs/__REVAMPING/FRONTEND/FRONTEND_ARCHITECTURE_OVERVIEW.txt index b7aa15ef..1d6a340f 100644 --- a/docs/__REVAMPING/FRONTEND/FRONTEND_ARCHITECTURE_OVERVIEW.txt +++ b/docs/__REVAMPING/FRONTEND/FRONTEND_ARCHITECTURE_OVERVIEW.txt @@ -157,20 +157,20 @@ HTML template connects to Alpine.js component: │ vendor-edit.html │ ├─────────────────────────────────────────────────────────────┤ │ {% extends "admin/base.html" %} │ -│ │ -│ {# This binds to the JavaScript function #} │ -│ {% block alpine_data %}adminVendorEdit(){% endblock %} │ +│ │ +│ {# This binds to the JavaScript function #} │ +│ {% block alpine_data %}adminVendorEdit(){% endblock %} │ │ └──────────────────┐ │ │ {% block content %} │ │ │
Loading...
│ │ │
│ │ -│

← Reactive binding │ │ +│

← Reactive binding │ │ │
│ │ │ {% endblock %} │ │ │ │ │ -│ {% block extra_scripts %} │ │ -│ ──────────┐ │ │ -│ {% endblock %} │ │ │ +│ {% block extra_scripts %} │ │ +│ ──────────┐ │ │ +│ {% endblock %} │ │ │ └───────────────────────────────────────────────────────│──│─┘ │ │ │ │ @@ -178,14 +178,14 @@ HTML template connects to Alpine.js component: │ vendor-edit.js │ │ │ ├───────────────────────────────────────────────────────│──│─┤ │ function adminVendorEdit() { ◄────────────────────────┘ │ │ -│ return { │ │ -│ ...data(), │ │ +│ return { │ │ +│ ...data(), │ │ │ vendor: null, ← Bound to x-text="vendor.name"│ │ │ loading: false, ← Bound to x-show="loading" │ │ -│ async init() {...} │ │ -│ }; │ │ -│ } │ │ -└───────────────────────────────────────────────────────────┘ +│ async init() {...} │ │ +│ }; │ │ +│ } │ │ +└──────────────────────────────────────────────────────────┘ 🔄 PAGE LIFECYCLE diff --git a/static/admin/js/components.js b/static/admin/js/components.js index fb8b40d0..53240e92 100644 --- a/static/admin/js/components.js +++ b/static/admin/js/components.js @@ -1,14 +1,8 @@ // static/admin/js/components.js -// Setup logging -const COMPONENTS_LOG_LEVEL = 3; - -const componentsLog = { - error: (...args) => COMPONENTS_LOG_LEVEL >= 1 && console.error('❌ [COMPONENTS ERROR]', ...args), - warn: (...args) => COMPONENTS_LOG_LEVEL >= 2 && console.warn('⚠️ [COMPONENTS WARN]', ...args), - info: (...args) => COMPONENTS_LOG_LEVEL >= 3 && console.info('ℹ️ [COMPONENTS INFO]', ...args), - debug: (...args) => COMPONENTS_LOG_LEVEL >= 4 && console.log('🔍 [COMPONENTS DEBUG]', ...args) -}; +// ✅ Use centralized logger - ONE LINE! +// Create custom logger for components page +const componentsLog = window.LogConfig.createLogger('COMPONENTS'); /** * Components Library Alpine.js Component @@ -132,7 +126,7 @@ function adminComponents() { } componentsLog.debug('Code copied to clipboard'); } catch (error) { - componentsLog.error('Failed to copy code:', error); + window.LogConfig.logError(error, 'Copy Code'); if (typeof Utils !== 'undefined' && Utils.showToast) { Utils.showToast('Failed to copy code', 'error'); } @@ -150,6 +144,8 @@ function adminComponents() { info: 'Here is some information.' }; + componentsLog.info('Showing toast example:', type); + if (typeof Utils !== 'undefined' && Utils.showToast) { Utils.showToast(messages[type] || messages.info, type); } else { @@ -170,6 +166,7 @@ function adminComponents() { } componentsLog.info('Initializing charts...'); + componentsLog.time('Chart Initialization'); // Pie Chart const pieCanvas = document.getElementById('examplePieChart'); @@ -284,9 +281,10 @@ function adminComponents() { componentsLog.debug('Bar chart initialized'); } + componentsLog.timeEnd('Chart Initialization'); componentsLog.info('All charts initialized successfully'); } catch (error) { - componentsLog.error('Error initializing charts:', error); + window.LogConfig.logError(error, 'Initialize Charts'); } } }; diff --git a/static/admin/js/dashboard.js b/static/admin/js/dashboard.js index 30d86852..3658a6cf 100644 --- a/static/admin/js/dashboard.js +++ b/static/admin/js/dashboard.js @@ -1,14 +1,7 @@ // static/admin/js/dashboard.js -// Log levels: 0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug -const DASHBOARD_LOG_LEVEL = 3; // Set to 3 for production, 4 for full debugging - -const dashLog = { - error: (...args) => DASHBOARD_LOG_LEVEL >= 1 && console.error('❌ [DASHBOARD ERROR]', ...args), - warn: (...args) => DASHBOARD_LOG_LEVEL >= 2 && console.warn('⚠️ [DASHBOARD WARN]', ...args), - info: (...args) => DASHBOARD_LOG_LEVEL >= 3 && console.info('ℹ️ [DASHBOARD INFO]', ...args), - debug: (...args) => DASHBOARD_LOG_LEVEL >= 4 && console.log('🔍 [DASHBOARD DEBUG]', ...args) -}; +// ✅ Use centralized logger - ONE LINE! +const dashLog = window.LogConfig.loggers.dashboard; function adminDashboard() { return { @@ -49,7 +42,11 @@ function adminDashboard() { window._dashboardInitialized = true; 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 ==='); }, @@ -63,8 +60,8 @@ function adminDashboard() { dashLog.debug('Dashboard state: loading=true, error=null'); try { - dashLog.info('Starting parallel data fetch...'); - const startTime = Date.now(); + dashLog.group('Loading dashboard data'); + const startTime = performance.now(); // Load stats and vendors in parallel await Promise.all([ @@ -72,17 +69,14 @@ function adminDashboard() { this.loadRecentVendors() ]); - const duration = Date.now() - startTime; + 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) { - dashLog.error('Dashboard load error:', error); - dashLog.error('Error details:', { - message: error.message, - name: error.name, - stack: error.stack - }); - + window.LogConfig.logError(error, 'Dashboard Load'); this.error = error.message; Utils.showToast('Failed to load dashboard data', 'error'); @@ -98,15 +92,17 @@ function adminDashboard() { */ async loadStats() { dashLog.info('Loading platform statistics...'); - dashLog.debug('API endpoint: /admin/dashboard/stats/platform'); + const url = '/admin/dashboard/stats/platform'; + + window.LogConfig.logApiCall('GET', url, null, 'request'); try { - const startTime = Date.now(); - const data = await apiClient.get('/admin/dashboard/stats/platform'); - const duration = Date.now() - startTime; + const startTime = performance.now(); + const data = await apiClient.get(url); + const duration = performance.now() - startTime; - dashLog.info(`Stats loaded in ${duration}ms`); - dashLog.debug('Raw stats data:', data); + window.LogConfig.logApiCall('GET', url, data, 'response'); + window.LogConfig.logPerformance('Load Stats', duration); // Map API response to stats cards this.stats = { @@ -129,18 +125,17 @@ function adminDashboard() { */ async loadRecentVendors() { dashLog.info('Loading recent vendors...'); - dashLog.debug('API endpoint: /admin/dashboard'); + const url = '/admin/dashboard'; + + window.LogConfig.logApiCall('GET', url, null, 'request'); try { - const startTime = Date.now(); - const data = await apiClient.get('/admin/dashboard'); - const duration = Date.now() - startTime; + const startTime = performance.now(); + const data = await apiClient.get(url); + const duration = performance.now() - startTime; - dashLog.info(`Recent vendors loaded in ${duration}ms`); - dashLog.debug('Vendors data:', { - count: data.recent_vendors?.length || 0, - hasData: !!data.recent_vendors - }); + window.LogConfig.logApiCall('GET', url, data, 'response'); + window.LogConfig.logPerformance('Load Recent Vendors', duration); this.recentVendors = data.recent_vendors || []; diff --git a/static/admin/js/icons-page.js b/static/admin/js/icons-page.js index 4e3bb0eb..0bce90cb 100644 --- a/static/admin/js/icons-page.js +++ b/static/admin/js/icons-page.js @@ -1,14 +1,8 @@ // static/admin/js/icons-page.js -// Setup logging -const ICONS_PAGE_LOG_LEVEL = 3; - -const iconsLog = { - error: (...args) => ICONS_PAGE_LOG_LEVEL >= 1 && console.error('❌ [ICONS PAGE ERROR]', ...args), - warn: (...args) => ICONS_PAGE_LOG_LEVEL >= 2 && console.warn('⚠️ [ICONS PAGE WARN]', ...args), - info: (...args) => ICONS_PAGE_LOG_LEVEL >= 3 && console.info('ℹ️ [ICONS PAGE INFO]', ...args), - debug: (...args) => ICONS_PAGE_LOG_LEVEL >= 4 && console.log('🔍 [ICONS PAGE DEBUG]', ...args) -}; +// ✅ Use centralized logger - ONE LINE! +// Create custom logger since icons page is not pre-configured +const iconsLog = window.LogConfig.createLogger('ICONS'); /** * Icons Browser Alpine.js Component @@ -60,9 +54,14 @@ function adminIcons() { } window._iconsPageInitialized = true; + const startTime = performance.now(); + // Load icons from global Icons object this.loadIcons(); + const duration = performance.now() - startTime; + window.LogConfig.logPerformance('Icons Page Init', duration); + iconsLog.info('=== ICONS PAGE INITIALIZATION COMPLETE ==='); }, @@ -169,7 +168,7 @@ function adminIcons() { Utils.showToast(`'${iconName}' code copied!`, 'success'); iconsLog.debug('Icon usage code copied:', iconName); } catch (error) { - iconsLog.error('Failed to copy code:', error); + window.LogConfig.logError(error, 'Copy Icon Usage'); Utils.showToast('Failed to copy code', 'error'); } }, @@ -183,7 +182,7 @@ function adminIcons() { Utils.showToast(`'${iconName}' copied!`, 'success'); iconsLog.debug('Icon name copied:', iconName); } catch (error) { - iconsLog.error('Failed to copy name:', error); + window.LogConfig.logError(error, 'Copy Icon Name'); Utils.showToast('Failed to copy name', 'error'); } }, diff --git a/static/admin/js/login.js b/static/admin/js/login.js index 346eccde..7a3346bd 100644 --- a/static/admin/js/login.js +++ b/static/admin/js/login.js @@ -1,14 +1,8 @@ // static/admin/js/login.js -// Log levels: 0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug -const LOG_LEVEL = 4; // Set to 4 for full debugging, 1 for errors only - -const log = { - error: (...args) => LOG_LEVEL >= 1 && console.error('❌ [ERROR]', ...args), - warn: (...args) => LOG_LEVEL >= 2 && console.warn('⚠️ [WARN]', ...args), - info: (...args) => LOG_LEVEL >= 3 && console.info('ℹ️ [INFO]', ...args), - debug: (...args) => LOG_LEVEL >= 4 && console.log('🔍 [DEBUG]', ...args) -}; +// ✅ Use centralized logger - ONE LINE! +// Create custom logger for login page +const loginLog = window.LogConfig.createLogger('LOGIN'); function adminLogin() { return { @@ -23,37 +17,37 @@ function adminLogin() { errors: {}, init() { - log.info('Login page initializing...'); - log.debug('Current pathname:', window.location.pathname); - log.debug('Current URL:', window.location.href); + loginLog.info('=== LOGIN PAGE INITIALIZING ==='); + loginLog.debug('Current pathname:', window.location.pathname); + loginLog.debug('Current URL:', window.location.href); // Just set theme - NO auth checking, NO token clearing! this.dark = localStorage.getItem('theme') === 'dark'; - log.debug('Dark mode:', this.dark); + loginLog.debug('Dark mode:', this.dark); // DON'T clear tokens on init! // If user lands here with a valid token, they might be navigating manually // or got redirected. Let them try to login or navigate away. const token = localStorage.getItem('admin_token'); if (token) { - log.warn('Found existing token on login page'); - log.debug('Token preview:', token.substring(0, 20) + '...'); - log.info('Not clearing token - user may have navigated here manually'); + loginLog.warn('Found existing token on login page'); + loginLog.debug('Token preview:', token.substring(0, 20) + '...'); + loginLog.info('Not clearing token - user may have navigated here manually'); } else { - log.debug('No existing token found'); + loginLog.debug('No existing token found'); } - log.info('Login page initialization complete'); + loginLog.info('=== LOGIN PAGE INITIALIZATION COMPLETE ==='); }, clearTokens() { - log.debug('Clearing all auth tokens...'); + loginLog.debug('Clearing all auth tokens...'); const tokensBefore = { admin_token: !!localStorage.getItem('admin_token'), admin_user: !!localStorage.getItem('admin_user'), token: !!localStorage.getItem('token') }; - log.debug('Tokens before clear:', tokensBefore); + loginLog.debug('Tokens before clear:', tokensBefore); localStorage.removeItem('admin_token'); localStorage.removeItem('admin_user'); @@ -64,67 +58,77 @@ function adminLogin() { admin_user: !!localStorage.getItem('admin_user'), token: !!localStorage.getItem('token') }; - log.debug('Tokens after clear:', tokensAfter); + loginLog.debug('Tokens after clear:', tokensAfter); }, clearErrors() { - log.debug('Clearing form errors'); + loginLog.debug('Clearing form errors'); this.error = null; this.success = null; this.errors = {}; }, validateForm() { - log.debug('Validating login form...'); + loginLog.debug('Validating login form...'); this.clearErrors(); let isValid = true; if (!this.credentials.username.trim()) { this.errors.username = 'Username is required'; - log.warn('Validation failed: Username is required'); + loginLog.warn('Validation failed: Username is required'); isValid = false; } if (!this.credentials.password) { this.errors.password = 'Password is required'; - log.warn('Validation failed: Password is required'); + loginLog.warn('Validation failed: Password is required'); isValid = false; } else if (this.credentials.password.length < 6) { this.errors.password = 'Password must be at least 6 characters'; - log.warn('Validation failed: Password too short'); + loginLog.warn('Validation failed: Password too short'); isValid = false; } - log.info('Form validation result:', isValid ? 'VALID' : 'INVALID'); + loginLog.info('Form validation result:', isValid ? 'VALID' : 'INVALID'); return isValid; }, async handleLogin() { - log.info('=== LOGIN ATTEMPT STARTED ==='); + loginLog.info('=== LOGIN ATTEMPT STARTED ==='); if (!this.validateForm()) { - log.warn('Form validation failed, aborting login'); + loginLog.warn('Form validation failed, aborting login'); return; } this.loading = true; this.clearErrors(); - log.debug('Login state set to loading'); + loginLog.debug('Login state set to loading'); try { - log.info('Calling login API endpoint...'); - log.debug('Username:', this.credentials.username); - log.debug('API endpoint: /api/v1/admin/auth/login'); + loginLog.info('Calling login API endpoint...'); + loginLog.debug('Username:', this.credentials.username); - const startTime = Date.now(); - const response = await apiClient.post('/admin/auth/login', { + const url = '/admin/auth/login'; + const payload = { username: this.credentials.username.trim(), password: this.credentials.password - }); - const duration = Date.now() - startTime; + }; - log.info(`Login API response received in ${duration}ms`); - log.debug('Response structure:', { + window.LogConfig.logApiCall('POST', url, { username: payload.username }, 'request'); + + const startTime = performance.now(); + const response = await apiClient.post(url, payload); + const duration = performance.now() - startTime; + + window.LogConfig.logApiCall('POST', url, { + hasToken: !!response.access_token, + user: response.user?.username + }, 'response'); + window.LogConfig.logPerformance('Login', duration); + + loginLog.info(`Login API response received in ${duration}ms`); + loginLog.debug('Response structure:', { hasToken: !!response.access_token, hasUser: !!response.user, userRole: response.user?.role, @@ -133,27 +137,27 @@ function adminLogin() { // Validate response if (!response.access_token) { - log.error('Invalid response: No access token'); + loginLog.error('Invalid response: No access token'); throw new Error('Invalid response from server - no token'); } if (response.user && response.user.role !== 'admin') { - log.error('Authorization failed: User is not admin', { + loginLog.error('Authorization failed: User is not admin', { actualRole: response.user.role }); throw new Error('Access denied. Admin privileges required.'); } - log.info('Login successful, storing authentication data...'); + loginLog.info('Login successful, storing authentication data...'); // Store authentication data localStorage.setItem('admin_token', response.access_token); localStorage.setItem('token', response.access_token); - log.debug('Token stored, length:', response.access_token.length); + loginLog.debug('Token stored, length:', response.access_token.length); if (response.user) { localStorage.setItem('admin_user', JSON.stringify(response.user)); - log.debug('User data stored:', { + loginLog.debug('User data stored:', { username: response.user.username, role: response.user.role, id: response.user.id @@ -163,7 +167,7 @@ function adminLogin() { // Verify storage const storedToken = localStorage.getItem('admin_token'); const storedUser = localStorage.getItem('admin_user'); - log.info('Storage verification:', { + loginLog.info('Storage verification:', { tokenStored: !!storedToken, userStored: !!storedUser, tokenLength: storedToken?.length @@ -171,44 +175,41 @@ function adminLogin() { // Show success message this.success = 'Login successful! Redirecting...'; - log.info('Success message displayed to user'); + loginLog.info('Success message displayed to user'); - log.info('Redirecting to dashboard immediately...'); - log.info('=== EXECUTING REDIRECT ==='); - log.debug('Target URL: /admin/dashboard'); - log.debug('Redirect method: window.location.href'); + loginLog.info('Redirecting to dashboard immediately...'); + loginLog.info('=== EXECUTING REDIRECT ==='); + loginLog.debug('Target URL: /admin/dashboard'); + loginLog.debug('Redirect method: window.location.href'); // Use href instead of replace to allow back button // But redirect IMMEDIATELY - don't wait! window.location.href = '/admin/dashboard'; } catch (error) { - log.error('Login failed:', error); - log.error('Error details:', { - message: error.message, - name: error.name, - stack: error.stack - }); + window.LogConfig.logError(error, 'Login'); this.error = error.message || 'Invalid username or password. Please try again.'; - log.info('Error message displayed to user:', this.error); + loginLog.info('Error message displayed to user:', this.error); // Only clear tokens on login FAILURE this.clearTokens(); - log.info('Tokens cleared after error'); + loginLog.info('Tokens cleared after error'); } finally { this.loading = false; - log.debug('Login state set to not loading'); - log.info('=== LOGIN ATTEMPT FINISHED ==='); + loginLog.debug('Login state set to not loading'); + loginLog.info('=== LOGIN ATTEMPT FINISHED ==='); } }, toggleDarkMode() { - log.debug('Toggling dark mode...'); + loginLog.debug('Toggling dark mode...'); this.dark = !this.dark; localStorage.setItem('theme', this.dark ? 'dark' : 'light'); - log.info('Dark mode:', this.dark ? 'ON' : 'OFF'); + loginLog.info('Dark mode:', this.dark ? 'ON' : 'OFF'); } } -} \ No newline at end of file +} + +loginLog.info('Login module loaded'); \ No newline at end of file diff --git a/static/admin/js/testing-hub.js b/static/admin/js/testing-hub.js index 6122a79d..6d274355 100644 --- a/static/admin/js/testing-hub.js +++ b/static/admin/js/testing-hub.js @@ -1,14 +1,8 @@ // static/admin/js/testing-hub.js -// Setup logging -const TESTING_HUB_LOG_LEVEL = 3; - -const testingLog = { - error: (...args) => TESTING_HUB_LOG_LEVEL >= 1 && console.error('❌ [TESTING HUB ERROR]', ...args), - warn: (...args) => TESTING_HUB_LOG_LEVEL >= 2 && console.warn('⚠️ [TESTING HUB WARN]', ...args), - info: (...args) => TESTING_HUB_LOG_LEVEL >= 3 && console.info('ℹ️ [TESTING HUB INFO]', ...args), - debug: (...args) => TESTING_HUB_LOG_LEVEL >= 4 && console.log('🔍 [TESTING HUB DEBUG]', ...args) -}; +// ✅ Use centralized logger - ONE LINE! +// Create custom logger for testing hub +const testingLog = window.LogConfig.createLogger('TESTING-HUB'); /** * Testing Hub Alpine.js Component diff --git a/static/admin/js/users.js b/static/admin/js/users.js index 18dab0ea..0af178b6 100644 --- a/static/admin/js/users.js +++ b/static/admin/js/users.js @@ -1,5 +1,16 @@ +// static/admin/js/users.js + +// ✅ Use centralized logger - ONE LINE! +const usersLog = window.LogConfig.loggers.users; + function adminUsers() { return { + // ✅ Inherit base layout functionality + ...data(), + + // ✅ Set page identifier + currentPage: 'users', + // State users: [], loading: false, @@ -22,15 +33,27 @@ function adminUsers() { }, // Initialization - init() { - Logger.info('Users page initialized', 'USERS'); - this.loadUsers(); - this.loadStats(); + async init() { + usersLog.info('=== USERS PAGE INITIALIZING ==='); + + // Prevent multiple initializations + if (window._usersInitialized) { + usersLog.warn('Users page already initialized, skipping...'); + return; + } + window._usersInitialized = true; + + await this.loadUsers(); + await this.loadStats(); + + usersLog.info('=== USERS PAGE INITIALIZATION COMPLETE ==='); }, // Load users from API async loadUsers() { + usersLog.info('Loading users...'); this.loading = true; + try { const params = new URLSearchParams({ page: this.pagination.page, @@ -38,15 +61,24 @@ function adminUsers() { ...this.filters }); - const response = await ApiClient.get(`/admin/users?${params}`); + const url = `/admin/users?${params}`; + window.LogConfig.logApiCall('GET', url, null, 'request'); + + const startTime = performance.now(); + const response = await apiClient.get(url); // ✅ Fixed: lowercase apiClient + const duration = performance.now() - startTime; + + window.LogConfig.logApiCall('GET', url, response, 'response'); + window.LogConfig.logPerformance('Load Users', duration); if (response.items) { this.users = response.items; this.pagination.total = response.total; this.pagination.pages = response.pages; + usersLog.info(`Loaded ${this.users.length} users`); } } catch (error) { - Logger.error('Failed to load users', 'USERS', error); + window.LogConfig.logError(error, 'Load Users'); Utils.showToast('Failed to load users', 'error'); } finally { this.loading = false; @@ -55,18 +87,28 @@ function adminUsers() { // Load statistics async loadStats() { + usersLog.info('Loading user statistics...'); + try { - const response = await ApiClient.get('/admin/users/stats'); + const url = '/admin/users/stats'; + window.LogConfig.logApiCall('GET', url, null, 'request'); + + const response = await apiClient.get(url); // ✅ Fixed: lowercase apiClient + + window.LogConfig.logApiCall('GET', url, response, 'response'); + if (response) { this.stats = response; + usersLog.debug('Stats loaded:', this.stats); } } catch (error) { - Logger.error('Failed to load stats', 'USERS', error); + window.LogConfig.logError(error, 'Load Stats'); } }, // Search with debounce debouncedSearch: Utils.debounce(function() { + usersLog.info('Search triggered:', this.filters.search); this.pagination.page = 1; this.loadUsers(); }, 500), @@ -75,6 +117,7 @@ function adminUsers() { nextPage() { if (this.pagination.page < this.pagination.pages) { this.pagination.page++; + usersLog.info('Next page:', this.pagination.page); this.loadUsers(); } }, @@ -82,59 +125,80 @@ function adminUsers() { previousPage() { if (this.pagination.page > 1) { this.pagination.page--; + usersLog.info('Previous page:', this.pagination.page); this.loadUsers(); } }, // Actions viewUser(user) { - Logger.info('View user', 'USERS', user); + usersLog.info('View user:', user.username); // TODO: Open view modal }, editUser(user) { - Logger.info('Edit user', 'USERS', user); + usersLog.info('Edit user:', user.username); // TODO: Open edit modal }, async toggleUserStatus(user) { const action = user.is_active ? 'deactivate' : 'activate'; + usersLog.info(`Toggle user status: ${action}`, user.username); + if (!confirm(`Are you sure you want to ${action} ${user.username}?`)) { + usersLog.info('Status toggle cancelled by user'); return; } try { - await ApiClient.put(`/admin/users/${user.id}/status`, { + const url = `/admin/users/${user.id}/status`; + window.LogConfig.logApiCall('PUT', url, { is_active: !user.is_active }, 'request'); + + await apiClient.put(url, { // ✅ Fixed: lowercase apiClient is_active: !user.is_active }); + Utils.showToast(`User ${action}d successfully`, 'success'); - this.loadUsers(); - this.loadStats(); + usersLog.info(`User ${action}d successfully`); + + await this.loadUsers(); + await this.loadStats(); } catch (error) { - Logger.error(`Failed to ${action} user`, 'USERS', error); + window.LogConfig.logError(error, `Toggle User Status (${action})`); Utils.showToast(`Failed to ${action} user`, 'error'); } }, async deleteUser(user) { + usersLog.warn('Delete user requested:', user.username); + if (!confirm(`Are you sure you want to delete ${user.username}? This action cannot be undone.`)) { + usersLog.info('Delete cancelled by user'); return; } try { - await ApiClient.delete(`/admin/users/${user.id}`); + const url = `/admin/users/${user.id}`; + window.LogConfig.logApiCall('DELETE', url, null, 'request'); + + await apiClient.delete(url); // ✅ Fixed: lowercase apiClient + Utils.showToast('User deleted successfully', 'success'); - this.loadUsers(); - this.loadStats(); + usersLog.info('User deleted successfully'); + + await this.loadUsers(); + await this.loadStats(); } catch (error) { - Logger.error('Failed to delete user', 'USERS', error); + window.LogConfig.logError(error, 'Delete User'); Utils.showToast('Failed to delete user', 'error'); } }, openCreateModal() { - Logger.info('Open create user modal', 'USERS'); + usersLog.info('Open create user modal'); // TODO: Open create modal } }; -} \ No newline at end of file +} + +usersLog.info('Users module loaded'); \ No newline at end of file diff --git a/static/admin/js/vendor-detail.js b/static/admin/js/vendor-detail.js index 754eb72b..061ccf4e 100644 --- a/static/admin/js/vendor-detail.js +++ b/static/admin/js/vendor-detail.js @@ -1,14 +1,8 @@ // static/admin/js/vendor-detail.js -// Log levels: 0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug -const VENDOR_DETAIL_LOG_LEVEL = 3; - -const detailLog = { - error: (...args) => VENDOR_DETAIL_LOG_LEVEL >= 1 && console.error('❌ [VENDOR_DETAIL ERROR]', ...args), - warn: (...args) => VENDOR_DETAIL_LOG_LEVEL >= 2 && console.warn('⚠️ [VENDOR_DETAIL WARN]', ...args), - info: (...args) => VENDOR_DETAIL_LOG_LEVEL >= 3 && console.info('ℹ️ [VENDOR_DETAIL INFO]', ...args), - debug: (...args) => VENDOR_DETAIL_LOG_LEVEL >= 4 && console.log('🔍 [VENDOR_DETAIL DEBUG]', ...args) -}; +// ✅ Use centralized logger - ONE LINE! +// Create custom logger for vendor detail +const detailLog = window.LogConfig.createLogger('VENDOR-DETAIL'); function adminVendorDetail() { return { @@ -57,9 +51,15 @@ function adminVendorDetail() { this.error = null; try { - const startTime = Date.now(); - const response = await apiClient.get(`/admin/vendors/${this.vendorCode}`); - const duration = Date.now() - startTime; + const url = `/admin/vendors/${this.vendorCode}`; + window.LogConfig.logApiCall('GET', url, null, 'request'); + + const startTime = performance.now(); + const response = await apiClient.get(url); + const duration = performance.now() - startTime; + + window.LogConfig.logApiCall('GET', url, response, 'response'); + window.LogConfig.logPerformance('Load Vendor Details', duration); this.vendor = response; @@ -72,7 +72,7 @@ function adminVendorDetail() { detailLog.debug('Full vendor data:', this.vendor); } catch (error) { - detailLog.error('Failed to load vendor:', error); + window.LogConfig.logError(error, 'Load Vendor Details'); this.error = error.message || 'Failed to load vendor details'; Utils.showToast('Failed to load vendor details', 'error'); } finally { @@ -107,8 +107,13 @@ function adminVendorDetail() { } try { + const url = `/admin/vendors/${this.vendorCode}?confirm=true`; + window.LogConfig.logApiCall('DELETE', url, null, 'request'); + detailLog.info('Deleting vendor:', this.vendorCode); - await apiClient.delete(`/admin/vendors/${this.vendorCode}?confirm=true`); + await apiClient.delete(url); + + window.LogConfig.logApiCall('DELETE', url, null, 'response'); Utils.showToast('Vendor deleted successfully', 'success'); detailLog.info('Vendor deleted successfully'); @@ -117,7 +122,7 @@ function adminVendorDetail() { setTimeout(() => window.location.href = '/admin/vendors', 1500); } catch (error) { - detailLog.error('Failed to delete vendor:', error); + window.LogConfig.logError(error, 'Delete Vendor'); Utils.showToast(error.message || 'Failed to delete vendor', 'error'); } }, diff --git a/static/admin/js/vendor-edit.js b/static/admin/js/vendor-edit.js index ce3f2d99..4944ba6c 100644 --- a/static/admin/js/vendor-edit.js +++ b/static/admin/js/vendor-edit.js @@ -1,14 +1,8 @@ // static/admin/js/vendor-edit.js -// Log levels: 0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug -const VENDOR_EDIT_LOG_LEVEL = 3; - -const editLog = { - error: (...args) => VENDOR_EDIT_LOG_LEVEL >= 1 && console.error('❌ [VENDOR_EDIT ERROR]', ...args), - warn: (...args) => VENDOR_EDIT_LOG_LEVEL >= 2 && console.warn('⚠️ [VENDOR_EDIT WARN]', ...args), - info: (...args) => VENDOR_EDIT_LOG_LEVEL >= 3 && console.info('ℹ️ [VENDOR_EDIT INFO]', ...args), - debug: (...args) => VENDOR_EDIT_LOG_LEVEL >= 4 && console.log('🔍 [VENDOR_EDIT DEBUG]', ...args) -}; +// ✅ Use centralized logger - ONE LINE! +// Create custom logger for vendor edit +const editLog = window.LogConfig.createLogger('VENDOR-EDIT'); function adminVendorEdit() { return { @@ -58,9 +52,15 @@ function adminVendorEdit() { this.loadingVendor = true; try { - const startTime = Date.now(); - const response = await apiClient.get(`/admin/vendors/${this.vendorCode}`); - const duration = Date.now() - startTime; + const url = `/admin/vendors/${this.vendorCode}`; + window.LogConfig.logApiCall('GET', url, null, 'request'); + + const startTime = performance.now(); + const response = await apiClient.get(url); + const duration = performance.now() - startTime; + + window.LogConfig.logApiCall('GET', url, response, 'response'); + window.LogConfig.logPerformance('Load Vendor', duration); this.vendor = response; @@ -83,7 +83,7 @@ function adminVendorEdit() { editLog.debug('Form data initialized:', this.formData); } catch (error) { - editLog.error('Failed to load vendor:', error); + window.LogConfig.logError(error, 'Load Vendor'); Utils.showToast('Failed to load vendor', 'error'); setTimeout(() => window.location.href = '/admin/vendors', 2000); } finally { @@ -108,12 +108,15 @@ function adminVendorEdit() { this.saving = true; try { - const startTime = Date.now(); - const response = await apiClient.put( - `/admin/vendors/${this.vendorCode}`, - this.formData - ); - const duration = Date.now() - startTime; + const url = `/admin/vendors/${this.vendorCode}`; + window.LogConfig.logApiCall('PUT', url, this.formData, 'request'); + + const startTime = performance.now(); + const response = await apiClient.put(url, this.formData); + const duration = performance.now() - startTime; + + window.LogConfig.logApiCall('PUT', url, response, 'response'); + window.LogConfig.logPerformance('Update Vendor', duration); this.vendor = response; Utils.showToast('Vendor updated successfully', 'success'); @@ -123,7 +126,7 @@ function adminVendorEdit() { // setTimeout(() => window.location.href = '/admin/vendors', 1500); } catch (error) { - editLog.error('Failed to update vendor:', error); + window.LogConfig.logError(error, 'Update Vendor'); // Handle validation errors if (error.details && error.details.validation_errors) { @@ -155,17 +158,21 @@ function adminVendorEdit() { this.saving = true; try { - const response = await apiClient.put( - `/admin/vendors/${this.vendorCode}/verification`, - { is_verified: !this.vendor.is_verified } - ); + const url = `/admin/vendors/${this.vendorCode}/verification`; + const payload = { is_verified: !this.vendor.is_verified }; + + window.LogConfig.logApiCall('PUT', url, payload, 'request'); + + const response = await apiClient.put(url, payload); + + window.LogConfig.logApiCall('PUT', url, response, 'response'); this.vendor = response; Utils.showToast(`Vendor ${action}ed successfully`, 'success'); editLog.info(`Vendor ${action}ed successfully`); } catch (error) { - editLog.error(`Failed to ${action} vendor:`, error); + window.LogConfig.logError(error, `Toggle Verification (${action})`); Utils.showToast(`Failed to ${action} vendor`, 'error'); } finally { this.saving = false; @@ -184,17 +191,21 @@ function adminVendorEdit() { this.saving = true; try { - const response = await apiClient.put( - `/admin/vendors/${this.vendorCode}/status`, - { is_active: !this.vendor.is_active } - ); + const url = `/admin/vendors/${this.vendorCode}/status`; + const payload = { is_active: !this.vendor.is_active }; + + window.LogConfig.logApiCall('PUT', url, payload, 'request'); + + const response = await apiClient.put(url, payload); + + window.LogConfig.logApiCall('PUT', url, response, 'response'); this.vendor = response; Utils.showToast(`Vendor ${action}d successfully`, 'success'); editLog.info(`Vendor ${action}d successfully`); } catch (error) { - editLog.error(`Failed to ${action} vendor:`, error); + window.LogConfig.logError(error, `Toggle Active Status (${action})`); Utils.showToast(`Failed to ${action} vendor`, 'error'); } finally { this.saving = false; diff --git a/static/admin/js/vendors.js b/static/admin/js/vendors.js index 62be60af..22877613 100644 --- a/static/admin/js/vendors.js +++ b/static/admin/js/vendors.js @@ -1,14 +1,7 @@ // static/admin/js/vendors.js -// Log levels: 0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug -const VENDORS_LOG_LEVEL = 3; - -const vendorsLog = { - error: (...args) => VENDORS_LOG_LEVEL >= 1 && console.error('❌ [VENDORS ERROR]', ...args), - warn: (...args) => VENDORS_LOG_LEVEL >= 2 && console.warn('⚠️ [VENDORS WARN]', ...args), - info: (...args) => VENDORS_LOG_LEVEL >= 3 && console.info('ℹ️ [VENDORS INFO]', ...args), - debug: (...args) => VENDORS_LOG_LEVEL >= 4 && console.log('🔍 [VENDORS DEBUG]', ...args) -}; +// ✅ Use centralized logger - ONE LINE! +const vendorsLog = window.LogConfig.loggers.vendors; // ============================================ // VENDOR LIST FUNCTION @@ -47,8 +40,10 @@ function adminVendors() { } window._vendorsInitialized = true; + vendorsLog.group('Loading vendors data'); await this.loadVendors(); await this.loadStats(); + vendorsLog.groupEnd(); vendorsLog.info('=== VENDORS PAGE INITIALIZATION COMPLETE ==='); }, @@ -122,9 +117,15 @@ function adminVendors() { this.error = null; try { - const startTime = Date.now(); - const response = await apiClient.get('/admin/vendors'); - const duration = Date.now() - startTime; + const url = '/admin/vendors'; + window.LogConfig.logApiCall('GET', url, null, 'request'); + + const startTime = performance.now(); + const response = await apiClient.get(url); + const duration = performance.now() - startTime; + + window.LogConfig.logApiCall('GET', url, response, 'response'); + window.LogConfig.logPerformance('Load Vendors', duration); // Handle different response structures this.vendors = response.vendors || response.items || response || []; @@ -142,7 +143,7 @@ function adminVendors() { this.page = 1; } catch (error) { - vendorsLog.error('Failed to load vendors:', error); + window.LogConfig.logError(error, 'Load Vendors'); this.error = error.message || 'Failed to load vendors'; Utils.showToast('Failed to load vendors', 'error'); } finally { @@ -155,15 +156,21 @@ function adminVendors() { vendorsLog.info('Loading vendor statistics...'); try { - const startTime = Date.now(); - const response = await apiClient.get('/admin/vendors/stats'); - const duration = Date.now() - startTime; + const url = '/admin/vendors/stats'; + window.LogConfig.logApiCall('GET', url, null, 'request'); + + const startTime = performance.now(); + const response = await apiClient.get(url); + const duration = performance.now() - startTime; + + window.LogConfig.logApiCall('GET', url, response, 'response'); + window.LogConfig.logPerformance('Load Vendor Stats', duration); this.stats = response; vendorsLog.info(`Stats loaded in ${duration}ms`, this.stats); } catch (error) { - vendorsLog.error('Failed to load stats:', error); + window.LogConfig.logError(error, 'Load Vendor Stats'); // Don't show error toast for stats, just log it } }, @@ -230,8 +237,13 @@ function adminVendors() { } try { + const url = `/admin/vendors/${vendor.vendor_code}`; + window.LogConfig.logApiCall('DELETE', url, null, 'request'); + vendorsLog.info('Deleting vendor:', vendor.vendor_code); - await apiClient.delete(`/admin/vendors/${vendor.vendor_code}`); + await apiClient.delete(url); + + window.LogConfig.logApiCall('DELETE', url, null, 'response'); Utils.showToast('Vendor deleted successfully', 'success'); vendorsLog.info('Vendor deleted successfully'); @@ -241,7 +253,7 @@ function adminVendors() { await this.loadStats(); } catch (error) { - vendorsLog.error('Failed to delete vendor:', error); + window.LogConfig.logError(error, 'Delete Vendor'); Utils.showToast(error.message || 'Failed to delete vendor', 'error'); } }, @@ -249,8 +261,12 @@ function adminVendors() { // Refresh vendors list async refresh() { vendorsLog.info('=== VENDORS REFRESH TRIGGERED ==='); + + vendorsLog.group('Refreshing vendors data'); await this.loadVendors(); await this.loadStats(); + vendorsLog.groupEnd(); + Utils.showToast('Vendors list refreshed', 'success'); vendorsLog.info('=== VENDORS REFRESH COMPLETE ==='); } diff --git a/static/shared/js/icons.js b/static/shared/js/icons.js index eae56a77..a19a5d83 100644 --- a/static/shared/js/icons.js +++ b/static/shared/js/icons.js @@ -106,6 +106,7 @@ const Icons = { // Testing & QA Icons 'clipboard-list': ``, 'check-circle': ``, + 'x-circle': ``, 'lightning-bolt': ``, 'clock': ``, 'lock-closed': ``,