-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #917 from woocommerce/feature/863-mc-phone-number
Implement `PhoneNumberCard` and `ContactInformation` components for contact info
- Loading branch information
Showing
12 changed files
with
404 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { __ } from '@wordpress/i18n'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import useGoogleMCPhoneNumber from '.~/hooks/useGoogleMCPhoneNumber'; | ||
import Section from '.~/wcdl/section'; | ||
import VerticalGapLayout from '.~/components/vertical-gap-layout'; | ||
import AppDocumentationLink from '.~/components/app-documentation-link'; | ||
import AppSpinner from '.~/components/app-spinner'; | ||
import PhoneNumberCard from './phone-number-card'; | ||
|
||
const description = __( | ||
'Your contact information is required by Google for verification purposes. It will be shared with the Google Merchant Center and will not be displayed to customers.', | ||
'google-listings-and-ads' | ||
); | ||
|
||
const mcTitle = __( 'Enter contact information', 'google-listings-and-ads' ); | ||
const settingsTitle = __( 'Contact information', 'google-listings-and-ads' ); | ||
|
||
export default function ContactInformation( { view, onPhoneNumberChange } ) { | ||
const phone = useGoogleMCPhoneNumber(); | ||
const isSetupMC = view === 'setup-mc'; | ||
|
||
const initEditing = isSetupMC ? ! phone.data.isValid : true; | ||
const title = isSetupMC ? mcTitle : settingsTitle; | ||
const trackContext = isSetupMC | ||
? 'setup-mc-contact-information' | ||
: 'settings-contact-information'; | ||
|
||
return ( | ||
<Section | ||
title={ title } | ||
description={ | ||
<div> | ||
<p>{ description }</p> | ||
<p> | ||
<AppDocumentationLink | ||
context={ trackContext } | ||
linkId="contact-information-read-more" | ||
// TODO: [lite-contact-info] add link | ||
href="https://example.com/" | ||
> | ||
{ __( 'Learn more', 'google-listings-and-ads' ) } | ||
</AppDocumentationLink> | ||
</p> | ||
</div> | ||
} | ||
> | ||
{ phone.loaded ? ( | ||
<VerticalGapLayout size="large"> | ||
<PhoneNumberCard | ||
phoneNumber={ phone } | ||
initEditing={ initEditing } | ||
onPhoneNumberChange={ onPhoneNumberChange } | ||
/> | ||
<div>TODO: add store address card</div> | ||
</VerticalGapLayout> | ||
) : ( | ||
<AppSpinner /> | ||
) } | ||
</Section> | ||
); | ||
} |
143 changes: 143 additions & 0 deletions
143
js/src/components/contact-information/phone-number-card.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { getCountryCallingCode } from 'libphonenumber-js'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { useState } from '@wordpress/element'; | ||
import { Flex, FlexItem, FlexBlock, CardDivider } from '@wordpress/components'; | ||
import { Spinner } from '@woocommerce/components'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import useCountryCallingCodeOptions from '.~/hooks/useCountryCallingCodeOptions'; | ||
import Section from '.~/wcdl/section'; | ||
import SelectControl from '.~/wcdl/select-control'; | ||
import AppInputControl from '.~/components/app-input-control'; | ||
import AccountCard, { APPEARANCE } from '.~/components/account-card'; | ||
import AppButton from '.~/components/app-button'; | ||
import AppSpinner from '.~/components/app-spinner'; | ||
import './phone-number-card.scss'; | ||
|
||
const noop = () => {}; | ||
|
||
function PhoneNumberContent( { | ||
initCountry, | ||
initNationalNumber, | ||
onPhoneNumberChange, | ||
} ) { | ||
const countryCallingCodeOptions = useCountryCallingCodeOptions(); | ||
const [ country, setCountry ] = useState( initCountry ); | ||
const [ number, setNumber ] = useState( initNationalNumber ); | ||
|
||
const handleChange = ( nextCountry, nextNumber ) => { | ||
setCountry( nextCountry ); | ||
setNumber( nextNumber ); | ||
|
||
const countryCallingCode = nextCountry | ||
? getCountryCallingCode( nextCountry ) | ||
: ''; | ||
onPhoneNumberChange( countryCallingCode, nextNumber, nextCountry ); | ||
}; | ||
|
||
const handleCountryChange = ( nextCountry ) => | ||
handleChange( nextCountry, number ); | ||
|
||
const handleNumberChange = ( nextNumber ) => | ||
handleChange( country, nextNumber ); | ||
|
||
return ( | ||
<Section.Card.Body> | ||
<Flex gap={ 4 }> | ||
<FlexItem> | ||
<SelectControl | ||
label={ __( | ||
'Country code', | ||
'google-listings-and-ads' | ||
) } | ||
isSearchable | ||
excludeSelectedOptions={ false } | ||
options={ countryCallingCodeOptions } | ||
selected={ country } | ||
onChange={ handleCountryChange } | ||
/> | ||
</FlexItem> | ||
<FlexBlock> | ||
<AppInputControl | ||
label={ __( | ||
'Phone number', | ||
'google-listings-and-ads' | ||
) } | ||
value={ number } | ||
onChange={ handleNumberChange } | ||
/> | ||
</FlexBlock> | ||
</Flex> | ||
</Section.Card.Body> | ||
); | ||
} | ||
|
||
export default function PhoneNumberCard( { | ||
phoneNumber, | ||
isPreview, | ||
initEditing, | ||
onEditClick, | ||
onPhoneNumberChange = noop, | ||
} ) { | ||
const [ isEditing, setEditing ] = useState( initEditing ); | ||
const { loaded, data } = phoneNumber; | ||
|
||
const editButton = isEditing ? null : ( | ||
<AppButton | ||
isSecondary | ||
onClick={ () => { | ||
if ( onEditClick ) { | ||
onEditClick(); | ||
} else { | ||
setEditing( true ); | ||
} | ||
} } | ||
> | ||
{ __( 'Edit', 'google-listings-and-ads' ) } | ||
</AppButton> | ||
); | ||
|
||
let description = null; | ||
let phoneNumberContent = null; | ||
|
||
if ( isEditing ) { | ||
description = __( | ||
'Please enter a phone number to be used for verification.', | ||
'google-listings-and-ads' | ||
); | ||
|
||
if ( loaded ) { | ||
phoneNumberContent = ( | ||
<> | ||
<CardDivider /> | ||
<PhoneNumberContent | ||
initCountry={ data.country } | ||
initNationalNumber={ data.nationalNumber } | ||
onPhoneNumberChange={ onPhoneNumberChange } | ||
/> | ||
</> | ||
); | ||
} else { | ||
phoneNumberContent = <AppSpinner />; | ||
} | ||
} else { | ||
description = loaded ? data.display : <Spinner />; | ||
} | ||
|
||
return ( | ||
<AccountCard | ||
className="gla-phone-number-card" | ||
appearance={ APPEARANCE.PHONE } | ||
description={ description } | ||
hideIcon={ isPreview } | ||
indicator={ editButton } | ||
> | ||
{ phoneNumberContent } | ||
</AccountCard> | ||
); | ||
} |
42 changes: 42 additions & 0 deletions
42
js/src/components/contact-information/phone-number-card.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
.gla-phone-number-card { | ||
// Country code selector | ||
.wcdl-select-control { | ||
.wcdl-select-control__input { | ||
margin-bottom: 0; | ||
} | ||
|
||
.woocommerce-select-control { | ||
.components-base-control { | ||
height: 36px; | ||
border-color: $gray-600; | ||
} | ||
|
||
.woocommerce-select-control__control-input { | ||
font-size: 13px; | ||
color: $gray-900; | ||
} | ||
|
||
.woocommerce-select-control__listbox { | ||
top: 37px; | ||
} | ||
|
||
.woocommerce-select-control__option { | ||
min-height: 36px; | ||
font-size: 13px; | ||
} | ||
} | ||
} | ||
|
||
// Phone number input | ||
.components-input-control .components-input-control__container { | ||
.components-input-control__input { | ||
height: 36px; | ||
font-size: 13px; | ||
color: $gray-900; | ||
} | ||
|
||
.components-input-control__backdrop { | ||
border-color: $gray-600; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { useMemo } from '@wordpress/element'; | ||
import { getCountries, getCountryCallingCode } from 'libphonenumber-js'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import useCountryKeyNameMap from './useCountryKeyNameMap'; | ||
|
||
const toOption = ( country, countryCallingCode, countryName ) => ( { | ||
key: country, | ||
keywords: [ countryName, countryCallingCode, country ], | ||
label: `${ countryName } (+${ countryCallingCode })`, | ||
} ); | ||
|
||
export default function useCountryCallingCodeOptions() { | ||
const countryNameDict = useCountryKeyNameMap(); | ||
|
||
return useMemo( () => { | ||
return getCountries().reduce( ( acc, country ) => { | ||
const countryName = countryNameDict[ country ]; | ||
if ( countryName ) { | ||
const countryCallingCode = getCountryCallingCode( country ); | ||
acc.push( | ||
toOption( country, countryCallingCode, countryName ) | ||
); | ||
} | ||
return acc; | ||
}, [] ); | ||
}, [ countryNameDict ] ); | ||
} |
Oops, something went wrong.