// app/static/store/js/login.js // noqa: js-003 - Standalone login page without store layout // noqa: js-004 - Standalone page has no currentPage sidebar highlight /** * Store login page logic */ // Create custom logger for store login page const storeLoginLog = window.LogConfig.createLogger('STORE-LOGIN'); function languageSelector(currentLang, enabledLanguages) { return { currentLang: currentLang || 'fr', languages: enabledLanguages || ['en', 'fr', 'de', 'lb'], async setLanguage(lang) { if (lang === this.currentLang) return; try { // noqa: JS-008 - Login page has no apiClient; raw fetch is intentional await fetch('/api/v1/platform/language/set', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ language: lang }), }); window.location.reload(); } catch (error) { storeLoginLog.error('Failed to set language:', error); } }, }; } function storeLogin() { return { credentials: { username: '', password: '' }, store: null, storeCode: null, loading: false, checked: false, error: '', success: '', errors: {}, dark: false, async init() { // Guard against multiple initialization if (window._storeLoginInitialized) return; window._storeLoginInitialized = true; try { storeLoginLog.info('=== STORE LOGIN PAGE INITIALIZING ==='); // Load theme const theme = localStorage.getItem('theme'); if (theme === 'dark') { this.dark = true; } storeLoginLog.debug('Dark mode:', this.dark); // Get store code from URL path // Supports both /store/{code}/login and /platforms/{platform}/store/{code}/login const pathSegments = window.location.pathname.split('/').filter(Boolean); const storeIndex = pathSegments.indexOf('store'); if (storeIndex !== -1 && pathSegments[storeIndex + 1]) { this.storeCode = pathSegments[storeIndex + 1]; storeLoginLog.debug('Store code from URL:', this.storeCode); await this.loadStore(); } this.checked = true; storeLoginLog.info('=== STORE LOGIN PAGE INITIALIZATION COMPLETE ==='); } catch (error) { storeLoginLog.error('Failed to initialize login page:', error); this.checked = true; } }, async loadStore() { storeLoginLog.info('Loading store information...'); this.loading = true; try { const response = await apiClient.get(`/store/info/${this.storeCode}`); this.store = response; storeLoginLog.info('Store loaded successfully:', { code: this.store.code, name: this.store.name }); } catch (error) { window.LogConfig.logError(error, 'Load Store'); this.error = 'Failed to load store information'; } finally { this.loading = false; } }, async handleLogin() { storeLoginLog.info('=== STORE LOGIN ATTEMPT STARTED ==='); this.clearErrors(); this.loading = true; try { if (!this.credentials.username) { this.errors.username = 'Username is required'; } if (!this.credentials.password) { this.errors.password = 'Password is required'; } if (Object.keys(this.errors).length > 0) { storeLoginLog.warn('Validation failed:', this.errors); this.loading = false; return; } storeLoginLog.info('Calling store login API...'); storeLoginLog.debug('Username:', this.credentials.username); storeLoginLog.debug('Store code:', this.storeCode); window.LogConfig.logApiCall('POST', '/store/auth/login', { username: this.credentials.username, store_code: this.storeCode }, 'request'); const startTime = performance.now(); const response = await apiClient.post('/store/auth/login', { email_or_username: this.credentials.username, password: this.credentials.password, store_code: this.storeCode }); const duration = performance.now() - startTime; window.LogConfig.logApiCall('POST', '/store/auth/login', { hasToken: !!response.access_token, user: response.user?.username }, 'response'); window.LogConfig.logPerformance('Store Login', duration); storeLoginLog.info('Login successful!'); storeLoginLog.debug('Storing authentication data...'); // Store token with correct key that apiClient expects localStorage.setItem('store_token', response.access_token); localStorage.setItem('currentUser', JSON.stringify(response.user)); localStorage.setItem('storeCode', this.storeCode); storeLoginLog.debug('Token stored as store_token in localStorage'); this.success = 'Login successful! Redirecting...'; // Check for last visited page (saved before logout) const lastPage = localStorage.getItem('store_last_visited_page'); const validLastPage = lastPage && lastPage.startsWith(`/store/${this.storeCode}/`) && !lastPage.includes('/login') && !lastPage.includes('/onboarding'); const redirectTo = validLastPage ? lastPage : `/store/${this.storeCode}/dashboard`; storeLoginLog.info('Last visited page:', lastPage); storeLoginLog.info('Redirecting to:', redirectTo); setTimeout(() => { window.location.href = redirectTo; }, 1000); } catch (error) { window.LogConfig.logError(error, 'Store Login'); if (error.status === 401) { this.error = 'Invalid username or password'; } else if (error.status === 403) { this.error = 'Your account does not have access to this store'; } else { this.error = error.message || 'Login failed. Please try again.'; } storeLoginLog.info('Error message displayed to user:', this.error); } finally { this.loading = false; storeLoginLog.info('=== STORE LOGIN ATTEMPT FINISHED ==='); } }, // Forgot password state rememberMe: false, showForgotPassword: false, forgotPasswordEmail: '', forgotPasswordLoading: false, async handleForgotPassword() { storeLoginLog.info('=== FORGOT PASSWORD ATTEMPT ==='); if (!this.forgotPasswordEmail.trim()) { this.error = 'Email is required'; return; } this.forgotPasswordLoading = true; this.clearErrors(); try { await apiClient.post('/store/auth/forgot-password', { email: this.forgotPasswordEmail.trim() }); this.success = 'If an account exists with this email, a password reset link has been sent.'; this.forgotPasswordEmail = ''; } catch (error) { window.LogConfig.logError(error, 'ForgotPassword'); this.error = error.message || 'Failed to send reset email. Please try again.'; } finally { this.forgotPasswordLoading = false; } }, clearErrors() { storeLoginLog.debug('Clearing form errors'); this.error = ''; this.errors = {}; }, toggleDarkMode() { storeLoginLog.debug('Toggling dark mode...'); this.dark = !this.dark; localStorage.setItem('theme', this.dark ? 'dark' : 'light'); storeLoginLog.info('Dark mode:', this.dark ? 'ON' : 'OFF'); } }; } storeLoginLog.info('Store login module loaded');