HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/hi.naniguide.com/resources/js/form-builder.js
class MailPurseFormBuilder {
    constructor() {
        this.fields = [];
        this.selectedField = null;
        this.fieldIdCounter = 0;
        this.isPreviewMode = false;
        
        this.init();
    }

    init() {
        this.setupDragAndDrop();
        this.setupEventListeners();
        this.loadExistingData();
    }

    setupDragAndDrop() {
        const fieldTypes = document.querySelectorAll('[data-field-type]');
        const dropZone = document.getElementById('drop-zone');

        fieldTypes.forEach(field => {
            field.draggable = true;
            
            field.addEventListener('dragstart', (e) => {
                e.dataTransfer.effectAllowed = 'copy';
                e.dataTransfer.setData('fieldType', field.dataset.fieldType);
                field.classList.add('dragging');
            });

            field.addEventListener('dragend', (e) => {
                field.classList.remove('dragging');
            });
        });

        dropZone.addEventListener('dragover', (e) => {
            e.preventDefault();
            e.dataTransfer.dropEffect = 'copy';
            dropZone.classList.add('drag-over');
        });

        dropZone.addEventListener('dragleave', (e) => {
            if (e.target === dropZone) {
                dropZone.classList.remove('drag-over');
            }
        });

        dropZone.addEventListener('drop', (e) => {
            e.preventDefault();
            dropZone.classList.remove('drag-over');
            
            const fieldType = e.dataTransfer.getData('fieldType');
            if (fieldType) {
                this.addField(fieldType);
            }
        });
    }

    setupEventListeners() {
        // Save button
        document.getElementById('btn-save').addEventListener('click', () => {
            this.saveForm();
        });

        // Preview button
        document.getElementById('btn-preview').addEventListener('click', () => {
            this.togglePreview();
        });

        // Close preview
        document.getElementById('preview-overlay').addEventListener('click', () => {
            this.closePreview();
        });

        // Popup settings
        if (window.formType === 'popup') {
            ['popup_width', 'popup_height', 'popup_bg_color', 'popup_overlay_color'].forEach(id => {
                const input = document.getElementById(id);
                if (input) {
                    input.addEventListener('change', () => {
                        this.updatePopupSettings();
                    });
                }
            });
        }
    }

    addField(type) {
        const field = {
            id: `field_${++this.fieldIdCounter}`,
            type: type,
            label: this.getDefaultLabel(type),
            name: `${type}_${this.fieldIdCounter}`,
            required: false,
            placeholder: '',
            options: type === 'select' ? ['Option 1', 'Option 2', 'Option 3'] : [],
            className: 'form-control'
        };

        this.fields.push(field);
        this.renderForm();
        this.selectField(field.id);
    }

    getDefaultLabel(type) {
        const labels = {
            text: 'Text Input',
            email: 'Email',
            textarea: 'Message',
            select: 'Select Option',
            checkbox: 'I agree',
            radio: 'Choice',
            submit: 'Submit'
        };
        return labels[type] || 'Field';
    }

    renderForm() {
        const dropZone = document.getElementById('drop-zone');
        
        if (this.fields.length === 0) {
            dropZone.innerHTML = `
                <div class="text-center">
                    <svg class="w-12 h-12 mx-auto text-gray-400 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"></path>
                    </svg>
                    <p>Drag form fields here to start building</p>
                </div>
            `;
            return;
        }

        let formHTML = '<form class="space-y-4">';
        
        this.fields.forEach(field => {
            formHTML += this.renderField(field);
        });

        formHTML += '</form>';
        
        dropZone.innerHTML = formHTML;
        dropZone.classList.remove('drag-over');

        // Add click handlers to fields
        dropZone.querySelectorAll('.form-field-element').forEach(el => {
            el.addEventListener('click', () => {
                this.selectField(el.dataset.fieldId);
            });
        });
    }

    renderField(field) {
        const fieldHTML = `
            <div class="form-field-element ${this.selectedField === field.id ? 'selected' : ''}" data-field-id="${field.id}">
                ${this.getFieldHTML(field)}
            </div>
        `;
        return fieldHTML;
    }

