Skip to content

Commit 0e634af

Browse files
author
Wacław Jacek
authored
Display EU customs specificity requirement in Create shipping label modal (#2633)
* Display EU customs specificity requirement in Create shipping label modal * Display warnings when customs item descriptions are too short
1 parent b58e2d4 commit 0e634af

File tree

6 files changed

+204
-68
lines changed

6 files changed

+204
-68
lines changed

client/extensions/woocommerce/woocommerce-services/state/shipping-label/selectors.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,8 @@ export const getCustomsErrors = (
418418

419419
items: mapValues( pick( customs.items, usedProductIds ), ( itemData, productId ) => {
420420
const itemErrors = {};
421-
if ( ! itemData.description ) {
422-
itemErrors.description = translate( 'This field is required' );
421+
if ( ! itemData.description || itemData.description.length < 3 ) {
422+
itemErrors.description = translate( 'You must provide a clear, specific description for every item.' );
423423
}
424424
if ( ! customs.ignoreWeightValidation[ productId ] ) {
425425
if ( isNil( itemData.weight ) || '' === itemData.weight ) {

client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/customs-step/index.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,29 @@ import StepConfirmationButton from '../step-confirmation-button';
2626
import getPackageDescriptions from '../packages-step/get-package-descriptions';
2727
import { getAllPackageDefinitions } from 'woocommerce/woocommerce-services/state/packages/selectors';
2828

29+
const customsSummary = ( errors, translate ) => {
30+
if ( ! hasNonEmptyLeaves( errors ) ) {
31+
return translate( 'Customs information valid' );
32+
}
33+
34+
const areAllErrorsDescriptionSpecificityErrors = errors.items && Object.values( errors.items ).every( ( item ) => {
35+
return 1 === Object.keys( item ).length && item.description;
36+
} );
37+
38+
if ( areAllErrorsDescriptionSpecificityErrors ) {
39+
return translate( 'Descriptions are incomplete' );
40+
}
41+
42+
return translate( 'Customs information incomplete' );
43+
};
44+
2945
const CustomsStep = props => {
3046
const { siteId, orderId, errors, expanded, translate, isSubmitted, packageDescriptions } = props;
31-
const summary = hasNonEmptyLeaves( errors )
32-
? translate( 'Customs information incomplete' )
33-
: translate( 'Customs information valid' );
3447

3548
return (
3649
<StepContainer
3750
title={ translate( 'Customs' ) }
38-
summary={ isSubmitted ? summary : '' }
51+
summary={ isSubmitted ? customsSummary( errors, translate ) : '' }
3952
expanded={ expanded }
4053
toggleStep={ props.toggleStep }
4154
isSuccess={ isSubmitted && ! hasNonEmptyLeaves( errors ) }

client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/customs-step/item-row-header.js

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,56 @@ import React from 'react';
55
import PropTypes from 'prop-types';
66
import { connect } from 'react-redux';
77
import { localize } from 'i18n-calypso';
8-
import { ExternalLink, Tooltip } from '@wordpress/components';
8+
import { Button, ExternalLink, Popover, Tooltip } from '@wordpress/components';
9+
import { useState } from '@wordpress/element';
910

1011
/**
1112
* Internal dependencies
1213
*/
1314
import { getShippingLabel } from 'woocommerce/woocommerce-services/state/shipping-label/selectors';
1415
import Gridicon from "gridicons";
1516

17+
const EUCustomsSpecificityRequirementPopover = localize( ( { togglePopoverVisible, translate } ) => (
18+
<Popover onFocusOutside={ togglePopoverVisible }>
19+
<p>
20+
{ translate( 'When shipping to countries that follow European Union (EU) customs rules, you must provide a clear, specific description on every item.' ) }
21+
</p>
22+
<p>
23+
{ translate( 'For example, if you are sending clothing, you must indicate what type of clothing (e.g. men\'s shirts, girl\'s vest, boy\'s jacket) for the description to be acceptable.' ) }
24+
</p>
25+
<p>
26+
{ translate( 'Otherwise, shipments may be delayed or interrupted at customs.' ) }
27+
</p>
28+
<p>
29+
<ExternalLink
30+
href="https://www.usps.com/international/new-eu-customs-rules.htm"
31+
>
32+
{ translate( 'Learn more about customs rules' ) }
33+
</ExternalLink>
34+
</p>
35+
</Popover>
36+
) );
37+
38+
export const DescriptionTitle = localize( ( { translate } ) => {
39+
const [ isPopoverVisible, setIsPopoverVisible ] = useState( false );
40+
41+
const togglePopoverVisible = () => {
42+
setIsPopoverVisible( ( state ) => ! state );
43+
};
44+
45+
return <span>
46+
{ translate( 'Description' ) }
47+
<Button onClick={ togglePopoverVisible }>
48+
<span>
49+
<Gridicon icon="info-outline" size={ 18 } />
50+
</span>
51+
</Button>
52+
<span className="popover-container">
53+
{ isPopoverVisible && <EUCustomsSpecificityRequirementPopover togglePopoverVisible={ togglePopoverVisible } /> }
54+
</span>
55+
</span>;
56+
} );
57+
1658
export const TariffCodeTitle = localize( ( { translate } ) => (
1759
<span>
1860
{ translate( 'HS Tariff number' ) } (
@@ -25,20 +67,31 @@ export const TariffCodeTitle = localize( ( { translate } ) => (
2567
</span>
2668
) );
2769

28-
export const OriginCountryTitle = localize( ( { translate } ) => (
29-
<span>
70+
export const OriginCountryTitle = localize( ( { translate } ) => {
71+
const [ isPopoverVisible, setIsPopoverVisible ] = useState( false );
72+
73+
const togglePopoverVisible = () => {
74+
setIsPopoverVisible( ( state ) => ! state );
75+
};
76+
77+
return <span>
3078
{ translate( 'Origin country' ) }
31-
<Tooltip text={ translate( 'Country where the product was manufactured or assembled' ) }>
32-
<span>
33-
<Gridicon icon="info-outline" size={ 18 } />
79+
<Button onClick={ togglePopoverVisible }>
80+
<span>
81+
<Gridicon icon="info-outline" size={ 18 } />
82+
</span>
83+
</Button>
84+
<span className="popover-container">
85+
{ isPopoverVisible && <Popover onFocusOutside={ togglePopoverVisible }>
86+
<p>{ translate( 'Country where the product was manufactured or assembled.' ) }</p>
87+
</Popover> }
3488
</span>
35-
</Tooltip>
36-
</span>
37-
) );
89+
</span>;
90+
} );
3891

3992
const ItemRowHeader = ( { translate, weightUnit } ) => (
4093
<div className="customs-step__item-rows-header">
41-
<span className="customs-step__item-description-column">{ translate( 'Description' ) }</span>
94+
<div className="customs-step__item-description-column"><DescriptionTitle /></div>
4295
<span className="customs-step__item-code-column">{ <TariffCodeTitle /> }</span>
4396
<span className="customs-step__item-weight-column">
4497
{ translate( 'Weight (%s per unit)', { args: [ weightUnit ] } ) }

client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/customs-step/item-row.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { getAllCountryNames } from 'woocommerce/state/sites/data/locations/selec
2626
import Dropdown from 'woocommerce/woocommerce-services/components/dropdown';
2727
import WeightField from 'woocommerce/woocommerce-services/components/weight-field';
2828
import PriceField from 'woocommerce/woocommerce-services/components/price-field';
29-
import { TariffCodeTitle, OriginCountryTitle } from './item-row-header';
29+
import { TariffCodeTitle, OriginCountryTitle, DescriptionTitle } from './item-row-header';
3030

3131
const ItemRow = props => {
3232
const {
@@ -49,7 +49,7 @@ const ItemRow = props => {
4949
<TextField
5050
id={ packageId + '_' + productId + '_description' }
5151
className="customs-step__item-description-column"
52-
title={ translate( 'Description' ) }
52+
title={ <DescriptionTitle /> }
5353
value={ description }
5454
placeholder={ defaultDescription }
5555
updateValue={ props.setCustomsItemDescription }

client/extensions/woocommerce/woocommerce-services/views/shipping-label/label-purchase-modal/customs-step/style.scss

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,30 @@
9292
@include breakpoint( '>960px' ) {
9393
margin-left: 4px;
9494
}
95+
96+
.components-button {
97+
height: 17px;
98+
margin-bottom: 8px;
99+
100+
span {
101+
margin-bottom: 0;
102+
}
103+
}
104+
105+
.popover-container {
106+
position: relative;
107+
z-index: 100;
108+
}
109+
110+
.components-popover {
111+
position: absolute;
112+
width: 280px;
113+
114+
.components-popover__content {
115+
padding: 20px;
116+
width: 100%;
117+
}
118+
}
95119
}
96120

97121
.customs-step__item-weight-column,

0 commit comments

Comments
 (0)