Add SmartPluginCardBody component.

This commit is contained in:
Gan Eng Chin 2022-12-10 00:41:00 +08:00
parent 542b26e346
commit 5da2385d41
No known key found for this signature in database
GPG Key ID: 94D5D972860ADB01
3 changed files with 116 additions and 1 deletions

View File

@ -0,0 +1,114 @@
/**
* External dependencies
*/
import { useState } from '@wordpress/element';
import { useDispatch } from '@wordpress/data';
import { Button } from '@wordpress/components';
import { Pill } from '@woocommerce/components';
import { __ } from '@wordpress/i18n';
import { recordEvent } from '@woocommerce/tracks';
import { PLUGINS_STORE_NAME } from '@woocommerce/data';
/**
* Internal dependencies
*/
import { PluginCardBody } from '~/marketing/components';
import { RecommendedPlugin } from '~/marketing/types';
import { getInAppPurchaseUrl } from '~/lib/in-app-purchase';
import { createNoticesFromResponse } from '~/lib/notices';
import './PluginCardBody.scss';
type SmartPluginCardBodyProps = {
plugin: RecommendedPlugin;
onInstalledAndActivated?: () => void;
};
/**
* A smart wrapper around PluginCardBody that accepts a `plugin` prop.
*
* It knows how to render the action button for the plugin,
* and has the logic for installing and activating plugin.
* This allows users to install and activate multiple plugins at the same time.
*/
export const SmartPluginCardBody = ( {
plugin,
onInstalledAndActivated = () => {},
}: SmartPluginCardBodyProps ) => {
const [ currentPlugin, setCurrentPlugin ] = useState< string | null >(
null
);
const { installAndActivatePlugins } = useDispatch( PLUGINS_STORE_NAME );
/**
* Install and activate a plugin.
*
* When the process is successful, `onInstalledAndActivated` will be called.
* A success notice will be displayed.
*
* When the process is not successful, an error notice will be displayed.
*/
const installAndActivate = async () => {
setCurrentPlugin( plugin.product );
try {
recordEvent( 'marketing_recommended_extension', {
name: plugin.title,
} );
const response = await installAndActivatePlugins( [
plugin.product,
] );
onInstalledAndActivated();
createNoticesFromResponse( response );
} catch ( error ) {
createNoticesFromResponse( error );
}
setCurrentPlugin( null );
};
const renderButton = () => {
const buttonDisabled = !! currentPlugin;
if ( plugin.direct_install ) {
return (
<Button
variant="secondary"
isBusy={ currentPlugin === plugin.product }
disabled={ buttonDisabled }
onClick={ installAndActivate }
>
{ __( 'Install plugin', 'woocommerce' ) }
</Button>
);
}
return (
<Button
variant="secondary"
href={ getInAppPurchaseUrl( plugin.url ) }
disabled={ buttonDisabled }
onClick={ () => {
recordEvent( 'marketing_recommended_extension', {
name: plugin.title,
} );
} }
>
{ __( 'View details', 'woocommerce' ) }
</Button>
);
};
return (
<PluginCardBody
icon={ <img src={ plugin.icon } alt={ plugin.title } /> }
name={ plugin.title }
pills={ plugin.tags.map( ( tag ) => (
<Pill key={ tag.slug }>{ tag.name }</Pill>
) ) }
description={ plugin.description }
button={ renderButton() }
/>
);
};

View File

@ -1 +1,2 @@
export { PluginCardBody } from './PluginCardBody'; export { PluginCardBody } from './PluginCardBody';
export { SmartPluginCardBody } from './SmartPluginCardBody';

View File

@ -4,7 +4,7 @@ export { default as ProductIcon } from './product-icon';
export { default as Slider } from './slider'; export { default as Slider } from './slider';
export { default as ReadBlogMessage } from './ReadBlogMessage'; export { default as ReadBlogMessage } from './ReadBlogMessage';
export { CollapsibleCard, CardBody, CardDivider } from './CollapsibleCard'; export { CollapsibleCard, CardBody, CardDivider } from './CollapsibleCard';
export { PluginCardBody } from './PluginCardBody'; export { PluginCardBody, SmartPluginCardBody } from './PluginCardBody';
export { CardHeaderTitle } from './CardHeaderTitle'; export { CardHeaderTitle } from './CardHeaderTitle';
export { CardHeaderDescription } from './CardHeaderDescription'; export { CardHeaderDescription } from './CardHeaderDescription';
export { CenteredSpinner } from './CenteredSpinner'; export { CenteredSpinner } from './CenteredSpinner';