Skip to content

Commit

Permalink
Reinstate EditStoreAddress flow in settings
Browse files Browse the repository at this point in the history
  • Loading branch information
joemcgill committed Nov 6, 2024
1 parent c024b95 commit 5098fe8
Show file tree
Hide file tree
Showing 7 changed files with 324 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { Icon, warning as warningIcon } from '@wordpress/icons';
import { getPath, getQuery } from '@woocommerce/navigation';

/**
* Internal dependencies
*/
import AccountCard from '.~/components/account-card';
import AppButton from '.~/components/app-button';
import './contact-information-preview-card.scss';

/**
* Renders a contact information card component.
* It adds loading & warning state to the regular `AccountCard`, and an edit button link.
*
* @param {Object} props React props
* @param {import('.~/components/account-card').APPEARANCE} props.appearance
* @param {string} props.editHref URL where Edit button should point to.
* @param {string} props.editEventName Tracing event name used when the "Edit" button is clicked.
* @param {boolean} props.loading Set to `true` if the card should be rendered in the loading state.
* @param {JSX.Element} props.content Main content of the card to be rendered once the data is loaded.
* @param {string} [props.warning] Warning title, to be used instead of the default one.
* @return {JSX.Element} Filled AccountCard component.
*/
export default function ContactInformationPreviewCard( {
editHref,
editEventName,
loading,
content,
appearance,
warning,
} ) {
const { subpath } = getQuery();
const editButton = (
<AppButton
isSecondary
href={ editHref }
text={ __( 'Edit', 'google-listings-and-ads' ) }
eventName={ editEventName }
eventProps={ { path: getPath(), subpath } }
/>
);
let description;
let title;

if ( loading ) {
description = (
<span
className="gla-contact-info-preview-card__placeholder"
aria-busy="true"
title={ __( 'Loading…', 'google-listings-and-ads' ) }
></span>
);
} else if ( warning ) {
title = (
<>
<Icon
icon={ warningIcon }
size={ 24 }
className="gla-contact-info-preview-card__notice-icon"
/>
{ warning }
</>
);
description = (
<span className="gla-contact-info-preview-card__notice-details">
{ content }
</span>
);
} else {
description = content;
}

return (
<AccountCard
appearance={ appearance }
className="gla-contact-info-preview-card"
icon={ null }
title={ title }
description={ description }
indicator={ editButton }
></AccountCard>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.gla-contact-info-preview-card {
// Vertically align icon inside the title.
.wcdl-subsection-title {
display: flex;
align-items: center;
}
&__notice-icon {
fill: $alert-red;
margin: calc(var(--main-gap) / -8) 0;
}
&__notice-details {
color: $gray-700;
}

&__placeholder {
display: inline-block;
width: 18em;

@include placeholder;
}
}
21 changes: 19 additions & 2 deletions js/src/components/contact-information/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { getEditStoreAddressUrl } from '.~/utils/urls';
import Section from '.~/wcdl/section';
import StoreAddressCard from './store-address-card';
import VerticalGapLayout from '.~/components/vertical-gap-layout';
import AppDocumentationLink from '.~/components/app-documentation-link';
import { StoreAddressCardPreview } from './store-address-card';

const learnMoreLinkId = 'contact-information-read-more';
const learnMoreUrl =
'https://woocommerce.com/document/google-for-woocommerce/get-started/requirements/#contact-information';

const description = (
<>
Expand Down Expand Up @@ -37,7 +43,18 @@ export function ContactInformationPreview() {
return (
<Section title={ settingsTitle } description={ description }>
<VerticalGapLayout size="overlap">
<StoreAddressCard />
<StoreAddressCardPreview
editHref={ getEditStoreAddressUrl() }
learnMore={
<AppDocumentationLink
context="settings-no-store-address-notice"
linkId={ learnMoreLinkId }
href={ learnMoreUrl }
>
{ __( 'Learn more', 'google-listings-and-ads' ) }
</AppDocumentationLink>
}
/>
</VerticalGapLayout>
</Section>
);
Expand Down
71 changes: 71 additions & 0 deletions js/src/components/contact-information/store-address-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import useStoreAddress from '.~/hooks/useStoreAddress';
import useStoreAddressSynced from '.~/hooks/useStoreAddressSynced';
import AccountCard, { APPEARANCE } from '.~/components/account-card';
import AppButton from '.~/components/app-button';
import ContactInformationPreviewCard from './contact-information-preview-card';
import ValidationErrors from '.~/components/validation-errors';
import TrackableLink from '.~/components/trackable-link';
import mapStoreAddressErrors from './mapStoreAddressErrors';
Expand Down Expand Up @@ -166,3 +167,73 @@ const StoreAddressCard = () => {
};

export default StoreAddressCard;

/**
* Trigger when store address edit button is clicked.
* Before `1.5.0` this name was used for tracking clicking "Edit in settings" to edit the WC address. As of `>1.5.0`, that event is now tracked as `edit_wc_store_address`.
*
* @event gla_edit_mc_store_address
* @property {string} path The path used in the page from which the link was clicked, e.g. `"/google/settings"`.
* @property {string|undefined} [subpath] The subpath used in the page, e.g. `"/edit-store-address"` or `undefined` when there is no subpath.
*/

/**
* Renders a component with the store address.
* In preview mode, meaning there will be no refresh button, just the edit link.
*
* @fires gla_edit_mc_store_address Whenever "Edit" is clicked.
*
* @param {Object} props React props
* @param {string} props.editHref URL where Edit button should point to.
* @param {JSX.Element} props.learnMore Link to be shown at the end of missing data message.
* @return {JSX.Element} Filled AccountCard component.
*/
export function StoreAddressCardPreview( { editHref, learnMore } ) {
const { loaded, data } = useStoreAddress( 'mc' );
let content, warning;

if ( loaded ) {
const {
isAddressFilled,
isMCAddressDifferent,
address,
address2,
city,
state,
country,
postcode,
} = data;
const stateAndCountry = state ? `${ state } - ${ country }` : country;

if ( isAddressFilled && ! isMCAddressDifferent ) {
content = [ address, address2, city, stateAndCountry, postcode ]
.filter( Boolean )
.join( ', ' );
} else {
warning = __(
'Please add your store address',
'google-listings-and-ads'
);
content = (
<>
{ __(
'Google requires the store address for all stores using Google Merchant Center. ',
'google-listings-and-ads'
) }
{ learnMore }
</>
);
}
}

return (
<ContactInformationPreviewCard
appearance={ APPEARANCE.ADDRESS }
editHref={ editHref }
editEventName="gla_edit_mc_store_address"
loading={ ! loaded }
warning={ warning }
content={ content }
></ContactInformationPreviewCard>
);
}
115 changes: 115 additions & 0 deletions js/src/settings/edit-store-address.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { getHistory } from '@woocommerce/navigation';
import { useState } from '@wordpress/element';
import { Flex } from '@wordpress/components';

/**
* Internal dependencies
*/
import { getSettingsUrl } from '.~/utils/urls';
import { useAppDispatch } from '.~/data';
import useLayout from '.~/hooks/useLayout';
import useStoreAddress from '.~/hooks/useStoreAddress';
import TopBar from '.~/components/stepper/top-bar';
import HelpIconButton from '.~/components/help-icon-button';
import Section from '.~/wcdl/section';
import AppButton from '.~/components/app-button';

import AppDocumentationLink from '.~/components/app-documentation-link';
import StoreAddressCard from '.~/components/contact-information/store-address-card';

const learnMoreLinkId = 'contact-information-read-more';
const learnMoreUrl =
'https://woocommerce.com/document/google-for-woocommerce/get-started/requirements/#contact-information';

/**
* Triggered when the save button in contact information page is clicked.
*
* @event gla_contact_information_save_button_click
*/

/**
* Renders the store address settings page.
*
* @see StoreAddressCard
* @fires gla_contact_information_save_button_click
* @fires gla_documentation_link_click with `{ context: "settings-store-address", link_id: "contact-information-read-more", href: "https://woocommerce.com/document/google-for-woocommerce/get-started/requirements/#contact-information" }`
*/
const EditStoreAddress = () => {
useLayout( 'full-content' );

const { updateGoogleMCContactInformation } = useAppDispatch();
const { data: address } = useStoreAddress();
const [ isSaving, setSaving ] = useState( false );

const handleSaveClick = () => {
setSaving( true );
updateGoogleMCContactInformation()
.then( () => getHistory().push( getSettingsUrl() ) )
.catch( () => setSaving( false ) );
};

const isReadyToSave =
address.isAddressFilled && address.isMCAddressDifferent;

return (
<>
<TopBar
title={ __( 'Edit store address', 'google-listings-and-ads' ) }
helpButton={
<HelpIconButton eventContext="edit-store-address" />
}
backHref={ getSettingsUrl() }
/>
<div className="gla-settings">
<Section
title={ __( 'Store address', 'google-listings-and-ads' ) }
description={
<div>
<p>
{ __(
'Your store address 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'
) }
</p>
<p>
<AppDocumentationLink
context="settings-store-address"
linkId={ learnMoreLinkId }
href={ learnMoreUrl }
>
{ __(
'Learn more',
'google-listings-and-ads'
) }
</AppDocumentationLink>
</p>
</div>
}
>
<StoreAddressCard
showValidation={ ! address.isAddressFilled }
/>
</Section>
<Section>
<Flex justify="flex-end">
<AppButton
isPrimary
loading={ isSaving }
disabled={ ! isReadyToSave }
eventName="gla_contact_information_save_button_click"
onClick={ handleSaveClick }
>
{ __( 'Save details', 'google-listings-and-ads' ) }
</AppButton>
</Flex>
</Section>
</div>
</>
);
};

export default EditStoreAddress;
3 changes: 3 additions & 0 deletions js/src/settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { ContactInformationPreview } from '.~/components/contact-information';
import LinkedAccounts from './linked-accounts';
import ReconnectWPComAccount from './reconnect-wpcom-account';
import ReconnectGoogleAccount from './reconnect-google-account';
import EditStoreAddress from './edit-store-address';
import EnableNewProductSyncNotice from '.~/components/enable-new-product-sync-notice';
import MainTabNav from '.~/components/main-tab-nav';
import RebrandingTour from '.~/components/tours/rebranding-tour';
Expand Down Expand Up @@ -53,6 +54,8 @@ const Settings = () => {
);
case subpaths.reconnectGoogleAccount:
return <ReconnectGoogleAccount />;
case subpaths.editStoreAddress:
return <EditStoreAddress />;
default:
}

Expand Down
8 changes: 8 additions & 0 deletions js/src/utils/urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const subpaths = {
editFreeListings: '/free-listings/edit',
editCampaign: '/campaigns/edit',
createCampaign: '/campaigns/create',
editStoreAddress: '/edit-store-address',
reconnectWPComAccount: '/reconnect-wpcom-account',
reconnectGoogleAccount: '/reconnect-google-account',
};
Expand Down Expand Up @@ -84,6 +85,13 @@ export const geReportsUrl = () => {
return getNewPath( null, reportsPath, null );
};

export const getEditStoreAddressUrl = () => {
return getNewPath(
{ subpath: subpaths.editStoreAddress },
settingsPath,
null
);
};
/**
* Returns the URL of the account re-connecting page.
*
Expand Down

0 comments on commit 5098fe8

Please sign in to comment.