diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 4bf7987f9ceb..c3f52b0a6f08 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -159,9 +159,13 @@ const ONYXKEYS = { /** Whether the user has seen HybridApp explanation modal */ NVP_SEEN_NEW_USER_MODAL: 'nvp_seen_new_user_modal', + /** Store the state of the subscription */ NVP_PRIVATE_SUBSCRIPTION: 'nvp_private_subscription', + /** Store the state of the private tax-exempt */ + NVP_PRIVATE_TAX_EXEMPT: 'nvp_private_taxExempt', + /** Store the stripe id status */ NVP_PRIVATE_STRIPE_CUSTOMER_ID: 'nvp_private_stripeCustomerID', @@ -841,6 +845,7 @@ type OnyxValuesMapping = { [ONYXKEYS.UPDATE_REQUIRED]: boolean; [ONYXKEYS.RESET_REQUIRED]: boolean; [ONYXKEYS.PLAID_CURRENT_EVENT]: string; + [ONYXKEYS.NVP_PRIVATE_TAX_EXEMPT]: boolean; [ONYXKEYS.LOGS]: OnyxTypes.CapturedLogs; [ONYXKEYS.SHOULD_STORE_LOGS]: boolean; [ONYXKEYS.SHOULD_MASK_ONYX_STATE]: boolean; diff --git a/src/components/ThreeDotsMenu/index.tsx b/src/components/ThreeDotsMenu/index.tsx index 7c3358e4688c..da72135c6035 100644 --- a/src/components/ThreeDotsMenu/index.tsx +++ b/src/components/ThreeDotsMenu/index.tsx @@ -91,7 +91,7 @@ function ThreeDotsMenu({ > diff --git a/src/languages/en.ts b/src/languages/en.ts index cb5e0b76edef..09aeb1320c07 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -4195,6 +4195,8 @@ export default { details: { title: 'Subscription details', annual: 'Annual subscription', + taxExempt: 'Request tax exempt status', + taxExemptEnabled: 'Tax exempt', payPerUse: 'Pay-per-use', subscriptionSize: 'Subscription size', headsUp: diff --git a/src/languages/es.ts b/src/languages/es.ts index 6f4ba907fc9c..893ec702b2d4 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -4718,6 +4718,8 @@ export default { details: { title: 'Datos de suscripción', annual: 'Suscripción anual', + taxExempt: 'Solicitar estado de exención de impuestos', + taxExemptEnabled: 'Exento de impuestos', payPerUse: 'Pago por uso', subscriptionSize: 'Tamaño de suscripción', headsUp: diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index f15fba20bc98..bc34cf32e885 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -318,6 +318,7 @@ const WRITE_COMMANDS = { UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_CREDIT_CARD_CHARGE_EXPORT_DEFAULT_VENDOR: 'UpdateSageIntacctNonreimbursableExpensesCreditCardChargeExportDefaultVendor', UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_ACCOUNT: 'UpdateSageIntacctNonreimbursableExpensesExportAccount', UPDATE_SAGE_INTACCT_NON_REIMBURSABLE_EXPENSES_EXPORT_VENDOR: 'UpdateSageIntacctNonreimbursableExpensesExportVendor', + REQUEST_TAX_EXEMPTION: 'RequestTaxExemption', EXPORT_SEARCH_ITEMS_TO_CSV: 'ExportSearchToCSV', CREATE_WORKSPACE_APPROVAL: 'CreateWorkspaceApproval', UPDATE_WORKSPACE_APPROVAL: 'UpdateWorkspaceApproval', @@ -563,6 +564,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_AUTO_RENEW]: Parameters.UpdateSubscriptionAutoRenewParams; [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_ADD_NEW_USERS_AUTOMATICALLY]: Parameters.UpdateSubscriptionAddNewUsersAutomaticallyParams; [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_SIZE]: Parameters.UpdateSubscriptionSizeParams; + [WRITE_COMMANDS.REQUEST_TAX_EXEMPTION]: null; [WRITE_COMMANDS.DELETE_MONEY_REQUEST_ON_SEARCH]: Parameters.DeleteMoneyRequestOnSearchParams; [WRITE_COMMANDS.HOLD_MONEY_REQUEST_ON_SEARCH]: Parameters.HoldMoneyRequestOnSearchParams; diff --git a/src/libs/actions/Subscription.ts b/src/libs/actions/Subscription.ts index aaec38dbf5f8..0b431d5f36ed 100644 --- a/src/libs/actions/Subscription.ts +++ b/src/libs/actions/Subscription.ts @@ -288,6 +288,10 @@ function cancelBillingSubscription(cancellationReason: FeedbackSurveyOptionID, c API.write(WRITE_COMMANDS.CANCEL_BILLING_SUBSCRIPTION, parameters); } +function requestTaxExempt() { + API.write(WRITE_COMMANDS.REQUEST_TAX_EXEMPTION, null); +} + export { openSubscriptionPage, updateSubscriptionAutoRenew, @@ -297,4 +301,5 @@ export { updateSubscriptionType, clearOutstandingBalance, cancelBillingSubscription, + requestTaxExempt, }; diff --git a/src/pages/settings/Subscription/SubscriptionDetails/index.tsx b/src/pages/settings/Subscription/SubscriptionDetails/index.tsx index 870914488176..c78847cb35aa 100644 --- a/src/pages/settings/Subscription/SubscriptionDetails/index.tsx +++ b/src/pages/settings/Subscription/SubscriptionDetails/index.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import Badge from '@components/Badge'; import Icon from '@components/Icon'; import * as Illustrations from '@components/Icon/Illustrations'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; @@ -13,6 +14,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeIllustrations from '@hooks/useThemeIllustrations'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; +import TaxExemptActions from '@pages/settings/Subscription/TaxExemptActions'; import variables from '@styles/variables'; import * as Subscription from '@userActions/Subscription'; import type {SubscriptionType} from '@src/CONST'; @@ -39,6 +41,7 @@ function SubscriptionDetails() { const illustrations = useThemeIllustrations(); const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION); + const [privateTaxExempt] = useOnyx(ONYXKEYS.NVP_PRIVATE_TAX_EXEMPT); const [account] = useOnyx(ONYXKEYS.ACCOUNT); const onOptionSelected = (option: SubscriptionType) => { @@ -80,10 +83,21 @@ function SubscriptionDetails() { return (
+ + + {translate('subscription.details.title')} + {privateTaxExempt && ( + + )} + + {!privateTaxExempt && } + {!!account?.isApprovedAccountant || !!account?.isApprovedAccountantClient ? ( ({horizontal: 0, vertical: 0}); + const threeDotsMenuContainerRef = useRef(null); + + const overflowMenu: ThreeDotsMenuProps['menuItems'] = useMemo( + () => [ + { + icon: Expensicons.Coins, + numberOfLinesTitle: 2, + text: translate('subscription.details.taxExempt'), + onSelected: () => { + Subscription.requestTaxExempt(); + Report.navigateToConciergeChat(); + }, + }, + ], + [translate], + ); + + const calculateAndSetThreeDotsMenuPosition = useCallback(() => { + if (shouldUseNarrowLayout) { + return; + } + threeDotsMenuContainerRef.current?.measureInWindow((x, y, width, height) => { + setThreeDotsMenuPosition({ + horizontal: x + width, + vertical: y + height, + }); + }); + }, [shouldUseNarrowLayout]); + + return ( + + + + ); +} + +TaxExemptActions.displayName = 'TaxExemptActions'; + +export default TaxExemptActions; diff --git a/src/styles/utils/positioning.ts b/src/styles/utils/positioning.ts index c266a7469bc2..cbfa8875b9ad 100644 --- a/src/styles/utils/positioning.ts +++ b/src/styles/utils/positioning.ts @@ -55,6 +55,9 @@ export default { r8: { right: 32, }, + rn3: { + right: -12, + }, b0: { bottom: 0, },