diff --git a/plugins/woocommerce-admin/client/marketing/components/PluginCardBody/SmartPluginCardBody.tsx b/plugins/woocommerce-admin/client/marketing/components/PluginCardBody/SmartPluginCardBody.tsx new file mode 100644 index 00000000000..f3272e48f78 --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/components/PluginCardBody/SmartPluginCardBody.tsx @@ -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 ( + + ); + } + + return ( + + ); + }; + + return ( + } + name={ plugin.title } + pills={ plugin.tags.map( ( tag ) => ( + { tag.name } + ) ) } + description={ plugin.description } + button={ renderButton() } + /> + ); +}; diff --git a/plugins/woocommerce-admin/client/marketing/components/PluginCardBody/index.ts b/plugins/woocommerce-admin/client/marketing/components/PluginCardBody/index.ts index e3497c710ba..5e2c782db33 100644 --- a/plugins/woocommerce-admin/client/marketing/components/PluginCardBody/index.ts +++ b/plugins/woocommerce-admin/client/marketing/components/PluginCardBody/index.ts @@ -1 +1,2 @@ export { PluginCardBody } from './PluginCardBody'; +export { SmartPluginCardBody } from './SmartPluginCardBody'; diff --git a/plugins/woocommerce-admin/client/marketing/components/index.js b/plugins/woocommerce-admin/client/marketing/components/index.js index a1679d3b906..dc971c75160 100644 --- a/plugins/woocommerce-admin/client/marketing/components/index.js +++ b/plugins/woocommerce-admin/client/marketing/components/index.js @@ -4,7 +4,7 @@ export { default as ProductIcon } from './product-icon'; export { default as Slider } from './slider'; export { default as ReadBlogMessage } from './ReadBlogMessage'; export { CollapsibleCard, CardBody, CardDivider } from './CollapsibleCard'; -export { PluginCardBody } from './PluginCardBody'; +export { PluginCardBody, SmartPluginCardBody } from './PluginCardBody'; export { CardHeaderTitle } from './CardHeaderTitle'; export { CardHeaderDescription } from './CardHeaderDescription'; export { CenteredSpinner } from './CenteredSpinner';