From 3f5844004cab524e8c8b5f0c7e10c621716da31e Mon Sep 17 00:00:00 2001 From: Chris Runnells Date: Thu, 7 Sep 2023 14:28:05 -1000 Subject: [PATCH] Revert "Remove Purchase files" This reverts commit 0f799159813565ef58a782cbec5e3af147b9ff2b. --- .../client/task-lists/fills/purchase.tsx | 91 ++++++++ .../OnboardingTasks/Tasks/Purchase.php | 203 ++++++++++++++++++ 2 files changed, 294 insertions(+) create mode 100644 plugins/woocommerce-admin/client/task-lists/fills/purchase.tsx create mode 100644 plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Purchase.php diff --git a/plugins/woocommerce-admin/client/task-lists/fills/purchase.tsx b/plugins/woocommerce-admin/client/task-lists/fills/purchase.tsx new file mode 100644 index 00000000000..316a82327b5 --- /dev/null +++ b/plugins/woocommerce-admin/client/task-lists/fills/purchase.tsx @@ -0,0 +1,91 @@ +/** + * External dependencies + */ +import React from 'react'; +import { registerPlugin } from '@wordpress/plugins'; +import { WooOnboardingTaskListItem } from '@woocommerce/onboarding'; +import { useState, useCallback } from '@wordpress/element'; +import { recordEvent } from '@woocommerce/tracks'; +import { useSelect } from '@wordpress/data'; +import { ONBOARDING_STORE_NAME, PLUGINS_STORE_NAME } from '@woocommerce/data'; + +/** + * Internal dependencies + */ +import CartModal from '../../dashboard/components/cart-modal'; +import { getCategorizedOnboardingProducts } from '../../dashboard/utils'; + +type PurchaseTaskItemProps = { + defaultTaskItem: React.ComponentType< { + onClick: () => void; + } >; +}; + +const PurchaseTaskItem = ( { defaultTaskItem }: PurchaseTaskItemProps ) => { + const [ cartModalOpen, setCartModalOpen ] = useState( false ); + + const { installedPlugins, productTypes, profileItems } = useSelect( + ( select ) => { + const { getProductTypes, getProfileItems } = select( + ONBOARDING_STORE_NAME + ); + const { getInstalledPlugins } = select( PLUGINS_STORE_NAME ); + + return { + installedPlugins: getInstalledPlugins(), + productTypes: getProductTypes(), + profileItems: getProfileItems(), + }; + } + ); + + const toggleCartModal = useCallback( () => { + if ( ! cartModalOpen ) { + recordEvent( 'tasklist_purchase_extensions' ); + } + + setCartModalOpen( ! cartModalOpen ); + }, [ cartModalOpen ] ); + + const groupedProducts = getCategorizedOnboardingProducts( + productTypes, + profileItems, + installedPlugins + ); + const { remainingProducts } = groupedProducts; + const DefaultTaskItem = defaultTaskItem; + + return ( + <> + { + if ( remainingProducts.length ) { + toggleCartModal(); + } + } } + /> + { cartModalOpen && ( + toggleCartModal() } + onClickPurchaseLater={ () => toggleCartModal() } + /> + ) } + + ); +}; + +const PurchaseTaskItemFill = () => { + return ( + + { ( { defaultTaskItem }: PurchaseTaskItemProps ) => ( + + ) } + + ); +}; + +registerPlugin( 'woocommerce-admin-task-purchase', { + // @ts-expect-error 'scope' does exist. @types/wordpress__plugins is outdated. + scope: 'woocommerce-tasks', + render: PurchaseTaskItemFill, +} ); diff --git a/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Purchase.php b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Purchase.php new file mode 100644 index 00000000000..2c9383f4a60 --- /dev/null +++ b/plugins/woocommerce/src/Admin/Features/OnboardingTasks/Tasks/Purchase.php @@ -0,0 +1,203 @@ +undo_dismiss(); + } + + /** + * Get the task arguments. + * ID. + * + * @return string + */ + public function get_id() { + return 'purchase'; + } + + /** + * Title. + * + * @return string + */ + public function get_title() { + $products = $this->get_paid_products_and_themes(); + $first_product = count( $products['purchaseable'] ) >= 1 ? $products['purchaseable'][0] : false; + + if ( ! $first_product ) { + return null; + } + + $product_label = isset( $first_product['label'] ) ? $first_product['label'] : $first_product['title']; + $additional_count = count( $products['purchaseable'] ) - 1; + + if ( $this->get_parent_option( 'use_completed_title' ) && $this->is_complete() ) { + return count( $products['purchaseable'] ) === 1 + ? sprintf( + /* translators: %1$s: a purchased product name */ + __( + 'You added %1$s', + 'woocommerce' + ), + $product_label + ) + : sprintf( + /* translators: %1$s: a purchased product name, %2$d the number of other products purchased */ + _n( + 'You added %1$s and %2$d other product', + 'You added %1$s and %2$d other products', + $additional_count, + 'woocommerce' + ), + $product_label, + $additional_count + ); + } + + return count( $products['purchaseable'] ) === 1 + ? sprintf( + /* translators: %1$s: a purchaseable product name */ + __( + 'Add %s to my store', + 'woocommerce' + ), + $product_label + ) + : sprintf( + /* translators: %1$s: a purchaseable product name, %2$d the number of other products to purchase */ + _n( + 'Add %1$s and %2$d more product to my store', + 'Add %1$s and %2$d more products to my store', + $additional_count, + 'woocommerce' + ), + $product_label, + $additional_count + ); + } + + /** + * Content. + * + * @return string + */ + public function get_content() { + $products = $this->get_paid_products_and_themes(); + + if ( count( $products['remaining'] ) === 1 ) { + return isset( $products['purchaseable'][0]['description'] ) ? $products['purchaseable'][0]['description'] : $products['purchaseable'][0]['excerpt']; + } + return sprintf( + /* translators: %1$s: list of product names comma separated, %2%s the last product name */ + __( + 'Good choice! You chose to add %1$s and %2$s to your store.', + 'woocommerce' + ), + implode( ', ', array_slice( $products['remaining'], 0, -1 ) ) . ( count( $products['remaining'] ) > 2 ? ',' : '' ), + end( $products['remaining'] ) + ); + } + + /** + * Action label. + * + * @return string + */ + public function get_action_label() { + return __( 'Purchase & install now', 'woocommerce' ); + } + + + /** + * Time. + * + * @return string + */ + public function get_time() { + return __( '2 minutes', 'woocommerce' ); + } + + /** + * Task completion. + * + * @return bool + */ + public function is_complete() { + $products = $this->get_paid_products_and_themes(); + return count( $products['remaining'] ) === 0; + } + + /** + * Dismissable. + * + * @return bool + */ + public function is_dismissable() { + return true; + } + + /** + * Task visibility. + * + * @return bool + */ + public function can_view() { + $products = $this->get_paid_products_and_themes(); + return count( $products['purchaseable'] ) > 0; + } + + /** + * Get purchaseable and remaining products. + * + * @return array purchaseable and remaining products and themes. + */ + public static function get_paid_products_and_themes() { + $relevant_products = OnboardingProducts::get_relevant_products(); + + $profiler_data = get_option( OnboardingProfile::DATA_OPTION, array() ); + $theme = isset( $profiler_data['theme'] ) ? $profiler_data['theme'] : null; + $paid_theme = $theme ? OnboardingThemes::get_paid_theme_by_slug( $theme ) : null; + if ( $paid_theme ) { + + $relevant_products['purchaseable'][] = $paid_theme; + + if ( isset( $paid_theme['is_installed'] ) && false === $paid_theme['is_installed'] ) { + $relevant_products['remaining'][] = $paid_theme['title']; + } + } + return $relevant_products; + } +}