|
| 1 | +import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider'; |
| 2 | +import {ModalActions} from '@components/Modal/Global/ModalContext'; |
| 3 | +import {connect, disconnect} from '@libs/actions/Delegate'; |
| 4 | +import {close as modalClose} from '@libs/actions/Modal'; |
| 5 | +import {getGpsPoints, stopGpsTrip} from '@libs/GPSDraftDetailsUtils'; |
| 6 | +import CONST from '@src/CONST'; |
| 7 | +import ONYXKEYS from '@src/ONYXKEYS'; |
| 8 | +import {isTrackingSelector} from '@src/selectors/GPSDraftDetails'; |
| 9 | +import type {Account} from '@src/types/onyx'; |
| 10 | +import useConfirmModal from './useConfirmModal'; |
| 11 | +import useLocalize from './useLocalize'; |
| 12 | +import useNetwork from './useNetwork'; |
| 13 | +import useOnyx from './useOnyx'; |
| 14 | + |
| 15 | +/** |
| 16 | + * Encapsulates the safety checks needed before switching to a delegator account: |
| 17 | + * 1. Offline check – blocks the switch and shows an offline modal. |
| 18 | + * 2. Chained delegation check – if already acting as a delegate and not returning |
| 19 | + * to the original user, shows the "not so fast" modal. |
| 20 | + * 3. GPS tracking check – if a GPS trip is in progress, asks the user to confirm |
| 21 | + * stopping the trip before switching. |
| 22 | + */ |
| 23 | +function useSwitchToDelegator() { |
| 24 | + const {translate} = useLocalize(); |
| 25 | + const {isOffline} = useNetwork(); |
| 26 | + const {showConfirmModal} = useConfirmModal(); |
| 27 | + const {isActingAsDelegate} = useDelegateNoAccessState(); |
| 28 | + const {showDelegateNoAccessModal} = useDelegateNoAccessActions(); |
| 29 | + |
| 30 | + const [delegatedAccess] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account: Account | undefined) => account?.delegatedAccess}); |
| 31 | + const [credentials] = useOnyx(ONYXKEYS.CREDENTIALS); |
| 32 | + const [stashedCredentials = CONST.EMPTY_OBJECT] = useOnyx(ONYXKEYS.STASHED_CREDENTIALS); |
| 33 | + const [session] = useOnyx(ONYXKEYS.SESSION); |
| 34 | + const [stashedSession] = useOnyx(ONYXKEYS.STASHED_SESSION); |
| 35 | + const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); |
| 36 | + const [gpsDraftDetails] = useOnyx(ONYXKEYS.GPS_DRAFT_DETAILS); |
| 37 | + const [isTrackingGPS = false] = useOnyx(ONYXKEYS.GPS_DRAFT_DETAILS, {selector: isTrackingSelector}); |
| 38 | + |
| 39 | + const showOfflineModal = () => { |
| 40 | + showConfirmModal({ |
| 41 | + title: translate('common.youAppearToBeOffline'), |
| 42 | + prompt: translate('common.offlinePrompt'), |
| 43 | + confirmText: translate('common.buttonConfirm'), |
| 44 | + shouldShowCancelButton: false, |
| 45 | + }); |
| 46 | + }; |
| 47 | + |
| 48 | + const showGpsInProgressModal = async (switchAccount: () => ReturnType<typeof connect | typeof disconnect>) => { |
| 49 | + const result = await showConfirmModal({ |
| 50 | + title: translate('gps.switchAccountWarningTripInProgress.title'), |
| 51 | + prompt: translate('gps.switchAccountWarningTripInProgress.prompt'), |
| 52 | + confirmText: translate('gps.switchAccountWarningTripInProgress.confirm'), |
| 53 | + cancelText: translate('common.cancel'), |
| 54 | + }); |
| 55 | + |
| 56 | + if (result.action !== ModalActions.CONFIRM) { |
| 57 | + return; |
| 58 | + } |
| 59 | + |
| 60 | + await stopGpsTrip(false, getGpsPoints(gpsDraftDetails), true); |
| 61 | + switchAccount(); |
| 62 | + }; |
| 63 | + |
| 64 | + const switchToDelegator = (email: string) => { |
| 65 | + if (isOffline) { |
| 66 | + modalClose(() => showOfflineModal()); |
| 67 | + return; |
| 68 | + } |
| 69 | + const isReturningToOriginalUser = isActingAsDelegate && email === stashedSession?.email; |
| 70 | + // Chained delegation isn't supported by the backend — if we're already acting as a delegate, |
| 71 | + // the only legal switch is back to the original user. Anything else triggers the "Not so fast" modal. |
| 72 | + if (isActingAsDelegate && !isReturningToOriginalUser) { |
| 73 | + modalClose(() => showDelegateNoAccessModal()); |
| 74 | + return; |
| 75 | + } |
| 76 | + const switchAction = isReturningToOriginalUser |
| 77 | + ? () => disconnect({stashedCredentials, stashedSession}) |
| 78 | + : () => connect({email, delegatedAccess, credentials, session, activePolicyID}); |
| 79 | + if (isTrackingGPS) { |
| 80 | + modalClose(() => showGpsInProgressModal(switchAction)); |
| 81 | + return; |
| 82 | + } |
| 83 | + switchAction(); |
| 84 | + }; |
| 85 | + |
| 86 | + return switchToDelegator; |
| 87 | +} |
| 88 | + |
| 89 | +export default useSwitchToDelegator; |
0 commit comments