Skip to content

Commit

Permalink
add tasks for new user first workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
ishpaul777 committed Jan 9, 2025
1 parent 5fb81d6 commit ba863a3
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 75 deletions.
125 changes: 84 additions & 41 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const selectableOnboardingChoices = {
const backendOnboardingChoices = {
ADMIN: 'newDotAdmin',
SUBMIT: 'newDotSubmit',
TRACK_WORKSPACE: 'newDotTrackWorkspace',
} as const;

const onboardingChoices = {
Expand All @@ -98,6 +99,50 @@ const selfGuidedTourTask: OnboardingTask = {
description: ({navatticURL}) => `[Take a self-guided product tour](${navatticURL}) and learn about everything Expensify has to offer.`,
};

const createWorkspaceTask: OnboardingTask = {
type: 'createWorkspace',
autoCompleted: true,
title: 'Create a workspace',
description:
'*Create a workspace* to track expenses, scan receipts, chat, and more.\n' +
'\n' +
'Here’s how to create a workspace:\n' +
'\n' +
'1. Click the settings tab.\n' +
'2. Click *Workspaces* > *New workspace*.\n' +
'\n' +
'*Your new workspace is ready! It’ll keep all of your spend (and chats) in one place.*',
};

const meetGuideTask: OnboardingTask = {
type: 'meetGuide',
autoCompleted: false,
title: 'Meet your setup specialist',
description: ({adminsRoomLink}) =>
`Meet your setup specialist, who can answer any questions as you get started with Expensify. Yes, a real human!\n` +
'\n' +
`Chat with the specialist in your [#admins room](${adminsRoomLink}).`,
};

const setupCategoriesTask: OnboardingTask = {
type: 'setupCategories',
autoCompleted: false,
title: 'Set up categories',
description: ({workspaceCategoriesLink}) =>
'*Set up categories* so your team can code expenses for easy reporting.\n' +
'\n' +
'Here’s how to set up categories:\n' +
'\n' +
'1. Click the settings tab.\n' +
'2. Go to *Workspaces*.\n' +
'3. Select your workspace.\n' +
'4. Click *Categories*.\n' +
"5. Disable any categories you don't need.\n" +
'6. Add your own categories in the top right.\n' +
'\n' +
`[Take me to workspace category settings](${workspaceCategoriesLink}).`,
};

const onboardingEmployerOrSubmitMessage: OnboardingMessage = {
message: 'Getting paid back is as easy as sending a message. Let’s go over the basics.',
video: {
Expand Down Expand Up @@ -5014,30 +5059,9 @@ const CONST = {
height: 960,
},
tasks: [
{
type: 'createWorkspace',
autoCompleted: true,
title: 'Create a workspace',
description:
'*Create a workspace* to track expenses, scan receipts, chat, and more.\n' +
'\n' +
'Here’s how to create a workspace:\n' +
'\n' +
'1. Click the settings tab.\n' +
'2. Click *Workspaces* > *New workspace*.\n' +
'\n' +
'*Your new workspace is ready! It’ll keep all of your spend (and chats) in one place.*',
},
createWorkspaceTask,
selfGuidedTourTask,
{
type: 'meetGuide',
autoCompleted: false,
title: 'Meet your setup specialist',
description: ({adminsRoomLink}) =>
`Meet your setup specialist, who can answer any questions as you get started with Expensify. Yes, a real human!\n` +
'\n' +
`Chat with the specialist in your [#admins room](${adminsRoomLink}).`,
},
meetGuideTask,
{
type: 'setupCategoriesAndTags',
autoCompleted: false,
Expand All @@ -5047,24 +5071,7 @@ const CONST = {
'\n' +
`Import them automatically by [connecting your accounting software](${workspaceAccountingLink}), or set them up manually in your [workspace settings](${workspaceSettingsLink}).`,
},
{
type: 'setupCategories',
autoCompleted: false,
title: 'Set up categories',
description: ({workspaceCategoriesLink}) =>
'*Set up categories* so your team can code expenses for easy reporting.\n' +
'\n' +
'Here’s how to set up categories:\n' +
'\n' +
'1. Click the settings tab.\n' +
'2. Go to *Workspaces*.\n' +
'3. Select your workspace.\n' +
'4. Click *Categories*.\n' +
"5. Disable any categories you don't need.\n" +
'6. Add your own categories in the top right.\n' +
'\n' +
`[Take me to workspace category settings](${workspaceCategoriesLink}).`,
},
setupCategoriesTask,
{
type: 'setupTags',
autoCompleted: false,
Expand Down Expand Up @@ -5141,6 +5148,42 @@ const CONST = {
},
],
},
[onboardingChoices.TRACK_WORKSPACE]: {
message: 'Here are some important tasks to help get your workspace set up.',
video: {
url: `${CLOUDFRONT_URL}/videos/guided-setup-manage-team-v2.mp4`,
thumbnailUrl: `${CLOUDFRONT_URL}/images/guided-setup-manage-team.jpg`,
duration: 55,
width: 1280,
height: 960,
},
tasks: [
createWorkspaceTask,
meetGuideTask,
setupCategoriesTask,
{
type: 'inviteAccountant',
autoCompleted: false,
title: 'Invite your accountant',
description: ({workspaceMembersLink}) =>
'*Invite your accountant to Expensify and share your expenses with them to make tax time easier.\n' +
'\n' +
'Here’s how to invite your accountant:\n' +
'\n' +
'1. Click your profile picture.\n' +
'2. Go to *Workspaces*.\n' +
'3. Select your workspace.\n' +
'4. Click *Members* > Invite member.\n' +
'5. Enter their email or phone number.\n' +
'6. Add an invite message if you’d like.\n' +
'7. You’ll be set as the expense approver. You can change this to any admin once you invite your team.\n' +
'\n' +
'That’s it, happy expensing! 😄\n' +
'\n' +
`[View your workspace members](${workspaceMembersLink}).`,
},
],
},
[onboardingChoices.PERSONAL_SPEND]: onboardingPersonalSpendMessage,
[onboardingChoices.CHAT_SPLIT]: {
message: 'Splitting bills with friends is as easy as sending a message. Here’s how.',
Expand Down
1 change: 1 addition & 0 deletions src/libs/API/parameters/CreateWorkspaceParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type CreateWorkspaceParams = {
customUnitID: string;
customUnitRateID: string;
engagementChoice?: string;
guidedSetupData?: string;
};

export default CreateWorkspaceParams;
6 changes: 5 additions & 1 deletion src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2642,7 +2642,7 @@ function getTrackExpenseInformation(
let createdWorkspaceParams: CreateWorkspaceParams | undefined;

if (isDraftReport) {
const workspaceData = Policy.buildPolicyData(undefined, policy?.makeMeAdmin, policy?.name, policy?.id, chatReport?.reportID);
const workspaceData = Policy.buildPolicyData(undefined, policy?.makeMeAdmin, policy?.name, policy?.id, chatReport?.reportID, CONST.ONBOARDING_CHOICES.TRACK_WORKSPACE);
createdWorkspaceParams = workspaceData.params;
optimisticData.push(...workspaceData.optimisticData);
successData.push(...workspaceData.successData);
Expand Down Expand Up @@ -3821,6 +3821,8 @@ function categorizeTrackedExpense(trackedExpenseParams: CategorizeTrackedExpense
policyExpenseCreatedReportActionID: createdWorkspaceParams?.expenseCreatedReportActionID,
adminsChatReportID: createdWorkspaceParams?.adminsChatReportID,
adminsCreatedReportActionID: createdWorkspaceParams?.adminsCreatedReportActionID,
engagementChoice: createdWorkspaceParams?.engagementChoice,
guidedSetupData: createdWorkspaceParams?.guidedSetupData,
};

API.write(WRITE_COMMANDS.CATEGORIZE_TRACKED_EXPENSE, parameters, {optimisticData, successData, failureData});
Expand Down Expand Up @@ -3902,6 +3904,8 @@ function shareTrackedExpense(
policyExpenseCreatedReportActionID: createdWorkspaceParams?.expenseCreatedReportActionID,
adminsChatReportID: createdWorkspaceParams?.adminsChatReportID,
adminsCreatedReportActionID: createdWorkspaceParams?.adminsCreatedReportActionID,
engagementChoice: createdWorkspaceParams?.engagementChoice,
guidedSetupData: createdWorkspaceParams?.guidedSetupData,
};

API.write(WRITE_COMMANDS.SHARE_TRACKED_EXPENSE, parameters, {optimisticData, successData, failureData});
Expand Down
36 changes: 33 additions & 3 deletions src/libs/actions/Policy/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {NullishDeep, OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-nat
import Onyx from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import type {ReportExportType} from '@components/ButtonWithDropdownMenu/types';
import {prepareOnboardingOnyxData} from '@libs/actions/Report';
import * as API from '@libs/API';
import type {
AddBillingCardAndRequestWorkspaceOwnerChangeParams,
Expand Down Expand Up @@ -78,9 +79,11 @@ import * as TransactionUtils from '@libs/TransactionUtils';
import type {PolicySelector} from '@pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover';
import * as PaymentMethods from '@userActions/PaymentMethods';
import * as PersistedRequests from '@userActions/PersistedRequests';
import type {OnboardingPurpose} from '@src/CONST';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {
IntroSelected,
InvitedEmailsToAccountIDs,
PersonalDetailsList,
Policy,
Expand Down Expand Up @@ -1676,6 +1679,12 @@ function createDraftInitialWorkspace(policyOwnerEmail = '', policyName = '', pol
Onyx.update(optimisticData);
}

let introSelected: OnyxEntry<IntroSelected>;
Onyx.connect({
key: ONYXKEYS.NVP_INTRO_SELECTED,
callback: (value) => (introSelected = value),
});

/**
* Generates onyx data for creating a new workspace
*
Expand All @@ -1685,7 +1694,7 @@ function createDraftInitialWorkspace(policyOwnerEmail = '', policyName = '', pol
* @param [policyID] custom policy id we will use for created workspace
* @param [expenseReportId] the reportID of the expense report that is being used to create the workspace
*/
function buildPolicyData(policyOwnerEmail = '', makeMeAdmin = false, policyName = '', policyID = generatePolicyID(), expenseReportId?: string, engagementChoice?: string) {
function buildPolicyData(policyOwnerEmail = '', makeMeAdmin = false, policyName = '', policyID = generatePolicyID(), expenseReportId?: string, engagementChoice?: OnboardingPurpose) {
const workspaceName = policyName || generateDefaultWorkspaceName(policyOwnerEmail);

const {customUnits, customUnitID, customUnitRateID, outputCurrency} = buildOptimisticDistanceRateCustomUnits();
Expand Down Expand Up @@ -1947,9 +1956,24 @@ function buildPolicyData(policyOwnerEmail = '', makeMeAdmin = false, policyName
expenseCreatedReportActionID,
customUnitID,
customUnitRateID,
engagementChoice,
};

if (!introSelected?.createWorkspace && engagementChoice) {
const {
guidedSetupData,
optimisticData: taskOptimisticData,
successData: taskSuccessData,
failureData: taskFailureData,
} = prepareOnboardingOnyxData(engagementChoice, CONST.ONBOARDING_MESSAGES[engagementChoice], expenseChatReportID, policyID);

params.guidedSetupData = JSON.stringify(guidedSetupData);
params.engagementChoice = engagementChoice;

optimisticData.push(...taskOptimisticData);
successData.push(...taskSuccessData);
failureData.push(...taskFailureData);
}

return {successData, optimisticData, failureData, params};
}

Expand All @@ -1962,7 +1986,13 @@ function buildPolicyData(policyOwnerEmail = '', makeMeAdmin = false, policyName
* @param [policyID] custom policy id we will use for created workspace
* @param [engagementChoice] Purpose of using application selected by user in guided setup flow
*/
function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName = '', policyID = generatePolicyID(), engagementChoice = ''): CreateWorkspaceParams {
function createWorkspace(
policyOwnerEmail = '',
makeMeAdmin = false,
policyName = '',
policyID = generatePolicyID(),
engagementChoice = CONST.ONBOARDING_CHOICES.MANAGE_TEAM,
): CreateWorkspaceParams {
const {optimisticData, failureData, successData, params} = buildPolicyData(policyOwnerEmail, makeMeAdmin, policyName, policyID, undefined, engagementChoice);
API.write(WRITE_COMMANDS.CREATE_WORKSPACE, params, {optimisticData, successData, failureData});

Expand Down
Loading

0 comments on commit ba863a3

Please sign in to comment.