/**
* HVAC Modal Forms
*
* Handles modal forms for creating new organizers, categories, and venues
* with role-based permissions and AJAX submission.
*/
(function($) {
'use strict';
class HVACModalForms {
constructor() {
this.init();
}
init() {
this.bindEvents();
this.createModalContainer();
}
bindEvents() {
// Listen for create new modal trigger
$(document).on('hvac:create-new-modal', (e, data) => {
this.showCreateModal(data.type, data.callback);
});
// Modal close events
$(document).on('click', '.hvac-modal-overlay, .hvac-modal-close', (e) => {
e.preventDefault();
this.closeModal();
});
// Prevent modal close when clicking inside modal content
$(document).on('click', '.hvac-modal-content', (e) => {
e.stopPropagation();
});
// Form submission
$(document).on('submit', '.hvac-modal-form', (e) => {
e.preventDefault();
this.handleFormSubmission(e.target);
});
// Escape key to close modal
$(document).on('keydown', (e) => {
if (e.keyCode === 27) { // ESC key
this.closeModal();
}
});
// Media upload handlers
$(document).on('click', '.hvac-modal .select-image-btn', (e) => {
e.preventDefault();
this.openMediaUploader(e.target);
});
$(document).on('click', '.hvac-modal .remove-image', (e) => {
e.preventDefault();
this.removeImage(e.target);
});
}
createModalContainer() {
if ($('#hvac-modal-container').length) {
return;
}
const modalHtml = `
`;
$('body').append(modalHtml);
}
showCreateModal(type, callback) {
this.currentCallback = callback;
const config = this.getModalConfig(type);
if (!config) {
console.error(`Unknown modal type: ${type}`);
return;
}
// Set modal title
$('.hvac-modal-title').text(config.title);
// Generate form HTML
const formHtml = this.generateFormHtml(type, config);
$('.hvac-modal-body').html(formHtml);
// Show modal
$('#hvac-modal-container').fadeIn(300);
// Focus first input
setTimeout(() => {
$('.hvac-modal-form input:first').focus();
}, 350);
}
getModalConfig(type) {
const configs = {
organizer: {
title: 'Add New Organizer',
fields: [
{ name: 'organizer_name', label: 'Organizer Name', type: 'text', required: true },
{ name: 'organizer_email', label: 'Email', type: 'email', required: false },
{ name: 'organizer_website', label: 'Website', type: 'url', required: false },
{ name: 'organizer_phone', label: 'Phone', type: 'tel', required: false },
{ name: 'organizer_featured_image', label: 'Featured Image', type: 'media', required: false }
],
action: 'hvac_create_organizer'
},
category: {
title: 'Add New Category',
fields: [
{ name: 'category_name', label: 'Category Name', type: 'text', required: true },
{ name: 'category_description', label: 'Description', type: 'textarea', required: false }
],
action: 'hvac_create_category',
permission_check: true
},
venue: {
title: 'Add New Venue',
fields: [
{ name: 'venue_name', label: 'Venue Name', type: 'text', required: true },
{ name: 'venue_address', label: 'Address', type: 'text', required: false },
{ name: 'venue_city', label: 'City', type: 'text', required: false },
{ name: 'venue_state', label: 'State/Province', type: 'text', required: false },
{ name: 'venue_zip', label: 'Zip/Postal Code', type: 'text', required: false },
{ name: 'venue_country', label: 'Country', type: 'text', required: false },
{ name: 'venue_website', label: 'Website', type: 'url', required: false },
{ name: 'venue_phone', label: 'Phone', type: 'tel', required: false },
{ name: 'venue_featured_image', label: 'Featured Image', type: 'media', required: false }
],
action: 'hvac_create_venue'
}
};
return configs[type] || null;
}
generateFormHtml(type, config) {
// Check for category permission
if (config.permission_check && !hvacModalForms.canCreateCategories) {
return `
Permission Denied
You don't have permission to create new categories. Please contact a master trainer for assistance.
`;
}
let formHtml = `
`;
return formHtml;
}
generateFieldHtml(field) {
const required = field.required ? 'required' : '';
const requiredMark = field.required ? '*' : '';
if (field.type === 'textarea') {
return `
`;
}
if (field.type === 'media') {
return `
`;
}
return `
`;
}
async handleFormSubmission(form) {
const $form = $(form);
const $submitBtn = $form.find('button[type="submit"]');
const action = $form.data('action');
// Disable submit button and show loading
$submitBtn.prop('disabled', true).text('Creating...');
try {
const formData = new FormData(form);
formData.append('action', action);
formData.append('nonce', hvacModalForms.nonce);
const response = await fetch(hvacModalForms.ajaxUrl, {
method: 'POST',
body: formData
});
const result = await response.json();
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
if (!result.success) {
throw new Error(result.data || 'Request failed');
}
// Success - call callback with new item
if (this.currentCallback) {
this.currentCallback(result.data);
}
this.closeModal();
this.showSuccessMessage(`Successfully created ${result.data.title}`);
} catch (error) {
console.error('Form submission error:', error);
this.showErrorMessage(error.message || 'Failed to create item');
} finally {
// Re-enable submit button
$submitBtn.prop('disabled', false).text($submitBtn.text().replace('Creating...', 'Create'));
}
}
closeModal() {
$('#hvac-modal-container').fadeOut(300);
this.currentCallback = null;
}
showSuccessMessage(message) {
// Create temporary success notification
const $notification = $(`
${this.escapeHtml(message)}
`);
$('body').append($notification);
setTimeout(() => {
$notification.addClass('show');
}, 100);
setTimeout(() => {
$notification.removeClass('show');
setTimeout(() => $notification.remove(), 300);
}, 3000);
}
showErrorMessage(message) {
// Create temporary error notification
const $notification = $(`
${this.escapeHtml(message)}
`);
$('body').append($notification);
setTimeout(() => {
$notification.addClass('show');
}, 100);
setTimeout(() => {
$notification.removeClass('show');
setTimeout(() => $notification.remove(), 300);
}, 5000);
}
openMediaUploader(button) {
const $button = $(button);
const $fieldContainer = $button.closest('.hvac-media-field');
const $imagePreview = $fieldContainer.find('.image-preview');
const $previewImg = $fieldContainer.find('.image-preview img');
const $imageIdInput = $fieldContainer.find('.image-id-input');
const $imageUrlInput = $fieldContainer.find('.image-url-input');
// Create WordPress media frame
const mediaUploader = wp.media({
title: 'Select Image',
button: {
text: 'Select Image'
},
multiple: false,
library: {
type: 'image'
}
});
// When an image is selected
mediaUploader.on('select', () => {
const attachment = mediaUploader.state().get('selection').first().toJSON();
// Update hidden inputs
$imageIdInput.val(attachment.id);
$imageUrlInput.val(attachment.url);
// Update preview
$previewImg.attr('src', attachment.url);
$previewImg.attr('alt', attachment.alt || attachment.title || 'Selected image');
$imagePreview.show();
// Update button text
$button.html('Change Image');
});
// Open the media modal
mediaUploader.open();
}
removeImage(button) {
const $button = $(button);
const $fieldContainer = $button.closest('.hvac-media-field');
const $imagePreview = $fieldContainer.find('.image-preview');
const $previewImg = $fieldContainer.find('.image-preview img');
const $imageIdInput = $fieldContainer.find('.image-id-input');
const $imageUrlInput = $fieldContainer.find('.image-url-input');
const $selectBtn = $fieldContainer.find('.select-image-btn');
// Clear inputs
$imageIdInput.val('');
$imageUrlInput.val('');
// Hide preview
$imagePreview.hide();
$previewImg.attr('src', '');
// Reset button text
$selectBtn.html('Select Image');
}
capitalizeFirst(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
}
// Initialize modal forms when document is ready
$(document).ready(function() {
new HVACModalForms();
});
})(jQuery);