diff --git a/.eslintrc.js b/.eslintrc.js
index cfbfdcc8fe91..fefad92ce29d 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -294,6 +294,7 @@ module.exports = {
files: ['*.ts', '*.tsx'],
rules: {
'rulesdir/prefer-at': 'error',
+ 'rulesdir/boolean-conditional-rendering': 'error',
},
},
],
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 52ceeca865b5..c1238d6805aa 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -79,7 +79,6 @@ This is a checklist for PR authors. Please make sure to complete all tasks and c
- [ ] I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
- [ ] I followed proper code patterns (see [Reviewing the code](https://github.com/Expensify/App/blob/main/contributingGuides/PR_REVIEW_GUIDELINES.md#reviewing-the-code))
- [ ] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. `toggleReport` and not `onIconClick`)
- - [ ] I verified that the left part of a conditional rendering a React component is a boolean and NOT a string, e.g. `myBool && `.
- [ ] I verified that comments were added to code that is not self explanatory
- [ ] I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
- [ ] I verified any copy / text shown in the product is localized by adding it to `src/languages/*` files and using the [translation method](https://github.com/Expensify/App/blob/4bd99402cebdf4d7394e0d1f260879ea238197eb/src/components/withLocalize.js#L60)
diff --git a/contributingGuides/REVIEWER_CHECKLIST.md b/contributingGuides/REVIEWER_CHECKLIST.md
index 4ff1f01b1475..5fc14328f3b4 100644
--- a/contributingGuides/REVIEWER_CHECKLIST.md
+++ b/contributingGuides/REVIEWER_CHECKLIST.md
@@ -19,7 +19,6 @@
- [ ] If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
- [ ] I verified proper code patterns were followed (see [Reviewing the code](https://github.com/Expensify/App/blob/main/contributingGuides/PR_REVIEW_GUIDELINES.md#reviewing-the-code))
- [ ] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. `toggleReport` and not `onIconClick`).
- - [ ] I verified that the left part of a conditional rendering a React component is a boolean and NOT a string, e.g. `myBool && `.
- [ ] I verified that comments were added to code that is not self explanatory
- [ ] I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
- [ ] I verified any copy / text shown in the product is localized by adding it to `src/languages/*` files and using the [translation method](https://github.com/Expensify/App/blob/4bd99402cebdf4d7394e0d1f260879ea238197eb/src/components/withLocalize.js#L60)
diff --git a/package-lock.json b/package-lock.json
index d34a33ab8aae..d3e928cc49a8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -220,7 +220,7 @@
"electron-builder": "25.0.0",
"eslint": "^8.57.0",
"eslint-config-airbnb-typescript": "^18.0.0",
- "eslint-config-expensify": "^2.0.66",
+ "eslint-config-expensify": "^2.0.73",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-deprecation": "^3.0.0",
"eslint-plugin-jest": "^28.6.0",
@@ -22904,10 +22904,11 @@
}
},
"node_modules/eslint-config-expensify": {
- "version": "2.0.66",
- "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-2.0.66.tgz",
- "integrity": "sha512-6L9EIAiOxZnqOcFEsIwEUmX0fvglvboyqQh7LTqy+1O2h2W3mmrMSx87ymXeyFMg1nJQtqkFnrLv5ENGS0QC3Q==",
+ "version": "2.0.73",
+ "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-2.0.73.tgz",
+ "integrity": "sha512-LHHyujwjTBizm9mIQMv6g/MsAbYdeOLZrOBdFqY/LyGPUJxOr9jt22xlmTFSdKhieLrbDwkcgkXjM38Z46Nb9A==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"@babel/eslint-parser": "^7.25.7",
"@lwc/eslint-plugin-lwc": "^1.7.2",
diff --git a/package.json b/package.json
index 3fd91b404e61..f1dbff2500b2 100644
--- a/package.json
+++ b/package.json
@@ -276,7 +276,7 @@
"electron-builder": "25.0.0",
"eslint": "^8.57.0",
"eslint-config-airbnb-typescript": "^18.0.0",
- "eslint-config-expensify": "^2.0.66",
+ "eslint-config-expensify": "^2.0.73",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-deprecation": "^3.0.0",
"eslint-plugin-jest": "^28.6.0",
diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx
index 8ccab44a2cb9..ad58294c0cc8 100644
--- a/src/components/AccountSwitcher.tsx
+++ b/src/components/AccountSwitcher.tsx
@@ -152,7 +152,7 @@ function AccountSwitcher() {
>
{currentUserPersonalDetails?.displayName}
- {canSwitchAccounts && (
+ {!!canSwitchAccounts && (
- {canSwitchAccounts && (
+ {!!canSwitchAccounts && (
{
diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx b/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx
index 103abb2df1bb..4de43a763231 100644
--- a/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx
+++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.tsx
@@ -86,7 +86,7 @@ function CarouselItem({item, onPress, isFocused, isModalHovered}: CarouselItemPr
/>
- {item.hasBeenFlagged && (
+ {!!item.hasBeenFlagged && (
{({safeAreaPaddingBottomStyle}) => {renderButton([styles.m4, styles.alignSelfCenter])}}
diff --git a/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx b/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx
index 23e13833df64..8f149182d9a6 100644
--- a/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx
+++ b/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx
@@ -47,7 +47,7 @@ function DefaultAttachmentView({fileName = '', shouldShowLoadingSpinnerIcon = fa
{fileName}
- {!shouldShowLoadingSpinnerIcon && shouldShowDownloadIcon && (
+ {!shouldShowLoadingSpinnerIcon && !!shouldShowDownloadIcon && (
- {report && !!title && (
+ {!!report && !!title && (
- {errorData.validationError && (
+ {!!errorData.validationError && (
- {icon && (
+ {!!icon && (
- {shouldShowIcon && icon && (
+ {shouldShowIcon && !!icon && (
(
<>
- {subtitle && (
+ {!!subtitle && (
- {animation && (
+ {!!animation && (
)}
- {icon && (
+ {!!icon && (
- {icon && (
+ {!!icon && (
({
enterKeyEventListenerPriority={enterKeyEventListenerPriority}
/>
)}
- {(shouldAlwaysShowDropdownMenu || options.length > 1) && popoverAnchorPosition && (
+ {(shouldAlwaysShowDropdownMenu || options.length > 1) && !!popoverAnchorPosition && (
{
diff --git a/src/components/CheckboxWithLabel.tsx b/src/components/CheckboxWithLabel.tsx
index db62aa9e1441..0647b495bd33 100644
--- a/src/components/CheckboxWithLabel.tsx
+++ b/src/components/CheckboxWithLabel.tsx
@@ -95,8 +95,8 @@ function CheckboxWithLabel(
style={[styles.flexRow, styles.alignItemsCenter, styles.noSelect, styles.w100]}
wrapperStyle={[styles.ml3, styles.pr2, styles.w100, styles.flexWrap, styles.flexShrink1]}
>
- {label && {label}}
- {LabelComponent && }
+ {!!label && {label}}
+ {!!LabelComponent && }
diff --git a/src/components/CollapsibleSection/index.tsx b/src/components/CollapsibleSection/index.tsx
index d339f005e3d3..3776dfa2cf9b 100644
--- a/src/components/CollapsibleSection/index.tsx
+++ b/src/components/CollapsibleSection/index.tsx
@@ -63,7 +63,7 @@ function CollapsibleSection({title, children, titleStyle, textStyle, wrapperStyl
src={src}
/>
- {shouldShowSectionBorder && }
+ {!!shouldShowSectionBorder && }
{children}
diff --git a/src/components/ConfirmContent.tsx b/src/components/ConfirmContent.tsx
index bda78b9b320d..cb0fc6e8e8cb 100644
--- a/src/components/ConfirmContent.tsx
+++ b/src/components/ConfirmContent.tsx
@@ -168,7 +168,7 @@ function ConfirmContent({
)}
- {iconSource && (
+ {!!iconSource && (
- {title && {titleAlreadyTranslated ?? translate(title)}}
+ {!!title && {titleAlreadyTranslated ?? translate(title)}}
{children}
>
);
diff --git a/src/components/DecisionModal.tsx b/src/components/DecisionModal.tsx
index a9bd0b204d79..927ba1ecab11 100644
--- a/src/components/DecisionModal.tsx
+++ b/src/components/DecisionModal.tsx
@@ -55,7 +55,7 @@ function DecisionModal({title, prompt = '', firstOptionText, secondOptionText, o
{prompt}
- {firstOptionText && (
+ {!!firstOptionText && (
- {isReceiptThumbnail && fileExtension && (
+ {isReceiptThumbnail && !!fileExtension && (
)}
- {ctaErrorMessage && (
+ {!!ctaErrorMessage && (
)}
- {icon && (
+ {!!icon && (
)}
- {policyAvatar && (
+ {!!policyAvatar && (
- {stepNames && (
+ {!!stepNames && (
{}, opti
/>
)}
- {hasDraftComment && optionItem.isAllowedToComment && (
+ {hasDraftComment && !!optionItem.isAllowedToComment && (
{}, opti
/>
)}
- {!shouldShowGreenDotIndicator && !hasBrickError && optionItem.isPinned && (
+ {!shouldShowGreenDotIndicator && !hasBrickError && !!optionItem.isPinned && (
))}
- {errorText && (
+ {!!errorText && (
- {coordinates && (
+ {!!coordinates && (
)}
- {otherIntegrationsItems && (
+ {!!otherIntegrationsItems && (
- customField && (
+ !!customField && (
- customField && (
+ !!customField && (
{
updateRecord({
diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldView.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldView.tsx
index d4c831d6155e..cb6513e785c1 100644
--- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldView.tsx
+++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldView.tsx
@@ -96,7 +96,7 @@ function NetSuiteImportCustomFieldView({
shouldBeBlocked={!customField}
onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_IMPORT_CUSTOM_FIELD_MAPPING.getRoute(policyID, importCustomField))}
>
- {customField && (
+ {!!customField && (
)}
- {!!paymentBankAccountID && isContinuousReconciliationOn && (
+ {!!paymentBankAccountID && !!isContinuousReconciliationOn && (
Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES)}
/>
- {xeroConfig?.importTrackingCategories && (
+ {!!xeroConfig?.importTrackingCategories && (
{menuItems.map((menuItem) => (
Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS)}
/>
- {sync?.syncReimbursedReports && (
+ {!!sync?.syncReimbursedReports && (
<>
- {policy?.areRulesEnabled && (
+ {!!policy?.areRulesEnabled && (
<>
{translate('workspace.rules.categoryRules.title')}
@@ -250,7 +250,7 @@ function CategorySettingsPage({
- {policyCategory?.areCommentsRequired && (
+ {!!policyCategory?.areCommentsRequired && (
)}
- {canUseCategoryAndTagApprovers && (
+ {!!canUseCategoryAndTagApprovers && (
<>
)}
- {policy?.tax?.trackingEnabled && (
+ {!!policy?.tax?.trackingEnabled && (
- {canUseWorkspaceRules && !!currentPolicy && (sections.at(0)?.data?.length ?? 0) > 0 && (
+ {!!canUseWorkspaceRules && !!currentPolicy && (sections.at(0)?.data?.length ?? 0) > 0 && (
@@ -140,7 +140,7 @@ function WorkspaceCategoriesSettingsPage({policy, route}: WorkspaceCategoriesSet
}}
/>
)}
- {canUseWorkspaceRules && categoryID && groupID && (
+ {!!canUseWorkspaceRules && !!categoryID && !!groupID && (
- {exportMenuItem?.description && (
+ {!!exportMenuItem?.description && (
{translate('workspace.moreFeatures.companyCards.integrationExportTitleFirstPart', {integration: exportMenuItem.description})}{' '}
- {exportMenuItem && (
+ {!!exportMenuItem && (
Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARD_NAME.getRoute(policyID, cardID, bank))}
/>
- {exportMenuItem && (
+ {!!exportMenuItem && (
- {url && (
+ {!!url && (
- {defaultUnit && (
+ {!!defaultUnit && (
)}
- {policy?.areCategoriesEnabled && OptionsListUtils.hasEnabledOptions(policyCategories ?? {}) && (
+ {!!policy?.areCategoriesEnabled && OptionsListUtils.hasEnabledOptions(policyCategories ?? {}) && (
- {isLoading && (
+ {!!isLoading && (
{translate('workspace.expensifyCard.settlementAccountDescription')}
- {isUsedContinuousReconciliation && (
+ {!!isUsedContinuousReconciliation && (
{translate('workspace.expensifyCard.settlementAccountInfoPt1')}{' '}
Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_RECONCILIATION_ACCOUNT_SETTINGS.getRoute(policyID, connectionParam))}>
diff --git a/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx b/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx
index 4f14950ec93d..0697ac0750cd 100644
--- a/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx
+++ b/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx
@@ -37,9 +37,9 @@ function WorkspaceInvoicesPage({route}: WorkspaceInvoicesPageProps) {
>
{(_hasVBA?: boolean, policyID?: string) => (
- {policyID && }
- {policyID && }
- {policyID && }
+ {!!policyID && }
+ {!!policyID && }
+ {!!policyID && }
)}
diff --git a/src/pages/workspace/members/WorkspaceOwnerChangeWrapperPage.tsx b/src/pages/workspace/members/WorkspaceOwnerChangeWrapperPage.tsx
index 325e1112ab4b..c6a37c668c1a 100644
--- a/src/pages/workspace/members/WorkspaceOwnerChangeWrapperPage.tsx
+++ b/src/pages/workspace/members/WorkspaceOwnerChangeWrapperPage.tsx
@@ -75,7 +75,7 @@ function WorkspaceOwnerChangeWrapperPage({route, policy}: WorkspaceOwnerChangeWr
}}
/>
- {policy?.isLoading && }
+ {!!policy?.isLoading && }
{shouldShowPaymentCardForm && }
{!policy?.isLoading && !shouldShowPaymentCardForm && (
- {policy?.areRulesEnabled && canUseCategoryAndTagApprovers && !isMultiLevelTags && (
+ {!!policy?.areRulesEnabled && !!canUseCategoryAndTagApprovers && !isMultiLevelTags && (
<>
{translate('workspace.tags.tagRules')}
diff --git a/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx
index 3fadba088648..eb9b89ee5679 100644
--- a/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx
+++ b/src/pages/workspace/tags/WorkspaceTagsSettingsPage.tsx
@@ -106,7 +106,7 @@ function WorkspaceTagsSettingsPage({route}: WorkspaceTagsSettingsPageProps) {
/>
- {canUseWorkspaceRules && policy?.areRulesEnabled && (
+ {!!canUseWorkspaceRules && !!policy?.areRulesEnabled && (
{translate('workspace.tags.trackBillable')}
diff --git a/src/pages/workspace/taxes/WorkspaceEditTaxPage.tsx b/src/pages/workspace/taxes/WorkspaceEditTaxPage.tsx
index 0f50ed8fe0b8..f10e0fba84a2 100644
--- a/src/pages/workspace/taxes/WorkspaceEditTaxPage.tsx
+++ b/src/pages/workspace/taxes/WorkspaceEditTaxPage.tsx
@@ -158,7 +158,7 @@ function WorkspaceEditTaxPage({
}}
/>
- {shouldShowDeleteMenuItem && (
+ {!!shouldShowDeleteMenuItem && (
- {removeApprovalWorkflow && !approvalWorkflow.isDefault && (
+ {!!removeApprovalWorkflow && !approvalWorkflow.isDefault && (