Create schedule sale pricing block (#37567)

* Create schedule sale pricing block

* Add auto show/hide and clean fields depending on the initial values

* Add validations to From and To dates fields

* Add changelog files

* Align block with the figma design

* Revert linter replacement in the editor global style.scss file

* Fix some words typos

* Move and rename schedule sale block to the blocks folder

* Load datetime format from @wordpress/date instead of using the woo options datastore

* Remove the min difference using by moment to compare dates from 'minute' to undefined

* Make sure the dates are normalized for comparison
This commit is contained in:
Maikel David Pérez Gómez 2023-04-11 10:53:37 -04:00 committed by GitHub
parent fa4dd90401
commit 8354ae2792
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 480 additions and 206 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add product schedule sale pricing block

View File

@ -47,6 +47,7 @@
"@wordpress/compose": "wp-6.0",
"@wordpress/core-data": "wp-6.0",
"@wordpress/data": "wp-6.0",
"@wordpress/date": "wp-6.0",
"@wordpress/editor": "wp-6.0",
"@wordpress/element": "wp-6.0",
"@wordpress/html-entities": "wp-6.0",
@ -60,6 +61,7 @@
"classnames": "^2.3.1",
"dompurify": "^2.3.6",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"prop-types": "^15.8.1",
"react-router-dom": "^6.3.0"
},
@ -80,6 +82,7 @@
"@types/wordpress__components": "^19.10.3",
"@types/wordpress__core-data": "^2.4.5",
"@types/wordpress__data": "^6.0.2",
"@types/wordpress__date": "^3.3.2",
"@types/wordpress__editor": "^13.0.0",
"@types/wordpress__media-utils": "^3.0.0",
"@types/wordpress__plugins": "^3.0.0",

View File

@ -0,0 +1,25 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "woocommerce/product-schedule-sale-fields",
"title": "Product schedule sale fields",
"category": "woocommerce",
"description": "The product schedule sale fields.",
"keywords": [ "products", "schedule", "sale" ],
"textdomain": "default",
"attributes": {
"name": {
"type": "string",
"__experimentalRole": "content"
}
},
"supports": {
"align": false,
"html": false,
"multiple": true,
"reusable": false,
"inserter": false,
"lock": false
},
"editorStyle": "file:./editor.css"
}

View File

