Files
orion/app/modules/loyalty/static/store/js/loyalty-settings.js
Samir Boulahtit 29d942322d
Some checks failed
CI / ruff (push) Successful in 10s
CI / pytest (push) Failing after 49m23s
CI / validate (push) Successful in 26s
CI / dependency-scanning (push) Successful in 30s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
feat(loyalty): make logo URL mandatory on program edit forms
Logo URL is required by Google Wallet API for LoyaltyClass creation.
Added validation across all three program edit screens (admin, merchant, store)
with a helpful hint explaining the requirement.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 20:08:38 +01:00

135 lines
4.6 KiB
JavaScript

// app/modules/loyalty/static/store/js/loyalty-settings.js
// noqa: js-006 - async init pattern is safe, loadData has try/catch
const loyaltySettingsLog = window.LogConfig.loggers.loyaltySettings || window.LogConfig.createLogger('loyaltySettings');
// ============================================
// STORE LOYALTY SETTINGS FUNCTION
// ============================================
function loyaltySettings() {
return {
// Inherit base layout functionality
...data(),
...createProgramFormMixin(),
// Page identifier
currentPage: 'loyalty-program',
// State
loading: false,
error: null,
isOwner: false,
// Initialize
async init() {
loyaltySettingsLog.info('=== LOYALTY SETTINGS INITIALIZING ===');
if (window._loyaltySettingsInitialized) {
loyaltySettingsLog.warn('Already initialized, skipping...');
return;
}
window._loyaltySettingsInitialized = true;
const parentInit = data().init;
if (parentInit) {
await parentInit.call(this);
}
// Check if user is merchant_owner
this.isOwner = this.currentUser?.role === 'merchant_owner';
await this.loadData();
loyaltySettingsLog.info('=== LOYALTY SETTINGS INITIALIZATION COMPLETE ===');
},
async loadData() {
this.loading = true;
this.error = null;
try {
await this.loadProgram();
} catch (error) {
loyaltySettingsLog.error('Failed to load data:', error);
this.error = error.message || 'Failed to load settings';
} finally {
this.loading = false;
}
},
async loadProgram() {
try {
loyaltySettingsLog.info('Loading program...');
const response = await apiClient.get('/store/loyalty/program');
if (response) {
this.populateSettings(response);
this.isNewProgram = false;
loyaltySettingsLog.info('Program loaded:', response.display_name);
}
} catch (error) {
if (error.status === 404) {
loyaltySettingsLog.info('No program configured — showing create form');
this.isNewProgram = true;
} else {
throw error;
}
}
},
async saveSettings() {
this.saving = true;
try {
const payload = this.buildPayload();
if (!payload) { this.saving = false; return; }
let response;
if (this.isNewProgram) {
response = await apiClient.post('/store/loyalty/program', payload);
Utils.showToast('Program created successfully', 'success');
} else {
response = await apiClient.put('/store/loyalty/program', payload);
Utils.showToast('Program updated successfully', 'success');
}
this.populateSettings(response);
this.isNewProgram = false;
loyaltySettingsLog.info('Program saved:', response.display_name);
} catch (error) {
Utils.showToast(`Failed to save: ${error.message}`, 'error');
loyaltySettingsLog.error('Save failed:', error);
} finally {
this.saving = false;
}
},
async deleteProgram() {
this.deleting = true;
try {
await apiClient.delete('/store/loyalty/program');
Utils.showToast('Loyalty program deleted', 'success');
loyaltySettingsLog.info('Program deleted');
// Redirect to terminal page
const storeCode = window.location.pathname.split('/')[2];
window.location.href = `/store/${storeCode}/loyalty/program`;
} catch (error) {
Utils.showToast(`Failed to delete: ${error.message}`, 'error');
loyaltySettingsLog.error('Delete failed:', error);
} finally {
this.deleting = false;
this.showDeleteModal = false;
}
},
};
}
// Register logger
if (!window.LogConfig.loggers.loyaltySettings) {
window.LogConfig.loggers.loyaltySettings = window.LogConfig.createLogger('loyaltySettings');
}
loyaltySettingsLog.info('Loyalty settings module loaded');