Files
orion/static/vendor/js/init-alpine.js
Samir Boulahtit 673748ed27 feat: remember last visited page after login
Users are now redirected to their last visited page after logging in,
instead of always going to the dashboard.

Implementation:
- Track current page in localStorage on every page load
- Exclude login, logout, onboarding, and error pages from tracking
- On login success, redirect to last visited page if valid
- Clear last visited page on logout

Admin:
- static/admin/js/init-alpine.js: Save page to admin_last_visited_page
- static/admin/js/login.js: Redirect to last page after login
- app/templates/admin/partials/header.html: Clear on logout

Vendor:
- static/vendor/js/init-alpine.js: Save page to vendor_last_visited_page
- static/vendor/js/login.js: Redirect to last page (validates vendor code)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 23:41:43 +01:00

182 lines
5.8 KiB
JavaScript

// app/static/vendor/js/init-alpine.js
/**
* Alpine.js initialization for vendor pages
* Provides common data and methods for all vendor pages
*/
// ✅ Use centralized logger
const vendorLog = window.LogConfig.log;
console.log('[VENDOR INIT-ALPINE] Loading...');
function data() {
console.log('[VENDOR INIT-ALPINE] data() function called');
return {
dark: false,
isSideMenuOpen: false,
isNotificationsMenuOpen: false,
isProfileMenuOpen: false,
currentPage: '',
currentUser: {},
vendor: null,
vendorCode: null,
init() {
// Set current page from URL
const path = window.location.pathname;
const segments = path.split('/').filter(Boolean);
this.currentPage = segments[segments.length - 1] || 'dashboard';
// Get vendor code from URL
if (segments[0] === 'vendor' && segments[1]) {
this.vendorCode = segments[1];
}
// Load user from localStorage
const user = localStorage.getItem('currentUser');
if (user) {
this.currentUser = JSON.parse(user);
}
// Load theme preference
const theme = localStorage.getItem('theme');
if (theme === 'dark') {
this.dark = true;
}
// Load vendor info
this.loadVendorInfo();
// Save last visited page (for redirect after login)
// Exclude login, logout, onboarding, error pages
if (!path.includes('/login') &&
!path.includes('/logout') &&
!path.includes('/onboarding') &&
!path.includes('/errors/')) {
try {
localStorage.setItem('vendor_last_visited_page', path);
} catch (e) {
// Ignore storage errors
}
}
},
async loadVendorInfo() {
if (!this.vendorCode) return;
try {
// apiClient prepends /api/v1, so /vendor/{code} → /api/v1/vendor/{code}
const response = await apiClient.get(`/vendor/${this.vendorCode}`);
this.vendor = response;
vendorLog.debug('Vendor info loaded', this.vendor);
} catch (error) {
vendorLog.error('Failed to load vendor info', error);
}
},
toggleSideMenu() {
this.isSideMenuOpen = !this.isSideMenuOpen;
},
closeSideMenu() {
this.isSideMenuOpen = false;
},
toggleNotificationsMenu() {
this.isNotificationsMenuOpen = !this.isNotificationsMenuOpen;
if (this.isNotificationsMenuOpen) {
this.isProfileMenuOpen = false;
}
},
closeNotificationsMenu() {
this.isNotificationsMenuOpen = false;
},
toggleProfileMenu() {
this.isProfileMenuOpen = !this.isProfileMenuOpen;
if (this.isProfileMenuOpen) {
this.isNotificationsMenuOpen = false;
}
},
closeProfileMenu() {
this.isProfileMenuOpen = false;
},
toggleTheme() {
this.dark = !this.dark;
localStorage.setItem('theme', this.dark ? 'dark' : 'light');
},
async handleLogout() {
console.log('🚪 Logging out vendor user...');
try {
// Call logout API
await apiClient.post('/vendor/auth/logout');
console.log('✅ Logout API called successfully');
} catch (error) {
console.error('⚠️ Logout API error (continuing anyway):', error);
} finally {
// Clear vendor tokens only (not admin or customer tokens)
console.log('🧹 Clearing vendor tokens...');
localStorage.removeItem('vendor_token');
localStorage.removeItem('vendor_user');
localStorage.removeItem('currentUser');
localStorage.removeItem('vendorCode');
localStorage.removeItem('vendor_last_visited_page');
// Note: Do NOT use localStorage.clear() - it would clear admin/customer tokens too
console.log('🔄 Redirecting to login...');
window.location.href = `/vendor/${this.vendorCode}/login`;
}
}
};
}
/**
* Language Selector Component
* Alpine.js component for language switching in vendor dashboard
*/
function languageSelector(currentLang, enabledLanguages) {
return {
isLangOpen: false,
currentLang: currentLang || 'fr',
languages: enabledLanguages || ['en', 'fr', 'de', 'lb'],
languageNames: {
'en': 'English',
'fr': 'Français',
'de': 'Deutsch',
'lb': 'Lëtzebuergesch'
},
languageFlags: {
'en': 'gb',
'fr': 'fr',
'de': 'de',
'lb': 'lu'
},
async setLanguage(lang) {
if (lang === this.currentLang) {
this.isLangOpen = false;
return;
}
try {
const response = await fetch('/api/v1/language/set', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ language: lang })
});
if (response.ok) {
this.currentLang = lang;
window.location.reload();
}
} catch (error) {
console.error('Failed to set language:', error);
}
this.isLangOpen = false;
}
};
}
window.languageSelector = languageSelector;