const { __ } = wp.i18n;
const { Toolbar, withAPIData, Dropdown, Dashicon } = wp.components;
/**
* When the display mode is 'Product category' search for and select product categories to pull products from.
*/
export class ProductsCategorySelect extends React.Component {
/**
* Constructor.
*/
constructor( props ) {
super( props );
this.state = {
selectedCategories: props.selected_display_setting,
openAccordion: [],
filterQuery: '',
firstLoad: true,
}
this.checkboxChange = this.checkboxChange.bind( this );
this.accordionToggle = this.accordionToggle.bind( this );
this.filterResults = this.filterResults.bind( this );
this.setFirstLoad = this.setFirstLoad.bind( this );
}
/**
* Handle checkbox toggle.
*
* @param Checked? boolean checked
* @param Categories array categories
*/
checkboxChange( checked, categories ) {
let selectedCategories = this.state.selectedCategories;
selectedCategories = selectedCategories.filter( category => ! categories.includes( category ) );
if ( checked ) {
selectedCategories.push( ...categories );
}
this.setState( {
selectedCategories: selectedCategories
} );
this.props.update_display_setting_callback( selectedCategories );
}
/**
* Handle accordion toggle.
*
* @param Category ID category
*/
accordionToggle( category ) {
let openAccordions = this.state.openAccordion;
if ( openAccordions.includes( category ) ) {
openAccordions = openAccordions.filter( c => c !== category );
} else {
openAccordions.push( category );
}
this.setState( {
openAccordion: openAccordions
} );
}
/**
* Filter categories.
*
* @param Event object evt
*/
filterResults( evt ) {
this.setState( {
filterQuery: evt.target.value
} );
}
/**
* Update firstLoad state.
*
* @param Booolean loaded
*/
setFirstLoad( loaded ) {
this.setState( {
firstLoad: !! loaded
} );
}
/**
* Render the list of categories and the search input.
*/
render() {
return (
);
}
}
/**
* The category search input.
*/
const ProductCategoryFilter = ( { filterResults } ) => {
return (
);
}
/**
* Fetch and build a tree of product categories.
*/
const ProductCategoryList = withAPIData( ( props ) => {
return {
categories: '/wc/v2/products/categories'
};
} )( ( { categories, filterQuery, selectedCategories, checkboxChange, accordionToggle, openAccordion, firstLoad, setFirstLoad } ) => {
if ( ! categories.data ) {
return __( 'Loading' );
}
if ( 0 === categories.data.length ) {
return __( 'No categories found' );
}
const handleCategoriesToCheck = ( evt, parent, categories ) => {
let ids = getCategoryChildren( parent, categories ).map( category => {
return category.id;
} );
ids.push( parent.id );
checkboxChange( evt.target.checked, ids );
};
const getCategoryChildren = ( parent, categories ) => {
let children = [];
categories.filter( ( category ) => category.parent === parent.id ).forEach( function( category ) {
children.push( category );
children.push( ...getCategoryChildren( category, categories ) );
} );
return children;
};
const categoryHasChildren = ( parent, categories ) => {
return !! getCategoryChildren( parent, categories ).length;
};
const isIndeterminate = ( category, categories ) => {
// Currect category selected?
if ( selectedCategories.includes( category.id ) ) {
return false;
}
// Has children?
let children = getCategoryChildren( category, categories ).map( category => {
return category.id;
} );
for ( let child of children ) {
if ( selectedCategories.includes( child ) ) {
return true;
}
}
return false;
}
const AccordionButton = ( { category, categories } ) => {
let icon = 'arrow-down-alt2';
if ( openAccordion.includes( category.id ) ) {
icon = 'arrow-up-alt2';
}
let style = null;
if ( ! categoryHasChildren( category, categories ) ) {
style = {
visibility: 'hidden',
};
};
return (
);
};
const CategoryTree = ( { categories, parent } ) => {
let filteredCategories = categories.filter( ( category ) => category.parent === parent );
if ( firstLoad && selectedCategories.length > 0 ) {
categoriesData.filter( ( category ) => category.parent === 0 ).forEach( function( category ) {
let children = getCategoryChildren( category, categoriesData );
for ( let child of children ) {
if ( selectedCategories.includes( child.id ) && ! openAccordion.includes( category.id ) ) {
accordionToggle( category.id );
break;
}
}
} );
setFirstLoad( false );
}
return ( filteredCategories.length > 0 ) && (
);
};
let categoriesData = categories.data;
if ( '' !== filterQuery ) {
categoriesData = categoriesData.filter( category => category.slug.includes( filterQuery.toLowerCase() ) );
}
return (
);
}
);