/** * External dependencies */ import { useState, useEffect } from '@wordpress/element'; import { getAttributes, getTerms } from '@woocommerce/editor-components/utils'; /** * Internal dependencies */ import { formatError } from '../base/utils/errors'; /** * Get attribute data (name, taxonomy etc) from server data. * * @param {number} attributeId Attribute ID to look for. * @param {Array|null} attributeList List of attributes. * @param {string} matchField Field to match on. e.g. id or slug. */ const getAttributeData = ( attributeId, attributeList, matchField = 'id' ) => { return Array.isArray( attributeList ) ? attributeList.find( ( attr ) => attr[ matchField ] === attributeId ) : null; }; /** * HOC that calls the useAttributes hook. * * @param {Function} OriginalComponent Component being wrapped. */ const withAttributes = ( OriginalComponent ) => { return ( props ) => { const { selected = [] } = props; const selectedSlug = selected.length ? selected[ 0 ].attr_slug : null; const [ attributes, setAttributes ] = useState( null ); const [ expandedAttribute, setExpandedAttribute ] = useState( 0 ); const [ termsList, setTermsList ] = useState( {} ); const [ loading, setLoading ] = useState( true ); const [ termsLoading, setTermsLoading ] = useState( false ); const [ error, setError ] = useState( null ); useEffect( () => { if ( attributes === null ) { getAttributes() .then( ( newAttributes ) => { newAttributes = newAttributes.map( ( attribute ) => ( { ...attribute, parent: 0, } ) ); setAttributes( newAttributes ); if ( selectedSlug ) { const selectedAttributeFromTerm = getAttributeData( selectedSlug, newAttributes, 'taxonomy' ); if ( selectedAttributeFromTerm ) { setExpandedAttribute( selectedAttributeFromTerm.id ); } } } ) .catch( async ( e ) => { setError( await formatError( e ) ); } ) .finally( () => { setLoading( false ); } ); } }, [ attributes, selectedSlug ] ); useEffect( () => { const attributeData = getAttributeData( expandedAttribute, attributes ); if ( ! attributeData ) { return; } setTermsLoading( true ); getTerms( expandedAttribute ) .then( ( newTerms ) => { newTerms = newTerms.map( ( term ) => ( { ...term, parent: expandedAttribute, attr_slug: attributeData.taxonomy, } ) ); setTermsList( ( previousTermsList ) => ( { ...previousTermsList, [ expandedAttribute ]: newTerms, } ) ); } ) .catch( async ( e ) => { setError( await formatError( e ) ); } ) .finally( () => { setTermsLoading( false ); } ); }, [ expandedAttribute, attributes ] ); return ( ); }; }; export default withAttributes;