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:
@@ -77,6 +77,60 @@ javascript_rules:
|
||||
file_pattern: "static/**/js/**/*.js"
|
||||
check: "async_error_handling"
|
||||
|
||||
- id: "JS-013"
|
||||
name: "Components overriding init() must call parent init"
|
||||
severity: "error"
|
||||
description: |
|
||||
When an Alpine.js component spreads ...data() and defines its own init() method,
|
||||
it MUST call the parent init() first. The parent init() sets critical properties
|
||||
like vendorCode (from URL), currentUser, and theme preference.
|
||||
|
||||
Without calling parent init(), properties like vendorCode will be null, causing
|
||||
API calls like `/vendor/${this.vendorCode}/settings` to fail with
|
||||
"Endpoint not found: /api/v1/vendor/null/settings".
|
||||
|
||||
WRONG (parent init never called):
|
||||
function vendorSettings() {
|
||||
return {
|
||||
...data(),
|
||||
async init() {
|
||||
await this.loadSettings(); // this.vendorCode is null!
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
RIGHT (call parent init first):
|
||||
function vendorSettings() {
|
||||
return {
|
||||
...data(),
|
||||
async init() {
|
||||
// IMPORTANT: Call parent init first to set vendorCode from URL
|
||||
const parentInit = data().init;
|
||||
if (parentInit) {
|
||||
await parentInit.call(this);
|
||||
}
|
||||
|
||||
await this.loadSettings(); // this.vendorCode is now set
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
This pattern is required for ALL page-specific JavaScript files that:
|
||||
1. Use ...data() to inherit base layout functionality
|
||||
2. Define their own init() method
|
||||
pattern:
|
||||
file_pattern: "static/vendor/js/**/*.js"
|
||||
check: "parent_init_call"
|
||||
required_when:
|
||||
- "contains: '...data()'"
|
||||
- "contains: 'async init()'"
|
||||
required_pattern:
|
||||
- "data\\(\\)\\.init"
|
||||
- "parentInit"
|
||||
exceptions:
|
||||
- "init-alpine.js"
|
||||
- "login.js"
|
||||
|
||||
- id: "JS-007"
|
||||
name: "Set loading state before async operations"
|
||||
severity: "warning"
|
||||
|
||||
Reference in New Issue
Block a user