feat: add configurable currency locale and fix vendor JS init
Currency Locale Configuration: - Add platform-level storefront settings (locale, currency) - Create PlatformSettingsService with resolution chain: vendor → AdminSetting → environment → hardcoded fallback - Add storefront_locale nullable field to Vendor model - Update shop routes to resolve and pass locale to templates - Add window.SHOP_CONFIG for frontend JavaScript access - Centralize formatPrice() in shop-layout.js using SHOP_CONFIG - Remove local formatPrice functions from shop templates Vendor JS Bug Fix: - Fix vendorCode being null on all vendor pages - Root cause: page components overriding init() without calling parent - Add parent init call to 14 vendor JS files - Add JS-013 architecture rule to prevent future regressions - Validator now checks vendor JS files for parent init pattern Files changed: - New: app/services/platform_settings_service.py - New: alembic/versions/s7a8b9c0d1e2_add_storefront_locale_to_vendors.py - Modified: 14 vendor JS files, shop templates, validation scripts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -219,12 +219,15 @@ function shopLayoutData() {
|
||||
}, 3000);
|
||||
},
|
||||
|
||||
// Format currency
|
||||
formatPrice(price) {
|
||||
return new Intl.NumberFormat('en-US', {
|
||||
// Format currency using configured locale
|
||||
formatPrice(amount) {
|
||||
if (!amount && amount !== 0) return '';
|
||||
const locale = window.SHOP_CONFIG?.locale || 'fr-LU';
|
||||
const currency = window.SHOP_CONFIG?.currency || 'EUR';
|
||||
return new Intl.NumberFormat(locale, {
|
||||
style: 'currency',
|
||||
currency: 'USD'
|
||||
}).format(price);
|
||||
currency: currency
|
||||
}).format(amount);
|
||||
},
|
||||
|
||||
// Format date
|
||||
|
||||
6
static/vendor/js/analytics.js
vendored
6
static/vendor/js/analytics.js
vendored
@@ -58,6 +58,12 @@ function vendorAnalytics() {
|
||||
}
|
||||
window._vendorAnalyticsInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.loadAllData();
|
||||
} catch (error) {
|
||||
|
||||
6
static/vendor/js/billing.js
vendored
6
static/vendor/js/billing.js
vendored
@@ -33,6 +33,12 @@ function vendorBilling() {
|
||||
if (window._vendorBillingInitialized) return;
|
||||
window._vendorBillingInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
try {
|
||||
// Check URL params for success/cancel
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
|
||||
6
static/vendor/js/content-page-edit.js
vendored
6
static/vendor/js/content-page-edit.js
vendored
@@ -44,6 +44,12 @@ function vendorContentPageEditor(pageId) {
|
||||
}
|
||||
window._vendorContentPageEditInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
try {
|
||||
contentPageEditLog.info('=== VENDOR CONTENT PAGE EDITOR INITIALIZING ===');
|
||||
contentPageEditLog.info('Page ID:', this.pageId);
|
||||
|
||||
6
static/vendor/js/content-pages.js
vendored
6
static/vendor/js/content-pages.js
vendored
@@ -36,6 +36,12 @@ function vendorContentPagesManager() {
|
||||
}
|
||||
window._vendorContentPagesInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
await this.loadPages();
|
||||
|
||||
contentPagesLog.info('=== VENDOR CONTENT PAGES MANAGER INITIALIZATION COMPLETE ===');
|
||||
|
||||
6
static/vendor/js/customers.js
vendored
6
static/vendor/js/customers.js
vendored
@@ -106,6 +106,12 @@ function vendorCustomers() {
|
||||
}
|
||||
window._vendorCustomersInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
// Load platform settings for rows per page
|
||||
if (window.PlatformSettings) {
|
||||
this.pagination.per_page = await window.PlatformSettings.getRowsPerPage();
|
||||
|
||||
6
static/vendor/js/inventory.js
vendored
6
static/vendor/js/inventory.js
vendored
@@ -137,6 +137,12 @@ function vendorInventory() {
|
||||
}
|
||||
window._vendorInventoryInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
// Load platform settings for rows per page
|
||||
if (window.PlatformSettings) {
|
||||
this.pagination.per_page = await window.PlatformSettings.getRowsPerPage();
|
||||
|
||||
6
static/vendor/js/messages.js
vendored
6
static/vendor/js/messages.js
vendored
@@ -65,6 +65,12 @@ function vendorMessages(initialConversationId = null) {
|
||||
if (window._vendorMessagesInitialized) return;
|
||||
window._vendorMessagesInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
try {
|
||||
messagesLog.debug('Initializing vendor messages page');
|
||||
await Promise.all([
|
||||
|
||||
6
static/vendor/js/notifications.js
vendored
6
static/vendor/js/notifications.js
vendored
@@ -60,6 +60,12 @@ function vendorNotifications() {
|
||||
}
|
||||
window._vendorNotificationsInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.loadNotifications();
|
||||
} catch (error) {
|
||||
|
||||
6
static/vendor/js/order-detail.js
vendored
6
static/vendor/js/order-detail.js
vendored
@@ -62,6 +62,12 @@ function vendorOrderDetail() {
|
||||
}
|
||||
window._orderDetailInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
if (!this.orderId) {
|
||||
this.error = 'Order ID not provided';
|
||||
this.loading = false;
|
||||
|
||||
6
static/vendor/js/orders.js
vendored
6
static/vendor/js/orders.js
vendored
@@ -137,6 +137,12 @@ function vendorOrders() {
|
||||
}
|
||||
window._vendorOrdersInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
// Load platform settings for rows per page
|
||||
if (window.PlatformSettings) {
|
||||
this.pagination.per_page = await window.PlatformSettings.getRowsPerPage();
|
||||
|
||||
6
static/vendor/js/products.js
vendored
6
static/vendor/js/products.js
vendored
@@ -121,6 +121,12 @@ function vendorProducts() {
|
||||
}
|
||||
window._vendorProductsInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
// Load platform settings for rows per page
|
||||
if (window.PlatformSettings) {
|
||||
this.pagination.per_page = await window.PlatformSettings.getRowsPerPage();
|
||||
|
||||
6
static/vendor/js/profile.js
vendored
6
static/vendor/js/profile.js
vendored
@@ -54,6 +54,12 @@ function vendorProfile() {
|
||||
}
|
||||
window._vendorProfileInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.loadProfile();
|
||||
} catch (error) {
|
||||
|
||||
6
static/vendor/js/settings.js
vendored
6
static/vendor/js/settings.js
vendored
@@ -68,6 +68,12 @@ function vendorSettings() {
|
||||
}
|
||||
window._vendorSettingsInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.loadSettings();
|
||||
} catch (error) {
|
||||
|
||||
6
static/vendor/js/team.js
vendored
6
static/vendor/js/team.js
vendored
@@ -73,6 +73,12 @@ function vendorTeam() {
|
||||
}
|
||||
window._vendorTeamInitialized = true;
|
||||
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
try {
|
||||
await Promise.all([
|
||||
this.loadMembers(),
|
||||
|
||||
Reference in New Issue
Block a user