diff --git a/src/CONST.ts b/src/CONST.ts index 38af2f2d4f8a..e027c1943639 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1103,6 +1103,7 @@ const CONST = { PLAN_TYPES_AND_PRICING_HELP_URL: 'https://help.expensify.com/articles/new-expensify/billing-and-subscriptions/Plan-types-and-pricing', MERGE_ACCOUNT_HELP_URL: 'https://help.expensify.com/articles/new-expensify/settings/Merge-Accounts', CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL: 'https://help.expensify.com/articles/new-expensify/expenses-&-payments/Connect-a-Business-Bank-Account', + REGISTER_FOR_WEBINAR_URL: 'https://events.zoom.us/eo/Aif1I8qCi1GZ7KnLnd1vwGPmeukSRoPjFpyFAZ2udQWn0-B86e1Z~AggLXsr32QYFjq8BlYLZ5I06Dg', TEST_RECEIPT_URL: `${CLOUDFRONT_URL}/images/fake-receipt__tacotodds.png`, // Use Environment.getEnvironmentURL to get the complete URL with port number DEV_NEW_EXPENSIFY_URL: 'https://dev.new.expensify.com:', @@ -7045,6 +7046,11 @@ const CONST = { EMBEDDED_DEMO_WHITELIST: ['http://', 'https://', 'about:'] as string[], EMBEDDED_DEMO_IFRAME_TITLE: 'Test Drive', }, + + ONBOARDING_HELP: { + TALK_TO_SALES: 'talkToSales', + REGISTER_FOR_WEBINAR: 'registerForWebinar', + }, } as const; type Country = keyof typeof CONST.ALL_COUNTRIES; diff --git a/src/components/ButtonWithDropdownMenu/types.ts b/src/components/ButtonWithDropdownMenu/types.ts index 9b1305d76a09..7559eedc3098 100644 --- a/src/components/ButtonWithDropdownMenu/types.ts +++ b/src/components/ButtonWithDropdownMenu/types.ts @@ -18,6 +18,8 @@ type WorkspaceTaxRatesBulkActionType = DeepValueOf; +type OnboardingHelpType = DeepValueOf; + type DropdownOption = { value: TValueType; text: string; @@ -134,4 +136,5 @@ export type { ButtonWithDropdownMenuProps, WorkspaceTaxRatesBulkActionType, ReportExportType, + OnboardingHelpType, }; diff --git a/src/components/OnboardingHelpDropdownButton.tsx b/src/components/OnboardingHelpDropdownButton.tsx new file mode 100644 index 000000000000..ac5b6a7e4fff --- /dev/null +++ b/src/components/OnboardingHelpDropdownButton.tsx @@ -0,0 +1,88 @@ +import React from 'react'; +import {useOnyx} from 'react-native-onyx'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {openExternalLink} from '@libs/actions/Link'; +import {initializeOpenAIRealtime, stopConnection} from '@libs/actions/OpenAI'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; +import type {DropdownOption, OnboardingHelpType} from './ButtonWithDropdownMenu/types'; +import {Close, Monitor, Phone} from './Icon/Expensicons'; + +type TalkToSalesButtonProps = { + reportID: string | undefined; + shouldUseNarrowLayout: boolean; + shouldShowTalkToSales: boolean; + shouldShowRegisterForWebinar: boolean; +}; + +function OnboardingHelpDropdownButton({reportID, shouldUseNarrowLayout, shouldShowTalkToSales, shouldShowRegisterForWebinar}: TalkToSalesButtonProps) { + const {translate} = useLocalize(); + const [talkToAISales] = useOnyx(ONYXKEYS.TALK_TO_AI_SALES, {canBeMissing: false}); + const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.accountID, canBeMissing: false}); + const styles = useThemeStyles(); + + if (!reportID || !accountID) { + return null; + } + + const abTestCtaText = (): string => { + const availableCTAs = [translate('aiSales.getHelp'), translate('aiSales.talkToSales'), translate('aiSales.talkToConcierge')]; + return availableCTAs.at(accountID % availableCTAs.length) ?? translate('aiSales.talkToSales'); + }; + + const talkToSalesOption = { + talkToSaleText: talkToAISales?.isTalkingToAISales ? translate('aiSales.hangUp') : abTestCtaText(), + talkToSalesIcon: talkToAISales?.isTalkingToAISales ? Close : Phone, + abTestCtaText: abTestCtaText(), + }; + + const options: Array> = []; + + if (shouldShowTalkToSales) { + options.push({ + text: talkToSalesOption.talkToSaleText, + icon: talkToSalesOption.talkToSalesIcon, + value: CONST.ONBOARDING_HELP.TALK_TO_SALES, + onSelected: () => { + if (talkToAISales?.isTalkingToAISales) { + stopConnection(); + } else { + initializeOpenAIRealtime(Number(reportID), talkToSalesOption.abTestCtaText); + } + }, + }); + } + + if (shouldShowRegisterForWebinar) { + options.push({ + text: translate('getAssistancePage.registerForWebinar'), + icon: Monitor, + value: CONST.ONBOARDING_HELP.REGISTER_FOR_WEBINAR, + onSelected: () => { + openExternalLink(CONST.REGISTER_FOR_WEBINAR_URL); + }, + }); + } + + if (options.length === 0) { + return null; + } + + return ( + null} + shouldAlwaysShowDropdownMenu + success={false} + buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM} + options={options} + isSplitButton={false} + customText={translate('getAssistancePage.onboardingHelp')} + isLoading={talkToAISales?.isLoading} + style={shouldUseNarrowLayout && styles.earlyDiscountButton} + /> + ); +} + +export default OnboardingHelpDropdownButton; diff --git a/src/languages/en.ts b/src/languages/en.ts index 7093625369a6..d1e0319f90aa 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -5001,6 +5001,8 @@ const translations = { scheduleADemo: 'Schedule demo', questionMarkButtonTooltip: 'Get assistance from our team', exploreHelpDocs: 'Explore help docs', + registerForWebinar: 'Register for webinar', + onboardingHelp: 'Onboarding help', }, emojiPicker: { skinTonePickerLabel: 'Change default skin tone', diff --git a/src/languages/es.ts b/src/languages/es.ts index babcb076fd71..6095bdafa470 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -5055,6 +5055,8 @@ const translations = { scheduleADemo: 'Programa una demostración', questionMarkButtonTooltip: 'Obtén ayuda de nuestro equipo', exploreHelpDocs: 'Explorar la documentación de ayuda', + registerForWebinar: 'Registrarse para el seminario web', + onboardingHelp: 'Ayuda de incorporación', }, emojiPicker: { skinTonePickerLabel: 'Elige el tono de piel por defecto', diff --git a/src/pages/home/HeaderView.tsx b/src/pages/home/HeaderView.tsx index c498dca5e1fb..06b51c049039 100644 --- a/src/pages/home/HeaderView.tsx +++ b/src/pages/home/HeaderView.tsx @@ -12,6 +12,7 @@ import {BackArrow, CalendarSolid, DotIndicator, FallbackAvatar} from '@component import LoadingBar from '@components/LoadingBar'; import MultipleAvatars from '@components/MultipleAvatars'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import OnboardingHelpDropdownButton from '@components/OnboardingHelpDropdownButton'; import ParentNavigationSubtitle from '@components/ParentNavigationSubtitle'; import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; import ReportHeaderSkeletonView from '@components/ReportHeaderSkeletonView'; @@ -31,6 +32,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {openExternalLink} from '@libs/actions/Link'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; +import getPlatform from '@libs/getPlatform'; import Navigation from '@libs/Navigation/Navigation'; import {getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils'; import Parser from '@libs/Parser'; @@ -75,7 +77,6 @@ import SCREENS from '@src/SCREENS'; import type {Report, ReportAction} from '@src/types/onyx'; import type {Icon as IconType} from '@src/types/onyx/OnyxCommon'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import TalkToSalesButton from './TalkToSalesButton'; type HeaderViewProps = { /** Toggles the navigationMenu open and closed */ @@ -124,9 +125,10 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, const styles = useThemeStyles(); const isSelfDM = isSelfDMReportUtils(report); const isGroupChat = isGroupChatReportUtils(report) || isDeprecatedGroupDM(report); + const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const {canUseTalkToAISales} = usePermissions(); - const shouldShowTalkToSales = !!canUseTalkToAISales && isAdminRoom(report); - + const isNativePlatform = getPlatform() === CONST.PLATFORM.IOS || getPlatform() === CONST.PLATFORM.ANDROID; + const shouldShowTalkToSales = !!canUseTalkToAISales && isAdminRoom(report) && !isNativePlatform; const allParticipants = getParticipantsAccountIDsForDisplay(report, false, true, undefined, reportMetadata); const shouldAddEllipsis = allParticipants?.length > CONST.DISPLAY_PARTICIPANTS_LIMIT; const participants = allParticipants.slice(0, CONST.DISPLAY_PARTICIPANTS_LIMIT); @@ -212,6 +214,8 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, const shouldDisplaySearchRouter = !isReportInRHP || isSmallScreenWidth; const [onboardingPurposeSelected] = useOnyx(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED, {canBeMissing: true}); const isChatUsedForOnboarding = isChatUsedForOnboardingReportUtils(report, onboardingPurposeSelected); + const shouldShowRegisterForWebinar = introSelected?.companySize === CONST.ONBOARDING_COMPANY_SIZE.MICRO && isChatUsedForOnboarding; + const shouldShowOnBoardingHelpDropdownButton = shouldShowTalkToSales || shouldShowRegisterForWebinar; const shouldShowEarlyDiscountBanner = shouldShowDiscount && isChatUsedForOnboarding; const shouldShowGuideBookingButtonInEarlyDiscountBanner = shouldShowGuideBooking && shouldShowEarlyDiscountBanner && !isDismissedDiscountBanner; @@ -230,10 +234,12 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, /> ); - const talkToSalesButton = ( - ); @@ -358,7 +364,7 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, )} - {!shouldShowEarlyDiscountBanner && shouldShowTalkToSales && !shouldUseNarrowLayout && talkToSalesButton} + {shouldShowOnBoardingHelpDropdownButton && !shouldUseNarrowLayout && onboardingHelpDropdownButton} {!shouldShowGuideBookingButtonInEarlyDiscountBanner && shouldShowGuideBooking && !shouldUseNarrowLayout && guideBookingButton} {!shouldUseNarrowLayout && !shouldShowDiscount && isChatUsedForOnboarding && ( {!isParentReportLoading && !isLoading && canJoin && shouldUseNarrowLayout && {joinButton}} - {!shouldShowEarlyDiscountBanner && shouldShowTalkToSales && shouldUseNarrowLayout && {talkToSalesButton}} + + {!shouldShowEarlyDiscountBanner && shouldShowOnBoardingHelpDropdownButton && shouldUseNarrowLayout && ( + {onboardingHelpDropdownButton} + )} + {!isLoading && !shouldShowDiscount && isChatUsedForOnboarding && shouldUseNarrowLayout && ( + + )} + + {!shouldShowGuideBookingButtonInEarlyDiscountBanner && !isLoading && shouldShowGuideBooking && shouldUseNarrowLayout && ( {guideBookingButton} )} - {!isLoading && !shouldShowDiscount && isChatUsedForOnboarding && shouldUseNarrowLayout && ( - - )} {!!report && shouldUseNarrowLayout && isOpenTaskReport(report, parentReportAction) && ( @@ -415,7 +426,7 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, {shouldShowEarlyDiscountBanner && ( setIsDismissedDiscountBanner(true)} diff --git a/src/pages/home/TalkToSalesButton/index.native.tsx b/src/pages/home/TalkToSalesButton/index.native.tsx deleted file mode 100644 index 00c992a20663..000000000000 --- a/src/pages/home/TalkToSalesButton/index.native.tsx +++ /dev/null @@ -1,5 +0,0 @@ -function TalkToSalesButton() { - return null; -} - -export default TalkToSalesButton; diff --git a/src/pages/home/TalkToSalesButton/index.tsx b/src/pages/home/TalkToSalesButton/index.tsx deleted file mode 100644 index 1bb1d318ed96..000000000000 --- a/src/pages/home/TalkToSalesButton/index.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React from 'react'; -import {useOnyx} from 'react-native-onyx'; -import Button from '@components/Button'; -import {Close, Phone} from '@components/Icon/Expensicons'; -import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {initializeOpenAIRealtime, stopConnection} from '@libs/actions/OpenAI'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; - -type TalkToSalesButtonProps = { - reportID: string | undefined; - shouldUseNarrowLayout: boolean; -}; - -function TalkToSalesButton({shouldUseNarrowLayout, reportID}: TalkToSalesButtonProps) { - const {translate} = useLocalize(); - const [talkToAISales] = useOnyx(ONYXKEYS.TALK_TO_AI_SALES, {canBeMissing: false}); - const styles = useThemeStyles(); - const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); - const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.accountID, canBeMissing: false}); - - if (!reportID || !accountID) { - return; - } - - // Only show for micro companies (1-10 employees) - if (introSelected?.companySize !== CONST.ONBOARDING_COMPANY_SIZE.MICRO) { - return null; - } - - const abTestCtaText = (): string => { - const availableCTAs = [translate('aiSales.getHelp'), translate('aiSales.talkToSales'), translate('aiSales.talkToConcierge')]; - return availableCTAs.at(accountID % availableCTAs.length) ?? translate('aiSales.talkToSales'); - }; - - const talkToSalesIcon = () => { - if (talkToAISales?.isLoading) { - return undefined; - } - if (talkToAISales?.isTalkingToAISales) { - return Close; - } - return Phone; - }; - - return ( -