Files
orion/app/modules/tenancy/static/admin/js/vendor-themes.js
Samir Boulahtit 4e28d91a78 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>
2026-02-01 14:34:16 +01:00

172 lines
5.6 KiB
JavaScript

// noqa: js-006 - async init pattern is safe, loadData has try/catch
// static/admin/js/vendor-themes.js
/**
* Admin vendor themes selection page
*/
// ✅ Use centralized logger
const vendorThemesLog = window.LogConfig.loggers.vendorTheme;
vendorThemesLog.info('Loading...');
function adminVendorThemes() {
vendorThemesLog.debug('adminVendorThemes() called');
return {
// Inherit base layout state
...data(),
// Set page identifier
currentPage: 'vendor-theme',
// State
loading: false,
error: '',
vendors: [],
selectedVendorCode: '',
// Selected vendor for filter (Tom Select)
selectedVendor: null,
vendorSelector: null,
// Search/filter
searchQuery: '',
async init() {
// Guard against multiple initialization
if (window._adminVendorThemesInitialized) {
return;
}
window._adminVendorThemesInitialized = true;
vendorThemesLog.info('Vendor Themes init() called');
// Initialize vendor selector (Tom Select)
this.$nextTick(() => {
this.initVendorSelector();
});
// Check localStorage for saved vendor
const savedVendorId = localStorage.getItem('vendor_themes_selected_vendor_id');
if (savedVendorId) {
vendorThemesLog.info('Restoring saved vendor:', savedVendorId);
await this.loadVendors();
// Restore vendor after vendors are loaded
setTimeout(async () => {
await this.restoreSavedVendor(parseInt(savedVendorId));
}, 200);
} else {
await this.loadVendors();
}
vendorThemesLog.info('Vendor Themes initialization complete');
},
/**
* Restore saved vendor from localStorage
*/
async restoreSavedVendor(vendorId) {
try {
const vendor = await apiClient.get(`/admin/vendors/${vendorId}`);
if (this.vendorSelector && vendor) {
// Use the vendor selector's setValue method
this.vendorSelector.setValue(vendor.id, vendor);
// Set the filter state
this.selectedVendor = vendor;
vendorThemesLog.info('Restored vendor:', vendor.name);
}
} catch (error) {
vendorThemesLog.warn('Failed to restore saved vendor, clearing localStorage:', error);
localStorage.removeItem('vendor_themes_selected_vendor_id');
}
},
/**
* Initialize vendor selector with Tom Select
*/
initVendorSelector() {
if (!this.$refs.vendorSelect) {
vendorThemesLog.warn('Vendor select element not found');
return;
}
this.vendorSelector = initVendorSelector(this.$refs.vendorSelect, {
placeholder: 'Search vendor...',
onSelect: (vendor) => {
vendorThemesLog.info('Vendor selected:', vendor);
this.selectedVendor = vendor;
// Save to localStorage
localStorage.setItem('vendor_themes_selected_vendor_id', vendor.id.toString());
},
onClear: () => {
vendorThemesLog.info('Vendor filter cleared');
this.selectedVendor = null;
// Clear from localStorage
localStorage.removeItem('vendor_themes_selected_vendor_id');
}
});
},
/**
* Clear vendor filter
*/
clearVendorFilter() {
if (this.vendorSelector) {
this.vendorSelector.clear();
}
this.selectedVendor = null;
// Clear from localStorage
localStorage.removeItem('vendor_themes_selected_vendor_id');
},
async loadVendors() {
this.loading = true;
this.error = '';
try {
const response = await apiClient.get('/admin/vendors?limit=1000');
this.vendors = response.vendors || [];
vendorThemesLog.debug('Loaded vendors:', this.vendors.length);
} catch (error) {
vendorThemesLog.error('Failed to load vendors:', error);
this.error = error.message || 'Failed to load vendors';
} finally {
this.loading = false;
}
},
/**
* Computed: Filtered vendors based on search and selected vendor
*/
get filteredVendors() {
let filtered = this.vendors;
// If a vendor is selected via Tom Select, show only that vendor
if (this.selectedVendor) {
filtered = this.vendors.filter(v => v.id === this.selectedVendor.id);
}
// Otherwise filter by search query
else if (this.searchQuery) {
const query = this.searchQuery.toLowerCase();
filtered = this.vendors.filter(v =>
v.name.toLowerCase().includes(query) ||
(v.vendor_code && v.vendor_code.toLowerCase().includes(query))
);
}
return filtered;
},
navigateToTheme() {
if (!this.selectedVendorCode) {
return;
}
window.location.href = `/admin/vendors/${this.selectedVendorCode}/theme`;
}
};
}
vendorThemesLog.info('Module loaded');