refactor: migrate templates and static files to self-contained modules
Templates Migration: - Migrate admin templates to modules (tenancy, billing, monitoring, marketplace, etc.) - Migrate vendor templates to modules (tenancy, billing, orders, messaging, etc.) - Migrate storefront templates to modules (catalog, customers, orders, cart, checkout, cms) - Migrate public templates to modules (billing, marketplace, cms) - Keep shared templates in app/templates/ (base.html, errors/, partials/, macros/) - Migrate letzshop partials to marketplace module Static Files Migration: - Migrate admin JS to modules: tenancy (23 files), core (5 files), monitoring (1 file) - Migrate vendor JS to modules: tenancy (4 files), core (2 files) - Migrate shared JS: vendor-selector.js to core, media-picker.js to cms - Migrate storefront JS: storefront-layout.js to core - Keep framework JS in static/ (api-client, utils, money, icons, log-config, lib/) - Update all template references to use module_static paths Naming Consistency: - Rename static/platform/ to static/public/ - Rename app/templates/platform/ to app/templates/public/ - Update all extends and static references Documentation: - Update module-system.md with shared templates documentation - Update frontend-structure.md with new module JS organization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
174
app/modules/tenancy/static/vendor/js/login.js
vendored
Normal file
174
app/modules/tenancy/static/vendor/js/login.js
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
// app/static/vendor/js/login.js
|
||||
// noqa: js-003 - Standalone login page without vendor layout
|
||||
// noqa: js-004 - Standalone page has no currentPage sidebar highlight
|
||||
/**
|
||||
* Vendor login page logic
|
||||
*/
|
||||
|
||||
// Create custom logger for vendor login page
|
||||
const vendorLoginLog = window.LogConfig.createLogger('VENDOR-LOGIN');
|
||||
|
||||
function vendorLogin() {
|
||||
return {
|
||||
credentials: {
|
||||
username: '',
|
||||
password: ''
|
||||
},
|
||||
vendor: null,
|
||||
vendorCode: null,
|
||||
loading: false,
|
||||
checked: false,
|
||||
error: '',
|
||||
success: '',
|
||||
errors: {},
|
||||
dark: false,
|
||||
|
||||
async init() {
|
||||
// Guard against multiple initialization
|
||||
if (window._vendorLoginInitialized) return;
|
||||
window._vendorLoginInitialized = true;
|
||||
|
||||
try {
|
||||
vendorLoginLog.info('=== VENDOR LOGIN PAGE INITIALIZING ===');
|
||||
|
||||
// Load theme
|
||||
const theme = localStorage.getItem('theme');
|
||||
if (theme === 'dark') {
|
||||
this.dark = true;
|
||||
}
|
||||
vendorLoginLog.debug('Dark mode:', this.dark);
|
||||
|
||||
// Get vendor code from URL path
|
||||
const pathSegments = window.location.pathname.split('/').filter(Boolean);
|
||||
if (pathSegments[0] === 'vendor' && pathSegments[1]) {
|
||||
this.vendorCode = pathSegments[1];
|
||||
vendorLoginLog.debug('Vendor code from URL:', this.vendorCode);
|
||||
await this.loadVendor();
|
||||
}
|
||||
this.checked = true;
|
||||
vendorLoginLog.info('=== VENDOR LOGIN PAGE INITIALIZATION COMPLETE ===');
|
||||
} catch (error) {
|
||||
vendorLoginLog.error('Failed to initialize login page:', error);
|
||||
this.checked = true;
|
||||
}
|
||||
},
|
||||
|
||||
async loadVendor() {
|
||||
vendorLoginLog.info('Loading vendor information...');
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await apiClient.get(`/vendor/info/${this.vendorCode}`);
|
||||
this.vendor = response;
|
||||
vendorLoginLog.info('Vendor loaded successfully:', {
|
||||
code: this.vendor.code,
|
||||
name: this.vendor.name
|
||||
});
|
||||
} catch (error) {
|
||||
window.LogConfig.logError(error, 'Load Vendor');
|
||||
this.error = 'Failed to load vendor information';
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
async handleLogin() {
|
||||
vendorLoginLog.info('=== VENDOR 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) {
|
||||
vendorLoginLog.warn('Validation failed:', this.errors);
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
vendorLoginLog.info('Calling vendor login API...');
|
||||
vendorLoginLog.debug('Username:', this.credentials.username);
|
||||
vendorLoginLog.debug('Vendor code:', this.vendorCode);
|
||||
|
||||
window.LogConfig.logApiCall('POST', '/vendor/auth/login', {
|
||||
username: this.credentials.username,
|
||||
vendor_code: this.vendorCode
|
||||
}, 'request');
|
||||
|
||||
const startTime = performance.now();
|
||||
const response = await apiClient.post('/vendor/auth/login', {
|
||||
email_or_username: this.credentials.username,
|
||||
password: this.credentials.password,
|
||||
vendor_code: this.vendorCode
|
||||
});
|
||||
const duration = performance.now() - startTime;
|
||||
|
||||
window.LogConfig.logApiCall('POST', '/vendor/auth/login', {
|
||||
hasToken: !!response.access_token,
|
||||
user: response.user?.username
|
||||
}, 'response');
|
||||
window.LogConfig.logPerformance('Vendor Login', duration);
|
||||
|
||||
vendorLoginLog.info('Login successful!');
|
||||
vendorLoginLog.debug('Storing authentication data...');
|
||||
|
||||
// Store token with correct key that apiClient expects
|
||||
localStorage.setItem('vendor_token', response.access_token);
|
||||
localStorage.setItem('currentUser', JSON.stringify(response.user));
|
||||
localStorage.setItem('vendorCode', this.vendorCode);
|
||||
vendorLoginLog.debug('Token stored as vendor_token in localStorage');
|
||||
|
||||
this.success = 'Login successful! Redirecting...';
|
||||
|
||||
// Check for last visited page (saved before logout)
|
||||
const lastPage = localStorage.getItem('vendor_last_visited_page');
|
||||
const validLastPage = lastPage &&
|
||||
lastPage.startsWith(`/vendor/${this.vendorCode}/`) &&
|
||||
!lastPage.includes('/login') &&
|
||||
!lastPage.includes('/onboarding');
|
||||
const redirectTo = validLastPage ? lastPage : `/vendor/${this.vendorCode}/dashboard`;
|
||||
|
||||
vendorLoginLog.info('Last visited page:', lastPage);
|
||||
vendorLoginLog.info('Redirecting to:', redirectTo);
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = redirectTo;
|
||||
}, 1000);
|
||||
|
||||
} catch (error) {
|
||||
window.LogConfig.logError(error, 'Vendor 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 vendor';
|
||||
} else {
|
||||
this.error = error.message || 'Login failed. Please try again.';
|
||||
}
|
||||
vendorLoginLog.info('Error message displayed to user:', this.error);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
vendorLoginLog.info('=== VENDOR LOGIN ATTEMPT FINISHED ===');
|
||||
}
|
||||
},
|
||||
|
||||
clearErrors() {
|
||||
vendorLoginLog.debug('Clearing form errors');
|
||||
this.error = '';
|
||||
this.errors = {};
|
||||
},
|
||||
|
||||
toggleDarkMode() {
|
||||
vendorLoginLog.debug('Toggling dark mode...');
|
||||
this.dark = !this.dark;
|
||||
localStorage.setItem('theme', this.dark ? 'dark' : 'light');
|
||||
vendorLoginLog.info('Dark mode:', this.dark ? 'ON' : 'OFF');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
vendorLoginLog.info('Vendor login module loaded');
|
||||
Reference in New Issue
Block a user