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