// app/modules/loyalty/static/admin/js/loyalty-program-edit.js // noqa: js-006 - async init pattern is safe, loadData has try/catch const loyaltyProgramEditLog = window.LogConfig.loggers.loyaltyProgramEdit || window.LogConfig.createLogger('loyaltyProgramEdit'); function adminLoyaltyProgramEdit() { return { ...data(), currentPage: 'loyalty-programs', merchantId: null, merchant: null, programId: null, settings: { loyalty_type: 'points', points_per_euro: 1, welcome_bonus_points: 0, minimum_redemption_points: 100, points_expiration_days: null, points_rewards: [], stamps_target: 10, stamps_reward_description: '', card_name: '', card_color: '#4F46E5', is_active: true }, loading: false, saving: false, deleting: false, error: null, isNewProgram: false, showDeleteModal: false, get backUrl() { return `/admin/loyalty/merchants/${this.merchantId}`; }, async init() { loyaltyProgramEditLog.info('=== ADMIN PROGRAM EDIT PAGE INITIALIZING ==='); if (window._adminProgramEditInitialized) return; window._adminProgramEditInitialized = true; // Extract merchant ID from URL: /admin/loyalty/merchants/{id}/program const pathParts = window.location.pathname.split('/'); const merchantsIndex = pathParts.indexOf('merchants'); if (merchantsIndex !== -1 && pathParts[merchantsIndex + 1]) { this.merchantId = parseInt(pathParts[merchantsIndex + 1]); } if (!this.merchantId) { this.error = 'Invalid merchant ID'; loyaltyProgramEditLog.error('Could not extract merchant ID from URL'); return; } loyaltyProgramEditLog.info('Merchant ID:', this.merchantId); await this.loadData(); loyaltyProgramEditLog.info('=== ADMIN PROGRAM EDIT PAGE INITIALIZATION COMPLETE ==='); }, async loadData() { this.loading = true; this.error = null; try { // Load merchant info and program data in parallel await Promise.all([ this.loadMerchant(), this.loadProgram() ]); } catch (error) { loyaltyProgramEditLog.error('Failed to load data:', error); this.error = error.message || 'Failed to load data'; } finally { this.loading = false; } }, async loadMerchant() { const response = await apiClient.get(`/admin/merchants/${this.merchantId}`); if (response) { this.merchant = response; loyaltyProgramEditLog.info('Merchant loaded:', this.merchant.name); } }, async loadProgram() { try { // Get program via merchant stats endpoint (includes program data) const response = await apiClient.get(`/admin/loyalty/merchants/${this.merchantId}/stats`); if (response && response.program) { const program = response.program; this.programId = program.id; this.isNewProgram = false; this.settings = { loyalty_type: program.loyalty_type || 'points', points_per_euro: program.points_per_euro || 1, welcome_bonus_points: program.welcome_bonus_points || 0, minimum_redemption_points: program.minimum_redemption_points || 100, points_expiration_days: program.points_expiration_days || null, points_rewards: program.points_rewards || [], stamps_target: program.stamps_target || 10, stamps_reward_description: program.stamps_reward_description || '', card_name: program.card_name || '', card_color: program.card_color || '#4F46E5', is_active: program.is_active !== false }; loyaltyProgramEditLog.info('Program loaded, ID:', this.programId); } else { this.isNewProgram = true; // Set default card name from merchant if (this.merchant) { this.settings.card_name = this.merchant.name + ' Loyalty'; } loyaltyProgramEditLog.info('No program found, create mode'); } } catch (error) { // If stats fail (e.g., no program), we're in create mode this.isNewProgram = true; if (this.merchant) { this.settings.card_name = this.merchant.name + ' Loyalty'; } loyaltyProgramEditLog.info('No program, switching to create mode'); } }, async saveSettings() { this.saving = true; try { // Ensure rewards have IDs this.settings.points_rewards = this.settings.points_rewards.map((r, i) => ({ ...r, id: r.id || `reward_${i + 1}`, is_active: r.is_active !== false })); if (this.isNewProgram) { const response = await apiClient.post( `/admin/loyalty/merchants/${this.merchantId}/program`, this.settings ); this.programId = response.id; this.isNewProgram = false; Utils.showToast('Program created successfully', 'success'); } else { await apiClient.patch( `/admin/loyalty/programs/${this.programId}`, this.settings ); Utils.showToast('Program updated successfully', 'success'); } loyaltyProgramEditLog.info('Program saved'); // Navigate back to merchant detail window.location.href = this.backUrl; } catch (error) { Utils.showToast(`Failed to save: ${error.message}`, 'error'); loyaltyProgramEditLog.error('Save failed:', error); } finally { this.saving = false; } }, confirmDelete() { this.showDeleteModal = true; }, async deleteProgram() { if (!this.programId) return; this.deleting = true; try { await apiClient.delete(`/admin/loyalty/programs/${this.programId}`); Utils.showToast('Program deleted', 'success'); loyaltyProgramEditLog.info('Program deleted'); window.location.href = this.backUrl; } catch (error) { Utils.showToast(`Failed to delete: ${error.message}`, 'error'); loyaltyProgramEditLog.error('Delete failed:', error); } finally { this.deleting = false; this.showDeleteModal = false; } }, addReward() { this.settings.points_rewards.push({ id: `reward_${Date.now()}`, name: '', points_required: 100, description: '', is_active: true }); }, removeReward(index) { this.settings.points_rewards.splice(index, 1); } }; } if (!window.LogConfig.loggers.loyaltyProgramEdit) { window.LogConfig.loggers.loyaltyProgramEdit = window.LogConfig.createLogger('loyaltyProgramEdit'); } loyaltyProgramEditLog.info('Admin loyalty program edit module loaded');