@ -0,0 +1,151 @@
/**
* External dependencies
*/
import { DateTimePickerControl } from '@woocommerce/components';
import { recordEvent } from '@woocommerce/tracks';
import { useBlockProps } from '@wordpress/block-editor';
import { BlockEditProps } from '@wordpress/blocks';
import { ToggleControl } from '@wordpress/components';
import { useEntityProp } from '@wordpress/core-data';
import { createElement, useEffect, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import moment from 'moment';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore We need this to get the datetime format for the DateTimePickerControl.
// eslint-disable-next-line @woocommerce/dependency-group
import { getSettings } from '@wordpress/date';
/**
* Internal dependencies
*/
import { ScheduleSalePricingBlockAttributes } from './types';
import { useValidation } from '../../hooks/use-validation';
export function Edit( {}: BlockEditProps< ScheduleSalePricingBlockAttributes > ) {
const blockProps = useBlockProps( {
className: 'wp-block-woocommerce-product-schedule-sale-fields',
} );
const dateTimeFormat = getSettings().formats.datetime;
const [ showScheduleSale, setShowScheduleSale ] = useState( false );
const [ salePrice ] = useEntityProp< string | null >(
'postType',
'product',
'sale_price'
);
const isSalePriceGreaterThanZero =
Number.parseFloat( salePrice || '0' ) > 0;
const [ dateOnSaleFromGmt, setDateOnSaleFromGmt ] = useEntityProp<
string | null
>( 'postType', 'product', 'date_on_sale_from_gmt' );
const [ dateOnSaleToGmt, setDateOnSaleToGmt ] = useEntityProp<
string | null
>( 'postType', 'product', 'date_on_sale_to_gmt' );
const today = moment().startOf( 'minute' ).toISOString();
function handleToggleChange( value: boolean ) {
recordEvent( 'product_pricing_schedule_sale_toggle_click', {
enabled: value,
} );
setShowScheduleSale( value );
if ( value ) {
setDateOnSaleFromGmt( today );
setDateOnSaleToGmt( '' );
} else {
setDateOnSaleFromGmt( '' );
setDateOnSaleToGmt( '' );
}
}
// Hide and clean date fields if the user manually change
// the sale price to zero or less.
useEffect( () => {
if ( ! isSalePriceGreaterThanZero ) {
setShowScheduleSale( false );
setDateOnSaleFromGmt( '' );
setDateOnSaleToGmt( '' );
}
}, [ isSalePriceGreaterThanZero ] );
// Automatically show date fields if `from` or `to` dates have
// any value.
useEffect( () => {
if ( dateOnSaleFromGmt || dateOnSaleToGmt ) {
setShowScheduleSale( true );
}
}, [ dateOnSaleFromGmt, dateOnSaleToGmt ] );
const isDateOnSaleToGmtValid = useValidation(
'product/date_on_sale_to_gmt',
() =>
! showScheduleSale ||
! dateOnSaleToGmt ||
moment( dateOnSaleFromGmt ).isBefore( dateOnSaleToGmt )
);
return (
<div { ...blockProps }>
<ToggleControl
label={ __( 'Schedule sale', 'woocommerce' ) }
checked={ showScheduleSale }
onChange={ handleToggleChange }
disabled={ ! isSalePriceGreaterThanZero }
/>
{ showScheduleSale && (
<div className="wp-block-columns">
<div className="wp-block-column">
<DateTimePickerControl
label={ __( 'From', 'woocommerce' ) }
placeholder={ __(
'Sale start date and time (optional)',
'woocommerce'
) }
dateTimeFormat={ dateTimeFormat }
currentDate={ dateOnSaleFromGmt }
onChange={ setDateOnSaleFromGmt }
/>
</div>
<div className="wp-block-column">
<DateTimePickerControl
label={ __( 'To', 'woocommerce' ) }
placeholder={ __(
'Sale end date and time (optional)',
'woocommerce'
) }
dateTimeFormat={ dateTimeFormat }
currentDate={ dateOnSaleToGmt }
onChange={ ( value ) =>
setDateOnSaleToGmt(
moment( value )
.startOf( 'minute' )
.toISOString()
)
}
className={
isDateOnSaleToGmtValid ? undefined : 'has-error'
}
help={
isDateOnSaleToGmtValid
? undefined
: __(
'To date must be greater than From date.',
'woocommerce'
)
}
/>
</div>
</div>
) }
</div>
);
}

View File

@ -0,0 +1,16 @@
.wp-block-woocommerce-product-schedule-sale-fields {
.components-toggle-control__label {
display: flex;
align-items: center;
}
.woocommerce-date-time-picker-control.has-error {
.components-base-control .components-input-control__backdrop {
border-color: $studio-red-50;
}
.components-base-control__help {
color: $studio-red-50;
}
}
}

View File

@ -0,0 +1,29 @@
/**
* External dependencies
*/
import { createElement } from '@wordpress/element';
import { BlockConfiguration } from '@wordpress/blocks';
/**
* Internal dependencies
*/
import { initBlock } from '../../utils/init-blocks';
import blockConfiguration from './block.json';
import { Edit } from './edit';
import { ScheduleSalePricingBlockAttributes } from './types';
const { name, ...metadata } =
blockConfiguration as BlockConfiguration< ScheduleSalePricingBlockAttributes >;
export { metadata, name };
export const settings: Partial<
BlockConfiguration< ScheduleSalePricingBlockAttributes >
> = {
example: {},
edit: Edit,
};
export function init() {
return initBlock( { name, metadata, settings } );
}

View File

@ -0,0 +1,8 @@
/**
* External dependencies
*/
import { BlockAttributes } from '@wordpress/blocks';
export interface ScheduleSalePricingBlockAttributes extends BlockAttributes {
name: string;
}

View File

@ -20,6 +20,7 @@ import { init as initSection } from '../section';
import { init as initTab } from '../tab';
import { init as initPricing } from '../pricing-block';
import { init as initCollapsible } from '../collapsible-block';
import { init as initScheduleSale } from '../../blocks/schedule-sale';
export const initBlocks = () => {
const coreBlocks = __experimentalGetCoreBlocks();
@ -38,4 +39,5 @@ export const initBlocks = () => {
initTab();
initPricing();
initCollapsible();
initScheduleSale();
};

View File

@ -47,3 +47,5 @@ export const VARIANT_SHIPPING_SECTION_BASIC_ID = `variant/${ SHIPPING_SECTION_BA
export const VARIANT_SHIPPING_SECTION_DIMENSIONS_ID = `variant/${ SHIPPING_SECTION_DIMENSIONS_ID }`;
export const PRODUCT_DETAILS_SLUG = 'product-details';
export const PRODUCT_SCHEDULED_SALE_SLUG = 'product-scheduled-sale';

View File

@ -1,3 +1,4 @@
@import 'blocks/schedule-sale/editor.scss';
@import 'components/editor/style.scss';
@import 'components/product-section-layout/style.scss';
@import 'components/edit-product-link-modal/style.scss';

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Add product schedule sale pricing block to blocks template definition

View File

@ -513,6 +513,9 @@ class WC_Post_Types {
),
),
),
array(
'woocommerce/product-schedule-sale-fields',
),
array(
'woocommerce/product-radio',
array(

File diff suppressed because it is too large Load Diff