    getFieldHTML(field) {
        switch (field.type) {
            case 'text':
            case 'email':
                return `
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-gray-700 mb-1">
                            ${field.label} ${field.required ? '<span class="text-red-500">*</span>' : ''}
                        </label>
                        <input type="${field.type}" 
                               name="${field.name}" 
                               placeholder="${field.placeholder}"
                               ${field.required ? 'required' : ''}
                               class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500">
                    </div>
                `;
            
            case 'textarea':
                return `
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-gray-700 mb-1">
                            ${field.label} ${field.required ? '<span class="text-red-500">*</span>' : ''}
                        </label>
                        <textarea name="${field.name}" 
                                  placeholder="${field.placeholder}"
                                  rows="4"
                                  ${field.required ? 'required' : ''}
                                  class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500"></textarea>
                    </div>
                `;
            
            case 'select':
                return `
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-gray-700 mb-1">
                            ${field.label} ${field.required ? '<span class="text-red-500">*</span>' : ''}
                        </label>
                        <select name="${field.name}" 
                                ${field.required ? 'required' : ''}
                                class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500">
                            <option value="">Select an option</option>
                            ${field.options.map(opt => `<option value="${opt}">${opt}</option>`).join('')}
                        </select>
                    </div>
                `;
            
            case 'checkbox':
                return `
                    <div class="mb-4">
                        <label class="flex items-center">
                            <input type="checkbox" 
                                   name="${field.name}" 
                                   value="1"
                                   ${field.required ? 'required' : ''}
                                   class="rounded border-gray-300 text-primary-600 focus:ring-primary-500">
                            <span class="ml-2 text-sm text-gray-700">${field.label}</span>
                            ${field.required ? '<span class="text-red-500">*</span>' : ''}
                        </label>
                    </div>
                `;
            
            case 'radio':
                return `
                    <div class="mb-4">
                        <label class="block text-sm font-medium text-gray-700 mb-2">
                            ${field.label} ${field.required ? '<span class="text-red-500">*</span>' : ''}
                        </label>
                        ${field.options.map((opt, index) => `
                            <label class="flex items-center mb-1">
                                <input type="radio" 
                                       name="${field.name}" 
                                       value="${opt}"
                                       ${field.required && index === 0 ? 'required' : ''}
                                       class="border-gray-300 text-primary-600 focus:ring-primary-500">
                                <span class="ml-2 text-sm text-gray-700">${opt}</span>
                            </label>
                        `).join('')}
                    </div>
                `;
            
            case 'submit':
                return `
                    <div class="mb-4">
                        <button type="submit" 
                                class="w-full px-4 py-2 text-white bg-primary-600 border border-transparent rounded-md shadow-sm hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-primary-500">
                            ${field.label}
                        </button>
                    </div>
                `;
            
            default:
                return '';
        }
    }

    selectField(fieldId) {
        this.selectedField = fieldId;
        const field = this.fields.find(f => f.id === fieldId);
        
        if (field) {
            this.renderForm();
            this.showProperties(field);
        }
    }

    showProperties(field) {
        const panel = document.getElementById('properties-panel');
        
        let propertiesHTML = `
            <div class="space-y-4">
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">Field Label</label>
                    <input type="text" 
                           id="prop-label" 
                           value="${field.label}"
                           class="w-full px-3 py-2 border border-gray-300 rounded-md">
                </div>
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">Field Name</label>
                    <input type="text" 
                           id="prop-name" 
                           value="${field.name}"
                           class="w-full px-3 py-2 border border-gray-300 rounded-md">
                </div>
        `;

        if (['text', 'email', 'textarea'].includes(field.type)) {
            propertiesHTML += `
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">Placeholder</label>
                    <input type="text" 
                           id="prop-placeholder" 
                           value="${field.placeholder}"
                           class="w-full px-3 py-2 border border-gray-300 rounded-md">
                </div>
            `;
        }

        if (['select', 'radio'].includes(field.type)) {
            propertiesHTML += `
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">Options (one per line)</label>
                    <textarea id="prop-options" 
                              rows="4"
                              class="w-full px-3 py-2 border border-gray-300 rounded-md">${field.options.join('\n')}</textarea>
                </div>
            `;
        }

        propertiesHTML += `
                <div>
                    <label class="flex items-center">
                        <input type="checkbox" 
                               id="prop-required" 
                               ${field.required ? 'checked' : ''}
                               class="rounded border-gray-300 text-primary-600">
                        <span class="ml-2 text-sm text-gray-700">Required</span>
                    </label>
                </div>
                <div class="pt-4 border-t">
                    <button type="button" 
                            onclick="formBuilder.removeField('${field.id}')"
                            class="w-full px-3 py-2 text-sm text-white bg-red-600 border border-transparent rounded-md hover:bg-red-700">
                        Remove Field
                    </button>
                </div>
            </div>
        `;

        panel.innerHTML = propertiesHTML;

        // Add change listeners
        document.getElementById('prop-label').addEventListener('input', (e) => {
            field.label = e.target.value;
            this.renderForm();
        });

        document.getElementById('prop-name').addEventListener('input', (e) => {
            field.name = e.target.value;
        });

        if (document.getElementById('prop-placeholder')) {
            document.getElementById('prop-placeholder').addEventListener('input', (e) => {
                field.placeholder = e.target.value;
                this.renderForm();
            });
        }

        if (document.getElementById('prop-options')) {
            document.getElementById('prop-options').addEventListener('input', (e) => {
                field.options = e.target.value.split('\n').filter(opt => opt.trim());
                this.renderForm();
            });
        }

        document.getElementById('prop-required').addEventListener('change', (e) => {
            field.required = e.target.checked;
            this.renderForm();
        });
    }

