diff --git a/src/CONST.ts b/src/CONST.ts index e7a5d10b81ae..d07a76cd8091 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -136,12 +136,24 @@ const onboardingEmployerOrSubmitMessage: OnboardingMessageType = { type OnboardingPurposeType = ValueOf; +type OnboardingCompanySizeType = ValueOf; + +type OnboardingAccountingType = ValueOf | null; + const onboardingInviteTypes = { IOU: 'iou', INVOICE: 'invoice', CHAT: 'chat', } as const; +const onboardingCompanySize = { + MICRO: '1-10', + SMALL: '11-50', + MEDIUM_SMALL: '51-100', + MEDIUM: '101-1000', + LARGE: '1001+', +} as const; + type OnboardingInviteType = ValueOf; type OnboardingTaskType = { @@ -4488,6 +4500,7 @@ const CONST = { SELECTABLE_ONBOARDING_CHOICES: {...selectableOnboardingChoices}, ONBOARDING_SIGNUP_QUALIFIERS: {...signupQualifiers}, ONBOARDING_INVITE_TYPES: {...onboardingInviteTypes}, + ONBOARDING_COMPANY_SIZE: {...onboardingCompanySize}, ACTIONABLE_TRACK_EXPENSE_WHISPER_MESSAGE: 'What would you like to do with this expense?', ONBOARDING_CONCIERGE: { [onboardingChoices.EMPLOYER]: @@ -5842,6 +5855,19 @@ type FeedbackSurveyOptionID = ValueOf; type CancellationType = ValueOf; -export type {Country, IOUAction, IOUType, RateAndUnit, OnboardingPurposeType, IOURequestType, SubscriptionType, FeedbackSurveyOptionID, CancellationType, OnboardingInviteType}; +export type { + Country, + IOUAction, + IOUType, + RateAndUnit, + OnboardingPurposeType, + OnboardingCompanySizeType, + IOURequestType, + SubscriptionType, + FeedbackSurveyOptionID, + CancellationType, + OnboardingInviteType, + OnboardingAccountingType, +}; export default CONST; diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 2a325bb4a74f..0b69fe9be80b 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -1,6 +1,6 @@ import type {ValueOf} from 'type-fest'; import type CONST from './CONST'; -import type {OnboardingPurposeType} from './CONST'; +import type {OnboardingCompanySizeType, OnboardingPurposeType} from './CONST'; import type * as FormTypes from './types/form'; import type * as OnyxTypes from './types/onyx'; import type Onboarding from './types/onyx/Onboarding'; @@ -342,6 +342,9 @@ const ONYXKEYS = { /** Onboarding policyID selected by the user during Onboarding flow */ ONBOARDING_POLICY_ID: 'onboardingPolicyID', + /** Onboarding company size selected by the user during Onboarding flow */ + ONBOARDING_COMPANY_SIZE: 'onboardingCompanySize', + /** Onboarding Purpose selected by the user during Onboarding flow */ ONBOARDING_ADMINS_CHAT_REPORT_ID: 'onboardingAdminsChatReportID', @@ -557,8 +560,6 @@ const ONYXKEYS = { DISPLAY_NAME_FORM_DRAFT: 'displayNameFormDraft', ONBOARDING_PERSONAL_DETAILS_FORM: 'onboardingPersonalDetailsForm', ONBOARDING_PERSONAL_DETAILS_FORM_DRAFT: 'onboardingPersonalDetailsFormDraft', - ONBOARDING_PERSONAL_WORK: 'onboardingWorkForm', - ONBOARDING_PERSONAL_WORK_DRAFT: 'onboardingWorkFormDraft', ROOM_NAME_FORM: 'roomNameForm', ROOM_NAME_FORM_DRAFT: 'roomNameFormDraft', REPORT_DESCRIPTION_FORM: 'reportDescriptionForm', @@ -721,7 +722,6 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.PROFILE_SETTINGS_FORM]: FormTypes.ProfileSettingsForm; [ONYXKEYS.FORMS.DISPLAY_NAME_FORM]: FormTypes.DisplayNameForm; [ONYXKEYS.FORMS.ONBOARDING_PERSONAL_DETAILS_FORM]: FormTypes.DisplayNameForm; - [ONYXKEYS.FORMS.ONBOARDING_PERSONAL_WORK]: FormTypes.WorkForm; [ONYXKEYS.FORMS.ROOM_NAME_FORM]: FormTypes.RoomNameForm; [ONYXKEYS.FORMS.REPORT_DESCRIPTION_FORM]: FormTypes.ReportDescriptionForm; [ONYXKEYS.FORMS.LEGAL_NAME_FORM]: FormTypes.LegalNameForm; @@ -960,6 +960,7 @@ type OnyxValuesMapping = { [ONYXKEYS.MAX_CANVAS_HEIGHT]: number; [ONYXKEYS.MAX_CANVAS_WIDTH]: number; [ONYXKEYS.ONBOARDING_PURPOSE_SELECTED]: OnboardingPurposeType; + [ONYXKEYS.ONBOARDING_COMPANY_SIZE]: OnboardingCompanySizeType; [ONYXKEYS.ONBOARDING_CUSTOM_CHOICES]: OnboardingPurposeType[] | []; [ONYXKEYS.ONBOARDING_ERROR_MESSAGE]: string; [ONYXKEYS.ONBOARDING_POLICY_ID]: string; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 47fabe3c421c..5d31b2428a4b 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -1179,9 +1179,13 @@ const ROUTES = { route: 'onboarding/personal-details', getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding/personal-details`, backTo), }, - ONBOARDING_WORK: { - route: 'onboarding/work', - getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding/work`, backTo), + ONBOARDING_EMPLOYEES: { + route: 'onboarding/employees', + getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding/employees`, backTo), + }, + ONBOARDING_ACCOUNTING: { + route: 'onboarding/accounting', + getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding/accounting`, backTo), }, ONBOARDING_PURPOSE: { route: 'onboarding/purpose', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 6e9efd15e910..0e29da05bdfe 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -528,7 +528,8 @@ const SCREENS = { ONBOARDING: { PERSONAL_DETAILS: 'Onboarding_Personal_Details', PURPOSE: 'Onboarding_Purpose', - WORK: 'Onboarding_Work', + EMPLOYEES: 'Onboarding_Employees', + ACCOUNTING: 'Onboarding_Accounting', }, WELCOME_VIDEO: { diff --git a/src/components/ContextMenuItem.tsx b/src/components/ContextMenuItem.tsx index fe7be45e1b57..c57c10e2c2b9 100644 --- a/src/components/ContextMenuItem.tsx +++ b/src/components/ContextMenuItem.tsx @@ -133,7 +133,7 @@ function ContextMenuItem( title={itemText} icon={itemIcon} onPress={triggerPressAndUpdateSuccess} - wrapperStyle={[styles.pr9, wrapperStyle]} + wrapperStyle={[styles.pr8, wrapperStyle]} success={!isThrottledButtonActive} description={description} descriptionTextStyle={styles.breakWord} diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 0643b0b1ba36..06bf8eb6434a 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -101,6 +101,7 @@ function BaseSelectionList( onLongPressRow, shouldShowTextInput = !!textInputLabel || !!textInputIconLeft, shouldShowListEmptyContent = true, + listItemWrapperStyle, shouldIgnoreFocus = false, scrollEventThrottle, contentContainerStyle, @@ -475,6 +476,7 @@ function BaseSelectionList( setFocusedIndex(normalizedIndex); }} shouldSyncFocus={!isTextInputFocusedRef.current} + wrapperStyle={listItemWrapperStyle} /> {item.footerContent && item.footerContent} diff --git a/src/components/SelectionList/RadioListItem.tsx b/src/components/SelectionList/RadioListItem.tsx index 067c2341ef67..1f0e174d4749 100644 --- a/src/components/SelectionList/RadioListItem.tsx +++ b/src/components/SelectionList/RadioListItem.tsx @@ -21,6 +21,7 @@ function RadioListItem({ alternateTextNumberOfLines = 2, onFocus, shouldSyncFocus, + wrapperStyle, }: RadioListItemProps) { const styles = useThemeStyles(); const fullTitle = isMultilineSupported ? item.text?.trimStart() : item.text; @@ -31,7 +32,7 @@ function RadioListItem({ return ( = Partial & { /** Whether to show the empty list content */ shouldShowListEmptyContent?: boolean; + /** The style is applied for the wrap component of list item */ + listItemWrapperStyle?: StyleProp; + /** Scroll event throttle for preventing onScroll callbacks to be fired too often */ scrollEventThrottle?: number; diff --git a/src/languages/en.ts b/src/languages/en.ts index 27c0a1025651..fa2d39cc29dd 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1724,9 +1724,9 @@ const translations = { getStarted: 'Get started', whatsYourName: "What's your name?", whereYouWork: 'Where do you work?', + errorSelection: 'Please make a selection to continue.', purpose: { title: 'What do you want to do today?', - errorSelection: 'Please make a selection to continue.', errorContinue: 'Please press continue to get set up.', errorBackButton: 'Please finish the setup questions to start using the app.', [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Get paid back by my employer', @@ -1735,6 +1735,18 @@ const translations = { [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: 'Chat and split expenses with friends', [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: 'Something else', }, + employees: { + title: 'How many employees do you have?', + [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1-10 employees', + [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11-50 employees', + [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51-100 employees', + [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM]: '101-1,000 employees', + [CONST.ONBOARDING_COMPANY_SIZE.LARGE]: 'More than 1,000 employees', + }, + accounting: { + title: 'Do you use any accounting software?', + noneOfAbove: 'None of the above', + }, error: { requiredFirstName: 'Please input your first name to continue.', }, diff --git a/src/languages/es.ts b/src/languages/es.ts index 58316a37c523..2a7a9864c17f 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1724,9 +1724,9 @@ const translations = { getStarted: 'Comenzar', whatsYourName: '¿Cómo te llamas?', whereYouWork: '¿Dónde trabajas?', + errorSelection: 'Por favor selecciona una opción para continuar.', purpose: { title: '¿Qué quieres hacer hoy?', - errorSelection: 'Por favor selecciona una opción para continuar.', errorContinue: 'Por favor, haz click en continuar para configurar tu cuenta.', errorBackButton: 'Por favor, finaliza las preguntas de configuración para empezar a utilizar la aplicación.', [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Cobrar de mi empresa', @@ -1735,6 +1735,18 @@ const translations = { [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: 'Chatea y divide gastos con tus amigos', [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: 'Algo más', }, + employees: { + title: '¿Cuántos empleados tienes?', + [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1-10 empleados', + [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11-50 empleados', + [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51-100 empleados', + [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM]: '101-1,000 empleados', + [CONST.ONBOARDING_COMPANY_SIZE.LARGE]: 'Más de 1,000 empleados', + }, + accounting: { + title: '¿Utilizas algún software de contabilidad?', + noneOfAbove: 'Ninguno de los anteriores', + }, error: { requiredFirstName: 'Introduce tu nombre para continuar.', }, diff --git a/src/libs/API/parameters/CompleteGuidedSetupParams.ts b/src/libs/API/parameters/CompleteGuidedSetupParams.ts index 0b2c0b66ef0a..1242b9285de9 100644 --- a/src/libs/API/parameters/CompleteGuidedSetupParams.ts +++ b/src/libs/API/parameters/CompleteGuidedSetupParams.ts @@ -1,4 +1,4 @@ -import type {OnboardingPurposeType} from '@src/CONST'; +import type {OnboardingAccountingType, OnboardingCompanySizeType, OnboardingPurposeType} from '@src/CONST'; type CompleteGuidedSetupParams = { firstName: string; @@ -7,6 +7,8 @@ type CompleteGuidedSetupParams = { guidedSetupData: string; engagementChoice: OnboardingPurposeType; paymentSelected?: string; + companySize?: OnboardingCompanySizeType; + userReportedIntegration?: OnboardingAccountingType; }; export default CompleteGuidedSetupParams; diff --git a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx index e564af8103cc..4aae43987797 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx @@ -9,9 +9,10 @@ import useThemeStyles from '@hooks/useThemeStyles'; import OnboardingModalNavigatorScreenOptions from '@libs/Navigation/AppNavigator/OnboardingModalNavigatorScreenOptions'; import type {OnboardingModalNavigatorParamList} from '@libs/Navigation/types'; import OnboardingRefManager from '@libs/OnboardingRefManager'; +import OnboardingAccounting from '@pages/OnboardingAccounting'; +import OnboardingEmployees from '@pages/OnboardingEmployees'; import OnboardingPersonalDetails from '@pages/OnboardingPersonalDetails'; import OnboardingPurpose from '@pages/OnboardingPurpose'; -import OnboardingWork from '@pages/OnboardingWork'; import CONST from '@src/CONST'; import SCREENS from '@src/SCREENS'; import Overlay from './Overlay'; @@ -52,8 +53,12 @@ function OnboardingModalNavigator() { component={OnboardingPersonalDetails} /> + diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 57e83d309966..0f3a168825b4 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -119,8 +119,12 @@ const config: LinkingOptions['config'] = { path: ROUTES.ONBOARDING_PERSONAL_DETAILS.route, exact: true, }, - [SCREENS.ONBOARDING.WORK]: { - path: ROUTES.ONBOARDING_WORK.route, + [SCREENS.ONBOARDING.EMPLOYEES]: { + path: ROUTES.ONBOARDING_EMPLOYEES.route, + exact: true, + }, + [SCREENS.ONBOARDING.ACCOUNTING]: { + path: ROUTES.ONBOARDING_ACCOUNTING.route, exact: true, }, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 0a65d4a91725..ff0f203907f3 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1396,7 +1396,10 @@ type OnboardingModalNavigatorParamList = { [SCREENS.ONBOARDING.PURPOSE]: { backTo?: string; }; - [SCREENS.ONBOARDING.WORK]: { + [SCREENS.ONBOARDING.EMPLOYEES]: { + backTo?: string; + }; + [SCREENS.ONBOARDING.ACCOUNTING]: { backTo?: string; }; }; diff --git a/src/libs/NavigationUtils.ts b/src/libs/NavigationUtils.ts index ea1710b9931c..2f967c2f9a5e 100644 --- a/src/libs/NavigationUtils.ts +++ b/src/libs/NavigationUtils.ts @@ -17,7 +17,13 @@ const CENTRAL_PANE_SCREEN_NAMES = new Set([ SCREENS.REPORT, ]); -const ONBOARDING_SCREEN_NAMES = new Set([SCREENS.ONBOARDING.PERSONAL_DETAILS, SCREENS.ONBOARDING.PURPOSE, SCREENS.ONBOARDING.WORK, SCREENS.ONBOARDING_MODAL.ONBOARDING]); +const ONBOARDING_SCREEN_NAMES = new Set([ + SCREENS.ONBOARDING.PERSONAL_DETAILS, + SCREENS.ONBOARDING.PURPOSE, + SCREENS.ONBOARDING_MODAL.ONBOARDING, + SCREENS.ONBOARDING.EMPLOYEES, + SCREENS.ONBOARDING.ACCOUNTING, +]); const removePolicyIDParamFromState = (state: State) => { const stateCopy = cloneDeep(state); diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 5db7bb972709..de896e6f72f5 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -7562,15 +7562,7 @@ function completePaymentOnboarding(paymentSelected: ValueOf, full = true) { diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 95bd2aa0b834..13b14d380758 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -70,7 +70,7 @@ import Parser from '@libs/Parser'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as PhoneNumber from '@libs/PhoneNumber'; import getPolicyEmployeeAccountIDs from '@libs/PolicyEmployeeListUtils'; -import {extractPolicyIDFromPath} from '@libs/PolicyUtils'; +import {extractPolicyIDFromPath, getPolicy} from '@libs/PolicyUtils'; import processReportIDDeeplink from '@libs/processReportIDDeeplink'; import * as Pusher from '@libs/Pusher/pusher'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; @@ -81,7 +81,7 @@ import {doesReportBelongToWorkspace} from '@libs/ReportUtils'; import shouldSkipDeepLinkNavigation from '@libs/shouldSkipDeepLinkNavigation'; import Visibility from '@libs/Visibility'; import CONFIG from '@src/CONFIG'; -import type {OnboardingPurposeType} from '@src/CONST'; +import type {OnboardingAccountingType, OnboardingCompanySizeType, OnboardingPurposeType} from '@src/CONST'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Route} from '@src/ROUTES'; @@ -3325,16 +3325,13 @@ function getReportPrivateNote(reportID: string | undefined) { function completeOnboarding( engagementChoice: OnboardingPurposeType, data: ValueOf, - { - firstName, - lastName, - }: { - firstName: string; - lastName: string; - }, + firstName = '', + lastName = '', adminsChatReportID?: string, onboardingPolicyID?: string, paymentSelected?: string, + companySize?: OnboardingCompanySizeType, + userReportedIntegration?: OnboardingAccountingType, ) { const actorAccountID = CONST.ACCOUNT_ID.CONCIERGE; const targetChatReport = ReportUtils.getChatByParticipants([actorAccountID, currentUserAccountID]); @@ -3647,6 +3644,38 @@ function completeOnboarding( }, ); + if (userReportedIntegration) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${onboardingPolicyID}`, + value: { + areConnectionsEnabled: true, + pendingFields: { + areConnectionsEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }, + }, + }); + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${onboardingPolicyID}`, + value: { + pendingFields: { + areConnectionsEnabled: null, + }, + }, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${onboardingPolicyID}`, + value: { + areConnectionsEnabled: getPolicy(onboardingPolicyID)?.areConnectionsEnabled, + pendingFields: { + areConnectionsEnabled: null, + }, + }, + }); + } + const guidedSetupData: GuidedSetupData = [ {type: 'message', ...introductionMessage}, {type: 'message', ...textMessage}, @@ -3691,6 +3720,8 @@ function completeOnboarding( actorAccountID, guidedSetupData: JSON.stringify(guidedSetupData), paymentSelected, + companySize, + userReportedIntegration, }; API.write(WRITE_COMMANDS.COMPLETE_GUIDED_SETUP, parameters, {optimisticData, successData, failureData}); diff --git a/src/libs/actions/Welcome/OnboardingFlow.ts b/src/libs/actions/Welcome/OnboardingFlow.ts index 0257faf39f14..3c11f3c440db 100644 --- a/src/libs/actions/Welcome/OnboardingFlow.ts +++ b/src/libs/actions/Welcome/OnboardingFlow.ts @@ -64,7 +64,7 @@ function adaptOnboardingRouteState() { } let adaptedOnboardingModalNavigatorState = {} as Readonly>; - if (currentRoute?.name === SCREENS.ONBOARDING.PERSONAL_DETAILS && selectedPurpose === CONST.ONBOARDING_CHOICES.MANAGE_TEAM) { + if (currentRoute?.name === SCREENS.ONBOARDING.ACCOUNTING && selectedPurpose === CONST.ONBOARDING_CHOICES.MANAGE_TEAM) { adaptedOnboardingModalNavigatorState = { index: 2, routes: [ @@ -73,7 +73,7 @@ function adaptOnboardingRouteState() { params: currentRoute?.params, }, { - name: SCREENS.ONBOARDING.WORK, + name: SCREENS.ONBOARDING.EMPLOYEES, params: currentRoute?.params, }, {...currentRoute}, @@ -119,7 +119,7 @@ function getOnboardingInitialPath(): string { if (isVsb) { Onyx.set(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED, CONST.ONBOARDING_CHOICES.MANAGE_TEAM); - return `/${ROUTES.ONBOARDING_WORK.route}`; + return `/${ROUTES.ONBOARDING_EMPLOYEES.route}`; } const isIndividual = onboardingValues.signupQualifier === CONST.ONBOARDING_SIGNUP_QUALIFIERS.INDIVIDUAL; if (isIndividual) { diff --git a/src/libs/actions/Welcome/index.ts b/src/libs/actions/Welcome/index.ts index d27a5e195a0e..d504c5550331 100644 --- a/src/libs/actions/Welcome/index.ts +++ b/src/libs/actions/Welcome/index.ts @@ -4,7 +4,7 @@ import Onyx from 'react-native-onyx'; import * as API from '@libs/API'; import {SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types'; import Log from '@libs/Log'; -import type {OnboardingPurposeType} from '@src/CONST'; +import type {OnboardingCompanySizeType, OnboardingPurposeType} from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type Onboarding from '@src/types/onyx/Onboarding'; import type TryNewDot from '@src/types/onyx/TryNewDot'; @@ -97,6 +97,10 @@ function setOnboardingPurposeSelected(value: OnboardingPurposeType) { Onyx.set(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED, value ?? null); } +function setOnboardingCompanySize(value: OnboardingCompanySizeType) { + Onyx.set(ONYXKEYS.ONBOARDING_COMPANY_SIZE, value); +} + function setOnboardingErrorMessage(value: string) { Onyx.set(ONYXKEYS.ONBOARDING_ERROR_MESSAGE, value ?? null); } @@ -190,4 +194,5 @@ export { setOnboardingPolicyID, completeHybridAppOnboarding, setOnboardingErrorMessage, + setOnboardingCompanySize, }; diff --git a/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx b/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx new file mode 100644 index 000000000000..0530d618d661 --- /dev/null +++ b/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx @@ -0,0 +1,192 @@ +import React, {useMemo, useState} from 'react'; +import {useOnyx} from 'react-native-onyx'; +import Button from '@components/Button'; +import FormHelpMessage from '@components/FormHelpMessage'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import Icon from '@components/Icon'; +import * as Expensicons from '@components/Icon/Expensicons'; +import ScreenWrapper from '@components/ScreenWrapper'; +import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; +import type {ListItem} from '@components/SelectionList/types'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useStyleUtils from '@hooks/useStyleUtils'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@libs/Navigation/Navigation'; +import variables from '@styles/variables'; +import * as Report from '@userActions/Report'; +import * as Welcome from '@userActions/Welcome'; +import * as OnboardingFlow from '@userActions/Welcome/OnboardingFlow'; +import CONST from '@src/CONST'; +import type {OnboardingAccountingType} from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {} from '@src/types/onyx/Bank'; +import type {BaseOnboardingAccountingProps} from './types'; + +type OnboardingListItem = ListItem & { + keyForList: OnboardingAccountingType; +}; + +function BaseOnboardingAccounting({shouldUseNativeStyles, route}: BaseOnboardingAccountingProps) { + const styles = useThemeStyles(); + const theme = useTheme(); + const StyleUtils = useStyleUtils(); + const {translate} = useLocalize(); + const {onboardingIsMediumOrLargerScreenWidth, shouldUseNarrowLayout} = useResponsiveLayout(); + const [onboardingPurposeSelected] = useOnyx(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED); + const [onboardingPolicyID] = useOnyx(ONYXKEYS.ONBOARDING_POLICY_ID); + const [onboardingAdminsChatReportID] = useOnyx(ONYXKEYS.ONBOARDING_ADMINS_CHAT_REPORT_ID); + const [onboardingCompanySize] = useOnyx(ONYXKEYS.ONBOARDING_COMPANY_SIZE); + + const [userReportedIntegration, setUserReportedIntegration] = useState(undefined); + const [error, setError] = useState(''); + + const accountingOptions: OnboardingListItem[] = useMemo(() => { + const policyAccountingOptions = Object.values(CONST.POLICY.CONNECTIONS.NAME) + .map((connectionName): OnboardingListItem | undefined => { + let text; + let accountingIcon; + switch (connectionName) { + case CONST.POLICY.CONNECTIONS.NAME.QBO: { + text = translate('workspace.accounting.qbo'); + accountingIcon = Expensicons.QBOCircle; + break; + } + case CONST.POLICY.CONNECTIONS.NAME.XERO: { + text = translate('workspace.accounting.xero'); + accountingIcon = Expensicons.XeroCircle; + break; + } + case CONST.POLICY.CONNECTIONS.NAME.NETSUITE: { + text = translate('workspace.accounting.netsuite'); + accountingIcon = Expensicons.NetSuiteSquare; + break; + } + case CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT: { + text = translate('workspace.accounting.intacct'); + accountingIcon = Expensicons.IntacctSquare; + break; + } + default: { + return; + } + } + return { + keyForList: connectionName, + text, + leftElement: ( + + ), + isSelected: userReportedIntegration === connectionName, + }; + }) + .filter((item): item is OnboardingListItem => !!item); + const noneAccountingOption: OnboardingListItem = { + keyForList: null, + text: translate('onboarding.accounting.noneOfAbove'), + leftElement: ( + + ), + isSelected: userReportedIntegration === null, + }; + return [...policyAccountingOptions, noneAccountingOption]; + }, [StyleUtils, styles.mr3, styles.onboardingSmallIcon, theme.success, translate, userReportedIntegration]); + + const footerContent = ( + <> + {!!error && ( + + )} +