-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Add Scan
to Split Bill
and implement IOU action startSplitBill
#28710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
d03ead5
Display 'Split' bill button in Scan flow
youssef-lr 6231e7c
Hide $0 amounts in Split Bill
youssef-lr 60ffec4
Add IOU action startSplitBillRequest
youssef-lr facfd16
Hide split amount if it's O
youssef-lr ec7610d
Add receipt status text in SplitBillDetailsPage
youssef-lr 057fc00
Allow editing merchant and date when creating split bill
youssef-lr 7361985
Fix navigation to newly created chat
youssef-lr 04ec01c
Show TabSelector when using Split Bill from workspace chat
youssef-lr 1404029
Display receipt in SplitBillDetailsPage
youssef-lr fbdf93d
Cleanup
youssef-lr 9fd07bc
Fix splitting bill with unkown users
youssef-lr 66c0ae2
Merge branch 'main' into youssef_startSplitBill
youssef-lr a51725a
Cleanup
youssef-lr 3820323
Add JSDocs
youssef-lr 51fbbf6
Remove created and merchant
youssef-lr 6f8b808
Only display scan status when receipt is being scanned
youssef-lr 19e5994
Cleanup
youssef-lr a1b79b0
Fix GH actions
youssef-lr 2af470b
Sve policy expense chat reportID in splits array
youssef-lr 53f28f3
Create optimistic details of participants if needed
youssef-lr 98bd046
Merge branch 'main' into youssef_startSplitBill
youssef-lr 027cc04
Show amount in split details page once it's created
youssef-lr 23e5e2b
Show SmartScan fields in ReadOnly split details page
youssef-lr 9b2b942
Rename receiptSource to receiptFilename
youssef-lr 424132f
Add null check
youssef-lr 2f99094
Bug fix
youssef-lr 66616b4
Merge branch 'main' into youssef_startSplitBill
youssef-lr ceb1872
Apply suggestions from code review
youssef-lr 10d24d0
Merge branch 'main' into youssef_startSplitBill
youssef-lr 5c47140
Hide showMore button when there are no more fields to display
youssef-lr 4083b0c
Merge branch 'main' into youssef_startSplitBill
youssef-lr e6de6c5
Fix navigation to split chat report
youssef-lr a5d29ba
Remove unnecessary param
youssef-lr 92c9a42
Reverse changes in TransactionUtils
youssef-lr 6c8f574
Apply suggestions from code review
youssef-lr 5f7656b
Tidy up code
youssef-lr 5527d4c
Add error to split chat created action on failure
youssef-lr 3a7504e
Merge branch 'youssef_startSplitBill' of github.com:Expensify/App int…
youssef-lr 25f0a2a
fix lint
youssef-lr ab6a140
Add comment
youssef-lr 993f0ce
Save splits optimistically in the transaction comment
youssef-lr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -114,8 +114,8 @@ const propTypes = { | |
/** File path of the receipt */ | ||
receiptPath: PropTypes.string, | ||
|
||
/** File source of the receipt */ | ||
receiptSource: PropTypes.string, | ||
/** File name of the receipt */ | ||
receiptFilename: PropTypes.string, | ||
|
||
/** List styles for OptionsSelector */ | ||
listStyles: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), | ||
|
@@ -141,6 +141,9 @@ const propTypes = { | |
/** Whether the money request is a distance request */ | ||
isDistanceRequest: PropTypes.bool, | ||
|
||
/** Whether the receipt associated with this report is being scanned */ | ||
isScanning: PropTypes.bool, | ||
|
||
/** A flag for verifying that the current report is a sub-report of a workspace chat */ | ||
isPolicyExpenseChat: PropTypes.bool, | ||
|
||
|
@@ -171,14 +174,15 @@ const defaultProps = { | |
reportID: '', | ||
...withCurrentUserPersonalDetailsDefaultProps, | ||
receiptPath: '', | ||
receiptSource: '', | ||
receiptFilename: '', | ||
listStyles: [], | ||
policyCategories: {}, | ||
policyTags: {}, | ||
transactionID: '', | ||
transaction: {}, | ||
mileageRate: {unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, rate: 0, currency: 'USD'}, | ||
isDistanceRequest: false, | ||
isScanning: false, | ||
isPolicyExpenseChat: false, | ||
}; | ||
|
||
|
@@ -188,9 +192,6 @@ function MoneyRequestConfirmationList(props) { | |
const {onSendMoney, onConfirm, onSelectParticipant, transaction} = props; | ||
const {translate, toLocaleDigit} = useLocalize(); | ||
|
||
// A flag and a toggler for showing the rest of the form fields | ||
const [shouldExpandFields, toggleShouldExpandFields] = useReducer((state) => !state, false); | ||
const shouldShowAllFields = props.isDistanceRequest || shouldExpandFields; | ||
const isTypeRequest = props.iouType === CONST.IOU.MONEY_REQUEST_TYPE.REQUEST; | ||
|
||
const {unit, rate, currency} = props.mileageRate; | ||
|
@@ -201,6 +202,14 @@ function MoneyRequestConfirmationList(props) { | |
const shouldShowCategories = | ||
props.isPolicyExpenseChat && Permissions.canUseCategories(props.betas) && (props.iouCategory || OptionsListUtils.hasEnabledOptions(_.values(props.policyCategories))); | ||
|
||
// A flag for showing SmartScan fields: date, merchant, and amount, only when we don't have a receiptPath (e.g. manual request) | ||
// or in the split details page which is ReadOnly | ||
const shouldShowSmartScanFields = (!props.receiptPath || props.isReadOnly) && !props.isScanning; | ||
|
||
// A flag and a toggler for showing the rest of the form fields | ||
const [shouldExpandFields, toggleShouldExpandFields] = useReducer((state) => !state, false); | ||
const shouldShowAllFields = props.isDistanceRequest || shouldExpandFields || !shouldShowSmartScanFields; | ||
|
||
// Fetches the first tag list of the policy | ||
const policyTag = PolicyUtils.getTag(props.policyTags); | ||
const policyTagList = lodashGet(policyTag, 'tags', {}); | ||
|
@@ -245,7 +254,10 @@ function MoneyRequestConfirmationList(props) { | |
const getParticipantsWithAmount = useCallback( | ||
(participantsList) => { | ||
const iouAmount = IOUUtils.calculateAmount(participantsList.length, props.iouAmount, props.iouCurrencyCode); | ||
return OptionsListUtils.getIOUConfirmationOptionsFromParticipants(participantsList, CurrencyUtils.convertToDisplayString(iouAmount, props.iouCurrencyCode)); | ||
return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( | ||
participantsList, | ||
props.iouAmount > 0 ? CurrencyUtils.convertToDisplayString(iouAmount, props.iouCurrencyCode) : '', | ||
); | ||
}, | ||
[props.iouAmount, props.iouCurrencyCode], | ||
); | ||
|
@@ -254,7 +266,9 @@ function MoneyRequestConfirmationList(props) { | |
|
||
const splitOrRequestOptions = useMemo(() => { | ||
let text; | ||
if (props.receiptPath || isDistanceRequestWithoutRoute) { | ||
if (props.receiptPath && props.hasMultipleParticipants && props.iouAmount === 0) { | ||
text = translate('iou.split'); | ||
} else if (props.receiptPath || isDistanceRequestWithoutRoute) { | ||
text = translate('iou.request'); | ||
} else { | ||
const translationKey = props.hasMultipleParticipants ? 'iou.splitAmount' : 'iou.requestAmount'; | ||
|
@@ -266,7 +280,7 @@ function MoneyRequestConfirmationList(props) { | |
value: props.hasMultipleParticipants ? CONST.IOU.MONEY_REQUEST_TYPE.SPLIT : CONST.IOU.MONEY_REQUEST_TYPE.REQUEST, | ||
}, | ||
]; | ||
}, [props.hasMultipleParticipants, props.receiptPath, translate, formattedAmount, isDistanceRequestWithoutRoute]); | ||
}, [props.hasMultipleParticipants, props.iouAmount, props.receiptPath, translate, formattedAmount, isDistanceRequestWithoutRoute]); | ||
|
||
const selectedParticipants = useMemo(() => _.filter(props.selectedParticipants, (participant) => participant.selected), [props.selectedParticipants]); | ||
const payeePersonalDetails = useMemo(() => props.payeePersonalDetails || props.currentUserPersonalDetails, [props.payeePersonalDetails, props.currentUserPersonalDetails]); | ||
|
@@ -290,7 +304,7 @@ function MoneyRequestConfirmationList(props) { | |
const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants.length, props.iouAmount, props.iouCurrencyCode, true); | ||
const formattedPayeeOption = OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail( | ||
payeePersonalDetails, | ||
CurrencyUtils.convertToDisplayString(myIOUAmount, props.iouCurrencyCode), | ||
props.iouAmount > 0 ? CurrencyUtils.convertToDisplayString(myIOUAmount, props.iouCurrencyCode) : '', | ||
); | ||
|
||
sections.push( | ||
|
@@ -459,6 +473,9 @@ function MoneyRequestConfirmationList(props) { | |
); | ||
}, [confirm, props.bankAccountRoute, props.iouCurrencyCode, props.iouType, props.isReadOnly, props.policyID, selectedParticipants, splitOrRequestOptions, translate, formError]); | ||
|
||
const {image: receiptImage, thumbnail: receiptThumbnail} = | ||
props.receiptPath && props.receiptFilename ? ReceiptUtils.getThumbnailAndImageURIs(props.receiptPath, props.receiptFilename) : {}; | ||
|
||
return ( | ||
<OptionsSelector | ||
sections={optionSelectorSections} | ||
|
@@ -483,12 +500,17 @@ function MoneyRequestConfirmationList(props) { | |
<ConfirmedRoute transactionID={props.transactionID} /> | ||
</View> | ||
)} | ||
{!_.isEmpty(props.receiptPath) ? ( | ||
{(receiptImage || receiptThumbnail) && ( | ||
<Image | ||
style={styles.moneyRequestImage} | ||
source={{uri: ReceiptUtils.getThumbnailAndImageURIs(props.receiptPath, props.receiptSource).image}} | ||
source={{uri: receiptThumbnail || receiptImage}} | ||
// AuthToken is required when retrieving the image from the server | ||
// but we don't need it to load the blob:// or file:// image when starting a money request / split bill | ||
// So if we have a thumbnail, it means we're retrieving the image from the server | ||
isAuthTokenRequired={!_.isEmpty(receiptThumbnail)} | ||
youssef-lr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/> | ||
) : ( | ||
)} | ||
{shouldShowSmartScanFields && ( | ||
<MenuItemWithTopDescription | ||
shouldShowRightIcon={!props.isReadOnly && !props.isDistanceRequest} | ||
title={formattedAmount} | ||
|
@@ -527,16 +549,18 @@ function MoneyRequestConfirmationList(props) { | |
)} | ||
{shouldShowAllFields && ( | ||
<> | ||
<MenuItemWithTopDescription | ||
shouldShowRightIcon={!props.isReadOnly && isTypeRequest} | ||
title={props.iouCreated || format(new Date(), CONST.DATE.FNS_FORMAT_STRING)} | ||
description={translate('common.date')} | ||
style={[styles.moneyRequestMenuItem]} | ||
titleStyle={styles.flex1} | ||
onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_DATE.getRoute(props.iouType, props.reportID))} | ||
disabled={didConfirm || props.isReadOnly || !isTypeRequest} | ||
/> | ||
{props.isDistanceRequest ? ( | ||
{shouldShowSmartScanFields && ( | ||
<MenuItemWithTopDescription | ||
shouldShowRightIcon={!props.isReadOnly && isTypeRequest} | ||
title={props.iouCreated || format(new Date(), CONST.DATE.FNS_FORMAT_STRING)} | ||
description={translate('common.date')} | ||
style={[styles.moneyRequestMenuItem]} | ||
titleStyle={styles.flex1} | ||
onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_DATE.getRoute(props.iouType, props.reportID))} | ||
disabled={didConfirm || props.isReadOnly} | ||
/> | ||
)} | ||
{props.isDistanceRequest && ( | ||
<MenuItemWithTopDescription | ||
shouldShowRightIcon={!props.isReadOnly && isTypeRequest} | ||
title={props.iouMerchant} | ||
|
@@ -546,15 +570,16 @@ function MoneyRequestConfirmationList(props) { | |
onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_DISTANCE.getRoute(props.iouType, props.reportID))} | ||
disabled={didConfirm || props.isReadOnly || !isTypeRequest} | ||
/> | ||
) : ( | ||
)} | ||
{shouldShowSmartScanFields && ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Coming from #29374. We should hide |
||
<MenuItemWithTopDescription | ||
shouldShowRightIcon={!props.isReadOnly && isTypeRequest} | ||
title={props.iouMerchant} | ||
description={translate('common.merchant')} | ||
style={[styles.moneyRequestMenuItem]} | ||
titleStyle={styles.flex1} | ||
onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_MERCHANT.getRoute(props.iouType, props.reportID))} | ||
disabled={didConfirm || props.isReadOnly || !isTypeRequest} | ||
disabled={didConfirm || props.isReadOnly} | ||
/> | ||
)} | ||
{shouldShowCategories && ( | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.