Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reporting: Add preset date selector to the Payment activity widget #8927

Merged
merged 37 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c2b3c35
wip - date range picker component
Jun 7, 2024
3861478
wip
Jun 7, 2024
1621039
WIP - Tweak Types
Jun 7, 2024
1a71275
Date range formatter
Jun 7, 2024
14437d5
minor - Edit / remove comments
Jun 7, 2024
f4b21bf
wip - CSS changes and add state to save selected date range.
Jun 7, 2024
27d144a
Merge branch 'develop' into 8734-add-date-selector
Jun 8, 2024
aaa1331
clarify start selection of date preset
Jun 9, 2024
604b999
refactor - make names concise
Jun 9, 2024
476f747
Add state in parent for date range
Jun 9, 2024
d123653
fix state & refresh component - Partially working
Jun 9, 2024
025bc43
fix state & refresh component - Partially working
Jun 9, 2024
79cbb36
Store fetched payment activity data per query, to fix caching bug
Jinksi Jun 10, 2024
a4d05bd
Changelog
Jun 10, 2024
1a0c23a
Fix payment-activity reducer test to expect state stored per-query
Jinksi Jun 10, 2024
5f5b49b
Update test snapshot
Jun 10, 2024
8c65863
Fixed issue with selected option reverting to the default
Jun 10, 2024
a3bcdc5
Remove unused declaration
Jun 10, 2024
ca689ed
Merge branch 'develop' into 8734-add-date-selector
jessy-p Jun 10, 2024
32d9d98
Add track events for date selector
Jun 10, 2024
d12cbaf
Merge branch 'develop' into 8734-add-date-selector
Jun 10, 2024
4b74499
Merge branch 'develop' into 8734-add-date-selector
jessy-p Jun 11, 2024
d42d16b
Update changelog
Jun 11, 2024
77f277c
Fix recordEvent params.
Jun 11, 2024
8ca3357
TypeScript cleanup
Jun 11, 2024
5c7d993
Merge branch 'develop' into 8734-add-date-selector
Jun 11, 2024
c373c4f
Simplify date selection logic to hook
Jun 11, 2024
d909a63
change generic `key` name
Jun 11, 2024
bd95962
Correct event name
Jun 11, 2024
c6c0cb0
Address feedback - commenting and minor changes
Jun 11, 2024
cdfb1eb
CSS fix for date range alignment
Jun 11, 2024
0079ea8
Merge branch 'develop' into 8734-add-date-selector
jessy-p Jun 12, 2024
ddee0f7
Add comment to describe `usePaymentActivityDateRangePresets` hook
Jinksi Jun 12, 2024
1cd45f7
Add comment explaining the caching behaviour of payment activity data
Jinksi Jun 12, 2024
ca617a1
Minor text change
Jun 12, 2024
870af45
Merge branch 'develop' into 8734-add-date-selector
Jun 12, 2024
bb1edc6
Update test snapshot
Jun 12, 2024
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
5 changes: 5 additions & 0 deletions changelog/8734-add-date-selector
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Significance: patch
Type: add
Comment: Changes behind a feature flag. The PR allows merchants to change the time period of stats shown in the payment activity widget.


132 changes: 132 additions & 0 deletions client/components/payment-activity/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/**
* External dependencies
*/
import { useState } from 'react';
import { __ } from '@wordpress/i18n';
import moment from 'moment';

interface DateRange {
/** The name of the date range preset. e.g. last_7_days */
preset_name: string;
/** The date range start datetime used to calculate transaction data, e.g. 2024-04-29T16:19:29 */
date_start: string;
/** The date range end datetime used to calculate transaction data, e.g. 2024-04-29T16:19:29 */
date_end: string;
}
nagpai marked this conversation as resolved.
Show resolved Hide resolved

