/**
* InvestEdu - Modal Management
* Handles modal creation, display, and interaction
*/
const Modals = {
/**
* Create and show modal
* @param {Object} options - Modal options
* @returns {HTMLElement} Modal element
*/
show(options = {}) {
const {
title = '',
content = '',
size = 'md', // sm, md, lg, xl
showCloseButton = true,
closeOnBackdrop = true,
buttons = []
} = options;
// Remove existing modal if any
this.close();
// Create modal overlay
const overlay = document.createElement('div');
overlay.className = 'modal-overlay fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4';
overlay.id = 'modal-overlay';
// Create modal container
const modal = document.createElement('div');
modal.className = `modal bg-white rounded-2xl shadow-xl max-w-${size === 'sm' ? 'sm' : size === 'lg' ? '2xl' : size === 'xl' ? '4xl' : 'lg'} w-full max-h-[90vh] overflow-y-auto`;
modal.id = 'modal';
// Modal header
if (title) {
const header = document.createElement('div');
header.className = 'modal-header p-6 border-b border-gray-200 flex items-center justify-between';
const titleElement = document.createElement('h2');
titleElement.className = 'text-xl font-bold text-slate-900';
titleElement.textContent = title;
header.appendChild(titleElement);
if (showCloseButton) {
const closeBtn = document.createElement('button');
closeBtn.className = 'text-gray-400 hover:text-gray-600 transition';
closeBtn.innerHTML = '';
closeBtn.onclick = () => this.close();
header.appendChild(closeBtn);
}
modal.appendChild(header);
}
// Modal body
const body = document.createElement('div');
body.className = 'modal-body p-6';
if (typeof content === 'string') {
body.innerHTML = content;
} else {
body.appendChild(content);
}
modal.appendChild(body);
// Modal footer
if (buttons.length > 0) {
const footer = document.createElement('div');
footer.className = 'modal-footer p-6 border-t border-gray-200 flex justify-end gap-3';
buttons.forEach(button => {
const btn = document.createElement('button');
btn.className = button.className || 'px-4 py-2 rounded-lg font-medium transition';
btn.textContent = button.text;
btn.onclick = () => {
if (button.onClick) {
button.onClick();
}
if (button.close !== false) {
this.close();
}
};
footer.appendChild(btn);
});
modal.appendChild(footer);
}
overlay.appendChild(modal);
document.body.appendChild(overlay);
// Close on backdrop click
if (closeOnBackdrop) {
overlay.addEventListener('click', (e) => {
if (e.target === overlay) {
this.close();
}
});
}
// Close on Escape key
const escapeHandler = (e) => {
if (e.key === 'Escape') {
this.close();
document.removeEventListener('keydown', escapeHandler);
}
};
document.addEventListener('keydown', escapeHandler);
// Animate in
setTimeout(() => {
overlay.classList.add('fade-in');
modal.classList.add('fade-in');
}, 10);
return modal;
},
/**
* Close modal
*/
close() {
const overlay = document.getElementById('modal-overlay');
if (overlay) {
overlay.remove();
}
},
/**
* Show confirmation modal
* @param {Object} options - Confirmation options
* @returns {Promise} User's choice
*/
confirm(options = {}) {
return new Promise((resolve) => {
const {
title = 'Confirm Action',
message = 'Are you sure you want to proceed?',
confirmText = 'Confirm',
cancelText = 'Cancel',
confirmClass = 'bg-red-600 text-white hover:bg-red-700'
} = options;
this.show({
title,
content: `${message}
`,
buttons: [
{
text: cancelText,
className: 'px-4 py-2 bg-gray-200 text-gray-700 rounded-lg font-medium hover:bg-gray-300 transition',
onClick: () => resolve(false),
close: true
},
{
text: confirmText,
className: `px-4 py-2 ${confirmClass} rounded-lg font-medium transition`,
onClick: () => resolve(true),
close: true
}
]
});
});
},
/**
* Show alert modal
* @param {Object} options - Alert options
*/
alert(options = {}) {
const {
title = 'Alert',
message = '',
type = 'info', // info, success, warning, error
buttonText = 'OK'
} = options;
const typeClasses = {
info: 'text-blue-600',
success: 'text-green-600',
warning: 'text-amber-600',
error: 'text-red-600'
};
this.show({
title,
content: `${message}
`,
buttons: [
{
text: buttonText,
className: 'px-4 py-2 bg-slate-800 text-white rounded-lg font-medium hover:bg-slate-700 transition',
close: true
}
]
});
}
};
// Export for use in other modules
if (typeof module !== 'undefined' && module.exports) {
module.exports = Modals;
}