Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: added

Port the Average order value dashboard widget from next-woocommerce-analytics, composed from the widgets-toolkit, data, and fields packages.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "@automattic/jetpack-premium-analytics-widget-average-order-value",
"version": "0.1.0-alpha",
"private": true,
"type": "module",
"dependencies": {
"@jetpack-premium-analytics/widgets-toolkit": "link:../../packages/widgets-toolkit",
"@wordpress/i18n": "^6.9.0",
"@wordpress/icons": "^13.0.0",
"@wordpress/widget-primitives": "next",
"react": "18.3.1"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* External dependencies
*/
import {
OrderMetricWidget,
WidgetRoot,
type ReportParamsFieldAttributes,
} from '@jetpack-premium-analytics/widgets-toolkit';
import type { AverageOrderValueAttributes } from './widget';
import type { WidgetRenderProps } from '@wordpress/widget-primitives';
import type { ComponentProps } from 'react';

// Report params are usually URL-driven (WidgetRoot's fallback), but callers may
// also pass them via `attributes`. Compose the render-only shape to cover both.
type AverageOrderValueRenderAttributes = AverageOrderValueAttributes &
Partial< ReportParamsFieldAttributes >;

type AverageOrderValueRenderProps = WidgetRenderProps< AverageOrderValueRenderAttributes > & {
setError?: ComponentProps< typeof WidgetRoot >[ 'setError' ];
};

/**
* Average order value widget.
*
* Thin composition over the widgets-toolkit: WidgetRoot provides the query
* client, chart theme, and resolved report params; OrderMetricWidget fetches
* the orders report and renders the average_order_value metric with a
* comparison delta and sparkline.
*/
export default function AverageOrderValueRender( {
attributes = {},
setError,
}: AverageOrderValueRenderProps ) {
return (
<WidgetRoot attributes={ attributes } setError={ setError } options={ { from: '/' } }>
<OrderMetricWidget metricKey="average_order_value" />
</WidgetRoot>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
import { getDefaultQueryParams } from '@jetpack-premium-analytics/data';
import { SELECTABLE_PRESETS, type SelectablePresetId } from '@jetpack-premium-analytics/datetime';
import {
DEFAULT_WIDGET_DASHBOARD_STORY_ARGS,
WidgetDashboardWithWidget as WidgetDashboardWithWidgetStory,
widgetDashboardWithWidgetArgTypes,
type WidgetDashboardWithWidgetControls,
} from '../../stories/widget-dashboard-with-widget';
import { registerReportMocks } from '../../../packages/widgets-toolkit/src/stories/mocks/register-report-mocks';
import AverageOrderValueRender from '../render';
import widgetDefinition from '../widget';
import type { Decorator, Meta, StoryObj } from '@storybook/react';
import type { WidgetRenderProps } from '@wordpress/widget-primitives';
import type { ComponentProps, ComponentType } from 'react';

registerReportMocks();

const AVERAGE_ORDER_VALUE_RENDER_MODULE = 'storybook/average-order-value';
const DEFAULT_PRESET = 'last-30-days' satisfies SelectablePresetId;
const PRESET_OPTIONS = SELECTABLE_PRESETS;

type AverageOrderValueRenderProps = ComponentProps< typeof AverageOrderValueRender >;

interface AverageOrderValueStoryControls {
withComparison: boolean;
preset: SelectablePresetId;
}

type AverageOrderValueStoryProps = AverageOrderValueRenderProps & AverageOrderValueStoryControls;

interface AverageOrderValueDashboardStoryProps
extends WidgetDashboardWithWidgetControls,
AverageOrderValueStoryControls {}

const withWidgetCanvas: Decorator = Story => (
<div style={ { width: '100%', height: '300px' } }>
<Story />
</div>
);

function getAverageOrderValueAttributes(
withComparison = false,
preset: SelectablePresetId = DEFAULT_PRESET
): AverageOrderValueRenderProps[ 'attributes' ] {
return {
reportParams: getDefaultQueryParams( withComparison, preset ),
};
}

function getDefaultQueryParamsSource( {
withComparison,
preset,
}: Partial< AverageOrderValueStoryControls > ) {
const hasComparison = Boolean( withComparison );
const storyPreset = preset ?? DEFAULT_PRESET;

if ( ! hasComparison && storyPreset === DEFAULT_PRESET ) {
return 'getDefaultQueryParams()';
}

if ( hasComparison && storyPreset === DEFAULT_PRESET ) {
return 'getDefaultQueryParams( true )';
}

return `getDefaultQueryParams( ${ hasComparison ? 'true' : 'false' }, '${ storyPreset }' )`;
}

function getAverageOrderValueSource( args: Partial< AverageOrderValueStoryControls > ) {
return `import { getDefaultQueryParams } from '@jetpack-premium-analytics/data';

<AverageOrderValueRender
\tattributes={ {
\t\treportParams: ${ getDefaultQueryParamsSource( args ) },
\t} }
/>`;
}

function renderAverageOrderValue( { withComparison, preset }: AverageOrderValueStoryControls ) {
return (
<AverageOrderValueRender
attributes={ getAverageOrderValueAttributes( withComparison, preset ) }
/>
);
}

function AverageOrderValueDashboardStory( {
withComparison,
preset,
...dashboardStoryArgs
}: AverageOrderValueDashboardStoryProps ) {
return (
<WidgetDashboardWithWidgetStory
{ ...dashboardStoryArgs }
widgetType={ widgetDefinition }
renderModule={ AVERAGE_ORDER_VALUE_RENDER_MODULE }
renderComponent={ AverageOrderValueRender as ComponentType< WidgetRenderProps< unknown > > }
attributes={ getAverageOrderValueAttributes( withComparison, preset ) }
/>
);
}

const meta = {
title: 'Packages/Premium Analytics/Widgets/AverageOrderValue',
component: AverageOrderValueRender,
tags: [ 'autodocs' ],
argTypes: {
preset: {
control: 'select',
options: PRESET_OPTIONS,
description: 'Date-range preset used to generate the widget report params.',
},
withComparison: {
control: 'boolean',
description: 'Include previous-period comparison report params.',
},
},
parameters: {
docs: {
description: {
component:
'Dashboard widget that displays the average order value with an optional comparison period and sparkline.',
},
},
},
} satisfies Meta< AverageOrderValueStoryProps >;

export default meta;

type Story = StoryObj< typeof meta >;
type DashboardStory = StoryObj< AverageOrderValueDashboardStoryProps >;

/**
* Default state for the current report period.
*/
export const Default: Story = {
render: renderAverageOrderValue,
args: {
preset: DEFAULT_PRESET,
withComparison: false,
},
decorators: [ withWidgetCanvas ],
parameters: {
docs: {
source: {
transform: (
_source: string,
storyContext: { args: Partial< AverageOrderValueStoryControls > }
) => getAverageOrderValueSource( storyContext.args ),
},
},
},
};

/**
* Comparison period enabled, showing period-over-period change and sparkline data.
*/
export const WithComparison: Story = {
render: renderAverageOrderValue,
args: {
preset: DEFAULT_PRESET,
withComparison: true,
},
decorators: [ withWidgetCanvas ],
parameters: {
docs: {
source: {
transform: (
_source: string,
storyContext: { args: Partial< AverageOrderValueStoryControls > }
) => getAverageOrderValueSource( storyContext.args ),
},
},
},
};

/**
* Renders the widget through the shared dashboard harness.
*/
export const WidgetDashboardWithWidget: DashboardStory = {
render: args => <AverageOrderValueDashboardStory { ...args } />,
args: {
...DEFAULT_WIDGET_DASHBOARD_STORY_ARGS,
preset: DEFAULT_PRESET,
withComparison: true,
},
argTypes: {
...widgetDashboardWithWidgetArgTypes,
preset: {
control: 'select',
options: PRESET_OPTIONS,
description: 'Date-range preset used to generate the widget report params.',
},
withComparison: {
control: 'boolean',
description: 'Include previous-period comparison report params.',
},
},
parameters: {
docs: {
source: {
code: `import { getDefaultQueryParams } from '@jetpack-premium-analytics/data';

<WidgetDashboardWithWidget
\twidgetType={ widgetDefinition }
\trenderModule="storybook/average-order-value"
\trenderComponent={ AverageOrderValueRender }
\tattributes={ {
\t\treportParams: getDefaultQueryParams( true ),
\t} }
/>`,
},
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "jpa/average-order-value",
"title": "Average order value",
"description": "Track the average value of each order over a set period of time.",
"category": "orders"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { chartBar } from '@wordpress/icons';

/**
* The widget has no user-configurable attributes. Report params still reach it
* through WidgetRoot: the dashboard date range, or `attributes.reportParams`
* when a host injects them (e.g. Storybook and dashboard previews).
*/
export type AverageOrderValueAttributes = Record< never, never >;

/**
* Widget type definition.
*
* Ported from `woocommerce-analytics/average-order-value-over-time` in
* woocommerce/woocommerce-analytics (next-woocommerce-analytics).
*
* Report params intentionally come from the analytics dashboard's global
* date-range state for now. Adding widget-level overrides needs a host-level
* control registry so analytics dashboards can hide the field while other
* dashboards can opt in.
*/
export default {
name: 'jpa/average-order-value',
title: __( 'Average order value', 'jetpack-premium-analytics' ),
description: __(
'Track the average value of each order over a set period of time.',
'jetpack-premium-analytics'
),
icon: chartBar,
};
Loading