/**
* Hook to manage the selected date range and date range presets for the payment activity widget.
*/
export const usePaymentActivityDateRangePresets = (): {
nagpai marked this conversation as resolved.
Show resolved Hide resolved
selectedDateRange: DateRange;
setSelectedDateRange: ( dateRange: DateRange ) => void;
dateRangePresets: {
[ key: string ]: {
start: moment.Moment;
end: moment.Moment;
displayKey: string;
};
};
} => {
const now = moment();
const yesterdayEndOfDay = moment()
.clone()
.subtract( 1, 'd' )
.set( { hour: 23, minute: 59, second: 59, millisecond: 0 } );
const todayEndOfDay = moment()
.clone()
.set( { hour: 23, minute: 59, second: 59, millisecond: 0 } );

const dateRangePresets: {
[ key: string ]: {
start: moment.Moment;
end: moment.Moment;
displayKey: string;
};
} = {
today: {
start: now
.clone()
.set( { hour: 0, minute: 0, second: 0, millisecond: 0 } ),
end: todayEndOfDay,
displayKey: __( 'Today', 'woocommerce-payments' ),
},
last_7_days: {
start: now
.clone()
.subtract( 7, 'days' )
.set( { hour: 0, minute: 0, second: 0, millisecond: 0 } ),
end: yesterdayEndOfDay,
displayKey: __( 'Last 7 days', 'woocommerce-payments' ),
},
last_4_weeks: {
start: now
.clone()
.subtract( 4, 'weeks' )
.set( { hour: 0, minute: 0, second: 0, millisecond: 0 } ),
end: yesterdayEndOfDay,
displayKey: __( 'Last 4 weeks', 'woocommerce-payments' ),
},
last_3_months: {
start: now
.clone()
.subtract( 3, 'months' )
.set( { hour: 0, minute: 0, second: 0, millisecond: 0 } ),
end: yesterdayEndOfDay,
displayKey: __( 'Last 3 months', 'woocommerce-payments' ),
},
last_12_months: {
start: now
.clone()
.subtract( 12, 'months' )
.set( { hour: 0, minute: 0, second: 0, millisecond: 0 } ),
end: yesterdayEndOfDay,
displayKey: __( 'Last 12 months', 'woocommerce-payments' ),
},
month_to_date: {
start: now.clone().startOf( 'month' ),
end: todayEndOfDay,
displayKey: __( 'Month to date', 'woocommerce-payments' ),
},
quarter_to_date: {
start: now.clone().startOf( 'quarter' ),
end: todayEndOfDay,
displayKey: __( 'Quarter to date', 'woocommerce-payments' ),
},
year_to_date: {
start: now.clone().startOf( 'year' ),
end: todayEndOfDay,
displayKey: __( 'Year to date', 'woocommerce-payments' ),
},
all_time: {
start: moment(
wcpaySettings.accountStatus.created,
'YYYY-MM-DD\\THH:mm:ss'
),
end: todayEndOfDay,
displayKey: __( 'All time', 'woocommerce-payments' ),
},
};

const defaultDateRange = {
preset_name: 'last_7_days',
date_start: dateRangePresets.last_7_days.start.format(
'YYYY-MM-DD\\THH:mm:ss'
),
date_end: dateRangePresets.last_7_days.end.format(
'YYYY-MM-DD\\THH:mm:ss'
),
};

const [ selectedDateRange, setSelectedDateRange ] = useState( {
preset_name: defaultDateRange.preset_name,
date_start: defaultDateRange.date_start,
date_end: defaultDateRange.date_end,
} );

return {
selectedDateRange,
setSelectedDateRange,
dateRangePresets,
};
};
96 changes: 76 additions & 20 deletions client/components/payment-activity/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import * as React from 'react';
import React from 'react';
import { Card, CardBody, CardHeader } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import interpolateComponents from '@automattic/interpolate-components';
Expand All @@ -12,27 +12,16 @@ import moment from 'moment';
*/

import EmptyStateAsset from 'assets/images/payment-activity-empty-state.svg?asset';
import InlineLabelSelect from '../inline-label-select';
import PaymentActivityDataComponent from './payment-activity-data';
import Survey from './survey';
import { WcPayOverviewSurveyContextProvider } from './survey/context';
import { recordEvent } from 'wcpay/tracks';
import { usePaymentActivityData } from 'wcpay/data';
import { usePaymentActivityDateRangePresets } from './hooks';
import { useSelectedCurrency } from 'wcpay/overview/hooks';
import type { DateRange } from './types';
import { WcPayOverviewSurveyContextProvider } from './survey/context';
import './style.scss';

/**
* This will be replaces in the future with a dynamic date range picker.
*/
const getDateRange = (): DateRange => {
return {
// Subtract 7 days from the current date.
date_start: moment()
.subtract( 7, 'd' )
.format( 'YYYY-MM-DD\\THH:mm:ss' ),
date_end: moment().format( 'YYYY-MM-DD\\THH:mm:ss' ),
};
};

