// static/vendor/js/settings.js /** * Vendor settings management page logic * Configure vendor preferences and integrations */ const vendorSettingsLog = window.LogConfig.loggers.vendorSettings || window.LogConfig.createLogger('vendorSettings', false); vendorSettingsLog.info('Loading...'); function vendorSettings() { vendorSettingsLog.info('vendorSettings() called'); return { // Inherit base layout state ...data(), // Set page identifier currentPage: 'settings', // Loading states loading: true, error: '', saving: false, // Settings data from API settings: null, // Active section activeSection: 'general', // Sections for navigation sections: [ { id: 'general', label: 'General', icon: 'cog' }, { id: 'business', label: 'Business Info', icon: 'office-building' }, { id: 'localization', label: 'Localization', icon: 'globe' }, { id: 'marketplace', label: 'Marketplace', icon: 'shopping-cart' }, { id: 'invoices', label: 'Invoices', icon: 'document-text' }, { id: 'branding', label: 'Branding', icon: 'color-swatch' }, { id: 'domains', label: 'Domains', icon: 'globe-alt' }, { id: 'api', label: 'API & Payments', icon: 'key' }, { id: 'notifications', label: 'Notifications', icon: 'bell' } ], // Forms for different sections generalForm: { subdomain: '', is_active: true }, businessForm: { name: '', description: '', contact_email: '', contact_phone: '', website: '', business_address: '', tax_number: '' }, // Track which fields are inherited from company businessInherited: { contact_email: false, contact_phone: false, website: false, business_address: false, tax_number: false }, // Company name for display companyName: '', marketplaceForm: { letzshop_csv_url_fr: '', letzshop_csv_url_en: '', letzshop_csv_url_de: '', letzshop_default_tax_rate: null, letzshop_boost_sort: '', letzshop_delivery_method: '', letzshop_preorder_days: null }, notificationForm: { email_notifications: true, order_notifications: true, marketing_emails: false }, localizationForm: { default_language: 'fr', dashboard_language: 'fr', storefront_language: 'fr', storefront_languages: ['fr', 'de', 'en'], storefront_locale: '' }, // Track changes per section hasChanges: false, hasBusinessChanges: false, hasLocalizationChanges: false, hasMarketplaceChanges: false, async init() { vendorSettingsLog.info('Settings init() called'); // Guard against multiple initialization if (window._vendorSettingsInitialized) { vendorSettingsLog.warn('Already initialized, skipping'); return; } 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) { vendorSettingsLog.error('Init failed:', error); this.error = 'Failed to initialize settings page'; } vendorSettingsLog.info('Settings initialization complete'); }, /** * Load vendor settings */ async loadSettings() { this.loading = true; this.error = ''; try { const response = await apiClient.get(`/vendor/settings`); this.settings = response; // Populate general form this.generalForm = { subdomain: response.subdomain || '', is_active: response.is_active !== false }; // Populate business info form with inheritance tracking const biz = response.business_info || {}; this.businessForm = { name: response.name || '', description: response.description || '', contact_email: biz.contact_email_override || '', contact_phone: biz.contact_phone_override || '', website: biz.website_override || '', business_address: biz.business_address_override || '', tax_number: biz.tax_number_override || '' }; this.businessInherited = { contact_email: biz.contact_email_inherited || false, contact_phone: biz.contact_phone_inherited || false, website: biz.website_inherited || false, business_address: biz.business_address_inherited || false, tax_number: biz.tax_number_inherited || false }; this.companyName = biz.company_name || ''; // Populate localization form from nested structure const loc = response.localization || {}; this.localizationForm = { default_language: loc.default_language || 'fr', dashboard_language: loc.dashboard_language || 'fr', storefront_language: loc.storefront_language || 'fr', storefront_languages: loc.storefront_languages || ['fr', 'de', 'en'], storefront_locale: loc.storefront_locale || '' }; // Populate marketplace form from nested structure const lz = response.letzshop || {}; this.marketplaceForm = { letzshop_csv_url_fr: lz.csv_url_fr || '', letzshop_csv_url_en: lz.csv_url_en || '', letzshop_csv_url_de: lz.csv_url_de || '', letzshop_default_tax_rate: lz.default_tax_rate, letzshop_boost_sort: lz.boost_sort || '', letzshop_delivery_method: lz.delivery_method || '', letzshop_preorder_days: lz.preorder_days }; // Reset all change flags this.hasChanges = false; this.hasBusinessChanges = false; this.hasLocalizationChanges = false; this.hasMarketplaceChanges = false; vendorSettingsLog.info('Loaded settings'); } catch (error) { vendorSettingsLog.error('Failed to load settings:', error); this.error = error.message || 'Failed to load settings'; } finally { this.loading = false; } }, /** * Mark general form as changed */ markChanged() { this.hasChanges = true; }, /** * Mark business form as changed */ markBusinessChanged() { this.hasBusinessChanges = true; }, /** * Mark localization form as changed */ markLocalizationChanged() { this.hasLocalizationChanges = true; }, /** * Mark marketplace form as changed */ markMarketplaceChanged() { this.hasMarketplaceChanges = true; }, /** * Get effective value for a business field (override or inherited) */ getEffectiveBusinessValue(field) { const override = this.businessForm[field]; if (override) return override; // Return the effective value from settings (includes company inheritance) return this.settings?.business_info?.[field] || ''; }, /** * Check if field is using inherited value */ isFieldInherited(field) { return this.businessInherited[field] && !this.businessForm[field]; }, /** * Reset a business field to inherit from company */ resetToCompany(field) { this.businessForm[field] = ''; this.hasBusinessChanges = true; }, /** * Save business info */ async saveBusinessInfo() { this.saving = true; try { // Determine which fields should be reset to company values const resetFields = []; for (const field of ['contact_email', 'contact_phone', 'website', 'business_address', 'tax_number']) { if (!this.businessForm[field] && this.settings?.business_info?.[field]) { resetFields.push(field); } } const payload = { name: this.businessForm.name, description: this.businessForm.description, contact_email: this.businessForm.contact_email || null, contact_phone: this.businessForm.contact_phone || null, website: this.businessForm.website || null, business_address: this.businessForm.business_address || null, tax_number: this.businessForm.tax_number || null, reset_to_company: resetFields }; await apiClient.put(`/vendor/settings/business-info`, payload); Utils.showToast('Business info saved', 'success'); vendorSettingsLog.info('Business info updated'); // Reload to get updated inheritance flags await this.loadSettings(); this.hasBusinessChanges = false; } catch (error) { vendorSettingsLog.error('Failed to save business info:', error); Utils.showToast(error.message || 'Failed to save business info', 'error'); } finally { this.saving = false; } }, /** * Save marketplace settings (Letzshop) */ async saveMarketplaceSettings() { this.saving = true; try { await apiClient.put(`/vendor/settings/letzshop`, this.marketplaceForm); Utils.showToast('Marketplace settings saved', 'success'); vendorSettingsLog.info('Marketplace settings updated'); this.hasMarketplaceChanges = false; } catch (error) { vendorSettingsLog.error('Failed to save marketplace settings:', error); Utils.showToast(error.message || 'Failed to save settings', 'error'); } finally { this.saving = false; } }, /** * Test Letzshop CSV URL */ async testLetzshopUrl(lang) { const url = this.marketplaceForm[`letzshop_csv_url_${lang}`]; if (!url) { Utils.showToast('Please enter a URL first', 'error'); return; } this.saving = true; try { // Try to fetch the URL to validate it const response = await fetch(url, { method: 'HEAD', mode: 'no-cors' }); Utils.showToast(`URL appears to be valid`, 'success'); } catch (error) { Utils.showToast('Could not validate URL - it may still work', 'warning'); } finally { this.saving = false; } }, /** * Reset settings to saved values */ resetSettings() { this.loadSettings(); }, /** * Switch active section */ setSection(sectionId) { this.activeSection = sectionId; }, /** * Toggle a storefront language */ toggleStorefrontLanguage(langCode) { const index = this.localizationForm.storefront_languages.indexOf(langCode); if (index === -1) { this.localizationForm.storefront_languages.push(langCode); } else { this.localizationForm.storefront_languages.splice(index, 1); } this.hasLocalizationChanges = true; }, /** * Save localization settings */ async saveLocalizationSettings() { this.saving = true; try { await apiClient.put(`/vendor/settings/localization`, this.localizationForm); Utils.showToast('Localization settings saved', 'success'); vendorSettingsLog.info('Localization settings updated'); this.hasLocalizationChanges = false; } catch (error) { vendorSettingsLog.error('Failed to save localization settings:', error); Utils.showToast(error.message || 'Failed to save settings', 'error'); } finally { this.saving = false; } } }; }