/** @format */ /** * External dependencies */ import { __ } from '@wordpress/i18n'; import { Component } from '@wordpress/element'; import { compose } from '@wordpress/compose'; import PropTypes from 'prop-types'; /** * WooCommerce dependencies */ import { getDateParamsFromQuery } from '@woocommerce/date'; import { getNewPath } from '@woocommerce/navigation'; import { SummaryList, SummaryListPlaceholder, SummaryNumber } from '@woocommerce/components'; import { calculateDelta, formatValue } from '@woocommerce/number'; import { formatCurrency } from '@woocommerce/currency'; /** * Internal dependencies */ import { getSummaryNumbers } from 'wc-api/reports/utils'; import ReportError from 'analytics/components/report-error'; import withSelect from 'wc-api/with-select'; import { recordEvent } from 'lib/tracks'; /** * Component to render summary numbers in reports. */ export class ReportSummary extends Component { formatVal( val, type ) { return 'currency' === type ? formatCurrency( val ) : formatValue( type, val ); } getValues( key, type ) { const { emptySearchResults, summaryData } = this.props; const { totals } = summaryData; const primaryValue = emptySearchResults ? 0 : totals.primary[ key ]; const secondaryValue = emptySearchResults ? 0 : totals.secondary[ key ]; return { delta: calculateDelta( primaryValue, secondaryValue ), prevValue: this.formatVal( secondaryValue, type ), value: this.formatVal( primaryValue, type ), }; } render() { const { charts, isRequesting, query, selectedChart, summaryData, endpoint, report, } = this.props; const { isError, isRequesting: isSummaryDataRequesting } = summaryData; if ( isError ) { return ; } if ( isRequesting || isSummaryDataRequesting ) { return ; } const { compare } = getDateParamsFromQuery( query ); const renderSummaryNumbers = ( { onToggle } ) => charts.map( chart => { const { key, order, orderby, label, type } = chart; const newPath = { chart: key }; if ( orderby ) { newPath.orderby = orderby; } if ( order ) { newPath.order = order; } const href = getNewPath( newPath ); const isSelected = selectedChart.key === key; const { delta, prevValue, value } = this.getValues( key, type ); return ( { // Wider than a certain breakpoint, there is no dropdown so avoid calling onToggle. if ( onToggle ) { onToggle(); } recordEvent( 'analytics_chart_tab_click', { report: report || endpoint, key } ); } } /> ); } ); return { renderSummaryNumbers }; } } ReportSummary.propTypes = { /** * Properties of all the charts available for that report. */ charts: PropTypes.array.isRequired, /** * The endpoint to use in API calls to populate the Summary Numbers. * For example, if `taxes` is provided, data will be fetched from the report * `taxes` endpoint (ie: `/wc/v4/reports/taxes/stats`). If the provided endpoint * doesn't exist, an error will be shown to the user with `ReportError`. */ endpoint: PropTypes.string.isRequired, /** * Allows specifying properties different from the `endpoint` that will be used * to limit the items when there is an active search. */ limitProperties: PropTypes.array, /** * The query string represented in object form. */ query: PropTypes.object.isRequired, /** * Whether there is an API call running. */ isRequesting: PropTypes.bool, /** * Properties of the selected chart. */ selectedChart: PropTypes.shape( { /** * Key of the selected chart. */ key: PropTypes.string.isRequired, /** * Chart label. */ label: PropTypes.string.isRequired, /** * Order query argument. */ order: PropTypes.oneOf( [ 'asc', 'desc' ] ), /** * Order by query argument. */ orderby: PropTypes.string, /** * Number type for formatting. */ type: PropTypes.oneOf( [ 'average', 'number', 'currency' ] ).isRequired, } ).isRequired, /** * Data to display in the SummaryNumbers. */ summaryData: PropTypes.object, /** * Report name, if different than the endpoint. */ report: PropTypes.string, }; ReportSummary.defaultProps = { summaryData: { totals: { primary: {}, secondary: {}, }, isError: false, isRequesting: false, }, }; export default compose( withSelect( ( select, props ) => { const { endpoint, isRequesting, limitProperties, query, filters, advancedFilters } = props; const limitBy = limitProperties || [ endpoint ]; if ( isRequesting ) { return {}; } const hasLimitByParam = limitBy.some( item => query[ item ] && query[ item ].length ); if ( query.search && ! hasLimitByParam ) { return { emptySearchResults: true, }; } const summaryData = getSummaryNumbers( { endpoint, query, select, limitBy, filters, advancedFilters, } ); return { summaryData, }; } ) )( ReportSummary );