    removeField(fieldId) {
        this.fields = this.fields.filter(f => f.id !== fieldId);
        this.selectedField = null;
        this.renderForm();
        document.getElementById('properties-panel').innerHTML = '<p class="text-sm text-gray-500">Select a field to edit its properties</p>';
    }

    generateHTML() {
        if (this.fields.length === 0) {
            return '';
        }

        let html = '<form class="space-y-4" method="POST">';
        
        this.fields.forEach(field => {
            html += this.getFieldHTML(field);
        });

        html += '</form>';
        
        return html;
    }

    saveForm() {
        const html = this.generateHTML();
        const builderData = JSON.stringify(this.fields);
        
        document.getElementById('html_content').value = html;
        document.getElementById('builder_data').value = builderData;
        
        // Update popup settings if applicable
        if (window.formType === 'popup') {
            document.getElementById('settings_popup_width').value = document.getElementById('popup_width').value;
            document.getElementById('settings_popup_height').value = document.getElementById('popup_height').value;
            document.getElementById('settings_popup_bg_color').value = document.getElementById('popup_bg_color').value;
            document.getElementById('settings_popup_overlay_color').value = document.getElementById('popup_overlay_color').value;
        }
        
        document.getElementById('form-builder-form').submit();
    }

    togglePreview() {
        if (this.isPreviewMode) {
            this.closePreview();
        } else {
            this.showPreview();
        }
    }

    showPreview() {
        const modal = document.getElementById('preview-modal');
        const overlay = document.getElementById('preview-overlay');
        const content = document.getElementById('preview-content');
        
        const html = this.generateHTML();
        
        if (window.formType === 'popup') {
            const width = document.getElementById('popup_width').value;
            const height = document.getElementById('popup_height').value;
            const bgColor = document.getElementById('popup_bg_color').value;
            const overlayColor = document.getElementById('popup_overlay_color').value;
            
            overlay.style.backgroundColor = this.hexToRgba(overlayColor, 0.5);
            content.style.width = width + 'px';
            content.style.height = height + 'px';
            content.style.backgroundColor = bgColor;
            content.innerHTML = `
                <div class="p-6">
                    <h2 class="text-xl font-bold mb-4">Preview</h2>
                    ${html}
                </div>
                <button onclick="formBuilder.closePreview()" 
                        class="absolute top-4 right-4 text-gray-500 hover:text-gray-700">
                    <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
                    </svg>
                </button>
            `;
        } else {
            content.style.width = '600px';
            content.style.maxWidth = '90%';
            content.innerHTML = `
                <div class="p-6">
                    <h2 class="text-xl font-bold mb-4">Preview</h2>
                    ${html}
                    <button onclick="formBuilder.closePreview()" 
                            class="mt-4 px-4 py-2 text-sm text-gray-700 bg-gray-200 border border-gray-300 rounded-md hover:bg-gray-300">
                        Close Preview
                    </button>
                </div>
            `;
        }
        
        modal.classList.remove('hidden');
        this.isPreviewMode = true;
    }

    closePreview() {
        document.getElementById('preview-modal').classList.add('hidden');
        this.isPreviewMode = false;
    }

    hexToRgba(hex, alpha) {
        const r = parseInt(hex.slice(1, 3), 16);
        const g = parseInt(hex.slice(3, 5), 16);
        const b = parseInt(hex.slice(5, 7), 16);
        return `rgba(${r}, ${g}, ${b}, ${alpha})`;
    }

    loadExistingData() {
        if (window.formBuilderData && Array.isArray(window.formBuilderData)) {
            this.fields = window.formBuilderData;
            this.fieldIdCounter = this.fields.length;
            this.renderForm();
        }
    }

    updatePopupSettings() {
        // This is called when popup settings change
        // Preview will use the updated values when shown
    }
}

// Initialize the form builder
const formBuilder = new MailPurseFormBuilder();