| New file |
| | |
| | | /** |
| | | * edit.js |
| | | * WordPress dependencies |
| | | */ |
| | | import { __ } from '@wordpress/i18n'; |
| | | import { useBlockProps, InspectorControls } from '@wordpress/block-editor'; |
| | | import { |
| | | PanelBody, |
| | | SelectControl, |
| | | ToggleControl, |
| | | TextControl, |
| | | Notice |
| | | } from '@wordpress/components'; |
| | | import { useState, useEffect } from '@wordpress/element'; |
| | | |
| | | /** |
| | | * Styles |
| | | */ |
| | | import './editor.scss'; |
| | | |
| | | /** |
| | | * Edit function for Form Block |
| | | */ |
| | | export default function Edit({ attributes, setAttributes }) { |
| | | const { |
| | | formType, |
| | | showLabels, |
| | | customEmailTo, |
| | | turnstileEnabled |
| | | } = attributes; |
| | | |
| | | const [isPreviewVisible, setIsPreviewVisible] = useState(true); |
| | | |
| | | const blockProps = useBlockProps({ |
| | | className: `jvb-form-block ${formType ? `jvb-form-block-${formType}` : ''}` |
| | | }); |
| | | |
| | | // Get form types from localized data, with fallback |
| | | const getFormTypes = () => { |
| | | if (typeof window !== 'undefined' && window.jvbFormsData && window.jvbFormsData.formTypes) { |
| | | return window.jvbFormsData.formTypes; |
| | | } |
| | | |
| | | // Fallback if data isn't available |
| | | return [ |
| | | { label: __('Select a form type', 'jvb'), value: '' }, |
| | | { label: __('No forms available', 'jvb'), value: '', disabled: true } |
| | | ]; |
| | | }; |
| | | |
| | | // Get available forms configuration |
| | | const getAvailableForms = () => { |
| | | console.log(window.jvbFormsData); |
| | | if (typeof window !== 'undefined' && window.jvbFormsData && window.jvbFormsData.availableForms) { |
| | | return window.jvbFormsData.availableForms; |
| | | } |
| | | return {}; |
| | | }; |
| | | |
| | | const formTypes = getFormTypes(); |
| | | const availableForms = getAvailableForms(); |
| | | |
| | | // Get form configuration based on selected type |
| | | const getCurrentFormConfig = () => { |
| | | if (!formType || !availableForms[formType]) { |
| | | return null; |
| | | } |
| | | return availableForms[formType]; |
| | | }; |
| | | |
| | | // Form labels based on the selected form type |
| | | const getFormLabels = () => { |
| | | const formConfig = getCurrentFormConfig(); |
| | | |
| | | if (formConfig) { |
| | | return { |
| | | title: formConfig.title || __('Form', 'jvb'), |
| | | description: Array.isArray(formConfig.description) |
| | | ? formConfig.description.join(' ') |
| | | : (formConfig.description || ''), |
| | | button: formConfig.submit || __('Submit', 'jvb') |
| | | }; |
| | | } |
| | | |
| | | return { |
| | | title: __('Form', 'jvb'), |
| | | description: formType ? __('Loading form configuration...', 'jvb') : __('Please select a form type in the sidebar', 'jvb'), |
| | | button: __('Submit', 'jvb') |
| | | }; |
| | | }; |
| | | |
| | | const formLabels = getFormLabels(); |
| | | |
| | | // Render a preview of the form in the editor |
| | | const renderFormPreview = () => { |
| | | if (!formType) { |
| | | return ( |
| | | <Notice status="warning" isDismissible={false}> |
| | | {__('Please select a form type in the block settings.', 'jvb')} |
| | | </Notice> |
| | | ); |
| | | } |
| | | |
| | | let formFields = []; |
| | | |
| | | switch (formType) { |
| | | case 'contact': |
| | | formFields = [ |
| | | { id: 'name', label: __('Name', 'jvb'), type: 'text', required: true }, |
| | | { id: 'email', label: __('Email', 'jvb'), type: 'email', required: true }, |
| | | { id: 'phone', label: __('Phone', 'jvb'), type: 'tel', required: true }, |
| | | { id: 'instagram', label: __('Instagram URL', 'jvb'), type: 'url' }, |
| | | { id: 'contact_methods', label: __('Preferred Contact', 'jvb'), type: 'checkboxes', |
| | | options: [ |
| | | { value: 'text', label: __('Text', 'jvb') }, |
| | | { value: 'call', label: __('Call', 'jvb') }, |
| | | { value: 'email', label: __('Email', 'jvb') }, |
| | | { value: 'instagram', label: __('Instagram', 'jvb') } |
| | | ] |
| | | }, |
| | | { id: 'message', label: __('Your Message', 'jvb'), type: 'textarea', required: true } |
| | | ]; |
| | | break; |
| | | |
| | | case 'feature_request': |
| | | formFields = [ |
| | | { id: 'name', label: __('Name', 'jvb'), type: 'text', help: __('Required if you want us to follow up.', 'jvb') }, |
| | | { id: 'email', label: __('Email', 'jvb'), type: 'email', help: __('Required if you want us to follow up.', 'jvb') }, |
| | | { id: 'follow_up', label: __('Would you like me to follow up with you?', 'jvb'), type: 'checkbox' }, |
| | | { id: 'target_audience', label: __('This Feature is For', 'jvb'), type: 'checkboxes', |
| | | options: [ |
| | | { value: 'artists', label: __('Artists', 'jvb') }, |
| | | { value: 'visitors', label: __('Site Visitors', 'jvb') }, |
| | | { value: 'partners', label: __('Partners', 'jvb') }, |
| | | { value: 'other', label: __('Other', 'jvb') } |
| | | ] |
| | | }, |
| | | { id: 'feature_name', label: __('Name your Feature', 'jvb'), type: 'text', required: true }, |
| | | { id: 'message', label: __('Describe Your Feature', 'jvb'), type: 'textarea', required: true } |
| | | ]; |
| | | break; |
| | | |
| | | case 'technical_issue': |
| | | formFields = [ |
| | | { id: 'name', label: __('Name', 'jvb'), type: 'text' }, |
| | | { id: 'email', label: __('Email', 'jvb'), type: 'email' }, |
| | | { id: 'follow_up', label: __('Would you like me to follow up with you?', 'jvb'), type: 'checkbox' }, |
| | | { id: 'issue_type', label: __('Type of Issue', 'jvb'), type: 'checkboxes', |
| | | options: [ |
| | | { value: 'visual', label: __('Visual', 'jvb') }, |
| | | { value: 'error', label: __('Error Page', 'jvb') }, |
| | | { value: 'other', label: __('Other', 'jvb') } |
| | | ] |
| | | }, |
| | | { id: 'message', label: __('Please describe the issue.', 'jvb'), type: 'textarea', required: true } |
| | | ]; |
| | | break; |
| | | } |
| | | |
| | | return ( |
| | | <> |
| | | <h3 className="jvb-form-title">{formLabels.title}</h3> |
| | | <p className="jvb-form-description">{formLabels.description}</p> |
| | | |
| | | <div className="jvb-form-preview"> |
| | | {formFields.map((field) => ( |
| | | <div key={field.id} className="jvb-form-field"> |
| | | {showLabels && ( |
| | | <label htmlFor={`jvb-${field.id}`} className={field.required ? 'required' : ''}> |
| | | {field.label} |
| | | </label> |
| | | )} |
| | | |
| | | {field.type === 'text' && ( |
| | | <input |
| | | type="text" |
| | | id={`jvb-${field.id}`} |
| | | placeholder={showLabels ? '' : field.label} |
| | | disabled |
| | | /> |
| | | )} |
| | | |
| | | {field.type === 'email' && ( |
| | | <input |
| | | type="email" |
| | | id={`jvb-${field.id}`} |
| | | placeholder={showLabels ? '' : field.label} |
| | | disabled |
| | | /> |
| | | )} |
| | | |
| | | {field.type === 'tel' && ( |
| | | <input |
| | | type="tel" |
| | | id={`jvb-${field.id}`} |
| | | placeholder={showLabels ? '' : field.label} |
| | | disabled |
| | | /> |
| | | )} |
| | | |
| | | {field.type === 'url' && ( |
| | | <input |
| | | type="url" |
| | | id={`jvb-${field.id}`} |
| | | placeholder={showLabels ? '' : field.label} |
| | | disabled |
| | | /> |
| | | )} |
| | | |
| | | {field.type === 'textarea' && ( |
| | | <textarea |
| | | id={`jvb-${field.id}`} |
| | | placeholder={showLabels ? '' : field.label} |
| | | disabled |
| | | rows="4" |
| | | ></textarea> |
| | | )} |
| | | |
| | | {field.type === 'checkbox' && ( |
| | | <div className="jvb-form-checkbox"> |
| | | <input |
| | | type="checkbox" |
| | | id={`jvb-${field.id}`} |
| | | disabled |
| | | /> |
| | | <label htmlFor={`jvb-${field.id}`}>{field.label}</label> |
| | | </div> |
| | | )} |
| | | |
| | | {field.type === 'checkboxes' && field.options && ( |
| | | <div className="jvb-form-checkboxes"> |
| | | {field.options.map((option) => ( |
| | | <div key={option.value} className="jvb-form-checkbox"> |
| | | <input |
| | | type="checkbox" |
| | | id={`jvb-${field.id}-${option.value}`} |
| | | disabled |
| | | /> |
| | | <label htmlFor={`jvb-${field.id}-${option.value}`}>{option.label}</label> |
| | | </div> |
| | | ))} |
| | | </div> |
| | | )} |
| | | |
| | | {field.help && ( |
| | | <p className="jvb-form-help">{field.help}</p> |
| | | )} |
| | | </div> |
| | | ))} |
| | | |
| | | {turnstileEnabled && ( |
| | | <div className="jvb-form-turnstile"> |
| | | <div className="jvb-turnstile-placeholder"> |
| | | <span>{__('Cloudflare Turnstile will appear here', 'jvb')}</span> |
| | | </div> |
| | | </div> |
| | | )} |
| | | |
| | | <div className="jvb-form-submit"> |
| | | <button type="button" className="jvb-form-button">{formLabels.button}</button> |
| | | </div> |
| | | </div> |
| | | </> |
| | | ); |
| | | }; |
| | | |
| | | return ( |
| | | <> |
| | | <InspectorControls> |
| | | <PanelBody title={__('Form Settings', 'jvb')}> |
| | | <SelectControl |
| | | label={__('Form Type', 'jvb')} |
| | | value={formType} |
| | | options={formTypes} |
| | | onChange={(value) => setAttributes({ formType: value })} |
| | | /> |
| | | |
| | | <ToggleControl |
| | | label={__('Show Field Labels', 'jvb')} |
| | | checked={showLabels} |
| | | onChange={(value) => setAttributes({ showLabels: value })} |
| | | help={__('Toggle to show or hide field labels.', 'jvb')} |
| | | /> |
| | | |
| | | <TextControl |
| | | label={__('Custom Recipient Email', 'jvb')} |
| | | value={customEmailTo || ''} |
| | | onChange={(value) => setAttributes({ customEmailTo: value })} |
| | | help={__('Leave empty to use the default email.', 'jvb')} |
| | | type="email" |
| | | /> |
| | | </PanelBody> |
| | | |
| | | <PanelBody title={__('Form Preview', 'jvb')} initialOpen={false}> |
| | | <ToggleControl |
| | | label={__('Show Preview', 'jvb')} |
| | | checked={isPreviewVisible} |
| | | onChange={(value) => setIsPreviewVisible(value)} |
| | | /> |
| | | |
| | | <p className="components-base-control__help"> |
| | | {__('This is just a preview. The actual form will be rendered on the frontend.', 'jvb')} |
| | | </p> |
| | | </PanelBody> |
| | | </InspectorControls> |
| | | |
| | | <div {...blockProps}> |
| | | {isPreviewVisible ? ( |
| | | renderFormPreview() |
| | | ) : ( |
| | | <div className="jvb-form-placeholder"> |
| | | <h3>{formLabels.title}</h3> |
| | | <p>{__('Form preview is hidden. Edit settings in the sidebar.', 'jvb')}</p> |
| | | </div> |
| | | )} |
| | | </div> |
| | | </> |
| | | ); |
| | | } |