Files
orion/app/modules/loyalty/static/admin/js/loyalty-program-edit.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

155 lines
5.8 KiB
JavaScript

// 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(),
...createProgramFormMixin(),
currentPage: 'loyalty-programs',
merchantId: null,
merchant: null,
programId: null,
loading: false,
error: null,
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 {
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.populateSettings(program);
loyaltyProgramEditLog.info('Program loaded, ID:', this.programId);
} else {
this.isNewProgram = true;
if (this.merchant) {
this.settings.card_name = this.merchant.name + ' Loyalty';
}
loyaltyProgramEditLog.info('No program found, create mode');
}
} catch (error) {
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 {
const payload = this.buildPayload();
if (!payload) { this.saving = false; return; }
if (this.isNewProgram) {
const response = await apiClient.post(
`/admin/loyalty/merchants/${this.merchantId}/program`,
payload
);
this.programId = response.id;
this.isNewProgram = false;
Utils.showToast('Program created successfully', 'success');
} else {
await apiClient.patch(
`/admin/loyalty/programs/${this.programId}`,
payload
);
Utils.showToast('Program updated successfully', 'success');
}
loyaltyProgramEditLog.info('Program saved');
window.location.href = this.backUrl;
} catch (error) {
Utils.showToast(`Failed to save: ${error.message}`, 'error');
loyaltyProgramEditLog.error('Save failed:', error);
} finally {
this.saving = false;
}
},
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;
}
},
};
}
if (!window.LogConfig.loggers.loyaltyProgramEdit) {
window.LogConfig.loggers.loyaltyProgramEdit = window.LogConfig.createLogger('loyaltyProgramEdit');
}
loyaltyProgramEditLog.info('Admin loyalty program edit module loaded');