| New file |
| | |
| | | import { useBlockProps, InspectorControls } from '@wordpress/block-editor'; |
| | | import { PanelBody, ToggleControl, Notice, Button } from '@wordpress/components'; |
| | | import { __ } from '@wordpress/i18n'; |
| | | import { useState, useEffect } from '@wordpress/element'; |
| | | import './editor.scss'; |
| | | |
| | | export default function Edit({ attributes, setAttributes }) { |
| | | const { sectionOrder, showSectionTitles, collapseByDefault } = attributes; |
| | | const [sections, setSections] = useState([]); |
| | | |
| | | // Get sections from localized script |
| | | const allSections = window.jvbFaq?.sections || []; |
| | | |
| | | // Initialize sections with proper ordering |
| | | useEffect(() => { |
| | | if (!allSections.length) return; |
| | | |
| | | if (sectionOrder.length === 0) { |
| | | // First time - use default order |
| | | const orderedSections = allSections.map(section => ({ |
| | | id: section.id, |
| | | name: section.name, |
| | | })); |
| | | setSections(orderedSections); |
| | | setAttributes({ sectionOrder: orderedSections.map(s => s.id) }); |
| | | } else { |
| | | // Use saved order, add any new sections at the end |
| | | const orderedSections = []; |
| | | const existingIds = new Set(sectionOrder); |
| | | |
| | | // Add sections in saved order |
| | | sectionOrder.forEach(id => { |
| | | const section = allSections.find(s => s.id === id); |
| | | if (section) { |
| | | orderedSections.push({ id: section.id, name: section.name }); |
| | | } |
| | | }); |
| | | |
| | | // Add any new sections that weren't in the saved order |
| | | allSections.forEach(section => { |
| | | if (!existingIds.has(section.id)) { |
| | | orderedSections.push({ id: section.id, name: section.name }); |
| | | } |
| | | }); |
| | | |
| | | setSections(orderedSections); |
| | | } |
| | | }, [allSections, sectionOrder]); |
| | | |
| | | const moveSection = (index, direction) => { |
| | | const newSections = [...sections]; |
| | | const newIndex = direction === 'up' ? index - 1 : index + 1; |
| | | |
| | | if (newIndex < 0 || newIndex >= newSections.length) return; |
| | | |
| | | // Swap sections |
| | | [newSections[index], newSections[newIndex]] = [newSections[newIndex], newSections[index]]; |
| | | |
| | | setSections(newSections); |
| | | setAttributes({ sectionOrder: newSections.map(s => s.id) }); |
| | | }; |
| | | |
| | | const blockProps = useBlockProps({ |
| | | className: 'faq-block-editor', |
| | | }); |
| | | |
| | | return ( |
| | | <> |
| | | <InspectorControls> |
| | | <PanelBody title={__('FAQ Settings', 'jvb')} initialOpen={true}> |
| | | <ToggleControl |
| | | label={__('Show Section Titles', 'jvb')} |
| | | checked={showSectionTitles} |
| | | onChange={(value) => setAttributes({ showSectionTitles: value })} |
| | | help={__('Display section names as headings', 'jvb')} |
| | | /> |
| | | <ToggleControl |
| | | label={__('Collapse by Default', 'jvb')} |
| | | checked={collapseByDefault} |
| | | onChange={(value) => setAttributes({ collapseByDefault: value })} |
| | | help={__('Questions start collapsed and expand on click', 'jvb')} |
| | | /> |
| | | </PanelBody> |
| | | |
| | | <PanelBody title={__('Section Order', 'jvb')} initialOpen={false}> |
| | | <p className="components-base-control__help"> |
| | | {__('Use the arrow buttons to reorder sections', 'jvb')} |
| | | </p> |
| | | {sections.length > 0 ? ( |
| | | <div className="faq-section-list"> |
| | | {sections.map((section, index) => ( |
| | | <div key={section.id} className="faq-section-item"> |
| | | <div className="faq-section-controls"> |
| | | <Button |
| | | icon="arrow-up-alt2" |
| | | label={__('Move up', 'jvb')} |
| | | disabled={index === 0} |
| | | onClick={() => moveSection(index, 'up')} |
| | | className="faq-section-button" |
| | | /> |
| | | <Button |
| | | icon="arrow-down-alt2" |
| | | label={__('Move down', 'jvb')} |
| | | disabled={index === sections.length - 1} |
| | | onClick={() => moveSection(index, 'down')} |
| | | className="faq-section-button" |
| | | /> |
| | | </div> |
| | | <span className="faq-section-name">{section.name}</span> |
| | | </div> |
| | | ))} |
| | | </div> |
| | | ) : ( |
| | | <Notice status="info" isDismissible={false}> |
| | | {__('No sections found. Create sections in the FAQ taxonomy.', 'jvb')} |
| | | </Notice> |
| | | )} |
| | | </PanelBody> |
| | | </InspectorControls> |
| | | |
| | | <div {...blockProps}> |
| | | <div className="faq-block-preview"> |
| | | <h3>{__('FAQ Block', 'jvb')}</h3> |
| | | <p> |
| | | {__('This block will display FAQs organized by sections.', 'jvb')} |
| | | </p> |
| | | {sections.length > 0 ? ( |
| | | <div className="faq-sections-preview"> |
| | | <strong>{__('Section Order:', 'jvb')}</strong> |
| | | <ol> |
| | | {sections.map((section) => ( |
| | | <li key={section.id}>{section.name}</li> |
| | | ))} |
| | | </ol> |
| | | </div> |
| | | ) : ( |
| | | <Notice status="warning" isDismissible={false}> |
| | | {__('No sections available. Create sections in the FAQ taxonomy.', 'jvb')} |
| | | </Notice> |
| | | )} |
| | | </div> |
| | | </div> |
| | | </> |
| | | ); |
| | | } |