/** * External dependencies */ import { __, _n, _x, sprintf } from '@wordpress/i18n'; import { Component, Fragment } from '@wordpress/element'; import { compose } from '@wordpress/compose'; import { Button, Card, CardBody, CardFooter, CheckboxControl, FormToggle, Popover, } from '@wordpress/components'; import interpolateComponents from 'interpolate-components'; import { withDispatch, withSelect } from '@wordpress/data'; import { keys, get, pickBy } from 'lodash'; import { H, Link, SelectControl, Form, TextControl, } from '@woocommerce/components'; import { formatValue } from '@woocommerce/number'; import { getSetting } from '@woocommerce/wc-admin-settings'; import { ONBOARDING_STORE_NAME, PLUGINS_STORE_NAME, pluginNames, SETTINGS_STORE_NAME, OPTIONS_STORE_NAME, } from '@woocommerce/data'; import { recordEvent } from '@woocommerce/tracks'; import { Text } from '@woocommerce/experimental'; import { Icon, info, check } from '@wordpress/icons'; /** * Internal dependencies */ import { getCountryCode, getCurrencyRegion, } from '../../../../../dashboard/utils'; import { CurrencyContext } from '../../../../../lib/currency-context'; import { createNoticesFromResponse } from '../../../../../lib/notices'; import { extensionBenefits } from '../../data/extension-benefits'; import { sellingVenueOptions } from '../../data/selling-venue-options'; import { platformOptions } from '../../data/platform-options'; import { getRevenueOptions } from '../../data/revenue-options'; import { getProductCountOptions } from '../../data/product-options'; const wcAdminAssetUrl = getSetting( 'wcAdminAssetUrl', '' ); class BusinessDetails extends Component { constructor( props ) { super(); const settings = get( props, 'settings', {} ); const profileItems = get( props, 'profileItems', {} ); const industrySlugs = get( profileItems, 'industry', [] ).map( ( industry ) => industry.slug ); const businessExtensions = get( profileItems, 'business_extensions', false ); this.state = { isPopoverVisible: false, }; this.initialValues = { other_platform: profileItems.other_platform || '', other_platform_name: profileItems.other_platform_name || '', product_count: profileItems.product_count || '', selling_venues: profileItems.selling_venues || '', revenue: profileItems.revenue || '', 'facebook-for-woocommerce': businessExtensions ? businessExtensions.includes( 'facebook-for-woocommerce' ) : true, 'mailchimp-for-woocommerce': businessExtensions ? businessExtensions.includes( 'mailchimp-for-woocommerce' ) : true, 'creative-mail-by-constant-contact': businessExtensions ? businessExtensions.includes( 'creative-mail-by-constant-contact' ) : true, 'kliken-marketing-for-google': businessExtensions ? businessExtensions.includes( 'kliken-marketing-for-google' ) : true, install_extensions: true, }; this.extensions = [ 'facebook-for-woocommerce', 'mailchimp-for-woocommerce', 'kliken-marketing-for-google', 'creative-mail-by-constant-contact', ]; this.bundleInstall = getCountryCode( settings.woocommerce_default_country ) === 'US' && ( industrySlugs.includes( 'fashion-apparel-accessories' ) || industrySlugs.includes( 'health-beauty' ) ) && ! industrySlugs.includes( 'cbd-other-hemp-derived-products' ); this.onContinue = this.onContinue.bind( this ); this.validate = this.validate.bind( this ); this.getNumberRangeString = this.getNumberRangeString.bind( this ); this.numberFormat = this.numberFormat.bind( this ); } onCreativeMailInstallAndActivated() { const { updateOptions } = this.props; updateOptions( { ce4wp_referred_by: { plugin: 'woocommerce', version: getSetting( 'wcVersion' ), time: Math.floor( new Date().getTime() / 1000 ), source: 'onboarding', }, } ); } onPostInstallAndActivePlugins( response ) { const activated = response.data.activated; if ( activated.includes( 'creative-mail-by-constant-contact' ) ) { this.onCreativeMailInstallAndActivated(); } } async onContinue( values ) { const { createNotice, goToNextStep, installAndActivatePlugins, updateProfileItems, } = this.props; const { install_extensions: installExtensions, other_platform: otherPlatform, other_platform_name: otherPlatformName, product_count: productCount, revenue, selling_venues: sellingVenues, } = values; const businessExtensions = this.getBusinessExtensions( values ); const { getCurrencyConfig } = this.context; recordEvent( 'storeprofiler_store_business_details_continue', { product_number: productCount, already_selling: sellingVenues, currency: getCurrencyConfig().code, revenue, used_platform: otherPlatform, used_platform_name: otherPlatformName, install_woocommerce_services: businessExtensions.includes( 'woocommerce-services' ), install_jetpack: businessExtensions.includes( 'jetpack' ), install_facebook: businessExtensions.includes( 'facebook-for-woocommerce' ), install_mailchimp: businessExtensions.includes( 'mailchimp-for-woocommerce' ), install_creative_mail: businessExtensions.includes( 'creative-mail-by-constant-contact' ), install_google_ads: businessExtensions.includes( 'kliken-marketing-for-google' ), install_extensions: installExtensions, bundle_install: this.bundleInstall, } ); const _updates = { other_platform: otherPlatform, other_platform_name: otherPlatform === 'other' ? otherPlatformName : '', product_count: productCount, revenue, selling_venues: sellingVenues, business_extensions: businessExtensions, }; // Remove possible empty values like `revenue` and `other_platform`. const updates = {}; Object.keys( _updates ).forEach( ( key ) => { if ( _updates[ key ] !== '' ) { updates[ key ] = _updates[ key ]; } } ); const promises = [ updateProfileItems( updates ).catch( () => { throw new Error(); } ), ]; if ( businessExtensions.length ) { promises.push( installAndActivatePlugins( businessExtensions ) .then( ( response ) => { createNoticesFromResponse( response ); this.onPostInstallAndActivePlugins( response ); } ) .catch( ( error ) => { createNoticesFromResponse( error ); throw new Error(); } ) ); } Promise.all( promises ) .then( () => { goToNextStep(); } ) .catch( () => { createNotice( 'error', __( 'There was a problem updating your business details', 'woocommerce-admin' ) ); } ); } validate( values ) { const errors = {}; if ( ! values.product_count.length ) { errors.product_count = __( 'This field is required', 'woocommerce-admin' ); } if ( ! values.selling_venues.length ) { errors.selling_venues = __( 'This field is required', 'woocommerce-admin' ); } if ( ! values.other_platform.length && [ 'other', 'brick-mortar-other' ].includes( values.selling_venues ) ) { errors.other_platform = __( 'This field is required', 'woocommerce-admin' ); } if ( ! values.other_platform_name && values.other_platform === 'other' && [ 'other', 'brick-mortar-other' ].includes( values.selling_venues ) ) { errors.other_platform_name = __( 'This field is required', 'woocommerce-admin' ); } if ( ! values.revenue.length && [ 'other', 'brick-mortar', 'brick-mortar-other', 'other-woocommerce', ].includes( values.selling_venues ) ) { errors.revenue = __( 'This field is required', 'woocommerce-admin' ); } return errors; } getBusinessExtensions( values ) { if ( this.bundleInstall ) { return values.install_extensions ? [ 'jetpack', 'woocommerce-services', 'woocommerce-payments', ...this.extensions, ] : []; } if ( values.selling_venues === '' ) { return []; } return keys( pickBy( values ) ).filter( ( name ) => this.extensions.includes( name ) ); } convertCurrency( value ) { const region = getCurrencyRegion( this.props.settings.woocommerce_default_country ); if ( region === 'US' ) { return value; } // These are rough exchange rates from USD. Precision is not paramount. // The keys here should match the keys in `getCurrencyData`. const exchangeRates = { US: 1, EU: 0.9, IN: 71.24, GB: 0.76, BR: 4.19, VN: 23172.5, ID: 14031.0, BD: 84.87, PK: 154.8, RU: 63.74, TR: 5.75, MX: 19.37, CA: 1.32, }; const exchangeRate = exchangeRates[ region ] || exchangeRates.US; const digits = exchangeRate.toString().split( '.' )[ 0 ].length; const multiplier = Math.pow( 10, 2 + digits ); return Math.round( ( value * exchangeRate ) / multiplier ) * multiplier; } numberFormat( value ) { const { getCurrencyConfig } = this.context; return formatValue( getCurrencyConfig(), 'number', value ); } getNumberRangeString( min, max = false, format = this.numberFormat ) { if ( ! max ) { return sprintf( _x( '%s+', 'store product count or revenue', 'woocommerce-admin' ), format( min ) ); } return sprintf( _x( '%1$s - %2$s', 'store product count or revenue range', 'woocommerce-admin' ), format( min ), format( max ) ); } renderBusinessExtensionHelpText( values ) { const { isInstallingActivating } = this.props; const extensions = this.getBusinessExtensions( values ); if ( extensions.length === 0 ) { return null; } const extensionsList = extensions .map( ( extension ) => { return pluginNames[ extension ]; } ) .join( ', ' ); if ( isInstallingActivating ) { return ( { sprintf( _n( 'Installing the following plugin: %s', 'Installing the following plugins: %s', extensions.length, 'woocommerce-admin' ), extensionsList ) } ); } const accountRequiredText = this.bundleInstall ? __( 'User accounts are required to use these features.', 'woocommerce-admin' ) : ''; return (
{ sprintf( _n( 'The following plugin will be installed for free: %s. %s', 'The following plugins will be installed for free: %s. %s', extensions.length, 'woocommerce-admin' ), extensionsList, accountRequiredText ) } { this.bundleInstall && ( { interpolateComponents( { mixedString: __( 'By installing Jetpack and WooCommerce Shipping plugins for free you agree to our {{link}}Terms of Service{{/link}}.', 'woocommerce-admin' ), components: { link: ( ), }, } ) } ) }
); } renderBusinessExtensions( values, getInputProps ) { // Show extensions when the currently selling elsewhere checkbox has been answered. if ( values.selling_venues === '' ) { return null; } return (
{ extensionBenefits.map( ( benefit ) => (
{ benefit.title }

{ benefit.description }

) ) }
); } renderBusinessExtensionsBundle( values, getInputProps ) { const { isPopoverVisible } = this.state; const checkMarkIcon = ( ); return (
{ isPopoverVisible && ( this.setState( { isPopoverVisible: false } ) } >
{ checkMarkIcon } { __( 'Manage your store on the go with the WooCommerce mobile app', 'woocommerce-admin' ) }
{ checkMarkIcon } { __( 'Accept credit cards with WooCommerce Payments', 'woocommerce-admin' ) }
{ checkMarkIcon } { __( 'Speed & security enhancements', 'woocommerce-admin' ) }
{ checkMarkIcon } { __( 'Automatic sales taxes', 'woocommerce-admin' ) }
{ checkMarkIcon } { __( 'Market on Facebook', 'woocommerce-admin' ) }
{ checkMarkIcon } { __( 'Contact customers with Mailchimp', 'woocommerce-admin' ) }
{ checkMarkIcon } { __( 'Drive sales with Google Ads', 'woocommerce-admin' ) }
{ checkMarkIcon } { __( 'Print shipping labels at home', 'woocommerce-admin' ) }
) }
); } render() { const { goToNextStep, isInstallingActivating, hasInstallActivateError, isUpdatingProfileItems, } = this.props; const { getCurrencyConfig } = this.context; const productCountOptions = getProductCountOptions( getCurrencyConfig() ); const revenueOptions = getRevenueOptions( getCurrencyConfig(), this.props.settings.woocommerce_default_country ); return (
{ ( { getInputProps, handleSubmit, values, isValidForm } ) => { const businessExtensions = this.bundleInstall ? this.renderBusinessExtensionsBundle( values, getInputProps ) : this.renderBusinessExtensions( values, getInputProps ); return (
{ __( 'Tell us about your business', 'woocommerce-admin' ) } { __( "We'd love to know if you are just getting started or you already have a business in place.", 'woocommerce-admin' ) }
{ [ 'other', 'brick-mortar', 'brick-mortar-other', 'other-woocommerce', ].includes( values.selling_venues ) && ( ) } { [ 'other', 'brick-mortar-other', ].includes( values.selling_venues ) && (
{ values.other_platform === 'other' && ( ) }
) }
{ businessExtensions && ( { businessExtensions } ) } { hasInstallActivateError && ( ) }
{ this.renderBusinessExtensionHelpText( values ) }
); } }
); } } BusinessDetails.contextType = CurrencyContext; export const BundleBusinessDetailsStep = compose( withSelect( ( select ) => { const { getSettings, getSettingsError, isUpdateSettingsRequesting, } = select( SETTINGS_STORE_NAME ); const { getProfileItems, getOnboardingError, isOnboardingRequesting, } = select( ONBOARDING_STORE_NAME ); const { getPluginsError, isPluginsRequesting } = select( PLUGINS_STORE_NAME ); const { general: settings = {} } = getSettings( 'general' ); return { hasInstallActivateError: getPluginsError( 'installPlugins' ) || getPluginsError( 'activatePlugins' ), isError: Boolean( getOnboardingError( 'updateProfileItems' ) ), profileItems: getProfileItems(), isSettingsError: Boolean( getSettingsError( 'general' ) ), settings, isUpdatingProfileItems: isOnboardingRequesting( 'updateProfileItems' ) || isUpdateSettingsRequesting( 'general' ), isInstallingActivating: isPluginsRequesting( 'installPlugins' ) || isPluginsRequesting( 'activatePlugins' ) || isPluginsRequesting( 'getJetpackConnectUrl' ), }; } ), withDispatch( ( dispatch ) => { const { updateProfileItems } = dispatch( ONBOARDING_STORE_NAME ); const { installAndActivatePlugins } = dispatch( PLUGINS_STORE_NAME ); const { createNotice } = dispatch( 'core/notices' ); const { updateOptions } = dispatch( OPTIONS_STORE_NAME ); return { createNotice, installAndActivatePlugins, updateProfileItems, updateOptions, }; } ) )( BusinessDetails );