diff --git a/.eslintrc.js b/.eslintrc.js index b76782af60f4..b71338d0c1a5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,6 +14,11 @@ const restrictedImportPaths = [ importNames: ['TouchableOpacity', 'TouchableWithoutFeedback', 'TouchableNativeFeedback', 'TouchableHighlight'], message: "Please use 'PressableWithFeedback' and/or 'PressableWithoutFeedback' from 'src/components/Pressable' instead.", }, + { + name: 'react-native-safe-area-context', + importNames: ['useSafeAreaInsets', 'SafeAreaConsumer', 'SafeAreaInsetsContext'], + message: "Please use 'useSafeAreaInsets' from 'src/hooks/useSafeAreaInset' and/or 'SafeAreaConsumer' from 'src/components/SafeAreaConsumer' instead.", + }, ]; const restrictedImportPatterns = [ diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 351a11506d68..4f7d1c71553a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -18,8 +18,8 @@ $ https://github.com/Expensify/App/issues/ Do NOT only link the issue number like this: $ # ---> -$ -PROPOSAL: +$ +PROPOSAL: ### Tests @@ -98,7 +98,7 @@ This is a checklist for PR authors. Please make sure to complete all tasks and c - [ ] The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory - [ ] If a new CSS style is added I verified that: - [ ] A similar style doesn't already exist - - [ ] The style can't be created with an existing [StyleUtils](https://github.com/Expensify/App/blob/main/src/styles/StyleUtils.js) function (i.e. `StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)`) + - [ ] The style can't be created with an existing [StyleUtils](https://github.com/Expensify/App/blob/main/src/styles/utils/index.ts) function (i.e. `StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)`) - [ ] If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic. - [ ] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like `Avatar` is modified, I verified that `Avatar` is working as expected in all cases) - [ ] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected. diff --git a/.github/workflows/platformDeploy.yml b/.github/workflows/platformDeploy.yml index bf27006e34a2..8ccc0a7f6056 100644 --- a/.github/workflows/platformDeploy.yml +++ b/.github/workflows/platformDeploy.yml @@ -347,6 +347,9 @@ jobs: if: ${{ failure() }} needs: [android, desktop, iOS, web] steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Post Slack message on failure uses: ./.github/actions/composite/announceFailedWorkflowInSlack with: diff --git a/.imgbotconfig b/.imgbotconfig index ff5c3345cc4d..45cdf03ec36e 100644 --- a/.imgbotconfig +++ b/.imgbotconfig @@ -1,6 +1,7 @@ { "ignoredFiles": [ - "assets/images/empty-state_background-fade.png" // Caused an issue with colour gradients, https://github.com/Expensify/App/issues/30499 + "assets/images/themeDependent/empty-state_background-fade-dark.png", // Caused an issue with colour gradients, https://github.com/Expensify/App/issues/30499 + "assets/images/themeDependent/empty-state_background-fade-light.png" ], "aggressiveCompression": "false" } diff --git a/.storybook/public/index.css b/.storybook/public/index.css index 8ace4b240684..2d2411c083c1 100644 --- a/.storybook/public/index.css +++ b/.storybook/public/index.css @@ -24,5 +24,5 @@ a.sidebar-item[data-selected="true"], a.sidebar-item[data-selected="true"]:focus } .sidebar-container { - background: #07271f; + background: #072419; } diff --git a/.storybook/theme.js b/.storybook/theme.js index 96631764726f..67898fb00943 100644 --- a/.storybook/theme.js +++ b/.storybook/theme.js @@ -7,17 +7,17 @@ export default create({ fontBase: 'ExpensifyNeue-Regular', fontCode: 'monospace', base: 'dark', - appBg: colors.darkHighlightBackground, - colorPrimary: colors.darkDefaultButton, + appBg: colors.productDark200, + colorPrimary: colors.productDark400, colorSecondary: colors.green, - appContentBg: colors.darkAppBackground, - textColor: colors.darkPrimaryText, - barTextColor: colors.darkPrimaryText, + appContentBg: colors.productDark100, + textColor: colors.productDark900, + barTextColor: colors.productDark900, barSelectedColor: colors.green, - barBg: colors.darkAppBackground, - appBorderColor: colors.darkBorders, - inputBg: colors.darkHighlightBackground, - inputBorder: colors.darkBorders, + barBg: colors.productDark100, + appBorderColor: colors.productDark400, + inputBg: colors.productDark200, + inputBorder: colors.productDark400, appBorderRadius: 8, inputBorderRadius: 8, }); diff --git a/__mocks__/@ua/react-native-airship.js b/__mocks__/@ua/react-native-airship.js index 1672c064f9be..29be662e96a1 100644 --- a/__mocks__/@ua/react-native-airship.js +++ b/__mocks__/@ua/react-native-airship.js @@ -31,7 +31,7 @@ const Airship = { }, contact: { identify: jest.fn(), - getNamedUserId: jest.fn(), + getNamedUserId: () => Promise.resolve(undefined), reset: jest.fn(), }, }; diff --git a/android/app/build.gradle b/android/app/build.gradle index e015ebeb4d27..25bb327eb97a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -91,8 +91,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001040503 - versionName "1.4.5-3" + versionCode 1001041000 + versionName "1.4.10-0" } flavorDimensions "default" diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index aa0e8136957f..a040598e982d 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -11,7 +11,6 @@ @drawable/rn_edit_text_material @style/AppTheme.Popup @style/TextViewSpinnerDropDownItem - @style/DatePickerDialogTheme @style/AlertDialogTheme @@ -28,18 +27,6 @@ @font/expneuebold - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/assets/images/home-background--mobile.svg b/assets/images/home-background--mobile.svg index 7c4d4d8289b7..d2fa08475c9d 100644 --- a/assets/images/home-background--mobile.svg +++ b/assets/images/home-background--mobile.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/images/home-fade-gradient--mobile.svg b/assets/images/home-fade-gradient--mobile.svg index 0b24b678a2e6..ad150f3c870c 100644 --- a/assets/images/home-fade-gradient--mobile.svg +++ b/assets/images/home-fade-gradient--mobile.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/images/home-fade-gradient.svg b/assets/images/home-fade-gradient.svg index bfe04d545364..c446d7b46a42 100644 --- a/assets/images/home-fade-gradient.svg +++ b/assets/images/home-fade-gradient.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/assets/images/themeDependent/empty-state_background-fade-dark.png b/assets/images/themeDependent/empty-state_background-fade-dark.png new file mode 100644 index 000000000000..59951ef707fb Binary files /dev/null and b/assets/images/themeDependent/empty-state_background-fade-dark.png differ diff --git a/assets/images/themeDependent/empty-state_background-fade-light.png b/assets/images/themeDependent/empty-state_background-fade-light.png new file mode 100644 index 000000000000..200996057b47 Binary files /dev/null and b/assets/images/themeDependent/empty-state_background-fade-light.png differ diff --git a/assets/images/themeDependent/example-check-image-dark-en.png b/assets/images/themeDependent/example-check-image-dark-en.png new file mode 100644 index 000000000000..6b8e84a0faa2 Binary files /dev/null and b/assets/images/themeDependent/example-check-image-dark-en.png differ diff --git a/assets/images/themeDependent/example-check-image-dark-es.png b/assets/images/themeDependent/example-check-image-dark-es.png new file mode 100644 index 000000000000..446678e401b6 Binary files /dev/null and b/assets/images/themeDependent/example-check-image-dark-es.png differ diff --git a/assets/images/themeDependent/example-check-image-light-en.png b/assets/images/themeDependent/example-check-image-light-en.png new file mode 100644 index 000000000000..d7b5f035c625 Binary files /dev/null and b/assets/images/themeDependent/example-check-image-light-en.png differ diff --git a/assets/images/themeDependent/example-check-image-light-es.png b/assets/images/themeDependent/example-check-image-light-es.png new file mode 100644 index 000000000000..2183b522a35b Binary files /dev/null and b/assets/images/themeDependent/example-check-image-light-es.png differ diff --git a/config/webpack/webpack.common.js b/config/webpack/webpack.common.js index 22d035368c42..008b4f45911f 100644 --- a/config/webpack/webpack.common.js +++ b/config/webpack/webpack.common.js @@ -66,7 +66,8 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ template: 'web/index.html', filename: 'index.html', splashLogo: fs.readFileSync(path.resolve(__dirname, `../../assets/images/new-expensify${mapEnvToLogoSuffix(envFile)}.svg`), 'utf-8'), - usePolyfillIO: platform === 'web', + isWeb: platform === 'web', + isProduction: envFile === '.env.production', isStaging: envFile === '.env.staging', }), new FontPreloadPlugin({ @@ -210,7 +211,21 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ // This is also why we have to use .website.js for our own web-specific files... // Because desktop also relies on "web-specific" module implementations // This also skips packing web only dependencies to desktop and vice versa - extensions: ['.web.js', platform === 'web' ? '.website.js' : '.desktop.js', '.js', '.jsx', '.web.ts', platform === 'web' ? '.website.ts' : '.desktop.ts', '.ts', '.web.tsx', '.tsx'], + extensions: [ + '.web.js', + ...(platform === 'desktop' ? ['.desktop.js'] : []), + '.website.js', + '.js', + '.jsx', + '.web.ts', + ...(platform === 'desktop' ? ['.desktop.ts'] : []), + '.website.ts', + ...(platform === 'desktop' ? ['.desktop.tsx'] : []), + '.website.tsx', + '.ts', + '.web.tsx', + '.tsx', + ], fallback: { 'process/browser': require.resolve('process/browser'), }, diff --git a/contributingGuides/NAVIGATION.md b/contributingGuides/NAVIGATION.md index 32d3919efbe4..8467b97c29fb 100644 --- a/contributingGuides/NAVIGATION.md +++ b/contributingGuides/NAVIGATION.md @@ -1,6 +1,6 @@ # Overview -The navigation in the App consists of a top-level Stack Navigator (called `RootStack`) with each of its `Screen` components handling different high-level flow. All those flows can be seen in `AuthScreens.js` file. +The navigation in the App consists of a top-level Stack Navigator (called `RootStack`) with each of its `Screen` components handling different high-level flow. All those flows can be seen in `AuthScreens.tsx` file. ## Terminology @@ -20,11 +20,11 @@ Navigation Actions - User actions correspond to resulting navigation actions tha ## Adding RHP flows -Most of the time, if you want to add some of the flows concerning one of your reports, e.g. `Money Request` from a user, you will most probably use `RightModalNavigator.js` and `ModalStackNavigators.js` file: +Most of the time, if you want to add some of the flows concerning one of your reports, e.g. `Money Request` from a user, you will most probably use `RightModalNavigator.tsx` and `ModalStackNavigators.tsx` file: -- Since each of those flows is kind of a modal stack, if you want to add a page to the existing flow, you should just add a page to the correct stack in `ModalStackNavigators.js`. +- Since each of those flows is kind of a modal stack, if you want to add a page to the existing flow, you should just add a page to the correct stack in `ModalStackNavigators.tsx`. -- If you want to create new flow, add a `Screen` in `RightModalNavigator.js` and make new modal in `ModalStackNavigators.js` with chosen pages. +- If you want to create new flow, add a `Screen` in `RightModalNavigator.tsx` and make new modal in `ModalStackNavigators.tsx` with chosen pages. When creating RHP flows, you have to remember a couple things: @@ -196,4 +196,4 @@ The action for the first step created with `getMinimalAction` looks like this: ``` ### Deeplinking -There is no minimal action for deeplinking directly to the `Profile` screen. But because the `Settings_root` is not on the stack, pressing UP will reset the params for navigators to the correct ones. \ No newline at end of file +There is no minimal action for deeplinking directly to the `Profile` screen. But because the `Settings_root` is not on the stack, pressing UP will reset the params for navigators to the correct ones. diff --git a/contributingGuides/REVIEWER_CHECKLIST.md b/contributingGuides/REVIEWER_CHECKLIST.md index 16c8f88927b1..b7cbd87dc4b9 100644 --- a/contributingGuides/REVIEWER_CHECKLIST.md +++ b/contributingGuides/REVIEWER_CHECKLIST.md @@ -46,7 +46,7 @@ - [ ] The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory - [ ] If a new CSS style is added I verified that: - [ ] A similar style doesn't already exist - - [ ] The style can't be created with an existing [StyleUtils](https://github.com/Expensify/App/blob/main/src/styles/StyleUtils.js) function (i.e. `StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG`) + - [ ] The style can't be created with an existing [StyleUtils](https://github.com/Expensify/App/blob/main/src/utils/index.ts) function (i.e. `StyleUtils.getBackgroundAndBorderStyle(theme.componentBG`) - [ ] If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic. - [ ] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like `Avatar` is modified, I verified that `Avatar` is working as expected in all cases) - [ ] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected. diff --git a/docs/_data/_routes.yml b/docs/_data/_routes.yml index efdcf41b63d5..e320b690c226 100644 --- a/docs/_data/_routes.yml +++ b/docs/_data/_routes.yml @@ -112,21 +112,11 @@ platforms: title: Expensify Card icon: /assets/images/hand-card.svg description: Explore how the Expensify Card combines convenience and security to enhance everyday business transactions. Discover how to apply for, oversee, and maximize your card perks here. - - - href: expensify-partner-program - title: Expensify Partner Program - icon: /assets/images/handshake.svg - description: Discover how to get the most out of Expensify as an ExpensifyApproved! accountant partner. Learn how to set up your clients, receive CPE credits, and take advantage of your partner discount. - href: get-paid-back title: Get Paid Back icon: /assets/images/money-into-wallet.svg description: Whether you submit an expense report or an invoice, find out here how to ensure a smooth and timely payback process every time. - - - href: send-payments - title: Send Payments - icon: /assets/images/money-wings.svg - description: Uncover step-by-step guidance on sending direct reimbursements to employees, paying an invoice to a vendor, and utilizing third-party payment options. - href: workspace-and-domain-settings title: Workspace & Domain Settings diff --git a/docs/_sass/_colors.scss b/docs/_sass/_colors.scss index b34a7d13b7f0..5556c43d87f6 100644 --- a/docs/_sass/_colors.scss +++ b/docs/_sass/_colors.scss @@ -2,8 +2,8 @@ $color-green400: #03D47C; $color-green-icons: #8B9C8F; $color-green-borders: #1A3D32; $color-button-background: #1A3D32; -$color-button-hovered: #2C6755; -$color-green-highlightBG: #07271F; +$color-button-hovered: #2A604F; +$color-green-highlightBG: #072419; $color-green-highlightBG-hover: #06231c; $color-green-appBG: #061B09; $color-green-hover: #00a862; diff --git a/docs/articles/expensify-classic/account-settings/Merge-Accounts.md b/docs/articles/expensify-classic/account-settings/Merge-Accounts.md index 7fc355b30bd9..abb218c74118 100644 --- a/docs/articles/expensify-classic/account-settings/Merge-Accounts.md +++ b/docs/articles/expensify-classic/account-settings/Merge-Accounts.md @@ -5,29 +5,32 @@ description: How to merge two Expensify accounts and why this is useful. # Overview -Merging accounts allows you to combine two accounts. When you combine two accounts, all receipts, expenses, expense reports, invoices, bills, imported cards, secondary logins, co-pilots, and group policy settings will be combined into one account. +Merging accounts allows you to combine two accounts. When you combine two accounts, all receipts, expenses, expense reports, invoices, bills, imported cards, secondary logins, co-pilots, and group workspace settings will be combined into one account. This can be useful if you start off with an account of your own but your organization creates a separate account for you. You can then track both personal and business expenses via one account. # How to merge accounts Merging two accounts together is fairly straightforward. Let’s go over how to do that below: 1. Navigate to [expensify.com](https://www.expensify.com) 2. Log into the account you want to set as the Primary account -3. Navigate to Settings > Account > Account Details -4. Scroll down to the Merge Accounts section and fill in the fields. Once you click Merge, a magic code link will be sent to you via email and you'll be prompted to enter the magic code -5. Copy the magic code, switch back to the expensify.com page, and paste the code into the required field +3. Navigate to **Settings > Account > Account Details** +4. Scroll down to Merge Accounts and fill in the fields 6. Click Merge Accounts +7. Once you click Merge, a magic code is sent to you via email +8. Paste the code into the required field If you have any questions about this process, feel free to reach out to Concierge for some assistance! # FAQ ## Can you merge accounts from the mobile app? No, accounts can only be merged from the full website at expensify.com. ## Can I administratively merge two accounts together? -No, only the account holder (user) can perform account merging. +No, only the account holder (member) can perform account merging. ## Is merging accounts reversible? No, merging accounts is not reversible. It is a permanent action that cannot be undone. +## I have open expenses in the account I'm merging from. Will those expenses merge into the new account? +All expenses must be reported and submitted for them to merge into the new account. Any open expenses will not merge. ## Are there any restrictions on account merging? Yes! Please see below: -* If your email address belongs to a verified domain (verified in Expensify), you must start the process from the email account under the verified domain. You cannot merge a verified company email account into a personal account. -* If you have two accounts with two different verified domains, you cannot merge them together. -## What happens to my “personal” Individual policy when merging accounts? -The old “personal” Individual policy will be deleted. If you plan to submit reports under a different policy in the future, ensure that any reports on the Individual policy in the old account are marked as Open before merging the accounts. You can typically do this by selecting “Undo Submit” on any submitted reports. +- If your email address belongs to a verified domain (verified in Expensify), you must start the process from the email account under the verified domain. You cannot merge a verified company email account into a personal account. +- If you have two accounts with two different verified domains, you cannot merge them together. +## What happens to my “personal” Individual workspace when merging accounts? +The old “personal” Individual workspace is deleted. If you plan to submit reports under a different workspace in the future, ensure that any reports on the Individual workspace in the old account are marked as Open before merging the accounts. You can typically do this by selecting “Undo Submit” on any submitted reports. diff --git a/docs/articles/expensify-classic/account-settings/Notification-Troubleshooting.md b/docs/articles/expensify-classic/account-settings/Notification-Troubleshooting.md new file mode 100644 index 000000000000..22df0dc7f6ca --- /dev/null +++ b/docs/articles/expensify-classic/account-settings/Notification-Troubleshooting.md @@ -0,0 +1,75 @@ +--- +title: Notification Troubleshooting +description: This article is about how to troubleshoot notifications from Expensify. +--- + +# Overview +Sometimes, members may have trouble receiving important email notifications from Expensify, such as Expensify Magic Code emails, account validation emails, secondary login validations, integration emails, or report action notifications (rejections, approvals, etc.). + +# Here's how to troubleshoot missing Expensify notifications: + +1. **No error message, but the email is never received** +The email might be delayed; give it 30-60 minutes to arrive in your inbox. +Check **Email Preferences** on the web via **Settings > Your Account > Preferences**In the **Contact Preferences** section. Ensure that the relevant boxes are checked for the email type you're missing. Check your email spam and trash folders, as Expensify messages might end up there inadvertently. +Check to make sure you haven't unintentionally blocked Expensify emails and whitelist [expensify.com](https://community.expensify.com/home/leaving?allowTrusted=1&target=http%3A%2F%2Fexpensify.com%2F), mg.expensify.com, and [amazonSES.com](https://community.expensify.com/home/leaving?allowTrusted=1&target=http%3A%2F%2Famazonses.com%2F) with your email provider. + +2. **A "We're having trouble emailing you" banner at the top of your screen** +Verify that your email address in your account settings is correct and is a real deliverable email address. +Re-send Verification Email: Look for an option to re-send a verification email, usually provided when this banner appears. + +![ExpensifyHelp_EmailError]({{site.url}}/assets/images/ExpensifyHelp_EmailError.png){:width="100%"} + +# Deep Dive + +**For Private Domains**: + +If your organization uses a private domain, consult your IT department or IT person to ensure that the following domains are whitelisted to receive our emails: expensify.com, mg.expensify.com, and amazonSES.com. These domains are the sources of various notification emails, so make sure they aren't being blocked. + +**For Public Domains (e.g., Gmail, Yahoo, Hotmail)**: + +To whitelist our emails on public email services: + +1. Check your Spam Folder: Search for messages from expensify.com in your Spam folder, open them, and click "Not Spam" at the top of the message. +2. Create a Filter: Set up a filter that identifies the entire expensify.com domain and directs all incoming messages to your inbox, preventing them from going to Spam. +3. Add Specific Contacts: While optional, adding specific email addresses from Expensify as contacts can further prevent emails from going to Spam. + +Please note that even if you receive emails from our Concierge support communication, ensure that both expensify.com and mg.expensify.com are whitelisted as they use different servers. + +**Email Server Blocking**: +Your email server may be blocking our emails due to spam filters or other services. Check with your IT department to investigate and resolve any server-level email blocking issues. + +**Mimecast**: +If your company uses Mimecast, a service that can affect email deliverability, check with your IT department. If Mimecast is in use, reach out to us at concierge@expensify.com through a new email, as this should ensure delivery to your inbox. Mimecast should eventually recognize the Expensify domain, preventing future filtering. + +**For Outlook Users**: +For Outlook users specifically: + +1. Click the gear icon in Outlook and select "View all Outlook settings." +2. Choose "Mail" from the settings menu. +3. Under the "Junk email" submenu, click "Add" under "Safe senders and domains." +4. Enter the email address you want to whitelist. +5. Click "Save." + +When you click the "Settings" link in the banner in Expensify, you'll be directed to your account settings page, where you may encounter a few different scenarios: + +- "Temporarily Suspended Emails": If the message mentions "temporarily suspended emails to," follow the steps provided in the yellow box. This situation typically occurs when we can't find a valid inbox to send our emails to. Possible reasons include: + - A misspelled email address during account creation. + - Use of a distribution list email (acting as an "alias" email) without a linked inbox. + - An auto-responder that has been responding to our emails for an extended period. +- To resolve this issue, confirm that the email address is indeed associated with an active inbox. Then, click the link that says "here," and your email should be unblocked shortly. +- SMTP Error (Gray Box): In some cases, you might encounter a gray box with an SMTP error message. This error can vary, but it typically looks something like this: + +![ExpensifyHelp_SMTPError]({{site.url}}/assets/images/ExpensifyHelp_SMTPError.png){:width="100%"} + +**These look a bit cryptic, yes, but hang in there!** + +The error messages you see are the raw message text received from your email provider's server to Amazon. These messages can vary in text, but the best course of action is to follow the link provided (by copying and pasting) in the text for the next steps. + +**Scenario 1**: If the message in the gray box includes "mimecast.com": It means that our emails are being blocked by the server. In this case, you should contact your IT person or team to address the issue. + +**Scenario 2**: If the message in the gray box mentions "blacklist at org/.com/.net," or resembles the screenshot provided, it indicates that your IT team has configured your email to use a third-party email reputation or blacklisting service. Here's what you need to know: +- All our emails are SPF and DKIM-signed, meaning they are cryptographically signed as coming from us and are not spam. +- The problem arises because we send mail from a cloud-based service. This means that the sender's IP serves multiple vendors, including Expensify. If one of those vendors is marked as spam, it can block all messages from that IP, even if they're from different vendors (including us). +- The better approach is for the server to flag spam via DKIM and SPF (rather than solely relying on the sender's IP address), as our messages are correctly signed and encrypted to prevent spoofing. + +To resolve these issues, consider discussing them with your IT team, as they can help implement the necessary changes to ensure you receive our emails without interruption. diff --git a/docs/articles/expensify-classic/bank-accounts-and-credit-cards/company-cards/Connect-Company-Cards.md b/docs/articles/expensify-classic/bank-accounts-and-credit-cards/company-cards/Company-Card-Settings.md similarity index 98% rename from docs/articles/expensify-classic/bank-accounts-and-credit-cards/company-cards/Connect-Company-Cards.md rename to docs/articles/expensify-classic/bank-accounts-and-credit-cards/company-cards/Company-Card-Settings.md index f2ff837d7638..fa5879d85ea8 100644 --- a/docs/articles/expensify-classic/bank-accounts-and-credit-cards/company-cards/Connect-Company-Cards.md +++ b/docs/articles/expensify-classic/bank-accounts-and-credit-cards/company-cards/Company-Card-Settings.md @@ -1,6 +1,6 @@ --- title: Company-Card-Settings.md -description: Company card settings +description: Once you connect your cards, customize the configuration using company card settings. --- # Overview Once you’ve imported your company cards via commercial card feed, direct bank feed, or CSV import, the next step is to configure the cards’ settings. diff --git a/docs/articles/expensify-classic/billing-and-subscriptions/Payment-Card.md b/docs/articles/expensify-classic/billing-and-subscriptions/Payment-Card.md deleted file mode 100644 index 41a1fb96f56f..000000000000 --- a/docs/articles/expensify-classic/billing-and-subscriptions/Payment-Card.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Payment Card -description: Payment Card ---- -## Resource Coming Soon! diff --git a/docs/articles/expensify-classic/expensify-card/Cardholder-Settings-and-Features.md b/docs/articles/expensify-classic/expensify-card/Cardholder-Settings-and-Features.md new file mode 100644 index 000000000000..bc0cb28f42b1 --- /dev/null +++ b/docs/articles/expensify-classic/expensify-card/Cardholder-Settings-and-Features.md @@ -0,0 +1,84 @@ +--- +title: Cardholder Settings and Features +description: Expensify Card Settings for Employees +--- + +# How to use your Expensify Card +Once you receive your card, you can start using it right away. + +First, you'll want to take note of the Smart Limit tied to your card – this is listed in your card settings via **Settings > Account > Credit Card Import**. This limit represents the total amount of unapproved expenses you can have on the card. + +It's crucial to continuously submit your expenses promptly, as that'll ensure they can be approved and restore your full limit. You can always chat with your admin if you need your limit adjusted. + +You can swipe your Expensify Card like you would with any other card. As you make purchases, you'll get instant alerts on your phone letting you know if you need to SmartScan receipts. Any SmartScanned receipts should merge with the card expense automatically. + +If your organization doesn't require itemized receipts, you can rely on eReceipts instead. As long as the expense isn't lodging-related, Expensify will automatically generate an IRS-compliant eReceipt for every transaction. + +You can report and submit Expensify Card expenses just like any other expenses. As they're approved, your Smart Limit will be refreshed accordingly, allowing you to keep making purchases. + +## Enable Notifications +Download the Expensify mobile app and enable push notifications to stay current on your spending activity. Your card is connected to your Expensify account, so each transaction on your card will trigger a push notification. We'll also send you a push notification if we detect potentially fraudulent activity and allow you to confirm your purchase. + +Follow the steps below to enable real-time alerts on your mobile device. + +**If you have an iPhone**: +1. Open the Expensify app and tap the three-bar icon in the upper-left corner +2. Tap **Settings** and enable **Receive realtime alerts** +3. Accept the confirmation dialogue to go to your iPhone's notification settings for Expensify. Turn on Allow Notifications, and choose the notification types you’d like! + +**If you have an Android**: +1. Go to Settings and open 'Apps and Notifications'. +2. Find and open Expensify and enable notifications. +3. Customize your alerts. Depending on your phone model, you may have extra options to customize the types of notifications you receive. + +## Your virtual card +Once you're assigned a limit, you'll be able to use your virtual card immediately. You can view your virtual card details via **Settings > Account > Credit Card Import > Show Details**. Keep in mind that your virtual card and physical card share a limit. + +The virtual Expensify Card includes a card number, expiration date, and security code (CVC). You can use the virtual card for online purchases, in-app transactions, and in-person payments once it's linked to a mobile wallet (Apple Pay or Google Pay). + +## How to access your virtual card details +Here's how to access your virtual card details via the Expensify mobile app: +1. Tap the three-bar icon in the upper-left corner +2. Tap **Settings > Connected Cards** +3. Under **Virtual Card**, tap **Show Details** + +From there, you can view your virtual card's number, CVV, expiration date, and billing address. + +Here's how to access your virtual card details via the Expensify web app: +1. Head to **Settings > Account > Credit Card Import** +2. Under **Virtual Card**, click **Show Details** + +From there, you can view your virtual card's card number, CVV, expiration date, and billing address. + +## How to add your virtual card to a digital wallet (Apple Pay or Google Pay) + +To use the Expensify Card for contactless payment, add it to your digital wallet from the mobile app: +1. Tap the three-bar icon in the upper-left corner +2. Tap **Settings > Connected Cards** +3. Depending on your device, tap **Add to Apple Wallet** or **Add to Gpay** +4. Complete the remaining steps + +## Expensify Card declines +As long as you've enabled 'Receive real-time alerts', you'll get a notification explaining the reason for each decline. You can enable alerts in the mobile app by clicking on the three-bar icon in the upper-left corner > **Settings** > toggle **Receive real-time alerts**. + +Here are some reasons an Expensify Card transaction might be declined: + +- You have an insufficient card limit + - If a transaction exceeds your Expensify Card's available limit, the transaction will be declined. You can see the remaining limit in the mobile app under **Settings > Connected Cards** or in the web app under **Settings > Account > Credit Card Import**. + - Submitting expenses and getting them approved will free up your limit for more spending. + +- Your card isn't active yet or it was disabled by your Domain Admin +- Your card information was entered incorrectly with the merchant. Entering incorrect card information, such as the CVC, ZIP, or expiration date, will also lead to declines. +There was suspicious activity +- If Expensify detects unusual or suspicious activity, we may block transactions as a security measure + - This could happen due to irregular spending patterns, attempted purchases from risky vendors, or multiple rapid transactions. + - Check your Expensify Home page to approve unusual merchants and try again. + - If the spending looks suspicious, we may complete a manual due diligence check, and our team will do this as quickly as possible - your cards will all be locked while this happens. +- The merchant is located in a restricted country + +# FAQ +## Can I use Smart Limits with a free Expensify account? +If you're on the Free plan, you won't have the option to use Smart Limits. Your card limit will simply reset at the end of each calendar month. + +## I still haven't received my Expensify Card. What should I do? +For more information on why your card hasn't arrived, you can check out this resource on [Requesting a Card](https://help.expensify.com/articles/expensify-classic/expensify-card/Request-the-Card#what-if-i-havent-received-my-card-after-multiple-weeks). diff --git a/docs/articles/expensify-classic/expensify-card/Expensify-Card-Perks.md b/docs/articles/expensify-classic/expensify-card/Expensify-Card-Perks.md index 4c216faffc18..8bcc11fbf167 100644 --- a/docs/articles/expensify-classic/expensify-card/Expensify-Card-Perks.md +++ b/docs/articles/expensify-classic/expensify-card/Expensify-Card-Perks.md @@ -5,7 +5,30 @@ description: Get the most out of your Expensify Card with exclusive perks! # Overview -The Expensify Card is packed with perks, both native to our Card program and through exclusive discounts with partnering solutions. Below, we’ll cover all of our exclusive offers in more detail and how to claim discounts with our partners. +The Expensify Card is packed with perks, both native to our Card program and through exclusive discounts with partnering solutions. The Expensify Card’s primary perks include: +- Swipe to Win, where every swipe has a chance to win fun personalized gifts for you and your closest friends and family members +- Unbeatable cash back incentive with each swipe +Below, we’ll cover all of our exclusive offers in more detail and how to claim discounts with our partners. + +# Expensify Card Perks + +## Swipe to Win +Swipe to Win is a new [Expensify Card](https://use.expensify.com/company-credit-card) perk that gives cardholders the chance to send a gift to a friend, family member, or essential worker on the frontlines! + +Winners can choose to _Send a Smile_ or _Send a Laugh_. To start, we’re offering one gift per option: + +- **Send A Smile:** Champagne by Expensify +- **Send a Laugh:** Jenga Set + +**How to Participate** +It’s easy! Once you have an Expensify Card, you just need to start using it. With each swipe, you're automatically entered to win and have a 1 in 250 chance of getting a prize! + +**How will I know if I’ve won?** +Winners will be notified immediately via the Expensify app, and receive additional instructions on how to choose and send their desired gift. + +If you don't have Expensify notifications turned on yet, here are some helpful guides: +- [Apple Notification Preferences](https://support.apple.com/en-us/HT201925) +- [Android Notification Preferences](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fsupport.google.com%2Fandroid%2Fanswer%2F9079661%3Fhl%3Den) # Partner Specific Perks @@ -188,4 +211,3 @@ Stripe Atlas helps removes obstacles typically associated with starting a busine **Receive $100 off Stripe Atlas and get access to a startup toolkit and special offers on additional Strip Atlas services.** **How to redeem:** Sign up with your Expensify Card. - diff --git a/docs/articles/expensify-classic/expensify-partner-program/Coming-Soon.md b/docs/articles/expensify-classic/expensify-partner-program/Coming-Soon.md deleted file mode 100644 index 6b85bb0364b5..000000000000 --- a/docs/articles/expensify-classic/expensify-partner-program/Coming-Soon.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Coming Soon -description: Coming Soon ---- diff --git a/docs/articles/expensify-classic/expensify-partner-program/Partner-Billing-Guide.md b/docs/articles/expensify-classic/expensify-partner-program/Partner-Billing-Guide.md new file mode 100644 index 000000000000..750a1fc10e77 --- /dev/null +++ b/docs/articles/expensify-classic/expensify-partner-program/Partner-Billing-Guide.md @@ -0,0 +1,87 @@ +--- +title: Partner Billing Guide +description: Understand how Expensify bills partners and their clients +--- + +# Overview + +The ExpensifyApproved! Partner Program offers exclusive billing rates and features tailored for accountants to ensure seamless client management. If you are an accountant or consultant who recommends spend management solutions to your clients, becoming an ExpensifyApproved! Accountant may be a great certification for you. This guide will walk you through the unique billing perks available to ExpensifyApproved! partners, emphasizing the importance of understanding and managing client billing effectively. To learn what perks partners receive, check out the ExpensifyApproved! program details here. + +# Get exclusive partner pricing + +All ExpensifyApproved! Partners are automatically eligible for a special rate of $9/seat monthly, without an annual commitment when they adopt the Expensify Card. This provides flexibility as active users can vary. Here are the specifics on pricing for our Approved! Partners’ clients: +- **Bundled pricing:** US Clients using the Expensify Card get up to a 50% discount, bringing their monthly bill to $9/seat. Reach out to your Partner Manager to discuss exclusive international pricing discount. +- **Unbundled pricing (or pay-per-use pricing):** Clients not using the Expensify Card are billed at $18/seat monthly. +- **No annual commitment:** Partners pay only for what they use, with no annual subscriptions required. +- **Expensify Card revenue share:** All partners receive a 0.5% revenue share on Expensify Card transactions made by clients. This revenue share can be passed back to the client for an additional discount to offset their Expensify bill. + +# Understanding the billing process + +Expensify bills the owner of the expense workspace for the activity on that workspace. If accountants retain ownership of client workspaces, they receive the bill and can then re-bill their clients based on individual agreements. + +Each month, Expensify will send a consolidated bill detailing: +- **Pay-per-use seats:** This is the number of active clients and their users for the month. +- **Expensify Card discount**: This amount reflects how much spend is put on your card, which then determines the discount for that month. +- **Total monthly price:** This amount is the overall price of Expensify when using the Expensify Card discount to offset the cost of the pay-per-use seats. +- **Workspace list:** This is an overview of all client workspaces with their respective active seats. + +## Consolidated Domain Billing + +If your firm wishes to consolidate all Expensify billing to a single account, the Consolidated Domain Billing feature is your go-to tool. It centralizes payment for all group workspaces owned by any domain member of your firm. + +### Activating Consolidated Domain Billing: + 1. Claim and verify your firm’s domain. + 2. Navigate to **Settings > Domains > [Domain Name] > Domain Admins** and set a **"Primary Domain Admin"** by using the drop down toggle to select an email address. + 3. Enable **Consolidated Domain Billing** in the same section. + +The Consolidated Domain Billing tool ensures that billing takes place under a single Expensify account associated with your firm. This eliminates the need to add multiple payment cards across various accounts to cover payments for multiple clients. + +## Maintaining a Console of all clients: + +If your firm wants to have a console view of all client workspaces and domains, you will want to create a single, centralized login to manage all client workspaces and domains, such as accounting@myfirm.com. + + 1. Create a dedicated email address that will act as the universal workspace owner, for example, accounting@myfirm.com. + 2. Register this email with Expensify or your chosen platform and ensure it is verified and secured. + 3. Within each client workspace settings, add your centralized email (e.g. accounting@myfirm.com) as a workspace admin. + 4. Do the same with each client domain. + +## Applying Client IDs to a bill + +Using client IDs for Optimized Billing in Expensify: A unique identifier feature for ExpensifyApproved! accountants. Streamline client Workspace recognition and make your billing process more efficient. + +# How to assign a client ID to a workspace + 1. Log in to your account: Ensure you’re using an Approved! accountant account. + 2. Navigate to the desired Workspace: Go to **Settings > Workspaces > [Workspace Name] > Overview**. + 3. Input the identifier: Here, you can input an alphanumeric unique identifier for each client workspace. +**Note:** If a client has multiple workspaces, ensure each workspace has a consistent client ID. + +# How to access and download billing receipts +- Accessing Billing: **Settings: Go to Settings > Your Account > Payments > Billing History.** +- Download the Receipt: Click on **"Download Receipt CSV".** + +# Deep Dive +- Using client IDs for all Workspaces: It's beneficial to use client IDs for all Workspaces to ensure each one is easily recognizable. +- Benefits of itemized billing receipts: Employing client IDs offers itemized billing by client, with each itemization detailing unique active users. + +# FAQ + +**Do I automatically get the special billing rate as an ExpensifyApproved! Partner?** +- Yes, when you join the ExpensifyApproved! program, you will automatically get the special billing rate. To join the ExpensifyApproved! Program, you need to enroll in ExpensifyApproved! University. + +**How can I check my billing details?** +- To check your billing details, be on the lookout for your detailed billing statement sent out at the end of each month. + +**Can I pass the bill to my clients?** +- Yes, you can pass the bill on to your clients. If you retain ownership of client workspaces in Expensify, you can re-bill your clients. If you’d like the client to own the billing of the Expensify, they can take over billing. + +**What if I don't want to use the Expensify Card?** +- If you prefer not to use the Expensify Card, your clients will be billed at $18/seat monthly. + +**Why use client IDs?** +- Client IDs provide a streamlined method to identify and manage workspaces, especially beneficial when a client has multiple workspaces. + +**Do I need a client ID for each Workspace?** +- Yes, if you want to ensure seamless identification and billing processes. + +**Where can I see the Billing Receipts?** +- All billing owners receive an emailed PDF of their monthly billing receipt, but a CSV version can also be downloaded from the platform. diff --git a/docs/articles/expensify-classic/expensify-partner-program/Your-Expensify-Partner-Manager.md b/docs/articles/expensify-classic/expensify-partner-program/Your-Expensify-Partner-Manager.md index 2db69d0a8791..8243833dcc23 100644 --- a/docs/articles/expensify-classic/expensify-partner-program/Your-Expensify-Partner-Manager.md +++ b/docs/articles/expensify-classic/expensify-partner-program/Your-Expensify-Partner-Manager.md @@ -1,5 +1,5 @@ --- -title: Your Expensify Partner Manager +title: Expensify Partner Support description: Understanding support for our partners --- @@ -10,6 +10,7 @@ Our well-rounded support methodology is designed to provide comprehensive assist ## 1. ExpensifyApproved! University **Purpose:** Equip your team with a comprehensive understanding of Expensify. + **Benefits:** - Foundation-level knowledge about the platform. - 3 CPE credits upon successful completion (US-only). @@ -17,16 +18,39 @@ Our well-rounded support methodology is designed to provide comprehensive assist - Visit university.Expensify.com to access our comprehensive training program. ## 2. Partner Manager -**Role:** A designated liaison for your firm. +**Role:** +A Partner Manager is a dedicated point of contact for your firm Partner Managers support our accounting partners by providing recommendations for client’s accounts, assisting with firm-wide training, and ensuring partners receive the full benefits of our partnership program. They will actively monitor open technical issues and be proactive with recommendations to increase efficiency. + + **Key Responsibilities:** - Handle any escalations promptly. - Organize firm-wide training sessions. - Assist with strategic planning and the introduction of new features. - Once you've completed the ExpensifyApproved! University, log in to your Expensify account. Click on the "Support" option to connect with your dedicated Partner Manager. +**How do I know if I have a Partner Manager?** + +For your firm to be assigned a Partner Manager, you must complete the ExpensifyApproved! University training course. Every external accountant or bookkeeper who completes the training is automatically enrolled in our program and receives all the benefits, including access to the Partner Manager. So everyone at your firm must complete the training to receive the maximum benefit. + +You can check to see if you’ve completed the course and enrolled in the ExpensifyApproved! Accountants program simply by logging into your Expensify account. In the bottom left-hand corner of the website, you will see the ExpensifyApproved! logo. + +**How do I contact my Partner Manager?** +1. Signing in to new.expensify.com and searching for your Partner Manager +2. Replying to or clicking the chat link on any email you get from your Partner Manager + +**How do I know if my Partner Manager is online?** + +You will be able to see if they are online via their status in new.expensify.com, which will either say “online” or have their working hours. + +**Can I get on a call with my Partner Manager?** + +Of course! You can ask your Partner Manager to schedule a call whenever you think one might be helpful. Partner Managers can discuss client onboarding strategies, firm-wide training, and client setups. + +We recommend continuing to work with Concierge for general support questions, as this team is always online and available to help immediately. ## 3. Client Setup Specialist **Purpose:** Ensure smooth onboarding for every client you refer. + **Duties:** - Comprehensive assistance with setting up Expensify. - Help with configuring accounting integrations. @@ -35,6 +59,7 @@ Our well-rounded support methodology is designed to provide comprehensive assist ## 4. Client Account Manager **Role:** Dedicated support for ongoing client needs. + **Responsibilities:** - Address day-to-day product inquiries. - Assist clients in navigating and optimizing their use of Expensify. @@ -42,6 +67,7 @@ Our well-rounded support methodology is designed to provide comprehensive assist ## 5. Concierge chat support **Availability:** Real-time support for any urgent inquiries. + **Features:** - Immediate assistance with an average response time of under two minutes. - Available to both accountants and clients for all product-related questions. diff --git a/docs/articles/expensify-classic/workspace-and-domain-settings/Creating-Per-Diem-Expenses.md b/docs/articles/expensify-classic/get-paid-back/Per-Diem-Expenses.md similarity index 89% rename from docs/articles/expensify-classic/workspace-and-domain-settings/Creating-Per-Diem-Expenses.md rename to docs/articles/expensify-classic/get-paid-back/Per-Diem-Expenses.md index 214188e35137..1b537839af77 100644 --- a/docs/articles/expensify-classic/workspace-and-domain-settings/Creating-Per-Diem-Expenses.md +++ b/docs/articles/expensify-classic/get-paid-back/Per-Diem-Expenses.md @@ -1,17 +1,17 @@ --- -title: Creating Per Diem Expenses +title: Per-Diem-Expenses description: How to create Per Diem expenses on mobile and web. --- # Overview What are Per Diems? Per diems, short for "per diem allowance" or "daily allowance," are fixed daily payments provided by your employer to cover expenses incurred during business or work-related travel. These allowances simplify expense tracking and reimbursement for meals, lodging, and incidental expenses during a trip. Per Diems can be masterfully tracked in Expensify! -## How To create per diem expenses +## How to create per diem expenses To add per diem expenses, you need three pieces of information: 1. Where did you go? - Specify your travel destination. 2. How long were you away? - Define the period you're claiming for. -3. Which rate did you use? - Select the appropriate per diem rate. +3. Which rate did you use? - Select the appropriate per diem rate (this is set by your employer). ### Step 1: On either the web or mobile app, click New Expense and choose Per Diem @@ -31,15 +31,15 @@ Finally, submit your Per Diem expense for approval, and you'll be on your way to # FAQ -## Can I Edit My Per Diems? +## Can I edit my per diem expenses? Per Diems cannot be amended. To make changes, delete the expense and recreate it as needed. -## What If My Admin Requires Daily Per Diems? +## What if my admin requires daily per diems? No problem! Create a separate Per Diem expense for each day of your trip. -## I Have Questions About the Amount I'm Due +## I have questions about the amount I'm due Reach out to your internal Admin team, as they've configured the rates in your policy to meet specific requirements. -## Can I Add Start and End Times to a Per Diem? +## Can I add start and end times to per diems? Unfortunately, you cannot add start and end times to Per Diems in Expensify. By following these steps, you can efficiently create and manage your Per Diem expenses in Expensify, making the process of tracking and getting reimbursed hassle-free. diff --git a/docs/articles/expensify-classic/get-paid-back/Per-Diem.md b/docs/articles/expensify-classic/get-paid-back/Per-Diem.md deleted file mode 100644 index 780e5969c441..000000000000 --- a/docs/articles/expensify-classic/get-paid-back/Per-Diem.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Per Diem -description: Per Diem ---- -## Resource Coming Soon! diff --git a/docs/articles/expensify-classic/get-paid-back/Trips.md b/docs/articles/expensify-classic/get-paid-back/Trips.md index 7efba1875a90..a65a8bfb8eec 100644 --- a/docs/articles/expensify-classic/get-paid-back/Trips.md +++ b/docs/articles/expensify-classic/get-paid-back/Trips.md @@ -1,5 +1,37 @@ --- title: Trips -description: Trips +description: Automate getting paid back for your travel through Expensify's Trips feature. --- -## Resource Coming Soon! +# Overview + +Discover how Expensify streamlines your travel expense management when it comes to trips. With the automatic classification of trip receipts and real-time notifications for travel changes, you can effortlessly stay organized and informed on all your trips. + +When a travel receipt/itinerary is uploaded into Expensify and SmartScanned, the Trips section of the mobile app will automatically populate your trip information.. If your flight has any cancellations, unexpected changes, or delays, we will make sure you know about it. We will notify you of the change as soon as it happens via the mobile app. + +For the receipt to be processed as a Trip, it must include the total amount of the expense, date, and merchant name. + +If your company is using a travel integration from the list shown below, you can automate this process entirely: +- [TravelPerk](https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/TravelPerk) +- [Egencia](https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Egencia) +- [Navan](https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Trip-Actions) + +# How to add a Trip to your account + +Trip receipts are typically sent via email, and will include multiple pages. With that in mind, we recommend emailing receipts directly to Expensify for ease. + +To email a flight or hotel receipt, you’ll forward the receipt from your Expensify-associated email address to receipts@expensify.com. + +# How to access your Trip information + +To view details about your past or upcoming trips, follow these steps within the Expensify mobile app: +1. Open the Expensify mobile app +2. Navigate to the "Menu" option (top left ≡ icon) +3. Select **Trips** + +# FAQ + +## How do I capture Trip receipts sent to my personal email address? +If you received your receipt in an email that is not associated with your Expensify account, you can add this email as a [secondary login](https://help.expensify.com/articles/expensify-classic/account-settings/Account-Details#how-to-add-a-secondary-login) to directly forward the receipt into your account. + +## How do I upload Trip receipts that were not sent to me by email? +If your trip receipt was not sent to you by email, you can manually upload the receipt to your account. Check out this resource for more information on [manually uploading receipts](https://help.expensify.com/articles/expensify-classic/get-paid-back/expenses/Upload-Receipts#manually-upload). diff --git a/docs/articles/expensify-classic/getting-started/support/Expensify-Support.md b/docs/articles/expensify-classic/getting-started/support/Expensify-Support.md new file mode 100644 index 000000000000..f4a6acdd8571 --- /dev/null +++ b/docs/articles/expensify-classic/getting-started/support/Expensify-Support.md @@ -0,0 +1,117 @@ +--- +title: Your Expensify Account Manager +description: Everything you need to know about Having an Expensify account manager +redirect_from: articles/other/Your-Expensify-Account-Manager/ +--- + + + +# Introduction to Expensify Support + +Expensify offers comprehensive support for customers of all sizes. From small business owners to multinational corporations, Expensify's support teams are available to assist! + +Expensify has four different support teams. Let's go over how each of them operates below. + +**Concierge Support:** +- Concierge is available 24/7 and is the first line of support +- Users can access Concierge through the Expensify app or via email at concierge@expensify.com +- Provides quick responses, usually within minutes +- Don't be your team's tech support - refer your users to Concierge for all their Expensify product questions + +**Setup Specialists:** +- Dedicated onboarding experts to assist users in getting started with Expensify +- Assist in connecting cards and bank accounts, configuring integrations, and more + +**Account Managers:** +- A dedicated point of contact for companies with more than ten users +- Serve as product specialists +- Available to answer questions and promote best practices +- Provide ongoing support and guidance + +**ExpensifyApproved! Accounting Partner Managers:** +- Offer an additional support layer for accounting partners +- Partner Managers are dedicated Expensify team members +- Provide firmwide training, assist with strategic goal planning, and collaborative marketing + +This comprehensive support structure ensures that Expensify users receive the assistance they need, whether new to the platform or looking to optimize their experience. + +# How to get support in Expensify + +## Concierge + +Reach out to Concierge when you have general questions about Expensify. Concierge can also be used to manage expenses, submit reports, and automate approvals. You can contact Concierge while logged into your Expensify account by clicking **Support** on the left-hand menu and then selecting **Concierge**. + +Try questions such as: +- What is SmartScan? +- How do I add a mileage expense from the mobile app? +- Where can I add a Secondary Login? + +## Setup Specialist + +Expensify provides onboarding guidance for anyone through a Setup Specialist! You can contact your Setup Specialist while logged into your Expensify account by clicking **Support** on the left-hand menu and then selecting **Account Setup Specialist**. + +### What to expect from your Setup Specialist: + +- Personalized Support: Your Setup Specialist is here to assist you with tailored support. They can answer your questions and arrange screen share calls to help you set up your Expensify account or familiarize you with the product. + +- Product Demos: Are you curious about how the Expensify Card works or how it integrates with your accounting software? Just let your Setup Specialist know, and they'll guide you and your team through any feature you'd like to explore. + +- Setup Assistant: You don't have to do it alone when setting up your Expensify account. When you're ready to begin, chat with your Setup Specialist in the #admins room. They'll ensure everything is configured correctly right from the start. + + +## Account Manager + +If you have more than ten active users, or you're an ExpensifyApproved! Accountant's client, you're eligible for a designated Account Manager. + +Once you've completed onboarding to Expensify with your Setup Specialist, your Account Manager will take over as the main point of contact. Your account manager is there to support you and other Workspace admins in reviewing your account, advising on best practices, and making changes to your Workspace on your behalf whenever you need a hand. + +They will actively monitor open technical issues and be proactive with recommendations to increase efficiency and minimize time spent on expense management. + +### How to contact your Account Manager + +If you are a Workspace admin or domain admin, you will hear from your Account Manager as soon as one is assigned to your company. + +Unlike Concierge, an Account Manager's support will not be real-time, 24 hours a day. Your Account Manager will be as responsive as possible when online, but anything sent when they're offline will not be responded to until they're working again. + +You can contact your Account Manager while logged into your Expensify account by clicking **Support** on the left-hand menu and then selecting **Account Manager**. + +## Partner Manager + +A Partner Manager is a dedicated point of contact to support our ExpensifyApproved! Accountants with questions about their Expensify account. Partner Managers support our accounting partners by providing recommendations for client's accounts, assisting with firm-wide training, and ensuring partners receive the full benefits of our partnership program. They will actively monitor open technical issues and be proactive with recommendations to increase efficiency and minimize time spent on expense management. + +For your firm to be assigned a Partner Manager, you must complete the [ExpensifyApproved! University](https://use.expensify.com/accountants-program) training course. Every external accountant or bookkeeper who completes the training is automatically enrolled in our program and receives benefits, including access to a Partner Manager. Everyone at your firm must complete the training to receive the maximum benefit. + +### How to contact your Partner Manager + +Your Partner Manager should reach out to you once you've completed ExpensifyApproved! University. Otherwise, you can contact your Partner Manager anytime by clicking **Support** on the left-hand menu and then selecting **Partner Manager**. + +## Tips on Contacting Expensify Support + +- **Use the Right Email**: Contact us from the email address linked to your Expensify account. This helps us locate your information accurately. +- **Be Clear and Specific**: When asking questions or reporting issues, provide specific examples like affected users' email addresses or report IDs. This makes it easier for us to assist you effectively. +- **Practice Kindness**: Remember that we're here to help. Please be polite, considerate, and patient as we work together to resolve any concerns you have. + +# FAQ +## Who gets an Account Manager? +Members who have 10 or more active users, or clients of ExpensifyApproved! Accounts are automatically assigned a dedicated Account Manager. + +To be assigned an Account Manager immediately, log into your Expensify account and go to **Settings > Workspaces > Group**, then click **Subscription** and increase your subscription size to 10 or more. + +## What if I'm unable to reach my Account Manager? +If you're unable to reach your account manager, then you can always reach out to Concierge for assistance. Your account manager will always reply once they're online again. + +## Can I schedule a call with my Account Manager? +Of course! You can ask your Account Manager for a call whenever you think one might be helpful. + +**What makes a successful call with an Account Manager**: +- Scheduling the call using their calendar link (this should be shared with you once you're assigned an Account Manager) +- Listing out exactly what you'd like to go over with the Account Manager, and then sharing that list with them before the call +- Having anyone else in your organization who regularly manages your Expensify setup join the call + +## When should I chat with Concierge instead of my Account Manager? +If you have a general question about the status of a report or updating an account setting, Concierge is more than capable of getting you the answers you need. + +We recommend working with Concierge on general support questions, as this team is always online and available to help immediately. + +## Who gets assigned a Setup Specialist? +This feature is specifically for new members! Whenever you start a free trial, a product Setup Specialist will be assigned to guide you through configuring your Expensify account. diff --git a/docs/articles/expensify-classic/getting-started/support/Your-Expensify-Account-Manager.md b/docs/articles/expensify-classic/getting-started/support/Your-Expensify-Account-Manager.md deleted file mode 100644 index a6fa0220c0dc..000000000000 --- a/docs/articles/expensify-classic/getting-started/support/Your-Expensify-Account-Manager.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: Your Expensify Account Manager -description: Everything you need to know about Having an Expensify account manager -redirect_from: articles/other/Your-Expensify-Account-Manager/ ---- - - - -# What is an account manager? -An account manager is a dedicated point of contact to support policy admins with questions about their Expensify account. They are available to help you and other policy admins review your account, advise on best practices, and make changes to your policy on your behalf whenever you need a hand. They will actively monitor open technical issues and be proactive with recommendations to increase efficiency and minimize time spent on expense management. - -Unlike Concierge, an account manager’s support will not be real-time, 24 hours a day. A benefit of Concierge is that you get real-time support every day. Your account manager will be super responsive when online, but anything sent when they’re offline will not be responded to until they’re online again. - -For real-time responses and simple troubleshooting issues, you can always message our general support by writing to Concierge via the in-product chat or by emailing concierge@expensify.com. - -# How do I know if I have an account manager? -If you are a policy admin or domain admin, you will also hear from your account manager as soon as one gets assigned to your company. If you'd like a reminder who your account manager is, just click the Support link on the left side of Expensify - you'll see your account manager's name and photo, with an option to contact them for help. - -## How do I contact my account manager? -We make it easy to contact your account manager: - -1. Log in to your Expensify account, click "Support" along the left side of the page, and click the “Account Manager” option -2. Reply to (or click the chat link on) any email you get from your account manager -3. Sign in to new.expensify.com and go to the #admins room for any of your policies. Your account manager is in your #admin rooms ready to help you, so you can ask for help here and your account manager will respond in the chat. - -# FAQs -## Who gets an account manager? -Every customer with 10 or more paid subscribers is automatically assigned a dedicated account manager. If you have fewer than 10 active users each month, you can still get an account manager by increasing your subscription to 10 or more users, To get assigned an account manager immediately, log into your Expensify account and go to Settings > Policies > Group, then click Subscription and increase your subscription size to 10 or more. - -## How do I know if my account manager is online? -You will be able to see if they are online via their status, which will either say something like “online” or have their working hours. - -## What if I’m unable to reach my account manager? -If for some reason, you’re unable to reach your account manager, perhaps because they’re offline, then you can always reach out to Concierge for assistance. Your account manager will always get back to you when they’re online again. - -## Can I get on a call with my account manager? -Of course! You can ask your account manager to schedule a call whenever you think one might be helpful. We usually find that the most effective calls are those that deal with general setup questions. For technical troubleshooting, we typically recommend chat as that allows your account manager time to look into the issue, test things on their end, and, if needed, consult the wider Expensify technical team. It also allows you to easily refer back to instructions and links. \ No newline at end of file diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Desktop.md b/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Desktop.md index d8c7c145a670..958e423273ce 100644 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Desktop.md +++ b/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Desktop.md @@ -76,6 +76,7 @@ Expensify's integration with QuickBooks brings in your Chart of Accounts as Cate 3. Expensify offers Auto-Categorization to automatically assign expenses to the appropriate expense categories. 4. If needed, you can edit the names of the imported Categories to simplify expense coding for your employees. Keep in mind that if you make changes to these accounts in QuickBooks Desktop, the category names in Expensify will update to match them during the next sync. 5. _**Important:**_ Each expense must have a category selected to export to QuickBooks Desktop. The selected category must be one imported from QuickBooks Desktop; you cannot manually create categories within Expensify policy settings. + ## Classes Classes can be imported from QuickBooks as either tags (line-item level) or report fields (header level). diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Online.md b/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Online.md index 9d17160d3a36..4075aaf18016 100644 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Online.md +++ b/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Online.md @@ -14,6 +14,8 @@ It's crucial to understand the requirements based on your specific QuickBooks su - An error will occur if you try to export to QuickBooks with a feature enabled that isn't part of your subscription. - Please be aware that Expensify does not support the Self-Employed subscription in QuickBooks Online. +![QuickBooks Online - Subscription types]({{site.url}}/assets/images/QBO1.png){:width="100%"} + # How to connect to QuickBooks Online ## Step 1: Setup employees in QuickBooks Online @@ -79,14 +81,20 @@ This is a single itemized vendor bill for each Expensify report. If the accounti The submitter will be listed as the vendor in the vendor bill. +![Vendor Bill]({{site.url}}/assets/images/QBO2-Bill.png){:width="100%"} + ## Check This is a single itemized check for each Expensify report. You can mark a check to be printed later in QuickBooks Online. +![Check to print]({{site.url}}/assets/images/QBO3-Checktoprint.png){:width="100%"} + ## Journal entry This is a single itemized journal entry for each Expensify report. +![Journal Entry]({{site.url}}/assets/images/QBO4-JournalEntry.png){:width="100%"} + # Non-reimbursable expenses Non-reimbursable expenses export to QuickBooks Online as: @@ -102,7 +110,9 @@ Using Credit/Debit Card Transactions: - Each expense will be exported as a bank transaction with its transaction date. - If you split an expense in Expensify, we'll consolidate it into a single credit card transaction in QuickBooks with multiple line items posted to the corresponding General Ledger accounts. -Pro-Tip: To ensure the payee field in QuickBooks Online reflects the merchant name for Credit Card expenses, ensure there's a matching Vendor in QuickBooks Online. Expensify checks for an exact match during export. If none are found, the payee will be mapped to a vendor we create and labeled as Credit Card Misc. or Debit Card Misc. +Pro-Tip: To ensure the payee field in QuickBooks Online reflects the merchant name for Credit Card expenses, ensure there's a matching Vendor in QuickBooks Online. Expensify checks for an exact match during export. If none are found, the payee will be mapped to a vendor we create and labeled as Credit Card Misc. or Debit Card Misc. + +![Expense]({{site.url}}/assets/images/QBO5-Expense.png){:width="100%"} If you centrally manage your company cards through Domains, you can export expenses from each card to a specific account in QuickBooks. @@ -224,6 +234,8 @@ Step 3: Importing Your Credit Card Transactions into QuickBooks Online - After completing Steps 1 and 2, you can import your credit card transactions into QuickBooks Online. These imported banking transactions will align with the ones brought in from Expensify. QuickBooks Online will guide you through the process of matching these transactions, similar to the example below: +![Transactions]({{site.url}}/assets/images/QBO7-Transactions.png){:width="100%"} + ## Tax in QuickBooks Online If your country applies taxes on sales (like GST, HST, or VAT), you can utilize Expensify's Tax Tracking along with your QuickBooks Online tax rates. Please note: Tax Tracking is not available for Workspaces linked to the US version of QuickBooks Online. If you need assistance applying taxes after reports are exported, contact QuickBooks. @@ -247,6 +259,8 @@ When working with QuickBooks Online Multi-Currency, there are some things to rem In QuickBooks Online, the currency conversion rates are not applied when exporting. All transactions will be exported with a 1:1 conversion rate, so for example, if a vendor's currency is CAD (Canadian Dollar) and the home currency is USD (US Dollar), the export will show these currencies without applying conversion rates. +![Check]({{site.url}}/assets/images/QBO6-Check.png){:width="100%"} + To correct this, you must manually update the conversion rate after the report has been exported to QuickBooks Online. Specifically for Vendor Bills: diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Trip-Actions.md b/docs/articles/expensify-classic/integrations/travel-integrations/Navan.md similarity index 100% rename from docs/articles/expensify-classic/integrations/travel-integrations/Trip-Actions.md rename to docs/articles/expensify-classic/integrations/travel-integrations/Navan.md diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Uber.md b/docs/articles/expensify-classic/integrations/travel-integrations/Uber.md index 3ee1c8656b4b..16da0c0caa5b 100644 --- a/docs/articles/expensify-classic/integrations/travel-integrations/Uber.md +++ b/docs/articles/expensify-classic/integrations/travel-integrations/Uber.md @@ -1,5 +1,24 @@ --- -title: Coming Soon -description: Coming Soon +title: Uber integration +description: Connecting your Uber account to Expensify --- -## Resource Coming Soon! +## Overview + +Link Expensify directly to your Uber account so your Uber for Business receipts populate automatically in Expensify. + +# How to connect Uber to Expensify + +You can do this right in the Uber app: + +1. Head to Account > Business hub > Get started +2. Tap Create an individual account > Get started +3. Enter your business email and tap Next +4. Select the payment card you'd like to use for your business profile +5. Choose how frequently you’d like to receive travel summaries +6. Select Expensify as your expense provider +Expensify and Uber are now connected! + +Now, every time you use Uber for Business – be it for rides or meals – the receipt will be imported and scanned into Expensify automatically. + +![Uber integration set up steps: Connecting your account](https://help.expensify.com/assets/images/Uber1.png){:width="100%"} +![Uber integration set up steps: Selecting Expensify](https://help.expensify.com/assets/images/Uber2.png){:width="100%"} diff --git a/docs/articles/new-expensify/billing-and-plan-types/The-Free-Plan.md b/docs/articles/new-expensify/billing-and-plan-types/The-Free-Plan.md index e157ede1969d..3b79072aa393 100644 --- a/docs/articles/new-expensify/billing-and-plan-types/The-Free-Plan.md +++ b/docs/articles/new-expensify/billing-and-plan-types/The-Free-Plan.md @@ -30,16 +30,38 @@ Once you’ve completed your company setup, you should have completed the follow - Invited members to the workspace - Assigned Expensify Cards -# Inviting Members to the Free Plan: +# Inviting Members to the Free Plan - Navigate to the Settings Menu and click **_Members_** to invite your team. You can invite employees one at a time, or you can invite multiple users by listing out their email addresses separated by a comma - To use the Expensify Card, you must invite them to your workspace via your company email address (i.e., admin@companyemail.com and NOT admin@gmail.com). # Managing the Free Plan -To access your workspace settings, click your profile icon and then on your workspace name. +## Workspace Settings -This settings menu allows you to manage your workspace members, issue additional Expensify Cards, and utilize this plan’s various bill pay and payment options. +To access your workspace settings, click your profile icon and then on your workspace name. This settings menu allows you to manage your workspace members, issue additional Expensify Cards, and utilize this plan’s various bill pay and payment options. + +## Paying an Expense Report +- Once a user creates an expense it will automatically be shared with you in a Processing report. +- Pay expenses directly through Expensify by choosing ‘Reimburse > via Direct Deposit (ACH)` in a report on www.expensify.com or by choosing ‘Pay with Expensify’ in a payment request on new.expensify.com. +- Notify your user that you’ll pay them manually outside of Expensify by choosing ‘Reimburse > I’ll do it manually’ in a report on www.expensify.com or choosing ‘Pay Elsewhere’ in a payment request on new.expensify.com. +- Reports with only non-reimbursable expenses on them have the option to ‘Mark as Closed’ in the report on www.expensify.com or ‘Mark as Done’ in the payment request on new.expensify.com. + +## Changing Submitted Expenses + +Request an edit an expense or remove an expense before you pay, you can let your user know by making a comment in the Report History section of their Processing report or chatting with them on new.expensify.com. + +# Managing Expenses + +## Creating an Expense +- You can create an expense either by swiping the Expensify card or just smartscan a receipt! +- Once you create an expense it will be automatically added to a report and shared with your admin. +- You can edit or delete any expense that hasn’t been paid or closed by your admin. + +## Getting paid for Expenses +- Automatic submission is already set up, so your admin can pay you back immediately once you create an expense. +- Your admin will get a notification when you send them a new expense, but you can also remind them to pay you by making a comment in the Report History section of your Processing report or chatting with them on new.expensify.com. # FAQs + ## Do I need a business bank account to use the Free Plan? You will need a US business checking account if you want to enable the Expensify Card and set up direct ACH reimbursement. @@ -50,9 +72,27 @@ If you're not in the US, you can still use the Free Plan, but the Expensify Card The Expensify Workplace only allows for one admin (the workspace creator). -## Scheduled Submit is set to weekly on the Free Plan. Can I change this? +## I am on a paid plan, can I switch to a Free Plan? + +You can set up a Free Plan, but you must honor any active subscription you have also. If you're on a paid plan, it is likely you want more functionality than what the Free Plan offers such as a direct connection with an accounting integration and approval workflows. + +## Can I get cashback on Expensify Card purchases if I have a free plan? + +You can get 1% credited back to your settlement account once you spend over $25,000 per month across all cards and 2% when you spend over $250,000! -No, expense reports on the Free Plan submit weekly, and there is no way to customize approval settings. +## Can I switch the workspace currency on the Free Plan? It looks set to USD + +Yes, you can change the currency of the Free Plan by going to Avatar > [Workspace Name] > General settings > Default currency. + +We do require a US business bank account for reimbursements and Expensify Card settlements though, so if you have a business bank account linked to your account, then the currency of the Free Plan will be USD. + +## Is a free plan available to people outside the USA? + +Yes! You can use the free plan anywhere in the world to track expenses, send invoices etc. Just remember, anything that requires a verified business bank account (such as ACH reimbursement and the Expensify Card) is only available to those with a US checking account! + +## Can I integrate the free plan with my accounting package? + +No. In order to use our accounting sync, you will need to update to a paid plan ## With the Free Plan, can I add my own categories? @@ -60,4 +100,48 @@ Categories are standardized on the Free Plan and can’t be edited. Custom categ ## With the Free Plan, can I export reports using a custom format? -The Free Plan offers standard report export formats. You'll need to upgrade to a paid plan to create a custom export format. \ No newline at end of file +The Free Plan offers standard report export formats. You'll need to upgrade to a paid plan to create a custom export format. + +## Can I change the mileage rate or unit used for distance tracking? + +Yes. The workspace admin can access the rate and unit settings by going to Avatar > [Workspace name] > Reimburse expenses > Track distance. + +## Can I add non-Expensify cardholders to my Workspace? + +Yes. You can invite any user to your Workspace. Just click invite and enter their email and they will be invited to download the app and join! + +## Expenses are automatically shared with the admin on a Processing report on the Free Plan, can I change this? + +No. Expense reports submitted on the Free Plan are set to submit automatically and do not allow for approvals. Different Scheduled Submit settings are available on our paid plans. + +## How do I give a user I invited to my Workspace an Expensify Card? + +You can give a user an Expensify Card by going to the Company Cards Page on expensify.com and setting a card limit >$0. Please note that in order to give a user a card, they must be using a private company email address (i.e. name@companyname.com NOT name@gmail.com) + +## Can I use a different bank account to the one I have added for some of the features in the workspace? + +No. The bank account you have added will be used to issue corporate cards, reimburse expenses, collect invoices, and pay bills! + +## Can I upgrade my Free Workspace to a Paid Workspace or do I need to create a new one? + +There is no way to upgrade a workspace, so you would need to create a new Workspace. Paid workspaces have more functionalities than what the Free Plan offers, such as a direct connection with an accounting integration and approval workflows. + +## Can I create more than one Processing report at a time? + +No. To keep things simple, we only allow one Processing report per user at a time. If you need to have more than one report at a time, our paid plans support unlimited reports. + +## A user has added an expense I need to change before I pay it, how do I let them know? + +Users can edit and delete expenses on Processing reports. If you need something changed, let them know by commenting in the Report History section of the report on expensify.com or by chatting with them in new.expensify.com. + +## Can I ‘Reopen’ a report once it’s Reimbursed or Closed? + +No. Once an admin reimburses or closes a report, it cannot be ‘reopened’, but you can always comment on a report to add context. + +## I accidentally reimbursed a report too soon. Can I cancel the reimbursement? + +Depending on how quickly you report it to us, we may be able to help cancel a reimbursement. Chat Concierge to see if we can help cancel a reimbursement. + +## As an admin, can I edit users’ expenses and delete them from reports? + +No. Only users can edit and delete expenses on the Free plan. Admin control of submitted expenses on a workspace is a feature of our paid plans. If you need something changed, let the user know by commenting in the Report History section of the report on www.expensify.com or by chatting with them in new.expensify.com. diff --git a/docs/articles/new-expensify/expensify-partner-program/Coming-Soon.md b/docs/articles/new-expensify/expensify-partner-program/Coming-Soon.md deleted file mode 100644 index 6b85bb0364b5..000000000000 --- a/docs/articles/new-expensify/expensify-partner-program/Coming-Soon.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Coming Soon -description: Coming Soon ---- diff --git a/docs/articles/new-expensify/get-paid-back/Distance-Requests.md b/docs/articles/new-expensify/get-paid-back/Distance-Requests.md new file mode 100644 index 000000000000..91b88409be8b --- /dev/null +++ b/docs/articles/new-expensify/get-paid-back/Distance-Requests.md @@ -0,0 +1,27 @@ +--- +title: Distance Requests +description: How to create a distance request and request reimbursement for mileage +--- + + +# Overview + +Expensify allows you to request reimbursement for mileage by creating a distance request from a map. You can send a distance request in Expensify's mobile, desktop, or web app. + + +# How to create and send a distance request + +1. Click the green + button and select Request Money. +2. Select Distance along the top row of the Request Money window. +3. Enter the Start and Finish addresses then click Next. If there are multiple stops, you can add them before clicking Next. +4. Choose who to send the request to by selecting your organization's workspace from the list of recent workspaces. +5. On the confirmation page, confirm the amount, date, distance, and optionally add a description or category. Click the Request button. +6. A workspace admin will receive your request and can reimburse you through Expensify or elsewhere! + + + +# FAQs + +## Is there an easy way to reuse recent locations? + +Yes! We save your recently used locations and list them out on the page where you select the Start and Finish. diff --git a/docs/articles/new-expensify/send-payments/Coming-Soon.md b/docs/articles/new-expensify/send-payments/Coming-Soon.md deleted file mode 100644 index 6b85bb0364b5..000000000000 --- a/docs/articles/new-expensify/send-payments/Coming-Soon.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Coming Soon -description: Coming Soon ---- diff --git a/docs/articles/new-expensify/workspace-and-domain-settings/Coming-Soon.md b/docs/articles/new-expensify/workspace-and-domain-settings/Coming-Soon.md deleted file mode 100644 index 6b85bb0364b5..000000000000 --- a/docs/articles/new-expensify/workspace-and-domain-settings/Coming-Soon.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Coming Soon -description: Coming Soon ---- diff --git a/docs/assets/images/ExpensifyHelp_EmailError.png b/docs/assets/images/ExpensifyHelp_EmailError.png new file mode 100644 index 000000000000..203f0cfe2b76 Binary files /dev/null and b/docs/assets/images/ExpensifyHelp_EmailError.png differ diff --git a/docs/assets/images/ExpensifyHelp_SMTPError.png b/docs/assets/images/ExpensifyHelp_SMTPError.png new file mode 100644 index 000000000000..b95ea70a9dfa Binary files /dev/null and b/docs/assets/images/ExpensifyHelp_SMTPError.png differ diff --git a/docs/assets/images/ExpensifyHelp_Time.png b/docs/assets/images/ExpensifyHelp_Time.png index a042ab60f681..f4d91b1e8aeb 100644 Binary files a/docs/assets/images/ExpensifyHelp_Time.png and b/docs/assets/images/ExpensifyHelp_Time.png differ diff --git a/docs/assets/images/QBO1.png b/docs/assets/images/QBO1.png new file mode 100644 index 000000000000..4037db44d3bb Binary files /dev/null and b/docs/assets/images/QBO1.png differ diff --git a/docs/assets/images/QBO2-Bill.png b/docs/assets/images/QBO2-Bill.png new file mode 100644 index 000000000000..f75716a85079 Binary files /dev/null and b/docs/assets/images/QBO2-Bill.png differ diff --git a/docs/assets/images/QBO3-Checktoprint.png b/docs/assets/images/QBO3-Checktoprint.png new file mode 100644 index 000000000000..732141a74353 Binary files /dev/null and b/docs/assets/images/QBO3-Checktoprint.png differ diff --git a/docs/assets/images/QBO4-JournalEntry.png b/docs/assets/images/QBO4-JournalEntry.png new file mode 100644 index 000000000000..342d20e49608 Binary files /dev/null and b/docs/assets/images/QBO4-JournalEntry.png differ diff --git a/docs/assets/images/QBO5-Expense.png b/docs/assets/images/QBO5-Expense.png new file mode 100644 index 000000000000..5d71f3955557 Binary files /dev/null and b/docs/assets/images/QBO5-Expense.png differ diff --git a/docs/assets/images/QBO6-Check.png b/docs/assets/images/QBO6-Check.png new file mode 100644 index 000000000000..087720a76875 Binary files /dev/null and b/docs/assets/images/QBO6-Check.png differ diff --git a/docs/assets/images/QBO7-Transactions.png b/docs/assets/images/QBO7-Transactions.png new file mode 100644 index 000000000000..c7752c42870b Binary files /dev/null and b/docs/assets/images/QBO7-Transactions.png differ diff --git a/docs/assets/images/Uber1.png b/docs/assets/images/Uber1.png new file mode 100644 index 000000000000..d5a7d651c6b9 Binary files /dev/null and b/docs/assets/images/Uber1.png differ diff --git a/docs/assets/images/Uber2.png b/docs/assets/images/Uber2.png new file mode 100644 index 000000000000..27ac9925a900 Binary files /dev/null and b/docs/assets/images/Uber2.png differ diff --git a/docs/assets/images/settings-old-dot.svg b/docs/assets/images/settings-old-dot.svg index ca5bc04bd0ff..85561a886459 100644 --- a/docs/assets/images/settings-old-dot.svg +++ b/docs/assets/images/settings-old-dot.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 6112ea67761f..61a597638cca 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.4.5 + 1.4.10 CFBundleSignature ???? CFBundleURLTypes @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.5.3 + 1.4.10.0 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index ff992cb90a6f..189451c9ffdd 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.4.5 + 1.4.10 CFBundleSignature ???? CFBundleVersion - 1.4.5.3 + 1.4.10.0 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index bfd562963324..390511397b0e 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -569,7 +569,7 @@ PODS: - react-native-config/App (= 1.4.6) - react-native-config/App (1.4.6): - React-Core - - react-native-document-picker (8.1.1): + - react-native-document-picker (8.2.1): - React-Core - react-native-flipper (0.159.0): - React-Core @@ -726,8 +726,6 @@ PODS: - React-Core - RNCPicker (2.4.4): - React-Core - - RNDateTimePicker (3.5.2): - - React-Core - RNDeviceInfo (10.3.0): - React-Core - RNDevMenu (4.1.1): @@ -919,7 +917,6 @@ DEPENDENCIES: - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" - "RNCPicker (from `../node_modules/@react-native-picker/picker`)" - - "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)" - RNDeviceInfo (from `../node_modules/react-native-device-info`) - RNDevMenu (from `../node_modules/react-native-dev-menu`) - RNFastImage (from `../node_modules/react-native-fast-image`) @@ -1121,8 +1118,6 @@ EXTERNAL SOURCES: :path: "../node_modules/@react-native-clipboard/clipboard" RNCPicker: :path: "../node_modules/@react-native-picker/picker" - RNDateTimePicker: - :path: "../node_modules/@react-native-community/datetimepicker" RNDeviceInfo: :path: "../node_modules/react-native-device-info" RNDevMenu: @@ -1233,7 +1228,7 @@ SPEC CHECKSUMS: react-native-blob-util: 99f4d79189252f597fe0d810c57a3733b1b1dea6 react-native-cameraroll: 8ffb0af7a5e5de225fd667610e2979fc1f0c2151 react-native-config: 7cd105e71d903104e8919261480858940a6b9c0e - react-native-document-picker: f68191637788994baed5f57d12994aa32cf8bf88 + react-native-document-picker: 69ca2094d8780cfc1e7e613894d15290fdc54bba react-native-flipper: dc5290261fbeeb2faec1bdc57ae6dd8d562e1de4 react-native-geolocation: 0f7fe8a4c2de477e278b0365cce27d089a8c5903 react-native-image-manipulator: c48f64221cfcd46e9eec53619c4c0374f3328a56 @@ -1270,7 +1265,6 @@ SPEC CHECKSUMS: RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60 RNCClipboard: d77213bfa269013bf4b857b7a9ca37ee062d8ef1 RNCPicker: 0b65be85fe7954fbb2062ef079e3d1cde252d888 - RNDateTimePicker: 7658208086d86d09e1627b5c34ba0cf237c60140 RNDeviceInfo: 4701f0bf2a06b34654745053db0ce4cb0c53ada7 RNDevMenu: 72807568fe4188bd4c40ce32675d82434b43c45d RNFastImage: 5c9c9fed9c076e521b3f509fe79e790418a544e8 diff --git a/ios/expensify_chat_adhoc.mobileprovision.gpg b/ios/expensify_chat_adhoc.mobileprovision.gpg index 1dae451f168c..f4691df10d67 100644 Binary files a/ios/expensify_chat_adhoc.mobileprovision.gpg and b/ios/expensify_chat_adhoc.mobileprovision.gpg differ diff --git a/package-lock.json b/package-lock.json index 8a4541d44236..20ba84846b69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.4.5-3", + "version": "1.4.10-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.5-3", + "version": "1.4.10-0", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -26,7 +26,6 @@ "@react-native-async-storage/async-storage": "^1.17.10", "@react-native-camera-roll/camera-roll": "5.4.0", "@react-native-clipboard/clipboard": "^1.12.1", - "@react-native-community/datetimepicker": "^3.5.2", "@react-native-community/geolocation": "^3.0.6", "@react-native-community/netinfo": "^9.3.10", "@react-native-firebase/analytics": "^12.3.0", @@ -78,7 +77,7 @@ "react-native-config": "^1.4.5", "react-native-dev-menu": "^4.1.1", "react-native-device-info": "^10.3.0", - "react-native-document-picker": "^8.0.0", + "react-native-document-picker": "^8.2.1", "react-native-draggable-flatlist": "^4.0.1", "react-native-fast-image": "^8.6.3", "react-native-fs": "^2.20.0", @@ -97,7 +96,7 @@ "react-native-pdf": "^6.7.3", "react-native-performance": "^5.1.0", "react-native-permissions": "^3.9.3", - "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#eae05855286dc699954415cc1d629bfd8e8e47e2", + "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#0d15d4618f58e99c1261921111e68ee85bb3c2a8", "react-native-plaid-link-sdk": "10.8.0", "react-native-qrcode-svg": "^6.2.0", "react-native-quick-sqlite": "^8.0.0-beta.2", @@ -8292,15 +8291,6 @@ "node": ">= 4.0.0" } }, - "node_modules/@react-native-community/datetimepicker": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@react-native-community/datetimepicker/-/datetimepicker-3.5.2.tgz", - "integrity": "sha512-TWRuAtr/DnrEcRewqvXMLea2oB+YF+SbtuYLHguALLxNJQLl/RFB7aTNZeF+OoH75zKFqtXECXV1/uxQUpA+sg==", - "license": "MIT", - "dependencies": { - "invariant": "^2.2.4" - } - }, "node_modules/@react-native-community/eslint-config": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/eslint-config/-/eslint-config-3.0.0.tgz", @@ -44224,8 +44214,9 @@ } }, "node_modules/react-native-document-picker": { - "version": "8.1.1", - "license": "MIT", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/react-native-document-picker/-/react-native-document-picker-8.2.1.tgz", + "integrity": "sha512-luH2hKdq4cUwE651OscyGderLMsCusOsBzw4MBca91CgprlAGVMm1/pDwJDV5t9LIewVK8DIgXGXzgrsusKVhA==", "dependencies": { "invariant": "^2.2.4" }, @@ -44523,9 +44514,9 @@ } }, "node_modules/react-native-picker-select": { - "version": "8.0.4", - "resolved": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#eae05855286dc699954415cc1d629bfd8e8e47e2", - "integrity": "sha512-3U/mtHN/pKC5yXtJnqj5rre8+4YPSqoXCn/3qKjb5u8BMIiuc5H3KJ0ZbKlZEg/8Uh4j0cvrtcNasdPgMqRgCQ==", + "version": "8.1.0", + "resolved": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#0d15d4618f58e99c1261921111e68ee85bb3c2a8", + "integrity": "sha512-ly0ZCt3K4RX7t9lfSb2OSGAw0cv8UqdMoxNfh5j+KujYYq+N8VsI9O/lmqquNeX/AMp5hM3fjetEWue4nZw/hA==", "license": "MIT", "dependencies": { "lodash.isequal": "^4.5.0" @@ -58711,14 +58702,6 @@ "joi": "^17.2.1" } }, - "@react-native-community/datetimepicker": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@react-native-community/datetimepicker/-/datetimepicker-3.5.2.tgz", - "integrity": "sha512-TWRuAtr/DnrEcRewqvXMLea2oB+YF+SbtuYLHguALLxNJQLl/RFB7aTNZeF+OoH75zKFqtXECXV1/uxQUpA+sg==", - "requires": { - "invariant": "^2.2.4" - } - }, "@react-native-community/eslint-config": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@react-native-community/eslint-config/-/eslint-config-3.0.0.tgz", @@ -84703,7 +84686,9 @@ "requires": {} }, "react-native-document-picker": { - "version": "8.1.1", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/react-native-document-picker/-/react-native-document-picker-8.2.1.tgz", + "integrity": "sha512-luH2hKdq4cUwE651OscyGderLMsCusOsBzw4MBca91CgprlAGVMm1/pDwJDV5t9LIewVK8DIgXGXzgrsusKVhA==", "requires": { "invariant": "^2.2.4" } @@ -84869,9 +84854,9 @@ "requires": {} }, "react-native-picker-select": { - "version": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#eae05855286dc699954415cc1d629bfd8e8e47e2", - "integrity": "sha512-3U/mtHN/pKC5yXtJnqj5rre8+4YPSqoXCn/3qKjb5u8BMIiuc5H3KJ0ZbKlZEg/8Uh4j0cvrtcNasdPgMqRgCQ==", - "from": "react-native-picker-select@git+https://github.com/Expensify/react-native-picker-select.git#eae05855286dc699954415cc1d629bfd8e8e47e2", + "version": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#0d15d4618f58e99c1261921111e68ee85bb3c2a8", + "integrity": "sha512-ly0ZCt3K4RX7t9lfSb2OSGAw0cv8UqdMoxNfh5j+KujYYq+N8VsI9O/lmqquNeX/AMp5hM3fjetEWue4nZw/hA==", + "from": "react-native-picker-select@git+https://github.com/Expensify/react-native-picker-select.git#0d15d4618f58e99c1261921111e68ee85bb3c2a8", "requires": { "lodash.isequal": "^4.5.0" } diff --git a/package.json b/package.json index f80e394e2c2a..db0e0c15a3f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.5-3", + "version": "1.4.10-0", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", @@ -51,6 +51,7 @@ "symbolicate:android": "npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map", "symbolicate:ios": "npx metro-symbolicate main.jsbundle.map", "test:e2e": "node tests/e2e/testRunner.js --development --skipCheckout --skipInstallDeps --buildMode none", + "test:e2e:dev": "node tests/e2e/testRunner.js --development --skipCheckout --config ./config.dev.js --buildMode skip --skipInstallDeps", "gh-actions-unused-styles": "./.github/scripts/findUnusedKeys.sh", "workflow-test": "./workflow_tests/scripts/runWorkflowTests.sh", "workflow-test:generate": "node workflow_tests/utils/preGenerateTest.js", @@ -73,7 +74,6 @@ "@react-native-async-storage/async-storage": "^1.17.10", "@react-native-camera-roll/camera-roll": "5.4.0", "@react-native-clipboard/clipboard": "^1.12.1", - "@react-native-community/datetimepicker": "^3.5.2", "@react-native-community/geolocation": "^3.0.6", "@react-native-community/netinfo": "^9.3.10", "@react-native-firebase/analytics": "^12.3.0", @@ -125,7 +125,7 @@ "react-native-config": "^1.4.5", "react-native-dev-menu": "^4.1.1", "react-native-device-info": "^10.3.0", - "react-native-document-picker": "^8.0.0", + "react-native-document-picker": "^8.2.1", "react-native-draggable-flatlist": "^4.0.1", "react-native-fast-image": "^8.6.3", "react-native-fs": "^2.20.0", @@ -144,7 +144,7 @@ "react-native-pdf": "^6.7.3", "react-native-performance": "^5.1.0", "react-native-permissions": "^3.9.3", - "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#eae05855286dc699954415cc1d629bfd8e8e47e2", + "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#0d15d4618f58e99c1261921111e68ee85bb3c2a8", "react-native-plaid-link-sdk": "10.8.0", "react-native-qrcode-svg": "^6.2.0", "react-native-quick-sqlite": "^8.0.0-beta.2", diff --git a/scripts/build-desktop.sh b/scripts/build-desktop.sh index 88ab17e7a2bd..025559dc4671 100755 --- a/scripts/build-desktop.sh +++ b/scripts/build-desktop.sh @@ -25,4 +25,4 @@ npx webpack --config config/webpack/webpack.desktop.js --env envFile=$ENV_FILE title "Building Desktop App Archive Using Electron" info "" shift 1 -npx electron-builder --config config/electronBuilder.config.js "$@" +npx electron-builder --config config/electronBuilder.config.js --publish always "$@" diff --git a/src/App.js b/src/App.js index ac34ece5c6c7..e273dcce1e47 100644 --- a/src/App.js +++ b/src/App.js @@ -6,8 +6,10 @@ import Onyx from 'react-native-onyx'; import {PickerStateProvider} from 'react-native-picker-select'; import {SafeAreaProvider} from 'react-native-safe-area-context'; import '../wdyr'; +import ColorSchemeWrapper from './components/ColorSchemeWrapper'; import ComposeProviders from './components/ComposeProviders'; import CustomStatusBar from './components/CustomStatusBar'; +import CustomStatusBarContextProvider from './components/CustomStatusBar/CustomStatusBarContextProvider'; import ErrorBoundary from './components/ErrorBoundary'; import HTMLEngineProvider from './components/HTMLEngineProvider'; import {LocaleContextProvider} from './components/LocaleContextProvider'; @@ -51,6 +53,9 @@ function App() { - + + + diff --git a/src/CONST.ts b/src/CONST.ts index dd6eafc7f0e6..6f1fe37f661d 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -483,6 +483,7 @@ const CONST = { MAX_REPORT_PREVIEW_RECEIPTS: 3, }, REPORT: { + MAX_COUNT_BEFORE_FOCUS_UPDATE: 30, MAXIMUM_PARTICIPANTS: 8, SPLIT_REPORTID: '-2', ACTIONS: { @@ -497,6 +498,7 @@ const CONST = { MODIFIEDEXPENSE: 'MODIFIEDEXPENSE', MOVED: 'MOVED', REIMBURSEMENTQUEUED: 'REIMBURSEMENTQUEUED', + REIMBURSEMENTDEQUEUED: 'REIMBURSEMENTDEQUEUED', RENAMED: 'RENAMED', REPORTPREVIEW: 'REPORTPREVIEW', SUBMITTED: 'SUBMITTED', @@ -557,6 +559,7 @@ const CONST = { UPDATE_REPORT_FIELD: 'POLICYCHANGELOG_UPDATE_REPORT_FIELD', UPDATE_TAG: 'POLICYCHANGELOG_UPDATE_TAG', UPDATE_TAG_ENABLED: 'POLICYCHANGELOG_UPDATE_TAG_ENABLED', + UPDATE_TAG_LIST: 'POLICYCHANGELOG_UPDATE_TAG_LIST', UPDATE_TAG_LIST_NAME: 'POLICYCHANGELOG_UPDATE_TAG_LIST_NAME', UPDATE_TAG_NAME: 'POLICYCHANGELOG_UPDATE_TAG_NAME', UPDATE_TIME_ENABLED: 'POLICYCHANGELOG_UPDATE_TIME_ENABLED', @@ -600,6 +603,7 @@ const CONST = { ADMINS: '#admins', }, STATE: { + OPEN: 'OPEN', SUBMITTED: 'SUBMITTED', PROCESSING: 'PROCESSING', }, @@ -698,6 +702,14 @@ const CONST = { DARK: 'dark', SYSTEM: 'system', }, + COLOR_SCHEME: { + LIGHT: 'light', + DARK: 'dark', + }, + STATUS_BAR_STYLE: { + LIGHT_CONTENT: 'light-content', + DARK_CONTENT: 'dark-content', + }, TRANSACTION: { DEFAULT_MERCHANT: 'Request', UNKNOWN_MERCHANT: 'Unknown Merchant', @@ -953,6 +965,7 @@ const CONST = { GUIDES_DOMAIN: 'team.expensify.com', HELP: 'help@expensify.com', INTEGRATION_TESTING_CREDS: 'integrationtestingcreds@expensify.com', + NOTIFICATIONS: 'notifications@expensify.com', PAYROLL: 'payroll@expensify.com', QA: 'qa@expensify.com', QA_TRAVIS: 'qa+travisreceipts@expensify.com', @@ -972,6 +985,7 @@ const CONST = { FIRST_RESPONDER: Number(Config?.EXPENSIFY_ACCOUNT_ID_FIRST_RESPONDER ?? 9375152), HELP: Number(Config?.EXPENSIFY_ACCOUNT_ID_HELP ?? -1), INTEGRATION_TESTING_CREDS: Number(Config?.EXPENSIFY_ACCOUNT_ID_INTEGRATION_TESTING_CREDS ?? -1), + NOTIFICATIONS: Number(Config?.EXPENSIFY_ACCOUNT_ID_NOTIFICATIONS ?? 11665625), PAYROLL: Number(Config?.EXPENSIFY_ACCOUNT_ID_PAYROLL ?? 9679724), QA: Number(Config?.EXPENSIFY_ACCOUNT_ID_QA ?? 3126513), QA_TRAVIS: Number(Config?.EXPENSIFY_ACCOUNT_ID_QA_TRAVIS ?? 8595733), @@ -1121,6 +1135,8 @@ const CONST = { }, IOU: { + // This is the transactionID used when going through the create money request flow so that it mimics a real transaction (like the edit flow) + OPTIMISTIC_TRANSACTION_ID: '1', // Note: These payment types are used when building IOU reportAction message values in the server and should // not be changed. PAYMENT_TYPE: { @@ -1133,6 +1149,11 @@ const CONST = { SPLIT: 'split', REQUEST: 'request', }, + REQUEST_TYPE: { + DISTANCE: 'distance', + MANUAL: 'manual', + SCAN: 'scan', + }, REPORT_ACTION_TYPE: { PAY: 'pay', CREATE: 'create', @@ -1156,6 +1177,9 @@ const CONST = { SVG: 'svg', }, RECEIPT_ERROR: 'receiptError', + CANCEL_REASON: { + PAYMENT_EXPIRED: 'CANCEL_REASON_PAYMENT_EXPIRED', + }, }, GROWL: { @@ -1359,7 +1383,6 @@ const CONST = { TIME_STARTS_01: /^01:\d{2} [AP]M$/, TIME_FORMAT: /^\d{2}:\d{2} [AP]M$/, DATE_TIME_FORMAT: /^\d{2}-\d{2} \d{2}:\d{2} [AP]M$/, - ATTACHMENT_ROUTE: /\/r\/(\d*)\/attachment/, ILLEGAL_FILENAME_CHARACTERS: /\/|<|>|\*|"|:|\?|\\|\|/g, ENCODE_PERCENT_CHARACTER: /%(25)+/g, @@ -1396,6 +1419,7 @@ const CONST = { this.EMAIL.FIRST_RESPONDER, this.EMAIL.HELP, this.EMAIL.INTEGRATION_TESTING_CREDS, + this.EMAIL.NOTIFICATIONS, this.EMAIL.PAYROLL, this.EMAIL.QA, this.EMAIL.QA_TRAVIS, @@ -2738,6 +2762,9 @@ const CONST = { NEW_CHAT: 'chat', NEW_ROOM: 'room', RECEIPT_TAB_ID: 'ReceiptTab', + IOU_REQUEST_TYPE: 'iouRequestType', + }, + TAB_REQUEST: { MANUAL: 'manual', SCAN: 'scan', DISTANCE: 'distance', @@ -2791,7 +2818,7 @@ const CONST = { HORIZONTAL_SPACER: { DEFAULT_BORDER_BOTTOM_WIDTH: 1, DEFAULT_MARGIN_VERTICAL: 8, - HIDDEN_MARGIN_VERTICAL: 0, + HIDDEN_MARGIN_VERTICAL: 4, HIDDEN_BORDER_BOTTOM_WIDTH: 0, }, @@ -2844,6 +2871,33 @@ const CONST = { RUNS: 20, }, + /** + * Bank account names + */ + BANK_NAMES: { + EXPENSIFY: 'expensify', + AMERICAN_EXPRESS: 'americanexpress', + BANK_OF_AMERICA: 'bank of america', + BB_T: 'bbt', + CAPITAL_ONE: 'capital one', + CHASE: 'chase', + CHARLES_SCHWAB: 'charles schwab', + CITIBANK: 'citibank', + CITIZENS_BANK: 'citizens bank', + DISCOVER: 'discover', + FIDELITY: 'fidelity', + GENERIC_BANK: 'generic bank', + HUNTINGTON_BANK: 'huntington bank', + HUNTINGTON_NATIONAL: 'huntington national', + NAVY_FEDERAL_CREDIT_UNION: 'navy federal credit union', + PNC: 'pnc', + REGIONS_BANK: 'regions bank', + SUNTRUST: 'suntrust', + TD_BANK: 'td bank', + US_BANK: 'us bank', + USAA: 'usaa', + }, + /** * Constants for maxToRenderPerBatch parameter that is used for FlatList or SectionList. This controls the amount of items rendered per batch, which is the next chunk of items rendered on every scroll. */ diff --git a/src/Expensify.js b/src/Expensify.js index 1b692f86a197..aece93c0ff4d 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -7,6 +7,7 @@ import _ from 'underscore'; import ConfirmModal from './components/ConfirmModal'; import DeeplinkWrapper from './components/DeeplinkWrapper'; import EmojiPicker from './components/EmojiPicker/EmojiPicker'; +import FocusModeNotification from './components/FocusModeNotification'; import GrowlNotification from './components/GrowlNotification'; import AppleAuthWrapper from './components/SignInButtons/AppleAuthWrapper'; import SplashScreenHider from './components/SplashScreenHider'; @@ -76,6 +77,9 @@ const propTypes = { /** Whether the app is waiting for the server's response to determine if a room is public */ isCheckingPublicRoom: PropTypes.bool, + /** Whether we should display the notification alerting the user that focus mode has been auto-enabled */ + focusModeNotification: PropTypes.bool, + ...withLocalizePropTypes, }; @@ -88,6 +92,7 @@ const defaultProps = { isSidebarLoaded: false, screenShareRequest: null, isCheckingPublicRoom: true, + focusModeNotification: false, }; const SplashScreenHiddenContext = React.createContext({}); @@ -221,6 +226,7 @@ function Expensify(props) { isVisible /> ) : null} + {props.focusModeNotification ? : null} )} @@ -261,6 +267,10 @@ export default compose( screenShareRequest: { key: ONYXKEYS.SCREEN_SHARE_REQUEST, }, + focusModeNotification: { + key: ONYXKEYS.FOCUS_MODE_NOTIFICATION, + initWithStoredValues: false, + }, }), )(Expensify); diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 5576eb64736d..9cd55b41455b 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -152,6 +152,12 @@ const ONYXKEYS = { /** The user's cash card and imported cards (including the Expensify Card) */ CARD_LIST: 'cardList', + /** Whether the user has tried focus mode yet */ + NVP_TRY_FOCUS_MODE: 'tryFocusMode', + + /** Boolean flag used to display the focus mode notification */ + FOCUS_MODE_NOTIFICATION: 'focusModeNotification', + /** Stores information about the user's saved statements */ WALLET_STATEMENT: 'walletStatement', @@ -265,6 +271,7 @@ const ONYXKEYS = { REPORT_USER_IS_LEAVING_ROOM: 'reportUserIsLeavingRoom_', SECURITY_GROUP: 'securityGroup_', TRANSACTION: 'transactions_', + TRANSACTION_VIOLATIONS: 'transactionViolations_', // Holds temporary transactions used during the creation and edit flow TRANSACTION_DRAFT: 'transactionsDraft_', @@ -382,6 +389,8 @@ type OnyxValues = { [ONYXKEYS.NVP_PRIORITY_MODE]: ValueOf; [ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE]: OnyxTypes.BlockedFromConcierge; [ONYXKEYS.NVP_PRIVATE_PUSH_NOTIFICATION_ID]: string; + [ONYXKEYS.NVP_TRY_FOCUS_MODE]: boolean; + [ONYXKEYS.FOCUS_MODE_NOTIFICATION]: boolean; [ONYXKEYS.NVP_LAST_PAYMENT_METHOD]: Record; [ONYXKEYS.NVP_RECENT_WAYPOINTS]: OnyxTypes.RecentWaypoint[]; [ONYXKEYS.PUSH_NOTIFICATIONS_ENABLED]: boolean; @@ -389,7 +398,7 @@ type OnyxValues = { [ONYXKEYS.IS_PLAID_DISABLED]: boolean; [ONYXKEYS.PLAID_LINK_TOKEN]: string; [ONYXKEYS.ONFIDO_TOKEN]: string; - [ONYXKEYS.NVP_PREFERRED_LOCALE]: ValueOf; + [ONYXKEYS.NVP_PREFERRED_LOCALE]: OnyxTypes.Locale; [ONYXKEYS.USER_WALLET]: OnyxTypes.UserWallet; [ONYXKEYS.WALLET_ONFIDO]: OnyxTypes.WalletOnfido; [ONYXKEYS.WALLET_ADDITIONAL_DETAILS]: OnyxTypes.WalletAdditionalDetails; @@ -407,6 +416,7 @@ type OnyxValues = { [ONYXKEYS.IS_LOADING_PAYMENT_METHODS]: boolean; [ONYXKEYS.IS_LOADING_REPORT_DATA]: boolean; [ONYXKEYS.IS_TEST_TOOLS_MODAL_OPEN]: boolean; + [ONYXKEYS.IS_LOADING_APP]: boolean; [ONYXKEYS.WALLET_TRANSFER]: OnyxTypes.WalletTransfer; [ONYXKEYS.LAST_ACCESSED_WORKSPACE_POLICY_ID]: string; [ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT]: boolean; @@ -419,6 +429,7 @@ type OnyxValues = { [ONYXKEYS.MAPBOX_ACCESS_TOKEN]: OnyxTypes.MapboxAccessToken; [ONYXKEYS.ONYX_UPDATES_FROM_SERVER]: OnyxTypes.OnyxUpdatesFromServer; [ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT]: number; + [ONYXKEYS.DEMO_INFO]: OnyxTypes.DemoInfo; [ONYXKEYS.MAX_CANVAS_AREA]: number; [ONYXKEYS.MAX_CANVAS_HEIGHT]: number; [ONYXKEYS.MAX_CANVAS_WIDTH]: number; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 24b698c24619..53763d6d7cd1 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -13,7 +13,8 @@ function getUrlWithBackToParam(url: TUrl, backTo?: string): const ROUTES = { HOME: '', - /** This is a utility route used to go to the user's concierge chat, or the sign-in page if the user's not authenticated */ + + // This is a utility route used to go to the user's concierge chat, or the sign-in page if the user's not authenticated CONCIERGE: 'concierge', FLAG_COMMENT: { route: 'flag/:reportID/:reportActionID', @@ -130,7 +131,10 @@ const ROUTES = { route: 'settings/profile/contact-methods/:contactMethod/details', getRoute: (contactMethod: string) => `settings/profile/contact-methods/${encodeURIComponent(contactMethod)}/details` as const, }, - SETTINGS_NEW_CONTACT_METHOD: 'settings/profile/contact-methods/new', + SETTINGS_NEW_CONTACT_METHOD: { + route: 'settings/profile/contact-methods/new', + getRoute: (backTo?: string) => getUrlWithBackToParam('settings/profile/contact-methods/new', backTo), + }, SETTINGS_2FA: { route: 'settings/security/two-factor-auth', getRoute: (backTo?: string) => getUrlWithBackToParam('settings/security/two-factor-auth', backTo), @@ -303,6 +307,82 @@ const ROUTES = { MONEY_REQUEST_MANUAL_TAB: ':iouType/new/:reportID?/manual', MONEY_REQUEST_SCAN_TAB: ':iouType/new/:reportID?/scan', + MONEY_REQUEST_CREATE: { + route: 'create/:iouType/start/:transactionID/:reportID', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/start/${transactionID}/${reportID}` as const, + }, + MONEY_REQUEST_STEP_CONFIRMATION: { + route: 'create/:iouType/confirmation/:transactionID/:reportID/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/confirmation/${transactionID}/${reportID}/` as const, + }, + MONEY_REQUEST_STEP_AMOUNT: { + route: 'create/:iouType/amount/:transactionID/:reportID/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`create/${iouType}/amount/${transactionID}/${reportID}/`, backTo), + }, + MONEY_REQUEST_STEP_CATEGORY: { + route: 'create/:iouType/category/:transactionID/:reportID/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`create/${iouType}/category/${transactionID}/${reportID}/`, backTo), + }, + MONEY_REQUEST_STEP_CURRENCY: { + route: 'create/:iouType/currency/:transactionID/:reportID/:pageIndex?/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, pageIndex = '', backTo = '') => + getUrlWithBackToParam(`create/${iouType}/currency/${transactionID}/${reportID}/${pageIndex}`, backTo), + }, + MONEY_REQUEST_STEP_DATE: { + route: 'create/:iouType/date/:transactionID/:reportID/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`create/${iouType}/date/${transactionID}/${reportID}/`, backTo), + }, + MONEY_REQUEST_STEP_DESCRIPTION: { + route: 'create/:iouType/description/:transactionID/:reportID/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`create/${iouType}/description/${transactionID}/${reportID}/`, backTo), + }, + MONEY_REQUEST_STEP_DISTANCE: { + route: 'create/:iouType/distance/:transactionID/:reportID/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`create/${iouType}/distance/${transactionID}/${reportID}/`, backTo), + }, + MONEY_REQUEST_STEP_MERCHANT: { + route: 'create/:iouType/merchante/:transactionID/:reportID/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`create/${iouType}/merchante/${transactionID}/${reportID}/`, backTo), + }, + MONEY_REQUEST_STEP_PARTICIPANTS: { + route: 'create/:iouType/participants/:transactionID/:reportID/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`create/${iouType}/participants/${transactionID}/${reportID}/`, backTo), + }, + MONEY_REQUEST_STEP_SCAN: { + route: 'create/:iouType/scan/:transactionID/:reportID/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`create/${iouType}/scan/${transactionID}/${reportID}/`, backTo), + }, + MONEY_REQUEST_STEP_TAG: { + route: 'create/:iouType/tag/:transactionID/:reportID/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`create/${iouType}/tag/${transactionID}/${reportID}/`, backTo), + }, + MONEY_REQUEST_STEP_WAYPOINT: { + route: 'create/:iouType/waypoint/:transactionID/:reportID/:pageIndex/', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string, pageIndex = '', backTo = '') => + getUrlWithBackToParam(`create/${iouType}/waypoint/${transactionID}/${reportID}/${pageIndex}`, backTo), + }, + MONEY_REQUEST_CREATE_TAB_DISTANCE: { + route: 'create/:iouType/start/:transactionID/:reportID/distance', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/start/${transactionID}/${reportID}/distance` as const, + }, + MONEY_REQUEST_CREATE_TAB_MANUAL: { + route: 'create/:iouType/start/:transactionID/:reportID/manual', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/start/${transactionID}/${reportID}/manual` as const, + }, + MONEY_REQUEST_CREATE_TAB_SCAN: { + route: 'create/:iouType/start/:transactionID/:reportID/scan', + getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/start/${transactionID}/${reportID}/scan` as const, + }, + IOU_REQUEST: 'request/new', IOU_SEND: 'send/new', IOU_SEND_ADD_BANK_ACCOUNT: 'send/new/add-bank-account', @@ -388,6 +468,7 @@ const ROUTES = { MONEY2020: 'money2020', } as const; +export {getUrlWithBackToParam}; export default ROUTES; // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/SCREENS.ts b/src/SCREENS.ts index f4cbcf4f2564..38bd88a87158 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -2,6 +2,7 @@ * This is a file containing constants for all of the screen names. In most cases, we should use the routes for * navigation. But there are situations where we may need to access screen names directly. */ +import DeepValueOf from './types/utils/DeepValueOf'; const PROTECTED_SCREENS = { HOME: 'Home', @@ -22,6 +23,25 @@ const SCREENS = { WORKSPACES: 'Settings_Workspaces', SECURITY: 'Settings_Security', STATUS: 'Settings_Status', + PROFILE: 'Settings_Profile', + PRONOUNS: 'Settings_Pronouns', + DISPLAY_NAME: 'Settings_Display_Name', + TIMEZONE: 'Settings_Timezone', + TIMEZONE_SELECT: 'Settings_Timezone_Select', + CONTACT_METHODS: 'Settings_ContactMethods', + CONTACT_METHOD_DETAILS: 'Settings_ContactMethodDetails', + NEW_CONTACT_METHOD: 'Settings_NewContactMethod', + SHARE_CODE: 'Settings_Share_Code', + ABOUT: 'Settings_About', + APP_DOWNLOAD_LINKS: 'Settings_App_Download_Links', + LOUNGE_ACCESS: 'Settings_Lounge_Access', + + PERSONAL_DETAILS_INITIAL: 'Settings_PersonalDetails_Initial', + PERSONAL_DETAILS_LEGAL_NAME: 'Settings_PersonalDetails_LegalName', + PERSONAL_DETAILS_DATE_OF_BIRTH: 'Settings_PersonalDetails_DateOfBirth', + PERSONAL_DETAILS_ADDRESS: 'Settings_PersonalDetails_Address', + PERSONAL_DETAILS_ADDRESS_COUNTRY: 'Settings_PersonalDetails_Address_Country', + WALLET: 'Settings_Wallet', WALLET_DOMAIN_CARD: 'Settings_Wallet_DomainCard', WALLET_CARD_GET_PHYSICAL: { @@ -30,15 +50,179 @@ const SCREENS = { ADDRESS: 'Settings_Card_Get_Physical_Address', CONFIRM: 'Settings_Card_Get_Physical_Confirm', }, + WALLET_TRANSFER_BALANCE: 'Settings_Wallet_Transfer_Balance', + WALLET_CHOOSE_TRANSFER_ACCOUNT: 'Settings_Wallet_Choose_Transfer_Account', + WALLET_ENABLE_PAYMENTS: 'Settings_Wallet_EnablePayments', + WALLET_CARD_ACTIVATE: 'Settings_Wallet_Card_Activate', + WALLET_REPORT_VIRTUAL_CARD_FRAUD: 'Settings_Wallet_ReportVirtualCardFraud', + WALLET_CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS: 'Settings_Wallet_Cards_Digital_Details_Update_Address', + + ADD_DEBIT_CARD: 'Settings_Add_Debit_Card', + ADD_BANK_ACCOUNT: 'Settings_Add_Bank_Account', + PREFERENCES_PRIORITY_MODE: 'Settings_Preferences_PriorityMode', + PREFERENCES_LANGUAGE: 'Settings_Preferences_Language', + PREFERENCES_THEME: 'Settings_Preferences_Theme', + CLOSE: 'Settings_Close', + STATUS_SET: 'Settings_Status_Set', + TWO_FACTOR_AUTH: 'Settings_TwoFactorAuth', + REPORT_CARD_LOST_OR_DAMAGED: 'Settings_ReportCardLostOrDamaged', }, SAVE_THE_WORLD: { ROOT: 'SaveTheWorld_Root', }, + RIGHT_MODAL: { + SETTINGS: 'Settings', + NEW_CHAT: 'NewChat', + SEARCH: 'Search', + DETAILS: 'Details', + PROFILE: 'Profile', + REPORT_DETAILS: 'Report_Details', + REPORT_SETTINGS: 'Report_Settings', + REPORT_WELCOME_MESSAGE: 'Report_WelcomeMessage', + PARTICIPANTS: 'Participants', + MONEY_REQUEST: 'MoneyRequest', + NEW_TASK: 'NewTask', + TEACHERS_UNITE: 'TeachersUnite', + TASK_DETAILS: 'Task_Details', + ENABLE_PAYMENTS: 'EnablePayments', + SPLIT_DETAILS: 'SplitDetails', + ADD_PERSONAL_BANK_ACCOUNT: 'AddPersonalBankAccount', + WALLET_STATEMENT: 'Wallet_Statement', + FLAG_COMMENT: 'Flag_Comment', + EDIT_REQUEST: 'EditRequest', + SIGN_IN: 'SignIn', + PRIVATE_NOTES: 'Private_Notes', + ROOM_MEMBERS: 'RoomMembers', + ROOM_INVITE: 'RoomInvite', + REFERRAL: 'Referral', + }, SIGN_IN_WITH_APPLE_DESKTOP: 'AppleSignInDesktop', SIGN_IN_WITH_GOOGLE_DESKTOP: 'GoogleSignInDesktop', DESKTOP_SIGN_IN_REDIRECT: 'DesktopSignInRedirect', SAML_SIGN_IN: 'SAMLSignIn', + + MONEY_REQUEST: { + CREATE: 'Money_Request_Create', + STEP_CONFIRMATION: 'Money_Request_Step_Confirmation', + STEP_AMOUNT: 'Money_Request_Step_Amount', + STEP_CATEGORY: 'Money_Request_Step_Category', + STEP_CURRENCY: 'Money_Request_Step_Currency', + STEP_DATE: 'Money_Request_Step_Date', + STEP_DESCRIPTION: 'Money_Request_Step_Description', + STEP_DISTANCE: 'Money_Request_Step_Distance', + STEP_MERCHANT: 'Money_Request_Step_Merchant', + STEP_PARTICIPANTS: 'Money_Request_Step_Participants', + STEP_SCAN: 'Money_Request_Step_Scan', + STEP_TAG: 'Money_Request_Step_Tag', + STEP_WAYPOINT: 'Money_Request_Step_Waypoint', + ROOT: 'Money_Request', + AMOUNT: 'Money_Request_Amount', + PARTICIPANTS: 'Money_Request_Participants', + CONFIRMATION: 'Money_Request_Confirmation', + CURRENCY: 'Money_Request_Currency', + DATE: 'Money_Request_Date', + DESCRIPTION: 'Money_Request_Description', + CATEGORY: 'Money_Request_Category', + TAG: 'Money_Request_Tag', + MERCHANT: 'Money_Request_Merchant', + WAYPOINT: 'Money_Request_Waypoint', + EDIT_WAYPOINT: 'Money_Request_Edit_Waypoint', + DISTANCE: 'Money_Request_Distance', + RECEIPT: 'Money_Request_Receipt', + }, + + IOU_SEND: { + ADD_BANK_ACCOUNT: 'IOU_Send_Add_Bank_Account', + ADD_DEBIT_CARD: 'IOU_Send_Add_Debit_Card', + ENABLE_PAYMENTS: 'IOU_Send_Enable_Payments', + }, + + REPORT_SETTINGS: { + ROOT: 'Report_Settings_Root', + ROOM_NAME: 'Report_Settings_Room_Name', + NOTIFICATION_PREFERENCES: 'Report_Settings_Notification_Preferences', + WRITE_CAPABILITY: 'Report_Settings_Write_Capability', + }, + + NEW_TASK: { + ROOT: 'NewTask_Root', + TASK_ASSIGNEE_SELECTOR: 'NewTask_TaskAssigneeSelector', + TASK_SHARE_DESTINATION_SELECTOR: 'NewTask_TaskShareDestinationSelector', + DETAILS: 'NewTask_Details', + TITLE: 'NewTask_Title', + DESCRIPTION: 'NewTask_Description', + }, + + TASK: { + TITLE: 'Task_Title', + DESCRIPTION: 'Task_Description', + ASSIGNEE: 'Task_Assignee', + }, + + PRIVATE_NOTES: { + VIEW: 'PrivateNotes_View', + LIST: 'PrivateNotes_List', + EDIT: 'PrivateNotes_Edit', + }, + + REPORT_DETAILS: { + ROOT: 'Report_Details_Root', + SHARE_CODE: 'Report_Details_Share_Code', + }, + + WORKSPACE: { + INITIAL: 'Workspace_Initial', + SETTINGS: 'Workspace_Settings', + CARD: 'Workspace_Card', + REIMBURSE: 'Workspace_Reimburse', + RATE_AND_UNIT: 'Workspace_RateAndUnit', + BILLS: 'Workspace_Bills', + INVOICES: 'Workspace_Invoices', + TRAVEL: 'Workspace_Travel', + MEMBERS: 'Workspace_Members', + INVITE: 'Workspace_Invite', + INVITE_MESSAGE: 'Workspace_Invite_Message', + CURRENCY: 'Workspace_Settings_Currency', + }, + + EDIT_REQUEST: { + ROOT: 'EditRequest_Root', + CURRENCY: 'EditRequest_Currency', + }, + + I_KNOW_A_TEACHER: 'I_Know_A_Teacher', + INTRO_SCHOOL_PRINCIPAL: 'Intro_School_Principal', + I_AM_A_TEACHER: 'I_Am_A_Teacher', + + ENABLE_PAYMENTS_ROOT: 'EnablePayments_Root', + ADD_PERSONAL_BANK_ACCOUNT_ROOT: 'AddPersonalBankAccount_Root', + REIMBURSEMENT_ACCOUNT_ROOT: 'Reimbursement_Account_Root', + WALLET_STATEMENT_ROOT: 'WalletStatement_Root', + SIGN_IN_ROOT: 'SignIn_Root', + DETAILS_ROOT: 'Details_Root', + PROFILE_ROOT: 'Profile_Root', + REPORT_WELCOME_MESSAGE_ROOT: 'Report_WelcomeMessage_Root', + REPORT_PARTICIPANTS_ROOT: 'ReportParticipants_Root', + ROOM_MEMBERS_ROOT: 'RoomMembers_Root', + ROOM_INVITE_ROOT: 'RoomInvite_Root', + SEARCH_ROOT: 'Search_Root', + NEW_CHAT_ROOT: 'NewChat_Root', + FLAG_COMMENT_ROOT: 'FlagComment_Root', + + SPLIT_DETAILS: { + ROOT: 'SplitDetails_Root', + EDIT_REQUEST: 'SplitDetails_Edit_Request', + EDIT_CURRENCY: 'SplitDetails_Edit_Currency', + }, + + REIMBURSEMENT_ACCOUNT: 'ReimbursementAccount', + GET_ASSISTANCE: 'GetAssistance', + REFERRAL_DETAILS: 'Referral_Details', + KEYBOARD_SHORTCUTS: 'KeyboardShortcuts', } as const; +type Screen = DeepValueOf; + export default SCREENS; export {PROTECTED_SCREENS}; +export type {Screen}; diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index c18b706e1acf..68d529c4a78d 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -168,7 +168,7 @@ function AddPlaidBankAccount({ value: account.plaidAccountID, label: `${account.addressName} ${account.mask}`, })); - const {icon, iconSize, iconStyles} = getBankIcon({themeStyles: styles}); + const {icon, iconSize, iconStyles} = getBankIcon({styles}); const plaidErrors = lodashGet(plaidData, 'errors'); const plaidDataErrorMessage = !_.isEmpty(plaidErrors) ? _.chain(plaidErrors).values().first().value() : ''; const bankName = lodashGet(plaidData, 'bankName'); diff --git a/src/components/AddressSearch/CurrentLocationButton.js b/src/components/AddressSearch/CurrentLocationButton.js index 3c7feb8fb70c..90d2c15733f1 100644 --- a/src/components/AddressSearch/CurrentLocationButton.js +++ b/src/components/AddressSearch/CurrentLocationButton.js @@ -7,7 +7,7 @@ import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import useLocalize from '@hooks/useLocalize'; import getButtonState from '@libs/getButtonState'; import colors from '@styles/colors'; -import * as StyleUtils from '@styles/StyleUtils'; +import useStyleUtils from '@styles/useStyleUtils'; import useThemeStyles from '@styles/useThemeStyles'; const propTypes = { @@ -25,6 +25,7 @@ const defaultProps = { function CurrentLocationButton({onPress, isDisabled}) { const styles = useThemeStyles(); + const StyleUtils = useStyleUtils(); const {translate} = useLocalize(); return ( diff --git a/src/components/AddressSearch/index.js b/src/components/AddressSearch/index.js index a401300e920d..2fed1d153947 100644 --- a/src/components/AddressSearch/index.js +++ b/src/components/AddressSearch/index.js @@ -14,8 +14,8 @@ import * as ApiUtils from '@libs/ApiUtils'; import compose from '@libs/compose'; import getCurrentPosition from '@libs/getCurrentPosition'; import * as GooglePlacesUtils from '@libs/GooglePlacesUtils'; -import * as StyleUtils from '@styles/StyleUtils'; import useTheme from '@styles/themes/useTheme'; +import useStyleUtils from '@styles/useStyleUtils'; import useThemeStyles from '@styles/useThemeStyles'; import variables from '@styles/variables'; import CONST from '@src/CONST'; @@ -165,6 +165,7 @@ function AddressSearch({ }) { const theme = useTheme(); const styles = useThemeStyles(); + const StyleUtils = useStyleUtils(); const [displayListViewBorder, setDisplayListViewBorder] = useState(false); const [isTyping, setIsTyping] = useState(false); const [isFocused, setIsFocused] = useState(false); diff --git a/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js index 33d6cb014df2..53afebfd2207 100644 --- a/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js +++ b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js @@ -11,7 +11,7 @@ import useWindowDimensions from '@hooks/useWindowDimensions'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import * as ContextMenuActions from '@pages/home/report/ContextMenu/ContextMenuActions'; import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu'; -import * as StyleUtils from '@styles/StyleUtils'; +import useStyleUtils from '@styles/useStyleUtils'; import useThemeStyles from '@styles/useThemeStyles'; import CONST from '@src/CONST'; import {propTypes as anchorForCommentsOnlyPropTypes} from './anchorForCommentsOnlyPropTypes'; @@ -33,6 +33,7 @@ const propTypes = { */ function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '', target = '', children = null, style = {}, onPress, ...rest}) { const styles = useThemeStyles(); + const StyleUtils = useStyleUtils(); useEffect( () => () => { ReportActionContextMenu.hideContextMenu(); diff --git a/src/components/AnonymousReportFooter.js b/src/components/AnonymousReportFooter.tsx similarity index 51% rename from src/components/AnonymousReportFooter.js rename to src/components/AnonymousReportFooter.tsx index 387e2ab01930..65dc813a829d 100644 --- a/src/components/AnonymousReportFooter.js +++ b/src/components/AnonymousReportFooter.tsx @@ -1,57 +1,52 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {Text, View} from 'react-native'; -import reportPropTypes from '@pages/reportPropTypes'; +import {OnyxCollection} from 'react-native-onyx'; +import {OnyxEntry} from 'react-native-onyx/lib/types'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@styles/useThemeStyles'; import * as Session from '@userActions/Session'; +import {PersonalDetails, Report} from '@src/types/onyx'; import AvatarWithDisplayName from './AvatarWithDisplayName'; import Button from './Button'; import ExpensifyWordmark from './ExpensifyWordmark'; -import participantPropTypes from './participantPropTypes'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; -const propTypes = { +type AnonymousReportFooterProps = { /** The report currently being looked at */ - report: reportPropTypes, + report: OnyxEntry; - isSmallSizeLayout: PropTypes.bool, + /** Whether the small screen size layout should be used */ + isSmallSizeLayout?: boolean; /** Personal details of all the users */ - personalDetails: PropTypes.objectOf(participantPropTypes), - - ...withLocalizePropTypes, -}; - -const defaultProps = { - report: {}, - isSmallSizeLayout: false, - personalDetails: {}, + personalDetails: OnyxCollection; }; -function AnonymousReportFooter(props) { +function AnonymousReportFooter({isSmallSizeLayout = false, personalDetails, report}: AnonymousReportFooterProps) { const styles = useThemeStyles(); + const {translate} = useLocalize(); + return ( - + - - - + + + - {props.translate('anonymousReportFooter.logoTagline')} + {translate('anonymousReportFooter.logoTagline')}