209 lines
5.6 KiB
JavaScript
209 lines
5.6 KiB
JavaScript
/**
|
|
* Modal System Helper Functions
|
|
* Utility functions for modal operations across all sections
|
|
*/
|
|
|
|
window.modalHelpers = {
|
|
/**
|
|
* Show a simple confirmation dialog
|
|
* Returns a Promise that resolves with true/false
|
|
*/
|
|
async confirm(options) {
|
|
return new Promise((resolve) => {
|
|
const component = Alpine.$data(document.body);
|
|
|
|
component.showConfirmModal({
|
|
title: options.title || 'Confirm Action',
|
|
message: options.message || 'Are you sure?',
|
|
warning: options.warning || '',
|
|
buttonText: options.buttonText || 'Confirm',
|
|
buttonClass: options.buttonClass || 'btn-danger',
|
|
onConfirm: () => resolve(true),
|
|
onCancel: () => resolve(false)
|
|
});
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Show a success message
|
|
*/
|
|
success(message, options = {}) {
|
|
const component = Alpine.$data(document.body);
|
|
|
|
component.showSuccessModal({
|
|
title: options.title || 'Success',
|
|
message: message,
|
|
redirectUrl: options.redirectUrl || null,
|
|
redirectDelay: options.redirectDelay || 2000
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Show an error message
|
|
*/
|
|
error(message, details = '') {
|
|
const component = Alpine.$data(document.body);
|
|
|
|
component.showErrorModal({
|
|
title: 'Error',
|
|
message: message,
|
|
details: details
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Show API error with proper formatting
|
|
*/
|
|
apiError(error) {
|
|
const component = Alpine.$data(document.body);
|
|
|
|
let message = 'An error occurred';
|
|
let details = '';
|
|
|
|
if (error.message) {
|
|
message = error.message;
|
|
}
|
|
|
|
if (error.details) {
|
|
details = typeof error.details === 'string'
|
|
? error.details
|
|
: JSON.stringify(error.details, null, 2);
|
|
} else if (error.error_code) {
|
|
details = `Error Code: ${error.error_code}`;
|
|
}
|
|
|
|
component.showErrorModal({
|
|
title: 'Error',
|
|
message: message,
|
|
details: details
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Show loading overlay
|
|
*/
|
|
showLoading() {
|
|
const component = Alpine.$data(document.body);
|
|
component.showLoading();
|
|
},
|
|
|
|
/**
|
|
* Hide loading overlay
|
|
*/
|
|
hideLoading() {
|
|
const component = Alpine.$data(document.body);
|
|
component.hideLoading();
|
|
},
|
|
|
|
/**
|
|
* Execute an async operation with loading state
|
|
*/
|
|
async withLoading(asyncFunction) {
|
|
try {
|
|
this.showLoading();
|
|
const result = await asyncFunction();
|
|
return result;
|
|
} finally {
|
|
this.hideLoading();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Execute an async operation with error handling
|
|
*/
|
|
async withErrorHandling(asyncFunction, errorMessage = 'Operation failed') {
|
|
try {
|
|
return await asyncFunction();
|
|
} catch (error) {
|
|
console.error('Operation error:', error);
|
|
this.apiError({
|
|
message: errorMessage,
|
|
details: error.message || error.toString()
|
|
});
|
|
throw error;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Execute an async operation with both loading and error handling
|
|
*/
|
|
async execute(asyncFunction, options = {}) {
|
|
const {
|
|
errorMessage = 'Operation failed',
|
|
successMessage = null,
|
|
redirectUrl = null
|
|
} = options;
|
|
|
|
try {
|
|
this.showLoading();
|
|
const result = await asyncFunction();
|
|
|
|
if (successMessage) {
|
|
this.success(successMessage, { redirectUrl });
|
|
}
|
|
|
|
return result;
|
|
} catch (error) {
|
|
console.error('Operation error:', error);
|
|
this.apiError({
|
|
message: errorMessage,
|
|
details: error.message || error.toString()
|
|
});
|
|
throw error;
|
|
} finally {
|
|
this.hideLoading();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Confirm a destructive action
|
|
*/
|
|
async confirmDelete(itemName, itemType = 'item') {
|
|
return this.confirm({
|
|
title: `Delete ${itemType}`,
|
|
message: `Are you sure you want to delete "${itemName}"?`,
|
|
warning: 'This action cannot be undone.',
|
|
buttonText: 'Delete',
|
|
buttonClass: 'btn-danger'
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Confirm logout
|
|
*/
|
|
async confirmLogout() {
|
|
return this.confirm({
|
|
title: 'Confirm Logout',
|
|
message: 'Are you sure you want to logout?',
|
|
buttonText: 'Logout',
|
|
buttonClass: 'btn-primary'
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Show validation errors
|
|
*/
|
|
validationError(errors) {
|
|
let message = 'Please correct the following errors:';
|
|
let details = '';
|
|
|
|
if (Array.isArray(errors)) {
|
|
details = errors.join('\n');
|
|
} else if (typeof errors === 'object') {
|
|
details = Object.entries(errors)
|
|
.map(([field, error]) => `${field}: ${error}`)
|
|
.join('\n');
|
|
} else {
|
|
details = errors.toString();
|
|
}
|
|
|
|
this.error(message, details);
|
|
}
|
|
};
|
|
|
|
// Shorthand aliases for convenience
|
|
window.showConfirm = window.modalHelpers.confirm.bind(window.modalHelpers);
|
|
window.showSuccess = window.modalHelpers.success.bind(window.modalHelpers);
|
|
window.showError = window.modalHelpers.error.bind(window.modalHelpers);
|
|
window.showLoading = window.modalHelpers.showLoading.bind(window.modalHelpers);
|
|
window.hideLoading = window.modalHelpers.hideLoading.bind(window.modalHelpers); |