diff --git a/assets/images/car.svg b/assets/images/car.svg new file mode 100644 index 000000000000..7172eb1db01e --- /dev/null +++ b/assets/images/car.svg @@ -0,0 +1,15 @@ + + + + + + diff --git a/src/CONST.js b/src/CONST.js index 2b8aece7816f..d1250537b84d 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -274,6 +274,7 @@ const CONST = { TASKS: 'tasks', THREADS: 'threads', SCAN_RECEIPTS: 'scanReceipts', + DISTANCE_REQUESTS: 'distanceRequests', }, BUTTON_STATES: { DEFAULT: 'default', @@ -2567,6 +2568,7 @@ const CONST = { RECEIPT_TAB_ID: 'ReceiptTab', MANUAL: 'manual', SCAN: 'scan', + DISTANCE: 'distance', }, }; diff --git a/src/ROUTES.js b/src/ROUTES.js index a6e21baddf59..88db46a60113 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -87,6 +87,7 @@ export default { MONEY_REQUEST_DESCRIPTION: ':iouType/new/description/:reportID?', MONEY_REQUEST_MANUAL_TAB: ':iouType/new/:reportID?/manual', MONEY_REQUEST_SCAN_TAB: ':iouType/new/:reportID?/scan', + MONEY_REQUEST_DISTANCE_TAB: ':iouType/new/:reportID?/distance', IOU_SEND_ADD_BANK_ACCOUNT: `${IOU_SEND}/add-bank-account`, IOU_SEND_ADD_DEBIT_CARD: `${IOU_SEND}/add-debit-card`, IOU_SEND_ENABLE_PAYMENTS: `${IOU_SEND}/enable-payments`, diff --git a/src/components/DistanceRequest.js b/src/components/DistanceRequest.js new file mode 100644 index 000000000000..7bbbfe3f3a01 --- /dev/null +++ b/src/components/DistanceRequest.js @@ -0,0 +1,40 @@ +import React, {useEffect} from 'react'; +import {View} from 'react-native'; +import PropTypes from 'prop-types'; +import {withOnyx} from 'react-native-onyx'; +import Text from './Text'; +import * as IOU from '../libs/actions/IOU'; +import styles from '../styles/styles'; +import ONYXKEYS from '../ONYXKEYS'; + +const propTypes = { + /** The transactionID of this request */ + transactionID: PropTypes.string, +}; + +const defaultProps = { + transactionID: '', +}; + +function DistanceRequest(props) { + useEffect(() => { + if (props.transactionID) { + return; + } + IOU.createEmptyTransaction(); + }, [props.transactionID]); + + return ( + + Distance Request + transactionID: {props.transactionID} + + ); +} + +DistanceRequest.displayName = 'DistanceRequest'; +DistanceRequest.propTypes = propTypes; +DistanceRequest.defaultProps = defaultProps; +export default withOnyx({ + transactionID: {key: ONYXKEYS.IOU, selector: (iou) => (iou && iou.transactionID) || ''}, +})(DistanceRequest); diff --git a/src/components/Icon/Expensicons.js b/src/components/Icon/Expensicons.js index 3b1470197f73..b0c1d5a9249c 100644 --- a/src/components/Icon/Expensicons.js +++ b/src/components/Icon/Expensicons.js @@ -15,6 +15,7 @@ import Bug from '../../../assets/images/bug.svg'; import Building from '../../../assets/images/building.svg'; import Calendar from '../../../assets/images/calendar.svg'; import Camera from '../../../assets/images/camera.svg'; +import Car from '../../../assets/images/car.svg'; import Cash from '../../../assets/images/cash.svg'; import ChatBubble from '../../../assets/images/chatbubble.svg'; import Checkmark from '../../../assets/images/checkmark.svg'; @@ -136,6 +137,7 @@ export { Building, Calendar, Camera, + Car, Cash, ChatBubble, Checkmark, diff --git a/src/components/TabSelector/TabSelector.js b/src/components/TabSelector/TabSelector.js index 7bb2f12d1181..3e0ff7eb4e99 100644 --- a/src/components/TabSelector/TabSelector.js +++ b/src/components/TabSelector/TabSelector.js @@ -27,7 +27,16 @@ const defaultProps = { onTabPress: () => {}, }; -const getIcon = (route) => (route === CONST.TAB.MANUAL ? Expensicons.Pencil : Expensicons.Receipt); +const getIcon = (route) => { + switch (route) { + case CONST.TAB.SCAN: + return Expensicons.Receipt; + case CONST.TAB.DISTANCE: + return Expensicons.Car; + default: + return Expensicons.Pencil; + } +}; function TabSelector({state, navigation, onTabPress}) { const {translate} = useLocalize(); diff --git a/src/languages/en.js b/src/languages/en.js index 54a1d1acbede..ff2187179c36 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -349,6 +349,7 @@ export default { tabSelector: { manual: 'Manual', scan: 'Scan', + distance: 'Distance', }, receipt: { upload: 'Upload receipt', diff --git a/src/languages/es.js b/src/languages/es.js index 58146873da87..e85ccdd5c510 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -348,6 +348,7 @@ export default { tabSelector: { manual: 'Manual', scan: 'Escanear', + distance: 'Distancia', }, receipt: { upload: 'Subir recibo', diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 04a72b15dd18..6c4d58a4c585 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -302,6 +302,10 @@ export default { path: ROUTES.MONEY_REQUEST_SCAN_TAB, exact: true, }, + distance: { + path: ROUTES.MONEY_REQUEST_DISTANCE_TAB, + exact: true, + }, }, }, Money_Request_Amount: ROUTES.MONEY_REQUEST_AMOUNT, diff --git a/src/libs/Permissions.js b/src/libs/Permissions.js index 7f8dcd036365..ec16f782201a 100644 --- a/src/libs/Permissions.js +++ b/src/libs/Permissions.js @@ -94,6 +94,14 @@ function canUseScanReceipts(betas) { return _.contains(betas, CONST.BETAS.SCAN_RECEIPTS) || canUseAllBetas(betas); } +/** + * @param {Array} betas + * @returns {Boolean} + */ +function canUseDistanceRequests(betas) { + return _.contains(betas, CONST.BETAS.DISTANCE_REQUESTS) || canUseAllBetas(betas); +} + export default { canUseChronos, canUsePayWithExpensify, @@ -105,4 +113,5 @@ export default { canUsePolicyExpenseChat, canUseTasks, canUseScanReceipts, + canUseDistanceRequests, }; diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 45fcd35eb839..653777b31835 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -20,6 +20,7 @@ import TransactionUtils from '../TransactionUtils'; import * as ErrorUtils from '../ErrorUtils'; import * as UserUtils from '../UserUtils'; import * as Report from './Report'; +import * as NumberUtils from '../NumberUtils'; let allReports; Onyx.connect({ @@ -1509,6 +1510,12 @@ function setMoneyRequestReceipt(receiptPath, receiptSource) { Onyx.merge(ONYXKEYS.IOU, {receiptPath, receiptSource}); } +function createEmptyTransaction() { + const transactionID = NumberUtils.rand64(); + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {}); + Onyx.merge(ONYXKEYS.IOU, {transactionID}); +} + /** * Navigates to the next IOU page based on where the IOU request was started * @@ -1562,5 +1569,6 @@ export { setMoneyRequestDescription, setMoneyRequestParticipants, setMoneyRequestReceipt, + createEmptyTransaction, navigateToNextPage, }; diff --git a/src/pages/iou/MoneyRequestSelectorPage.js b/src/pages/iou/MoneyRequestSelectorPage.js index 3d59721e404a..d2033802da4c 100644 --- a/src/pages/iou/MoneyRequestSelectorPage.js +++ b/src/pages/iou/MoneyRequestSelectorPage.js @@ -16,6 +16,7 @@ import styles from '../../styles/styles'; import MoneyRequestAmount from './steps/MoneyRequestAmount'; import ReceiptSelector from './ReceiptSelector'; import * as IOU from '../../libs/actions/IOU'; +import DistanceRequest from '../../components/DistanceRequest'; import DragAndDropProvider from '../../components/DragAndDrop/Provider'; import usePermissions from '../../hooks/usePermissions'; import OnyxTabNavigator, {TopTab} from '../../libs/Navigation/OnyxTabNavigator'; @@ -62,7 +63,7 @@ function MoneyRequestSelectorPage(props) { const iouType = lodashGet(props.route, 'params.iouType', ''); const reportID = lodashGet(props.route, 'params.reportID', ''); const {translate} = useLocalize(); - const {canUseScanReceipts} = usePermissions(); + const {canUseScanReceipts, canUseDistanceRequests} = usePermissions(); const title = { [CONST.IOU.MONEY_REQUEST_TYPE.REQUEST]: translate('iou.requestMoney'), @@ -85,7 +86,7 @@ function MoneyRequestSelectorPage(props) { title={title[iouType]} onBackButtonPress={Navigation.dismissModal} /> - {canUseScanReceipts && iouType === CONST.IOU.MONEY_REQUEST_TYPE.REQUEST ? ( + {(canUseScanReceipts || canUseDistanceRequests) && iouType === CONST.IOU.MONEY_REQUEST_TYPE.REQUEST ? ( ( @@ -101,11 +102,19 @@ function MoneyRequestSelectorPage(props) { component={MoneyRequestAmount} initialParams={{reportID, iouType}} /> - + {canUseScanReceipts && ( + + )} + {canUseDistanceRequests && ( + + )} ) : (