Skip to content

Commit ebb4b40

Browse files
authored
Add support phone and email in the admin settings page (#5471)
* Extract and use two new components for support email and phone * Add controlling the disable attribute for "Save Settings" button in the settings page * Update Card Reader settings components.
1 parent 22fc52f commit ebb4b40

File tree

14 files changed

+398
-121
lines changed

14 files changed

+398
-121
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: add
3+
4+
New support phone and email fields the general settings page.

client/card-readers/settings/index.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ const ReadersSettingsDescription = (): JSX.Element => (
4343
);
4444

4545
const ReceiptSettings = (): JSX.Element => {
46-
const [ isSaveDisabled, setSaveDisabled ] = useState( false );
46+
const [ isBusinessInputsValid, setBusinessInputsValid ] = useState( true );
47+
const [ isContactsInputsValid, setContactsInputsValid ] = useState( true );
48+
const areInputsValid = isBusinessInputsValid && isContactsInputsValid;
4749

4850
return (
4951
<SettingsLayout displayBanner={ false }>
@@ -52,18 +54,18 @@ const ReceiptSettings = (): JSX.Element => {
5254
<Card className="card-readers-settings__wrapper">
5355
<CardBody>
5456
<BusinessDetailsSection
55-
setSaveDisabled={ setSaveDisabled }
57+
setInputsValid={ setBusinessInputsValid }
5658
/>
5759
<ContactsDetailsSection
58-
setSaveDisabled={ setSaveDisabled }
60+
setInputsValid={ setContactsInputsValid }
5961
/>
6062
<AddressDetailsSection />
6163
<BrandingDetailsSection />
6264
</CardBody>
6365
</Card>
6466
</LoadableSettingsSection>
6567
</SettingsSection>
66-
<SaveSettingsSection disabled={ isSaveDisabled } />
68+
<SaveSettingsSection disabled={ ! areInputsValid } />
6769
</SettingsLayout>
6870
);
6971
};

client/card-readers/settings/sections/business-details.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { useState } from '@wordpress/element';
1212
*/
1313
import { useAccountBusinessName, useAccountBusinessURL } from '../../../data';
1414

15-
const BusinessDetailsSection = ( { setSaveDisabled } ) => {
15+
const BusinessDetailsSection = ( { setInputsValid } ) => {
1616
const [ hasError, setHasError ] = useState( false );
1717

1818
const [
@@ -36,10 +36,10 @@ const BusinessDetailsSection = ( { setSaveDisabled } ) => {
3636
const validateBusinessURL = ( event ) => {
3737
if ( event.target.checkValidity() ) {
3838
setHasError( false );
39-
setSaveDisabled( false );
39+
setInputsValid( true );
4040
} else {
4141
setHasError( true );
42-
setSaveDisabled( true );
42+
setInputsValid( false );
4343
}
4444
};
4545

client/card-readers/settings/sections/contacts-details.js

Lines changed: 10 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -2,113 +2,30 @@
22
/**
33
* External dependencies
44
*/
5-
import React, { useEffect, useState } from 'react';
65
import { __ } from '@wordpress/i18n';
7-
import { TextControl, Notice, BaseControl } from '@wordpress/components';
8-
import PhoneNumberInput from 'settings/phone-input';
96

107
/**
118
* Internal dependencies
129
*/
13-
import {
14-
useGetSavingError,
15-
useAccountBusinessSupportEmail,
16-
useAccountBusinessSupportPhone,
17-
} from '../../../data';
18-
19-
const ContactDetailsSection = ( { setSaveDisabled } ) => {
20-
const [
21-
accountBusinessSupportEmail,
22-
setAccountBusinessSupportEmail,
23-
] = useAccountBusinessSupportEmail();
24-
25-
const [
26-
accountBusinessSupportPhone,
27-
setAccountBusinessSupportPhone,
28-
] = useAccountBusinessSupportPhone();
29-
30-
let businessSupportEmailErrorMessage = useGetSavingError()?.data?.details
31-
?.account_business_support_email?.message;
32-
33-
let businessSupportPhoneErrorMessage = useGetSavingError()?.data?.details
34-
?.account_business_support_phone?.message;
35-
36-
const [ isPhoneValid, setPhoneValidity ] = useState( true );
37-
38-
if ( '' === accountBusinessSupportEmail ) {
39-
businessSupportEmailErrorMessage = __(
40-
'Support email cannot be empty, please specify.',
41-
'woocommerce-payments'
42-
);
43-
}
44-
45-
if ( '' === accountBusinessSupportPhone ) {
46-
businessSupportPhoneErrorMessage = __(
47-
'Support phone number cannot be empty, please specify.',
48-
'woocommerce-payments'
49-
);
50-
}
10+
import SupportPhoneInput from 'wcpay/settings/support-phone-input';
11+
import SupportEmailInput from 'wcpay/settings/support-email-input';
12+
import React, { useEffect, useState } from 'react';
5113

52-
if ( ! isPhoneValid ) {
53-
businessSupportPhoneErrorMessage = __(
54-
'Please enter a valid mobile phone number.',
55-
'woocommerce-payments'
56-
);
57-
}
14+
const ContactDetailsSection = ( { setInputsValid } ) => {
15+
const [ isEmailInputValid, setEmailInputValid ] = useState( true );
16+
const [ isPhoneInputValid, setPhoneInputValid ] = useState( true );
5817

5918
useEffect( () => {
60-
setSaveDisabled(
61-
'' === accountBusinessSupportEmail ||
62-
'' === accountBusinessSupportPhone ||
63-
! isPhoneValid
64-
);
65-
}, [
66-
isPhoneValid,
67-
accountBusinessSupportEmail,
68-
accountBusinessSupportPhone,
69-
setSaveDisabled,
70-
] );
19+
setInputsValid( isEmailInputValid && isPhoneInputValid );
20+
}, [ isEmailInputValid, isPhoneInputValid, setInputsValid ] );
7121

7222
return (
7323
<>
7424
<h4>
7525
{ __( 'Customer support contacts', 'woocommerce-payments' ) }
7626
</h4>
77-
{ businessSupportEmailErrorMessage && (
78-
<Notice status="error" isDismissible={ false }>
79-
<span>{ businessSupportEmailErrorMessage }</span>
80-
</Notice>
81-
) }
82-
<TextControl
83-
className="card-readers-business-email-input"
84-
label={ __( 'Support email', 'woocommerce-payments' ) }
85-
value={ accountBusinessSupportEmail }
86-
onChange={ setAccountBusinessSupportEmail }
87-
type="email"
88-
/>
89-
{ businessSupportPhoneErrorMessage && (
90-
<Notice status="error" isDismissible={ false }>
91-
<span>{ businessSupportPhoneErrorMessage }</span>
92-
</Notice>
93-
) }
94-
<BaseControl
95-
label={ __( 'Support phone number', 'woocommerce-payments' ) }
96-
className="card-readers-business-phone-input"
97-
id="support-phone-number-input"
98-
>
99-
<PhoneNumberInput
100-
onValueChange={ setAccountBusinessSupportPhone }
101-
value={ accountBusinessSupportPhone }
102-
onValidationChange={ setPhoneValidity }
103-
inputProps={ {
104-
ariaLabel: __(
105-
'Support phone number',
106-
'woocommerce-payments'
107-
),
108-
} }
109-
id="support-phone-number-input"
110-
/>
111-
</BaseControl>
27+
<SupportEmailInput setInputVallid={ setEmailInputValid } />
28+
<SupportPhoneInput setInputVallid={ setPhoneInputValid } />
11229
</>
11330
);
11431
};

client/card-readers/settings/sections/test/index.test.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import BrandingFileUpload from '../../file-upload';
1414

1515
jest.mock( '../../file-upload', () => jest.fn() );
1616

17-
const setDisabledMock = jest.fn();
17+
const setInputsValidMock = jest.fn();
1818

1919
describe( 'Card Reader Business Details section', () => {
2020
beforeEach( () => {
@@ -33,7 +33,7 @@ describe( 'Card Reader Business Details section', () => {
3333

3434
test( 'Renders Business section', () => {
3535
render(
36-
<BusinessDetailsSection setSaveDisabled={ setDisabledMock } />
36+
<BusinessDetailsSection setInputsValid={ setInputsValidMock } />
3737
);
3838

3939
const heading = screen.queryByRole( 'heading', {
@@ -44,7 +44,7 @@ describe( 'Card Reader Business Details section', () => {
4444

4545
test( 'Renders Business settings', () => {
4646
render(
47-
<BusinessDetailsSection setSaveDisabled={ setDisabledMock } />
47+
<BusinessDetailsSection setInputsValid={ setInputsValidMock } />
4848
);
4949

5050
const name = screen.getByLabelText( 'Business name' );
@@ -58,7 +58,7 @@ describe( 'Card Reader Business Details section', () => {
5858
describe( 'Card Reader Contact Details section', () => {
5959
test( 'Renders Contacts section', () => {
6060
render(
61-
<ContactsDetailsSection setSaveDisabled={ setDisabledMock } />
61+
<ContactsDetailsSection setInputsValid={ setInputsValidMock } />
6262
);
6363

6464
const heading = screen.queryByRole( 'heading', {
@@ -69,7 +69,7 @@ describe( 'Card Reader Contact Details section', () => {
6969

7070
test( 'Renders Contacts settings', () => {
7171
render(
72-
<ContactsDetailsSection setSaveDisabled={ setDisabledMock } />
72+
<ContactsDetailsSection setInputsValid={ setInputsValidMock } />
7373
);
7474

7575
const email = screen.getByLabelText( 'Support email' );

client/settings/phone-input/style.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@
129129
margin-top: $gap-large;
130130
}
131131

132+
.no-top-margin .iti {
133+
margin-top: 0;
134+
}
135+
132136
.iti__selected-flag {
133137
background-color: inherit !important;
134138

client/settings/settings-manager/index.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/**
33
* External dependencies
44
*/
5-
import React, { useContext } from 'react';
5+
import React, { useContext, useState } from 'react';
66
import { ExternalLink } from '@wordpress/components';
77
import { __, sprintf } from '@wordpress/i18n';
88

@@ -115,6 +115,9 @@ const SettingsManager = () => {
115115
upe: isUpeEnabled,
116116
},
117117
} = useContext( WCPaySettingsContext );
118+
const [ isTransactionInputsValid, setTransactionInputsValid ] = useState(
119+
true
120+
);
118121

119122
return (
120123
<SettingsLayout>
@@ -151,7 +154,11 @@ const SettingsManager = () => {
151154
<WcPayUpeContextProvider
152155
defaultIsUpeEnabled={ isUpeEnabled }
153156
>
154-
<Transactions />
157+
<Transactions
158+
setTransactionInputsValid={
159+
setTransactionInputsValid
160+
}
161+
/>
155162
</WcPayUpeContextProvider>
156163
</ErrorBoundary>
157164
</LoadableSettingsSection>
@@ -164,7 +171,7 @@ const SettingsManager = () => {
164171
</LoadableSettingsSection>
165172
</SettingsSection>
166173
<AdvancedSettings />
167-
<SaveSettingsSection />
174+
<SaveSettingsSection disabled={ ! isTransactionInputsValid } />
168175
</SettingsLayout>
169176
);
170177
};
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { TextControl, Notice } from '@wordpress/components';
5+
import { __ } from '@wordpress/i18n';
6+
7+
/**
8+
* Internal dependencies
9+
*/
10+
import { useAccountBusinessSupportEmail, useGetSavingError } from 'wcpay/data';
11+
import { useEffect, useRef } from 'react';
12+
13+
const SupportEmailInput = ( { setInputVallid } ) => {
14+
const [ supportEmail, setSupportEmail ] = useAccountBusinessSupportEmail();
15+
16+
let supportEmailError = useGetSavingError()?.data?.details
17+
?.account_business_support_email?.message;
18+
19+
const currentEmail = useRef( supportEmail ).current;
20+
if ( '' === supportEmail && '' !== currentEmail ) {
21+
supportEmailError = __(
22+
'Support email cannot be empty once it has been set before, please specify.',
23+
'woocommerce-payments'
24+
);
25+
}
26+
27+
useEffect( () => {
28+
if ( setInputVallid ) {
29+
setInputVallid( ! supportEmailError );
30+
}
31+
}, [ supportEmailError, setInputVallid ] );
32+
33+
return (
34+
<>
35+
{ supportEmailError && (
36+
<Notice status="error" isDismissible={ false }>
37+
<span>{ supportEmailError }</span>
38+
</Notice>
39+
) }
40+
41+
<TextControl
42+
className="settings__account-business-support-email-input"
43+
help={ __(
44+
'This may be visible on receipts, invoices, and automated emails from your store.',
45+
'woocommerce-payments'
46+
) }
47+
label={ __( 'Support email', 'woocommerce-payments' ) }
48+
value={ supportEmail }
49+
onChange={ setSupportEmail }
50+
data-testid={ 'account-business-support-email-input' }
51+
/>
52+
</>
53+
);
54+
};
55+
56+
export default SupportEmailInput;

0 commit comments

Comments
 (0)