/** * MPR Express Checkout - Standardized Modal Helper * * Provides a consistent API for managing modals across the module. * * Usage: * const modal = new MPRModal('my-modal-id'); * modal.show(); * modal.setHeader('success', 'icon-check', 'Operation Complete'); * modal.setBody('

Content here

'); * modal.setFooter([ * { type: 'cancel', label: 'Close' }, * { type: 'primary', label: 'Continue', icon: 'arrow-right', onClick: () => {} } * ]); */ class MPRModal { /** * @param {string} modalId - The modal element ID (without #) * @param {Object} options - Configuration options * @param {Function} options.onShow - Callback when modal is shown * @param {Function} options.onHide - Callback when modal is hidden * @param {Function} options.onCancel - Callback when cancel/close is clicked */ constructor(modalId, options = {}) { this.modalId = modalId; this.$modal = $(`#${modalId}`); this.$header = this.$modal.find('.mpr-modal-header'); this.$title = this.$modal.find('.mpr-modal-title'); this.$titleText = this.$modal.find('.mpr-modal-title-text'); this.$titleIcon = this.$modal.find('.mpr-modal-icon'); this.$body = this.$modal.find('.mpr-modal-body'); this.$footer = this.$modal.find('.mpr-modal-footer'); this.options = options; this.currentView = null; this._bindEvents(); } /** * Bind modal events */ _bindEvents() { this.$modal.on('shown.bs.modal', () => { if (typeof this.options.onShow === 'function') { this.options.onShow(); } }); this.$modal.on('hidden.bs.modal', () => { if (typeof this.options.onHide === 'function') { this.options.onHide(); } }); this.$modal.on('click', '[data-dismiss="modal"]', () => { if (typeof this.options.onCancel === 'function') { this.options.onCancel(); } }); } /** * Show the modal * @param {Object} options - Bootstrap modal options */ show(options = {}) { if (this.$modal.length === 0) { console.error('[MPRModal] Modal element not found'); return; } this.$modal.modal({ backdrop: options.static ? 'static' : true, keyboard: !options.static, ...options }); } /** * Hide the modal */ hide() { this.$modal.modal('hide'); } /** * Set header appearance * @param {string} type - Header type: default, primary, success, warning, danger, dark * @param {string} icon - Icon class without prefix (e.g., 'shield' for icon-shield) * @param {string} title - Title text */ setHeader(type, icon, title) { // Remove all header type classes this.$header.removeClass( 'mpr-modal-header-default mpr-modal-header-primary mpr-modal-header-success ' + 'mpr-modal-header-warning mpr-modal-header-danger mpr-modal-header-dark' ); this.$header.addClass(`mpr-modal-header-${type}`); if (icon) { if (this.$titleIcon.length) { this.$titleIcon.attr('class', `mpr-icon icon-${icon} mpr-modal-icon`); } else { this.$title.prepend(``); this.$titleIcon = this.$modal.find('.mpr-modal-icon'); } } if (title !== undefined) { this.$titleText.text(title); } } /** * Set only the header type/color * @param {string} type - Header type: default, primary, success, warning, danger, dark */ setHeaderType(type) { this.$header.removeClass( 'mpr-modal-header-default mpr-modal-header-primary mpr-modal-header-success ' + 'mpr-modal-header-warning mpr-modal-header-danger mpr-modal-header-dark' ); this.$header.addClass(`mpr-modal-header-${type}`); } /** * Set the header title * @param {string} title - Title text */ setTitle(title) { this.$titleText.text(title); } /** * Set the header icon * @param {string} icon - Icon class without prefix */ setIcon(icon) { if (this.$titleIcon.length) { this.$titleIcon.attr('class', `icon-${icon} mpr-modal-icon`); } } /** * Set modal size * @param {string} size - Size: sm, md, lg, xl, fullwidth */ setSize(size) { const $dialog = this.$modal.find('.modal-dialog'); $dialog.removeClass('modal-sm modal-lg modal-xl modal-fullwidth'); if (size === 'sm') { $dialog.addClass('modal-sm'); } else if (size === 'lg') { $dialog.addClass('modal-lg'); } else if (size === 'xl') { $dialog.addClass('modal-xl'); } else if (size === 'fullwidth') { $dialog.addClass('modal-fullwidth'); } } /** * Set body content * @param {string} html - HTML content for the body */ setBody(html) { this.$body.html(html); } /** * Append content to body * @param {string} html - HTML content to append */ appendBody(html) { this.$body.append(html); } /** * Set footer buttons * @param {Array} buttons - Array of button configurations * Each button: { type, label, icon, id, onClick, disabled, className, size } * type: 'cancel', 'primary', 'success', 'warning', 'danger', 'default', 'dark', * 'outline-primary', 'outline-danger', 'ghost' * size: 'sm', 'lg' (optional) */ setFooter(buttons) { this.$footer.empty(); buttons.forEach(btn => { const btnType = btn.type === 'cancel' ? 'default' : btn.type; let btnClass = `mpr-btn mpr-btn-${btnType}`; if (btn.size) { btnClass += ` mpr-btn-${btn.size}`; } if (btn.className) { btnClass += ` ${btn.className}`; } const $btn = $(' `; $('body').append(html); return new MPRModal(id, config); }; // Export for module systems if available if (typeof module !== 'undefined' && module.exports) { module.exports = MPRModal; }