const PaymentActivityEmptyState: React.FC = () => (
<Card>
<CardHeader>
Expand Down Expand Up @@ -62,15 +51,40 @@ const PaymentActivityEmptyState: React.FC = () => (
</Card>
);

const formatDateRange = (
start: moment.Moment,
end: moment.Moment
): string => {
// Today - show only today's date.
if ( start.isSame( end, 'day' ) ) {
return start.format( 'MMMM D, YYYY' );
}

// Different years - show year for both start and end
if ( ! start.isSame( end, 'year' ) ) {
return `${ start.format( 'MMMM D, YYYY' ) } - ${ end.format(
'MMMM D, YYYY'
) }`;
}

// Same year - show year only for end date.
return `${ start.format( 'MMMM D' ) } - ${ end.format( 'MMMM D, YYYY' ) }`;
};

const PaymentActivity: React.FC = () => {
const isOverviewSurveySubmitted =
wcpaySettings.isOverviewSurveySubmitted ?? false;

const { selectedCurrency } = useSelectedCurrency();

const {
selectedDateRange,
setSelectedDateRange,
dateRangePresets,
} = usePaymentActivityDateRangePresets();
const { paymentActivityData, isLoading } = usePaymentActivityData( {
currency: selectedCurrency ?? wcpaySettings.accountDefaultCurrency,
...getDateRange(),
date_start: selectedDateRange.date_start,
date_end: selectedDateRange.date_end,
timezone: moment( new Date() ).format( 'Z' ),
} );

Expand All @@ -83,11 +97,53 @@ const PaymentActivity: React.FC = () => {
return <></>;
}

const options = Object.keys( dateRangePresets ).map( ( presetName ) => {
const preset = dateRangePresets[ presetName ];
return {
key: presetName,
name: preset.displayKey,
hint: formatDateRange( preset.start, preset.end ),
};
} );

return (
<Card>
<CardHeader>
<CardHeader className="wcpay-payment-activity__card__header">
{ __( 'Your payment activity', 'woocommerce-payments' ) }
{ /* Filters go here */ }
<InlineLabelSelect
label="Period"
options={ options }
value={ options.find(
( option ) =>
option.key === selectedDateRange.preset_name
) }
placeholder="Select an option..."
onChange={ ( changes ) => {
const selectedItem = changes.selectedItem;
if ( selectedItem ) {
const start = dateRangePresets[
selectedItem.key
].start
.clone()
.format( 'YYYY-MM-DD\\THH:mm:ss' );
const end = dateRangePresets[ selectedItem.key ].end
.clone()
.format( 'YYYY-MM-DD\\THH:mm:ss' );
const { key: presetName } = selectedItem;
recordEvent(
'wcpay_overview_payment_activity_period_change',
{
preset_name: presetName,
}
);
setSelectedDateRange( {
date_start: start,
date_end: end,
preset_name: presetName,
} );
}
} }
/>
</CardHeader>
<CardBody className="wcpay-payment-activity__card__body">
<PaymentActivityDataComponent
Expand Down
22 changes: 22 additions & 0 deletions client/components/payment-activity/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,28 @@
padding: 16px 0 19px;
}
}

&__header {
.wcpay-filter.components-custom-select-control {
.wcpay-filter.components-custom-select-control {
&__menu {
// Ensure date preset items are shown without vertical scroll.
max-height: fit-content;
}

&__item {
// Set alignment of columns in the date preset dropdown.
grid-template-columns: 10% 25% 65%;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this custom to our needs, or would this benefit other clients of InlineLabelSelect.

Side note (FYI @Jinksi ) – looks like the CSS classes for InlineLabelSelect are out of date? (custom-select-control)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be custom to our needs IMO. For other use cases, where the list longer, it may not be suitable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the CSS classes for InlineLabelSelect are out of date?

InlineLabelSelect only extends the existing Gutenberg custom-select-control styles by adding the .wcpay-filter class.

.wcpay-filter.components-custom-select-control {

}

@include breakpoint( '<660px' ) {
// Sets Mobile view of the payment activity widget header. Date preset dropdown is moved to a new line.
flex-direction: column !important;
gap: 16px;
}
nagpai marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,58 @@ exports[`PaymentActivity component should render 1`] = `
class="css-mgwsf4-View-Content em57xhy0"
>
<div
class="components-flex components-card__header components-card-header css-1g5oj2q-View-Flex-sx-Base-sx-Items-ItemsRow-Header-borderRadius-borderColor-medium em57xhy0"
class="components-flex components-card__header components-card-header wcpay-payment-activity__card__header css-1g5oj2q-View-Flex-sx-Base-sx-Items-ItemsRow-Header-borderRadius-borderColor-medium em57xhy0"
data-wp-c16t="true"
data-wp-component="CardHeader"
>
Your payment activity
<div
class="wcpay-filter components-custom-select-control"
>
<button
aria-describedby="Currently selected: Last 7 days"
aria-expanded="false"
aria-haspopup="listbox"
aria-label="Period"
class="components-button wcpay-filter components-custom-select-control__button"
id="downshift-0-toggle-button"
type="button"
>
<label
class="wcpay-filter components-custom-select-control__label"
for="downshift-0-toggle-button"
id="downshift-0-label"
>
Period
</label>
<span
class="wcpay-filter components-custom-select-control__button-value"
>
Last 7 days
</span>
<svg
aria-hidden="true"
class="wcpay-filter components-custom-select-control__button-icon"
focusable="false"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"
/>
</svg>
</button>
<ul
aria-hidden="true"
aria-labelledby="downshift-0-label"
class="wcpay-filter components-custom-select-control__menu"
id="downshift-0-menu"
role="listbox"
tabindex="-1"
/>
</div>
</div>
<div
class="components-card__body components-card-body wcpay-payment-activity__card__body css-1nwhnu3-View-Body-borderRadius-medium em57xhy0"
Expand Down
4 changes: 0 additions & 4 deletions client/components/payment-activity/types.ts

This file was deleted.

10 changes: 8 additions & 2 deletions client/data/payment-activity/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@
* Internal Dependencies
*/
import TYPES from './action-types';
import { PaymentActivityData, PaymentActivityAction } from './types';
import type {
PaymentActivityData,
PaymentActivityAction,
PaymentActivityQuery,
} from './types';

export function updatePaymentActivity(
data: PaymentActivityData
data: PaymentActivityData,
query: PaymentActivityQuery
): PaymentActivityAction {
return {
type: TYPES.SET_PAYMENT_ACTIVITY_DATA,
query,
data,
};
}
Loading
Loading