/** * 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 = `
`; config.fields.forEach(field => { formHtml += this.generateFieldHtml(field); }); formHtml += `
`; return formHtml; } generateFieldHtml(field) { const required = field.required ? 'required' : ''; const requiredMark = field.required ? '*' : ''; if (field.type === 'textarea') { return `
`; } if (field.type === 'media') { return `

Recommended: 300x300 pixels or larger

`; } 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);