diff --git a/src/components/AddPaymentCard/PaymentCardChangeCurrencyForm.tsx b/src/components/AddPaymentCard/PaymentCardChangeCurrencyForm.tsx
index 8ccee64f1118..22f32d7f50d3 100644
--- a/src/components/AddPaymentCard/PaymentCardChangeCurrencyForm.tsx
+++ b/src/components/AddPaymentCard/PaymentCardChangeCurrencyForm.tsx
@@ -84,6 +84,7 @@ function PaymentCardChangeCurrencyForm({changeBillingCurrency, isSecurityCodeReq
submitButtonText={translate('common.save')}
scrollContextEnabled
style={[styles.mh5, styles.flexGrow1]}
+ shouldHideFixErrorsAlert
>
<>
diff --git a/src/components/SubStepForms/DateOfBirthStep.tsx b/src/components/SubStepForms/DateOfBirthStep.tsx
index 3142b46277f1..54f1510800b4 100644
--- a/src/components/SubStepForms/DateOfBirthStep.tsx
+++ b/src/components/SubStepForms/DateOfBirthStep.tsx
@@ -84,6 +84,7 @@ function DateOfBirthStep({
style={[styles.mh5, styles.flexGrow2, styles.justifyContentBetween]}
submitButtonStyles={[styles.mb0]}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{formTitle}
({
style={[styles.mh5, styles.flexGrow1]}
submitButtonStyles={[styles.mb0]}
enabledWhenOffline={enabledWhenOffline}
+ shouldHideFixErrorsAlert
>
{formTitle}
diff --git a/src/components/SubStepForms/YesNoStep.tsx b/src/components/SubStepForms/YesNoStep.tsx
index 50e26cef78f3..45181b5f875e 100644
--- a/src/components/SubStepForms/YesNoStep.tsx
+++ b/src/components/SubStepForms/YesNoStep.tsx
@@ -58,6 +58,7 @@ function YesNoStep({title, description, defaultValue, onSelectedValue, submitBut
style={[styles.mh5, styles.flexGrow1]}
submitButtonStyles={submitButtonStyles}
isLoading={reimbursementAccount?.isSavingCorpayOnboardingBeneficialOwnersFields}
+ shouldHideFixErrorsAlert
>
{title}
{description}
diff --git a/src/components/TextPicker/TextSelectorModal.tsx b/src/components/TextPicker/TextSelectorModal.tsx
index c0c733956e86..58886c84fa29 100644
--- a/src/components/TextPicker/TextSelectorModal.tsx
+++ b/src/components/TextPicker/TextSelectorModal.tsx
@@ -123,6 +123,7 @@ function TextSelectorModal({
submitButtonText={translate('common.save')}
style={[styles.mh5, styles.flex1]}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{!!subtitle && {subtitle}}
;
-
- /** Contains plaid data */
- plaidData: OnyxEntry;
-};
-
-type PlaidStepProps = PlaidOnyxProps & SubStepProps;
const BANK_INFO_STEP_KEYS = INPUT_IDS.BANK_INFO_STEP;
-function PlaidStep({personalBankAccountDraft, onNext, plaidData}: PlaidStepProps) {
+function PlaidStep({onNext}: SubStepProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const isFocused = useIsFocused();
+ const [personalBankAccountDraft] = useOnyx(ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_FORM_DRAFT);
+ const [plaidData] = useOnyx(ONYXKEYS.PLAID_DATA);
const selectedPlaidAccountID = personalBankAccountDraft?.[BANK_INFO_STEP_KEYS.PLAID_ACCOUNT_ID] ?? '';
const handleNextPress = useCallback(() => {
@@ -47,12 +36,12 @@ function PlaidStep({personalBankAccountDraft, onNext, plaidData}: PlaidStepProps
[BANK_INFO_STEP_KEYS.PLAID_ACCESS_TOKEN]: plaidData?.[BANK_INFO_STEP_KEYS.PLAID_ACCESS_TOKEN] ?? '',
};
- BankAccounts.updateAddPersonalBankAccountDraft(bankAccountData);
+ updateAddPersonalBankAccountDraft(bankAccountData);
onNext();
}, [onNext, personalBankAccountDraft, plaidData]);
const handleSelectPlaidAccount = (plaidAccountID: string) => {
- BankAccounts.updateAddPersonalBankAccountDraft({plaidAccountID});
+ updateAddPersonalBankAccountDraft({plaidAccountID});
};
useEffect(() => {
@@ -60,25 +49,26 @@ function PlaidStep({personalBankAccountDraft, onNext, plaidData}: PlaidStepProps
if (isFocused || plaidBankAccounts.length) {
return;
}
- BankAccounts.clearPersonalBankAccountSetupType();
+ clearPersonalBankAccountSetupType();
}, [isFocused, plaidData]);
return (
0}
+ shouldHideFixErrorsAlert
>
({
- personalBankAccountDraft: {
- key: ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_FORM_DRAFT,
- },
- plaidData: {
- key: ONYXKEYS.PLAID_DATA,
- },
-})(PlaidStep);
+export default PlaidStep;
diff --git a/src/pages/GroupChatNameEditPage.tsx b/src/pages/GroupChatNameEditPage.tsx
index a67f1fd0f3e2..5ca9576d165b 100644
--- a/src/pages/GroupChatNameEditPage.tsx
+++ b/src/pages/GroupChatNameEditPage.tsx
@@ -91,6 +91,7 @@ function GroupChatNameEditPage({report}: GroupChatNameEditPageProps) {
validate={validate}
style={[styles.mh5, styles.flex1]}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{translate(
diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/AccountHolderDetails.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/AccountHolderDetails.tsx
index 9ce9e9862e81..47f47b778e4d 100644
--- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/AccountHolderDetails.tsx
+++ b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/AccountHolderDetails.tsx
@@ -123,6 +123,7 @@ function AccountHolderDetails({onNext, isEditing, corpayFields}: BankInfoSubStep
validate={validate}
onSubmit={handleSubmit}
style={[styles.mh5, styles.flexGrow1]}
+ shouldHideFixErrorsAlert={(accountHolderDetailsFields?.length ?? 0) <= 1}
>
{translate('bankInfoStep.whatAreYour')}
diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx
index 000e18bb37d0..2a0971d3617c 100644
--- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx
+++ b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx
@@ -100,6 +100,7 @@ function BankAccountDetails({onNext, isEditing, corpayFields}: BankInfoSubStepPr
validate={validate}
style={[styles.mh5, styles.flexGrow1]}
isSubmitDisabled={!inputs}
+ shouldHideFixErrorsAlert={(bankAccountDetailsFields?.length ?? 0) <= 1}
>
<>
{translate('bankInfoStep.whatAreYour')}
diff --git a/src/pages/ReimbursementAccount/NonUSD/BeneficialOwnerInfo/BeneficialOwnerDetailsFormSubSteps/Documents.tsx b/src/pages/ReimbursementAccount/NonUSD/BeneficialOwnerInfo/BeneficialOwnerDetailsFormSubSteps/Documents.tsx
index d614554557e9..be819b6f863d 100644
--- a/src/pages/ReimbursementAccount/NonUSD/BeneficialOwnerInfo/BeneficialOwnerDetailsFormSubSteps/Documents.tsx
+++ b/src/pages/ReimbursementAccount/NonUSD/BeneficialOwnerInfo/BeneficialOwnerDetailsFormSubSteps/Documents.tsx
@@ -87,6 +87,14 @@ function Documents({onNext, isEditing, ownerBeingModifiedID}: DocumentsProps) {
shouldSaveDraft: isEditing,
});
+ const testForShouldHideFixErrorsAlert =
+ [
+ isDocumentNeededStatus.isProofOfOwnershipNeeded,
+ isDocumentNeededStatus.isCopyOfIDNeeded,
+ isDocumentNeededStatus.isProofOfAddressNeeded,
+ isDocumentNeededStatus.isCodiceFiscaleNeeded,
+ ].filter(Boolean).length <= 1;
+
return (
{translate('ownershipInfoStep.uploadDocuments')}
{translate('ownershipInfoStep.pleaseUpload')}
diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/AverageReimbursement.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/AverageReimbursement.tsx
index ddf7bcfc9241..22b1c33aa31e 100644
--- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/AverageReimbursement.tsx
+++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/AverageReimbursement.tsx
@@ -58,6 +58,7 @@ function AverageReimbursement({onNext, isEditing}: AverageReimbursementProps) {
validate={validate}
style={[styles.flexGrow1]}
submitButtonStyles={[styles.mh5]}
+ shouldHideFixErrorsAlert
>
{translate('businessInfoStep.whatsYourExpectedAverageReimbursements')}
{translate('businessInfoStep.whereWasTheBusinessIncorporated')}
{shouldGatherState && (
diff --git a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/PaymentVolume.tsx b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/PaymentVolume.tsx
index 70d610687212..5a1758452c10 100644
--- a/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/PaymentVolume.tsx
+++ b/src/pages/ReimbursementAccount/NonUSD/BusinessInfo/subSteps/PaymentVolume.tsx
@@ -58,6 +58,7 @@ function PaymentVolume({onNext, isEditing}: PaymentVolumeProps) {
validate={validate}
style={[styles.flexGrow1]}
submitButtonStyles={[styles.mh5]}
+ shouldHideFixErrorsAlert
>
{translate('businessInfoStep.whatsTheBusinessAnnualPayment')}
{translate('businessInfoStep.whatsTheBusinessRegistrationNumber')}
): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, shouldGatherBothEmails ? [SIGNER_EMAIL, SECOND_SIGNER_EMAIL] : [SIGNER_EMAIL]);
+ const errors = getFieldRequiredErrors(values, shouldGatherBothEmails ? [SIGNER_EMAIL, SECOND_SIGNER_EMAIL] : [SIGNER_EMAIL]);
if (values[SIGNER_EMAIL] && !Str.isValidEmail(values[SIGNER_EMAIL])) {
errors[SIGNER_EMAIL] = translate('bankAccount.error.email');
}
@@ -56,6 +57,7 @@ function EnterEmail({onSubmit, isUserDirector}: EnterEmailProps) {
onSubmit={onSubmit}
validate={validate}
style={[styles.mh5, styles.flexGrow1]}
+ shouldHideFixErrorsAlert={!shouldGatherBothEmails}
>
{translate(shouldGatherBothEmails ? 'signerInfoStep.enterTwoEmails' : 'signerInfoStep.enterOneEmail')}
{!shouldGatherBothEmails && {translate('signerInfoStep.regulationRequiresOneMoreDirector')}}
diff --git a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/UploadDocuments.tsx b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/UploadDocuments.tsx
index 449d5a74a9d2..bd83f80112b6 100644
--- a/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/UploadDocuments.tsx
+++ b/src/pages/ReimbursementAccount/NonUSD/SignerInfo/subSteps/UploadDocuments.tsx
@@ -83,6 +83,7 @@ function UploadDocuments({onNext, isEditing}: UploadDocumentsProps) {
onSubmit={handleSubmit}
validate={validate}
style={[styles.mh5, styles.flex1]}
+ shouldHideFixErrorsAlert
>
{translate('signerInfoStep.uploadID')}
diff --git a/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx
index 99b1fdd02a85..64f415b98f2f 100644
--- a/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx
+++ b/src/pages/ReimbursementAccount/USD/BankInfo/subSteps/Plaid.tsx
@@ -9,6 +9,7 @@ import type {SubStepProps} from '@hooks/useSubStep/types';
import useThemeStyles from '@hooks/useThemeStyles';
import {setBankAccountSubStep, validatePlaidSelection} from '@userActions/BankAccounts';
import {updateReimbursementAccountDraft} from '@userActions/ReimbursementAccount';
+import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import INPUT_IDS from '@src/types/form/ReimbursementAccountForm';
@@ -47,7 +48,7 @@ function Plaid({onNext, setUSDBankAccountStep}: PlaidProps) {
onNext(bankAccountData);
}, [plaidData, reimbursementAccountDraft, onNext]);
- const bankAccountID = Number(reimbursementAccount?.achData?.bankAccountID ?? '-1');
+ const bankAccountID = reimbursementAccount?.achData?.bankAccountID ?? CONST.DEFAULT_NUMBER_ID;
useEffect(() => {
const plaidBankAccounts = plaidData?.bankAccounts ?? [];
@@ -72,6 +73,7 @@ function Plaid({onNext, setUSDBankAccountStep}: PlaidProps) {
submitButtonText={translate('common.next')}
style={[styles.mh5, styles.flexGrow1]}
isSubmitButtonVisible={(plaidData?.bankAccounts ?? []).length > 0}
+ shouldHideFixErrorsAlert
>
): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, [BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS]);
+ const errors = getFieldRequiredErrors(values, [BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS]);
if (!values.hasNoConnectionToCannabis) {
errors.hasNoConnectionToCannabis = translate('bankAccount.error.restrictedBusiness');
@@ -136,6 +136,7 @@ function ConfirmationBusiness({onNext, onMove}: SubStepProps) {
submitButtonText={translate('common.confirm')}
style={[styles.mh5, styles.flexGrow1]}
enabledWhenOffline={false}
+ shouldHideFixErrorsAlert
>
): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS);
+ const errors = getFieldRequiredErrors(values, STEP_FIELDS);
- if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) {
+ if (values.incorporationDate && !isValidDate(values.incorporationDate)) {
errors.incorporationDate = translate('common.error.dateInvalid');
- } else if (values.incorporationDate && !ValidationUtils.isValidPastDate(values.incorporationDate)) {
+ } else if (values.incorporationDate && !isValidPastDate(values.incorporationDate)) {
errors.incorporationDate = translate('bankAccount.error.incorporationDateFuture');
}
@@ -54,6 +54,7 @@ function IncorporationDateBusiness({onNext, isEditing}: SubStepProps) {
onSubmit={handleSubmit}
style={[styles.mh5, styles.flexGrow1]}
submitButtonStyles={[styles.mb0]}
+ shouldHideFixErrorsAlert
>
{translate('businessInfoStep.selectYourCompanysIncorporationDate')}
): FormInputErrors =>
- ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS);
+ getFieldRequiredErrors(values, STEP_FIELDS);
function IncorporationStateBusiness({onNext, isEditing}: SubStepProps) {
const {translate} = useLocalize();
@@ -41,6 +41,7 @@ function IncorporationStateBusiness({onNext, isEditing}: SubStepProps) {
onSubmit={handleSubmit}
style={[styles.mh0, styles.flexGrow1]}
submitButtonStyles={[styles.ph5, styles.mb0]}
+ shouldHideFixErrorsAlert
>
{translate('businessInfoStep.pleaseSelectTheStateYourCompanyWasIncorporatedIn')}
): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS);
+ const errors = getFieldRequiredErrors(values, STEP_FIELDS);
- if (values.companyName && !ValidationUtils.isValidCompanyName(values.companyName)) {
+ if (values.companyName && !isValidCompanyName(values.companyName)) {
errors.companyName = translate('bankAccount.error.companyName');
}
@@ -55,6 +55,7 @@ function NameBusiness({onNext, isEditing}: SubStepProps) {
onSubmit={handleSubmit}
style={[styles.mh5, styles.flexGrow1]}
submitButtonStyles={[styles.mb0]}
+ shouldHideFixErrorsAlert
>
{translate('businessInfoStep.enterTheNameOfYourBusiness')}
): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS);
+ const errors = getFieldRequiredErrors(values, STEP_FIELDS);
- if (values.companyPhone && !ValidationUtils.isValidUSPhone(values.companyPhone, true)) {
+ if (values.companyPhone && !isValidUSPhone(values.companyPhone, true)) {
errors.companyPhone = translate('bankAccount.error.phoneNumber');
}
@@ -53,6 +53,7 @@ function PhoneNumberBusiness({onNext, isEditing}: SubStepProps) {
onSubmit={handleSubmit}
style={[styles.mh5, styles.flexGrow1]}
submitButtonStyles={[styles.mb0]}
+ shouldHideFixErrorsAlert
>
{translate('businessInfoStep.enterYourCompanysPhoneNumber')}
): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS);
+ const errors = getFieldRequiredErrors(values, STEP_FIELDS);
- if (values.companyTaxID && !ValidationUtils.isValidTaxID(values.companyTaxID)) {
+ if (values.companyTaxID && !isValidTaxID(values.companyTaxID)) {
errors.companyTaxID = translate('bankAccount.error.taxID');
}
@@ -53,6 +53,7 @@ function TaxIdBusiness({onNext, isEditing}: SubStepProps) {
onSubmit={handleSubmit}
style={[styles.mh5, styles.flexGrow1]}
submitButtonStyles={[styles.mb0]}
+ shouldHideFixErrorsAlert
>
{translate('businessInfoStep.enterYourCompanysTaxIdNumber')}
): FormInputErrors =>
- ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS);
+ getFieldRequiredErrors(values, STEP_FIELDS);
const defaultIncorporationType = reimbursementAccount?.achData?.incorporationType ?? '';
@@ -41,6 +41,7 @@ function TypeBusiness({onNext, isEditing}: SubStepProps) {
onSubmit={handleSubmit}
style={[styles.flexGrow1]}
submitButtonStyles={[styles.ph5, styles.mb0]}
+ shouldHideFixErrorsAlert
>
{translate('businessInfoStep.selectYourCompanysType')}
): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS);
+ const errors = getFieldRequiredErrors(values, STEP_FIELDS);
- if (values.website && !ValidationUtils.isValidWebsite(Str.sanitizeURL(values.website, CONST.COMPANY_WEBSITE_DEFAULT_SCHEME))) {
+ if (values.website && !isValidWebsite(Str.sanitizeURL(values.website, CONST.COMPANY_WEBSITE_DEFAULT_SCHEME))) {
errors.website = translate('bankAccount.error.website');
}
@@ -46,7 +46,7 @@ function WebsiteBusiness({onNext, isEditing}: SubStepProps) {
fieldIds: STEP_FIELDS,
onNext: (values) => {
const website = Str.sanitizeURL((values as {website: string})?.website, CONST.COMPANY_WEBSITE_DEFAULT_SCHEME);
- BankAccounts.addBusinessWebsiteForDraft(website);
+ addBusinessWebsiteForDraft(website);
onNext();
},
shouldSaveDraft: true,
@@ -60,6 +60,7 @@ function WebsiteBusiness({onNext, isEditing}: SubStepProps) {
onSubmit={handleSubmit}
style={[styles.mh5, styles.flexGrow1]}
submitButtonStyles={[styles.mb0]}
+ shouldHideFixErrorsAlert
>
{translate('businessInfoStep.enterYourCompanysWebsite')}
{translate('common.websiteExample')}
diff --git a/src/pages/RoomDescriptionPage.tsx b/src/pages/RoomDescriptionPage.tsx
index 799ca14dcf95..14885c2ba08c 100644
--- a/src/pages/RoomDescriptionPage.tsx
+++ b/src/pages/RoomDescriptionPage.tsx
@@ -109,6 +109,7 @@ function RoomDescriptionPage({report, policies}: RoomDescriptionPageProps) {
validate={validate}
submitButtonText={translate('common.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{translate('reportDescriptionPage.explainerText')}
diff --git a/src/pages/Search/SavedSearchRenamePage.tsx b/src/pages/Search/SavedSearchRenamePage.tsx
index 695949661fb1..6e8444bbefbb 100644
--- a/src/pages/Search/SavedSearchRenamePage.tsx
+++ b/src/pages/Search/SavedSearchRenamePage.tsx
@@ -61,6 +61,7 @@ function SavedSearchRenamePage({route}: {route: {params: {q: string; name: strin
onSubmit={onSaveSearch}
style={[styles.mh5, styles.flex1]}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{translate('iou.explainHold')}
diff --git a/src/pages/iou/request/step/IOURequestStepDate.tsx b/src/pages/iou/request/step/IOURequestStepDate.tsx
index 4536c43c9ae4..303b1b453c0b 100644
--- a/src/pages/iou/request/step/IOURequestStepDate.tsx
+++ b/src/pages/iou/request/step/IOURequestStepDate.tsx
@@ -1,83 +1,71 @@
import lodashIsEmpty from 'lodash/isEmpty';
-import React from 'react';
+import React, {useMemo} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
-import {withOnyx} from 'react-native-onyx';
+import {useOnyx} from 'react-native-onyx';
import DatePicker from '@components/DatePicker';
import FormProvider from '@components/Form/FormProvider';
import InputWrapper from '@components/Form/InputWrapper';
import type {FormOnyxValues} from '@components/Form/types';
import useLocalize from '@hooks/useLocalize';
+import usePolicy from '@hooks/usePolicy';
import useThemeStyles from '@hooks/useThemeStyles';
-import * as IOUUtils from '@libs/IOUUtils';
+import {isValidMoneyRequestType, shouldUseTransactionDraft} from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
-import * as ReportUtils from '@libs/ReportUtils';
-import * as TransactionUtils from '@libs/TransactionUtils';
-import * as IOU from '@userActions/IOU';
+import {canEditFieldOfMoneyRequest} from '@libs/ReportUtils';
+import {areRequiredFieldsEmpty, getFormattedCreated} from '@libs/TransactionUtils';
+import {setDraftSplitTransaction, setMoneyRequestCreated, updateMoneyRequestDate} from '@userActions/IOU';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type SCREENS from '@src/SCREENS';
import INPUT_IDS from '@src/types/form/MoneyRequestDateForm';
-import type * as OnyxTypes from '@src/types/onyx';
+import type {Report, Transaction} from '@src/types/onyx';
import StepScreenWrapper from './StepScreenWrapper';
import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
import withWritableReportOrNotFound from './withWritableReportOrNotFound';
-type IOURequestStepDateOnyxProps = {
- /** The draft transaction that holds data to be persisted on the current transaction */
- splitDraftTransaction: OnyxEntry;
+type IOURequestStepDateProps = WithWritableReportOrNotFoundProps & {
+ /** Holds data related to Money Request view state, rather than the underlying Money Request data. */
+ transaction: OnyxEntry;
- /** The actions from the parent report */
- reportActions: OnyxEntry;
-
- /** Session info for the currently logged in user. */
- session: OnyxEntry;
-
- /** The policy of the report */
- policy: OnyxEntry;
-
- /** Collection of categories attached to a policy */
- policyCategories: OnyxEntry;
-
- /** Collection of tags attached to a policy */
- policyTags: OnyxEntry;
+ /** The report linked to the transaction */
+ report: OnyxEntry;
};
-type IOURequestStepDateProps = IOURequestStepDateOnyxProps &
- WithWritableReportOrNotFoundProps & {
- /** Holds data related to Money Request view state, rather than the underlying Money Request data. */
- transaction: OnyxEntry;
-
- /** The report linked to the transaction */
- report: OnyxEntry;
- };
-
function IOURequestStepDate({
route: {
- params: {action, iouType, reportID, backTo, reportActionID},
+ params: {action, iouType, reportID, backTo, reportActionID, transactionID},
},
transaction,
- splitDraftTransaction,
- policy,
- policyTags,
- policyCategories,
- reportActions,
report,
- session,
}: IOURequestStepDateProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
+ const policy = usePolicy(report?.policyID);
+ const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report?.policyID}`);
+ const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`);
+ const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`);
+ const reportActionsReportID = useMemo(() => {
+ let actionsReportID;
+ if (action === CONST.IOU.ACTION.EDIT) {
+ actionsReportID = iouType === CONST.IOU.TYPE.SPLIT ? report?.reportID : report?.parentReportID;
+ }
+ return actionsReportID;
+ }, [action, iouType, report?.reportID, report?.parentReportID]);
+ const [reportAction] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportActionsReportID}`, {
+ canEvict: false,
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ selector: (reportActions) => reportActions?.[`${report?.parentReportActionID || reportActionID}`],
+ });
+ const [session] = useOnyx(ONYXKEYS.SESSION);
const isEditing = action === CONST.IOU.ACTION.EDIT;
// In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value
const isEditingSplitBill = iouType === CONST.IOU.TYPE.SPLIT && isEditing;
- const currentCreated =
- isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? TransactionUtils.getFormattedCreated(splitDraftTransaction) : TransactionUtils.getFormattedCreated(transaction);
- const parentReportAction = reportActions?.[(isEditingSplitBill ? reportActionID : report?.parentReportActionID) ?? -1];
- const canEditingSplitBill =
- isEditingSplitBill && session && parentReportAction && session.accountID === parentReportAction.actorAccountID && TransactionUtils.areRequiredFieldsEmpty(transaction);
- const canEditMoneyRequest = isEditing && ReportUtils.canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.DATE);
+ const currentCreated = isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? getFormattedCreated(splitDraftTransaction) : getFormattedCreated(transaction);
+ const canEditingSplitBill = isEditingSplitBill && session && reportAction && session.accountID === reportAction.actorAccountID && areRequiredFieldsEmpty(transaction);
+ const canEditMoneyRequest = isEditing && canEditFieldOfMoneyRequest(reportAction, CONST.EDIT_REQUEST_FIELD.DATE);
// eslint-disable-next-line rulesdir/no-negated-variables
- const shouldShowNotFound = !IOUUtils.isValidMoneyRequestType(iouType) || (isEditing && !canEditMoneyRequest && !canEditingSplitBill);
+ const shouldShowNotFound = !isValidMoneyRequestType(iouType) || (isEditing && !canEditMoneyRequest && !canEditingSplitBill);
const navigateBack = () => {
Navigation.goBack(backTo);
@@ -94,17 +82,17 @@ function IOURequestStepDate({
// In the split flow, when editing we use SPLIT_TRANSACTION_DRAFT to save draft value
if (isEditingSplitBill) {
- IOU.setDraftSplitTransaction(transaction?.transactionID ?? '-1', {created: newCreated});
+ setDraftSplitTransaction(transactionID, {created: newCreated});
navigateBack();
return;
}
- const isTransactionDraft = IOUUtils.shouldUseTransactionDraft(action);
+ const isTransactionDraft = shouldUseTransactionDraft(action);
- IOU.setMoneyRequestCreated(transaction?.transactionID ?? '-1', newCreated, isTransactionDraft);
+ setMoneyRequestCreated(transactionID, newCreated, isTransactionDraft);
if (isEditing) {
- IOU.updateMoneyRequestDate(transaction?.transactionID ?? '-1', reportID, newCreated, policy, policyTags, policyCategories);
+ updateMoneyRequestDate(transactionID, reportID, newCreated, policy, policyTags, policyCategories);
}
navigateBack();
@@ -125,6 +113,7 @@ function IOURequestStepDate({
onSubmit={updateDate}
submitButtonText={translate('common.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
({
- splitDraftTransaction: {
- key: ({route}) => {
- const transactionID = route?.params.transactionID ?? -1;
- return `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`;
- },
- },
- reportActions: {
- key: ({
- route: {
- params: {action, iouType},
- },
- report,
- }) => {
- let reportID;
- if (action === CONST.IOU.ACTION.EDIT) {
- reportID = iouType === CONST.IOU.TYPE.SPLIT ? report?.reportID : report?.parentReportID;
- }
- return `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID ?? '-1'}`;
- },
- canEvict: false,
- },
- policy: {
- key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '-1'}`,
- },
- policyCategories: {
- key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '-1'}`,
- },
- policyTags: {
- key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '-1'}`,
- },
- session: {
- key: ONYXKEYS.SESSION,
- },
-})(IOURequestStepDate);
-
// eslint-disable-next-line rulesdir/no-negated-variables
-const IOURequestStepDateWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepDateWithOnyx);
+const IOURequestStepDateWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepDate);
// eslint-disable-next-line rulesdir/no-negated-variables
const IOURequestStepDateWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepDateWithFullTransactionOrNotFound);
diff --git a/src/pages/iou/request/step/IOURequestStepDescription.tsx b/src/pages/iou/request/step/IOURequestStepDescription.tsx
index 70bb913d0738..7e67307ae5aa 100644
--- a/src/pages/iou/request/step/IOURequestStepDescription.tsx
+++ b/src/pages/iou/request/step/IOURequestStepDescription.tsx
@@ -152,6 +152,7 @@ function IOURequestStepDescription({
validate={validate}
submitButtonText={translate('common.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
;
-
- userLocation: OnyxEntry;
+type IOURequestStepWaypointProps = WithWritableReportOrNotFoundProps & {
+ transaction: OnyxEntry;
};
-type IOURequestStepWaypointProps = IOURequestStepWaypointOnyxProps &
- WithWritableReportOrNotFoundProps & {
- transaction: OnyxEntry;
- };
-
function IOURequestStepWaypoint({
route: {
params: {action, backTo, iouType, pageIndex, reportID, transactionID},
},
transaction,
- recentWaypoints = [],
- userLocation,
}: IOURequestStepWaypointProps) {
const styles = useThemeStyles();
const {windowWidth} = useWindowDimensions();
@@ -65,12 +54,31 @@ function IOURequestStepWaypoint({
const isFocused = navigation.isFocused();
const {translate} = useLocalize();
const {isOffline} = useNetwork();
+ const [userLocation] = useOnyx(ONYXKEYS.USER_LOCATION);
+ const [recentWaypoints = []] = useOnyx(ONYXKEYS.NVP_RECENT_WAYPOINTS, {
+ // Only grab the most recent 20 waypoints because that's all that is shown in the UI. This also puts them into the format of data
+ // that the google autocomplete component expects for it's "predefined places" feature.
+ selector: (waypoints) =>
+ (waypoints ? waypoints.slice(0, CONST.RECENT_WAYPOINTS_NUMBER as number) : [])
+ .filter((waypoint) => waypoint.keyForList?.includes(CONST.YOUR_LOCATION_TEXT) !== true)
+ .map((waypoint) => ({
+ name: waypoint.name,
+ description: waypoint.address ?? '',
+ geometry: {
+ location: {
+ lat: waypoint.lat ?? 0,
+ lng: waypoint.lng ?? 0,
+ },
+ },
+ })),
+ });
const textInput = useRef(null);
const parsedWaypointIndex = parseInt(pageIndex, 10);
const allWaypoints = transaction?.comment?.waypoints ?? {};
const currentWaypoint = allWaypoints[`waypoint${pageIndex}`] ?? {};
const waypointCount = Object.keys(allWaypoints).length;
const filledWaypointCount = Object.values(allWaypoints).filter((waypoint) => !isEmptyObject(waypoint)).length;
+ const shouldUseTransactionDraft = shouldUseTransactionDraftIOUUtils(action);
const waypointDescriptionKey = useMemo(() => {
switch (parsedWaypointIndex) {
@@ -100,26 +108,26 @@ function IOURequestStepWaypoint({
const validate = (values: FormOnyxValues<'waypointForm'>): Partial> => {
const errors = {};
const waypointValue = values[`waypoint${pageIndex}`] ?? '';
- if (isOffline && waypointValue !== '' && !ValidationUtils.isValidAddress(waypointValue)) {
- ErrorUtils.addErrorMessage(errors, `waypoint${pageIndex}`, translate('bankAccount.error.address'));
+ if (isOffline && waypointValue !== '' && !isValidAddress(waypointValue)) {
+ addErrorMessage(errors, `waypoint${pageIndex}`, translate('bankAccount.error.address'));
}
// If the user is online, and they are trying to save a value without using the autocomplete, show an error message instructing them to use a selected address instead.
// That enables us to save the address with coordinates when it is selected
if (!isOffline && waypointValue !== '' && waypointAddress !== waypointValue) {
- ErrorUtils.addErrorMessage(errors, `waypoint${pageIndex}`, translate('distance.error.selectSuggestedAddress'));
+ addErrorMessage(errors, `waypoint${pageIndex}`, translate('distance.error.selectSuggestedAddress'));
}
return errors;
};
- const saveWaypoint = (waypoint: FormOnyxValues<'waypointForm'>) => Transaction.saveWaypoint(transactionID, pageIndex, waypoint, IOUUtils.shouldUseTransactionDraft(action));
+ const saveWaypoint = (waypoint: FormOnyxValues<'waypointForm'>) => saveWaypointAction(transactionID, pageIndex, waypoint, shouldUseTransactionDraft);
const submit = (values: FormOnyxValues<'waypointForm'>) => {
const waypointValue = values[`waypoint${pageIndex}`] ?? '';
// Allows letting you set a waypoint to an empty value
if (waypointValue === '') {
- Transaction.removeWaypoint(transaction, pageIndex, IOUUtils.shouldUseTransactionDraft(action));
+ removeWaypoint(transaction, pageIndex, shouldUseTransactionDraft);
}
// While the user is offline, the auto-complete address search will not work
@@ -140,7 +148,7 @@ function IOURequestStepWaypoint({
};
const deleteStopAndHideModal = () => {
- Transaction.removeWaypoint(transaction, pageIndex, IOUUtils.shouldUseTransactionDraft(action));
+ removeWaypoint(transaction, pageIndex, shouldUseTransactionDraft);
setRestoreFocusType(CONST.MODAL.RESTORE_FOCUS_TYPE.DELETE);
setIsDeleteStopModalOpen(false);
goBack();
@@ -155,7 +163,7 @@ function IOURequestStepWaypoint({
keyForList: `${values.name ?? 'waypoint'}_${Date.now()}`,
};
- Transaction.saveWaypoint(transactionID, pageIndex, waypoint, IOUUtils.shouldUseTransactionDraft(action));
+ saveWaypointAction(transactionID, pageIndex, waypoint, shouldUseTransactionDraft);
goBack();
};
@@ -208,6 +216,7 @@ function IOURequestStepWaypoint({
shouldValidateOnChange={false}
shouldValidateOnBlur={false}
submitButtonText={translate('common.save')}
+ shouldHideFixErrorsAlert
>
({
- userLocation: {
- key: ONYXKEYS.USER_LOCATION,
- },
- recentWaypoints: {
- key: ONYXKEYS.NVP_RECENT_WAYPOINTS,
-
- // Only grab the most recent 20 waypoints because that's all that is shown in the UI. This also puts them into the format of data
- // that the google autocomplete component expects for it's "predefined places" feature.
- selector: (waypoints) =>
- (waypoints ? waypoints.slice(0, CONST.RECENT_WAYPOINTS_NUMBER as number) : [])
- .filter((waypoint) => waypoint.keyForList?.includes(CONST.YOUR_LOCATION_TEXT) !== true)
- .map((waypoint) => ({
- name: waypoint.name,
- description: waypoint.address ?? '',
- geometry: {
- location: {
- lat: waypoint.lat ?? 0,
- lng: waypoint.lng ?? 0,
- },
- },
- })),
- },
- })(IOURequestStepWaypoint),
- ),
- true,
-);
+export default withWritableReportOrNotFound(withFullTransactionOrNotFound(IOURequestStepWaypoint), true);
diff --git a/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx b/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx
index 4e34fc47a6ed..4fdc94c49a0b 100644
--- a/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx
+++ b/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx
@@ -13,7 +13,7 @@ import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@navigation/Navigation';
-import * as ExitSurvey from '@userActions/ExitSurvey';
+import {saveExitReason} from '@userActions/ExitSurvey';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
@@ -68,12 +68,13 @@ function ExitSurveyReasonPage() {
if (!reason) {
return;
}
- ExitSurvey.saveExitReason(reason);
+ saveExitReason(reason);
Navigation.navigate(ROUTES.SETTINGS_EXIT_SURVEY_RESPONSE.getRoute(reason, ROUTES.SETTINGS_EXIT_SURVEY_REASON.route));
}}
submitButtonText={translate('common.next')}
shouldValidateOnBlur
shouldValidateOnChange
+ shouldHideFixErrorsAlert
>
{isOffline && }
{!isOffline && (
diff --git a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx
index ba451cf8ce55..4b26a5b2b898 100644
--- a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx
+++ b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx
@@ -111,6 +111,7 @@ function ExitSurveyResponsePage({route, navigation}: ExitSurveyResponsePageProps
}}
shouldValidateOnBlur
shouldValidateOnChange
+ shouldHideFixErrorsAlert
>
{isOffline && }
{!isOffline && (
diff --git a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
index c49c286e9749..0f1ad2db5595 100644
--- a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
+++ b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
@@ -144,6 +144,7 @@ function NewContactMethodPage({route}: NewContactMethodPageProps) {
onSubmit={handleValidateMagicCode}
submitButtonText={translate('common.add')}
style={[styles.flexGrow1, styles.mh5]}
+ shouldHideFixErrorsAlert
>
{translate('common.pleaseEnterEmailOrPhoneNumber')}
diff --git a/src/pages/settings/Profile/CustomStatus/SetDatePage.tsx b/src/pages/settings/Profile/CustomStatus/SetDatePage.tsx
index 51dddadbc8d1..7886e89e05a9 100644
--- a/src/pages/settings/Profile/CustomStatus/SetDatePage.tsx
+++ b/src/pages/settings/Profile/CustomStatus/SetDatePage.tsx
@@ -1,46 +1,40 @@
import React, {useCallback} from 'react';
-import {withOnyx} from 'react-native-onyx';
-import type {OnyxEntry} from 'react-native-onyx';
+import {useOnyx} from 'react-native-onyx';
import DatePicker from '@components/DatePicker';
import FormProvider from '@components/Form/FormProvider';
import InputWrapper from '@components/Form/InputWrapper';
import type {FormOnyxValues} from '@components/Form/types';
+import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
-import * as User from '@libs/actions/User';
import DateUtils from '@libs/DateUtils';
import Navigation from '@libs/Navigation/Navigation';
-import * as ValidationUtils from '@libs/ValidationUtils';
+import {getDatePassedError, getFieldRequiredErrors} from '@libs/ValidationUtils';
+import {updateDraftCustomStatus} from '@userActions/User';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import INPUT_IDS from '@src/types/form/SettingsStatusClearDateForm';
-import type * as OnyxTypes from '@src/types/onyx';
+import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
type DateTime = {
dateTime: string;
};
-
-type SetDatePageOnyxProps = {
- customStatus: OnyxEntry;
-};
-
-type SetDatePageProps = SetDatePageOnyxProps;
-
-function SetDatePage({customStatus}: SetDatePageProps) {
+function SetDatePage() {
const styles = useThemeStyles();
const {translate} = useLocalize();
+ const [customStatus, customStatusMetadata] = useOnyx(ONYXKEYS.CUSTOM_STATUS_DRAFT);
const customClearAfter = customStatus?.clearAfter ?? '';
const onSubmit = (value: DateTime) => {
- User.updateDraftCustomStatus({clearAfter: DateUtils.combineDateAndTime(customClearAfter, value.dateTime)});
+ updateDraftCustomStatus({clearAfter: DateUtils.combineDateAndTime(customClearAfter, value.dateTime)});
Navigation.goBack(ROUTES.SETTINGS_STATUS_CLEAR_AFTER);
};
const validate = useCallback((values: FormOnyxValues) => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.DATE_TIME]);
- const dateError = ValidationUtils.getDatePassedError(values.dateTime);
+ const errors = getFieldRequiredErrors(values, [INPUT_IDS.DATE_TIME]);
+ const dateError = getDatePassedError(values.dateTime);
if (values.dateTime && dateError) {
errors.dateTime = dateError;
@@ -49,6 +43,10 @@ function SetDatePage({customStatus}: SetDatePageProps) {
return errors;
}, []);
+ if (isLoadingOnyxValue(customStatusMetadata)) {
+ return ;
+ }
+
return (
({
- customStatus: {
- key: ONYXKEYS.CUSTOM_STATUS_DRAFT,
- },
-})(SetDatePage);
+export default SetDatePage;
diff --git a/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.tsx b/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.tsx
index 55c0100a84db..412f52ed9656 100644
--- a/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.tsx
+++ b/src/pages/settings/Profile/CustomStatus/StatusClearAfterPage.tsx
@@ -11,10 +11,10 @@ import Text from '@components/Text';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
-import * as User from '@libs/actions/User';
import DateUtils from '@libs/DateUtils';
import Navigation from '@libs/Navigation/Navigation';
-import * as ValidationUtils from '@libs/ValidationUtils';
+import {validateDateTimeIsAtLeastOneMinuteInFuture} from '@libs/ValidationUtils';
+import {updateDraftCustomStatus} from '@userActions/User';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
@@ -47,7 +47,7 @@ const useValidateCustomDate = (data: string) => {
const [customDateError, setCustomDateError] = useState('');
const [customTimeError, setCustomTimeError] = useState('');
const validate = () => {
- const {dateValidationErrorKey, timeValidationErrorKey} = ValidationUtils.validateDateTimeIsAtLeastOneMinuteInFuture(data);
+ const {dateValidationErrorKey, timeValidationErrorKey} = validateDateTimeIsAtLeastOneMinuteInFuture(data);
setCustomDateError(dateValidationErrorKey);
setCustomTimeError(timeValidationErrorKey);
@@ -113,7 +113,7 @@ function StatusClearAfterPage() {
const selectedRange = statusType.find((item) => item.isSelected);
calculatedDraftDate = DateUtils.getDateFromStatusType(selectedRange?.value ?? CONST.CUSTOM_STATUS_TYPES.NEVER);
}
- User.updateDraftCustomStatus({clearAfter: calculatedDraftDate});
+ updateDraftCustomStatus({clearAfter: calculatedDraftDate});
Navigation.goBack(ROUTES.SETTINGS_STATUS);
};
@@ -125,11 +125,11 @@ function StatusClearAfterPage() {
setDraftPeriod(mode.value);
if (mode.value === CONST.CUSTOM_STATUS_TYPES.CUSTOM) {
- User.updateDraftCustomStatus({clearAfter: DateUtils.getOneHourFromNow()});
+ updateDraftCustomStatus({clearAfter: DateUtils.getOneHourFromNow()});
} else {
const selectedRange = statusType.find((item) => item.value === mode.value);
const calculatedDraftDate = DateUtils.getDateFromStatusType(selectedRange?.value ?? CONST.CUSTOM_STATUS_TYPES.NEVER);
- User.updateDraftCustomStatus({clearAfter: calculatedDraftDate});
+ updateDraftCustomStatus({clearAfter: calculatedDraftDate});
Navigation.goBack(ROUTES.SETTINGS_STATUS);
}
},
@@ -137,7 +137,7 @@ function StatusClearAfterPage() {
);
useEffect(() => {
- User.updateDraftCustomStatus({
+ updateDraftCustomStatus({
clearAfter: draftClearAfter || clearAfter,
});
@@ -179,6 +179,7 @@ function StatusClearAfterPage() {
scrollContextEnabled={false}
isSubmitButtonVisible={false}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{timePeriodOptions()}
diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
index 0d400211cc4c..81197aabf401 100644
--- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
@@ -12,8 +12,8 @@ import ScreenWrapper from '@components/ScreenWrapper';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
-import * as ValidationUtils from '@libs/ValidationUtils';
-import * as PersonalDetails from '@userActions/PersonalDetails';
+import {getAgeRequirementError, getFieldRequiredErrors} from '@libs/ValidationUtils';
+import {updateDateOfBirth} from '@userActions/PersonalDetails';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import INPUT_IDS from '@src/types/form/DateOfBirthForm';
@@ -28,11 +28,11 @@ function DateOfBirthPage() {
*/
const validate = useCallback((values: FormOnyxValues) => {
const requiredFields = ['dob' as const];
- const errors = ValidationUtils.getFieldRequiredErrors(values, requiredFields);
+ const errors = getFieldRequiredErrors(values, requiredFields);
const minimumAge = CONST.DATE_BIRTH.MIN_AGE;
const maximumAge = CONST.DATE_BIRTH.MAX_AGE;
- const dateError = ValidationUtils.getAgeRequirementError(values.dob ?? '', minimumAge, maximumAge);
+ const dateError = getAgeRequirementError(values.dob ?? '', minimumAge, maximumAge);
if (values.dob && dateError) {
errors.dob = dateError;
@@ -58,9 +58,10 @@ function DateOfBirthPage() {
style={[styles.flexGrow1, styles.ph5]}
formID={ONYXKEYS.FORMS.DATE_OF_BIRTH_FORM}
validate={validate}
- onSubmit={PersonalDetails.updateDateOfBirth}
+ onSubmit={updateDateOfBirth}
submitButtonText={translate('common.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.SUBSCRIPTION_SIZE]);
- if (values[INPUT_IDS.SUBSCRIPTION_SIZE] && !ValidationUtils.isValidSubscriptionSize(values[INPUT_IDS.SUBSCRIPTION_SIZE])) {
+ const errors = getFieldRequiredErrors(values, [INPUT_IDS.SUBSCRIPTION_SIZE]);
+ if (values[INPUT_IDS.SUBSCRIPTION_SIZE] && !isValidSubscriptionSize(values[INPUT_IDS.SUBSCRIPTION_SIZE])) {
errors.subscriptionSize = translate('subscription.subscriptionSize.error.size');
}
@@ -59,6 +59,7 @@ function Size({onNext}: SizeProps) {
validate={validate}
style={[styles.mh5, styles.flexGrow1]}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{translate('subscription.subscriptionSize.yourSize')}
diff --git a/src/pages/tasks/NewTaskDescriptionPage.tsx b/src/pages/tasks/NewTaskDescriptionPage.tsx
index e70b6ea15d20..46df166b1eae 100644
--- a/src/pages/tasks/NewTaskDescriptionPage.tsx
+++ b/src/pages/tasks/NewTaskDescriptionPage.tsx
@@ -1,10 +1,10 @@
import React from 'react';
import {View} from 'react-native';
-import {withOnyx} from 'react-native-onyx';
-import type {OnyxEntry} from 'react-native-onyx';
+import {useOnyx} from 'react-native-onyx';
import FormProvider from '@components/Form/FormProvider';
import InputWrapperWithRef from '@components/Form/InputWrapper';
import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
+import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import TextInput from '@components/TextInput';
@@ -25,18 +25,14 @@ import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import INPUT_IDS from '@src/types/form/NewTaskForm';
-import type {Task} from '@src/types/onyx';
+import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
-type NewTaskDescriptionPageOnyxProps = {
- /** Task Creation Data */
- task: OnyxEntry;
-};
+type NewTaskDescriptionPageProps = PlatformStackScreenProps;
-type NewTaskDescriptionPageProps = NewTaskDescriptionPageOnyxProps & PlatformStackScreenProps;
-
-function NewTaskDescriptionPage({task, route}: NewTaskDescriptionPageProps) {
+function NewTaskDescriptionPage({route}: NewTaskDescriptionPageProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
+ const [task, taskMetadata] = useOnyx(ONYXKEYS.TASK);
const {inputCallbackRef, inputRef} = useAutoFocusInput();
const goBack = () => Navigation.goBack(ROUTES.NEW_TASK.getRoute(route.params?.backTo));
@@ -55,6 +51,10 @@ function NewTaskDescriptionPage({task, route}: NewTaskDescriptionPageProps) {
return errors;
};
+ if (isLoadingOnyxValue(taskMetadata)) {
+ return ;
+ }
+
return (
({
- task: {
- key: ONYXKEYS.TASK,
- },
-})(NewTaskDescriptionPage);
+export default NewTaskDescriptionPage;
diff --git a/src/pages/tasks/NewTaskTitlePage.tsx b/src/pages/tasks/NewTaskTitlePage.tsx
index 88a44aca8501..cd29082aced3 100644
--- a/src/pages/tasks/NewTaskTitlePage.tsx
+++ b/src/pages/tasks/NewTaskTitlePage.tsx
@@ -1,38 +1,34 @@
import React from 'react';
import {View} from 'react-native';
-import {withOnyx} from 'react-native-onyx';
-import type {OnyxEntry} from 'react-native-onyx';
+import {useOnyx} from 'react-native-onyx';
import FormProvider from '@components/Form/FormProvider';
import InputWrapperWithRef from '@components/Form/InputWrapper';
import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
+import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import TextInput from '@components/TextInput';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
-import * as ErrorUtils from '@libs/ErrorUtils';
+import {addErrorMessage} from '@libs/ErrorUtils';
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import type {NewTaskNavigatorParamList} from '@libs/Navigation/types';
-import * as TaskActions from '@userActions/Task';
+import {setTitleValue} from '@userActions/Task';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import INPUT_IDS from '@src/types/form/NewTaskForm';
-import type {Task} from '@src/types/onyx';
+import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
-type NewTaskTitlePageOnyxProps = {
- /** Task Creation Data */
- task: OnyxEntry;
-};
-type NewTaskTitlePageProps = NewTaskTitlePageOnyxProps & PlatformStackScreenProps;
+type NewTaskTitlePageProps = PlatformStackScreenProps;
-function NewTaskTitlePage({task, route}: NewTaskTitlePageProps) {
+function NewTaskTitlePage({route}: NewTaskTitlePageProps) {
const styles = useThemeStyles();
const {inputCallbackRef} = useAutoFocusInput();
-
+ const [task, taskMetadata] = useOnyx(ONYXKEYS.TASK);
const {translate} = useLocalize();
const goBack = () => Navigation.goBack(ROUTES.NEW_TASK.getRoute(route.params?.backTo));
@@ -41,9 +37,9 @@ function NewTaskTitlePage({task, route}: NewTaskTitlePageProps) {
if (!values.taskTitle) {
// We error if the user doesn't enter a task name
- ErrorUtils.addErrorMessage(errors, 'taskTitle', translate('newTaskPage.pleaseEnterTaskName'));
+ addErrorMessage(errors, 'taskTitle', translate('newTaskPage.pleaseEnterTaskName'));
} else if (values.taskTitle.length > CONST.TITLE_CHARACTER_LIMIT) {
- ErrorUtils.addErrorMessage(errors, 'taskTitle', translate('common.error.characterLimitExceedCounter', {length: values.taskTitle.length, limit: CONST.TITLE_CHARACTER_LIMIT}));
+ addErrorMessage(errors, 'taskTitle', translate('common.error.characterLimitExceedCounter', {length: values.taskTitle.length, limit: CONST.TITLE_CHARACTER_LIMIT}));
}
return errors;
@@ -52,10 +48,14 @@ function NewTaskTitlePage({task, route}: NewTaskTitlePageProps) {
// On submit, we want to call the assignTask function and wait to validate
// the response
const onSubmit = (values: FormOnyxValues) => {
- TaskActions.setTitleValue(values.taskTitle);
+ setTitleValue(values.taskTitle);
goBack();
};
+ if (isLoadingOnyxValue(taskMetadata)) {
+ return ;
+ }
+
return (
({
- task: {
- key: ONYXKEYS.TASK,
- },
-})(NewTaskTitlePage);
+export default NewTaskTitlePage;
diff --git a/src/pages/tasks/TaskDescriptionPage.tsx b/src/pages/tasks/TaskDescriptionPage.tsx
index 9fdf1757ca96..bc4fad61aaaa 100644
--- a/src/pages/tasks/TaskDescriptionPage.tsx
+++ b/src/pages/tasks/TaskDescriptionPage.tsx
@@ -110,6 +110,7 @@ function TaskDescriptionPage({report, currentUserPersonalDetails}: TaskDescripti
onSubmit={submit}
submitButtonText={translate('common.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
= {};
if (!title) {
- ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, translate('newTaskPage.pleaseEnterTaskName'));
+ addErrorMessage(errors, INPUT_IDS.TITLE, translate('newTaskPage.pleaseEnterTaskName'));
} else if (title.length > CONST.TITLE_CHARACTER_LIMIT) {
- ErrorUtils.addErrorMessage(errors, INPUT_IDS.TITLE, translate('common.error.characterLimitExceedCounter', {length: title.length, limit: CONST.TITLE_CHARACTER_LIMIT}));
+ addErrorMessage(errors, INPUT_IDS.TITLE, translate('common.error.characterLimitExceedCounter', {length: title.length, limit: CONST.TITLE_CHARACTER_LIMIT}));
}
return errors;
@@ -54,7 +54,7 @@ function TaskTitlePage({report, currentUserPersonalDetails}: TaskTitlePageProps)
if (values.title !== report?.reportName && !isEmptyObject(report)) {
// Set the title of the report in the store and then call EditTask API
// to update the title of the report on the server
- Task.editTask(report, {title: values.title});
+ editTask(report, {title: values.title});
}
Navigation.dismissModal(report?.reportID);
@@ -62,16 +62,16 @@ function TaskTitlePage({report, currentUserPersonalDetails}: TaskTitlePageProps)
[report],
);
- if (!ReportUtils.isTaskReport(report)) {
+ if (!isTaskReport(report)) {
Navigation.isNavigationReady().then(() => {
Navigation.dismissModal(report?.reportID);
});
}
const inputRef = useRef(null);
- const isOpen = ReportUtils.isOpenTaskReport(report);
- const canModifyTask = Task.canModifyTask(report, currentUserPersonalDetails.accountID);
- const isTaskNonEditable = ReportUtils.isTaskReport(report) && (!canModifyTask || !isOpen);
+ const isOpen = isOpenTaskReport(report);
+ const canModifyTask = canModifyTaskAction(report, currentUserPersonalDetails.accountID);
+ const isTaskNonEditable = isTaskReport(report) && (!canModifyTask || !isOpen);
return (
): FormInputErrors => {
const errors: FormInputErrors = {};
- if (values[params.expenseType] && !ValidationUtils.isNumeric(values[params.expenseType])) {
- ErrorUtils.addErrorMessage(errors, params.expenseType, translate('workspace.netsuite.advancedConfig.error.customFormID'));
+ if (values[params.expenseType] && !isNumeric(values[params.expenseType])) {
+ addErrorMessage(errors, params.expenseType, translate('workspace.netsuite.advancedConfig.error.customFormID'));
}
return errors;
@@ -55,7 +55,7 @@ function NetSuiteCustomFormIDPage({policy}: WithPolicyConnectionsProps) {
const updateCustomFormID = useCallback(
(formValues: FormOnyxValues) => {
if (config?.customFormIDOptions?.[customFormIDKey]?.[CONST.NETSUITE_MAP_EXPORT_DESTINATION[exportDestination]] !== formValues[params.expenseType]) {
- Connections.updateNetSuiteCustomFormIDOptions(policyID, formValues[params.expenseType], isReimbursable, exportDestination, config?.customFormIDOptions);
+ updateNetSuiteCustomFormIDOptions(policyID, formValues[params.expenseType], isReimbursable, exportDestination, config?.customFormIDOptions);
}
Navigation.goBack(ROUTES.POLICY_ACCOUNTING_NETSUITE_ADVANCED.getRoute(policyID));
},
@@ -86,12 +86,13 @@ function NetSuiteCustomFormIDPage({policy}: WithPolicyConnectionsProps) {
submitButtonText={translate('common.confirm')}
shouldValidateOnBlur
shouldValidateOnChange
+ shouldHideFixErrorsAlert
>
Policy.clearNetSuiteErrorField(policyID, customFormIDKey)}
+ onClose={() => clearNetSuiteErrorField(policyID, customFormIDKey)}
>
customSegment?.[fieldName as keyof typeof customSegment]?.toLowerCase() === formValues[key].toLowerCase(),
)
) {
- ErrorUtils.addErrorMessage(errors, fieldName, translate('workspace.netsuite.import.importCustomFields.customSegments.errors.uniqueFieldError', {fieldName: fieldLabel}));
+ addErrorMessage(errors, fieldName, translate('workspace.netsuite.import.importCustomFields.customSegments.errors.uniqueFieldError', {fieldName: fieldLabel}));
}
return errors;
@@ -129,6 +129,7 @@ function NetSuiteImportCustomFieldEdit({
shouldValidateOnBlur
shouldValidateOnChange
isSubmitDisabled={!!settingsPendingAction([`${importCustomField}_${valueIndex}`], config?.pendingFields)}
+ shouldHideFixErrorsAlert
>
= {
+ const renderMap: Record = {
mapping: renderSelection,
};
@@ -174,7 +175,7 @@ function NetSuiteImportCustomFieldEdit({
contentContainerStyle={[styles.pb2, styles.flex1]}
titleStyle={styles.ph5}
connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE}
- shouldBeBlocked={!customField || !PolicyUtils.isNetSuiteCustomFieldPropertyEditable(customField, fieldName)}
+ shouldBeBlocked={!customField || !isNetSuiteCustomFieldPropertyEditable(customField, fieldName)}
shouldUseScrollView={false}
>
{renderMap[fieldName] || renderForm}
diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/ChooseCustomListStep.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/ChooseCustomListStep.tsx
index b51ad476a10b..fa674b52782c 100644
--- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/ChooseCustomListStep.tsx
+++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/ChooseCustomListStep.tsx
@@ -6,7 +6,7 @@ import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useNetSuiteImportAddCustomListFormSubmit from '@hooks/useNetSuiteImportAddCustomListForm';
import useThemeStyles from '@hooks/useThemeStyles';
-import * as ValidationUtils from '@libs/ValidationUtils';
+import {getFieldRequiredErrors} from '@libs/ValidationUtils';
import NetSuiteCustomListPicker from '@pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteCustomListPicker';
import type {CustomFieldSubStepWithPolicy} from '@pages/workspace/accounting/netsuite/types';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -19,7 +19,7 @@ function ChooseCustomListStep({policy, onNext, isEditing, netSuiteCustomFieldFor
const {translate} = useLocalize();
const validate = useCallback((values: FormOnyxValues): FormInputErrors => {
- return ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.LIST_NAME]);
+ return getFieldRequiredErrors(values, [INPUT_IDS.LIST_NAME]);
}, []);
const handleSubmit = useNetSuiteImportAddCustomListFormSubmit({
@@ -39,6 +39,7 @@ function ChooseCustomListStep({policy, onNext, isEditing, netSuiteCustomFieldFor
enabledWhenOffline
submitFlexEnabled
shouldUseScrollView
+ shouldHideFixErrorsAlert
>
{translate(`workspace.netsuite.import.importCustomFields.customLists.addForm.listNameTitle`)}
): FormInputErrors => {
const errors: FormInputErrors = {};
- if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.INTERNAL_ID])) {
+ if (!isRequiredFulfilled(values[INPUT_IDS.INTERNAL_ID])) {
errors[INPUT_IDS.INTERNAL_ID] = translate('workspace.netsuite.import.importCustomFields.requiredFieldError', {fieldName: fieldLabel});
} else if (customSegments?.find((customSegment) => customSegment.internalID.toLowerCase() === values[INPUT_IDS.INTERNAL_ID].toLowerCase())) {
errors[INPUT_IDS.INTERNAL_ID] = translate('workspace.netsuite.import.importCustomFields.customSegments.errors.uniqueFieldError', {fieldName: fieldLabel});
@@ -59,6 +59,7 @@ function CustomSegmentInternalIdStep({customSegmentType, onNext, isEditing, netS
enabledWhenOffline
submitFlexEnabled
shouldUseScrollView
+ shouldHideFixErrorsAlert
>
diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/CustomSegmentNameStep.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/CustomSegmentNameStep.tsx
index ad3d4d8c39ca..b56c270f8eae 100644
--- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/CustomSegmentNameStep.tsx
+++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/CustomSegmentNameStep.tsx
@@ -11,7 +11,7 @@ import useLocalize from '@hooks/useLocalize';
import useNetSuiteImportAddCustomSegmentFormSubmit from '@hooks/useNetSuiteImportAddCustomSegmentForm';
import useThemeStyles from '@hooks/useThemeStyles';
import Parser from '@libs/Parser';
-import * as ValidationUtils from '@libs/ValidationUtils';
+import {isRequiredFulfilled} from '@libs/ValidationUtils';
import type {CustomFieldSubStepWithPolicy} from '@pages/workspace/accounting/netsuite/types';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -37,7 +37,7 @@ function CustomSegmentNameStep({customSegmentType, onNext, isEditing, customSegm
(values: FormOnyxValues): FormInputErrors => {
const errors: FormInputErrors = {};
- if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.SEGMENT_NAME])) {
+ if (!isRequiredFulfilled(values[INPUT_IDS.SEGMENT_NAME])) {
errors[INPUT_IDS.SEGMENT_NAME] = translate('workspace.netsuite.import.importCustomFields.requiredFieldError', {
fieldName: translate(`workspace.netsuite.import.importCustomFields.customSegments.addForm.${customSegmentRecordType}Name`),
});
@@ -60,6 +60,7 @@ function CustomSegmentNameStep({customSegmentType, onNext, isEditing, customSegm
enabledWhenOffline
submitFlexEnabled
shouldUseScrollView
+ shouldHideFixErrorsAlert
>
diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/CustomSegmentScriptIdStep.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/CustomSegmentScriptIdStep.tsx
index 529c720dfb9f..72dba52d8307 100644
--- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/CustomSegmentScriptIdStep.tsx
+++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/CustomSegmentScriptIdStep.tsx
@@ -11,7 +11,7 @@ import useLocalize from '@hooks/useLocalize';
import useNetSuiteImportAddCustomSegmentFormSubmit from '@hooks/useNetSuiteImportAddCustomSegmentForm';
import useThemeStyles from '@hooks/useThemeStyles';
import Parser from '@libs/Parser';
-import * as ValidationUtils from '@libs/ValidationUtils';
+import {isRequiredFulfilled} from '@libs/ValidationUtils';
import type {CustomFieldSubStepWithPolicy} from '@pages/workspace/accounting/netsuite/types';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
@@ -36,7 +36,7 @@ function CustomSegmentScriptIdStep({customSegmentType, onNext, isEditing, custom
(values: FormOnyxValues): FormInputErrors => {
const errors: FormInputErrors = {};
- if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.SCRIPT_ID])) {
+ if (!isRequiredFulfilled(values[INPUT_IDS.SCRIPT_ID])) {
errors[INPUT_IDS.SCRIPT_ID] = translate('workspace.netsuite.import.importCustomFields.requiredFieldError', {fieldName: fieldLabel});
} else if (customSegments?.find((customSegment) => customSegment.scriptID.toLowerCase() === values[INPUT_IDS.SCRIPT_ID].toLowerCase())) {
errors[INPUT_IDS.SCRIPT_ID] = translate('workspace.netsuite.import.importCustomFields.customSegments.errors.uniqueFieldError', {fieldName: fieldLabel});
@@ -63,6 +63,7 @@ function CustomSegmentScriptIdStep({customSegmentType, onNext, isEditing, custom
enabledWhenOffline
submitFlexEnabled
shouldUseScrollView
+ shouldHideFixErrorsAlert
>
diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/TransactionFieldIDStep.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/TransactionFieldIDStep.tsx
index 1b787212f0ac..e7a6ea88ec98 100644
--- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/TransactionFieldIDStep.tsx
+++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/substeps/TransactionFieldIDStep.tsx
@@ -11,7 +11,7 @@ import useLocalize from '@hooks/useLocalize';
import useNetSuiteImportAddCustomListFormSubmit from '@hooks/useNetSuiteImportAddCustomListForm';
import useThemeStyles from '@hooks/useThemeStyles';
import Parser from '@libs/Parser';
-import * as ValidationUtils from '@libs/ValidationUtils';
+import {isRequiredFulfilled} from '@libs/ValidationUtils';
import type {CustomFieldSubStepWithPolicy} from '@pages/workspace/accounting/netsuite/types';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -35,7 +35,7 @@ function TransactionFieldIDStep({onNext, isEditing, netSuiteCustomFieldFormValue
const validate = useCallback(
(values: FormOnyxValues): FormInputErrors => {
const errors: FormInputErrors = {};
- if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.TRANSACTION_FIELD_ID])) {
+ if (!isRequiredFulfilled(values[INPUT_IDS.TRANSACTION_FIELD_ID])) {
errors[INPUT_IDS.TRANSACTION_FIELD_ID] = translate('workspace.netsuite.import.importCustomFields.requiredFieldError', {fieldName: fieldLabel});
} else if (customLists?.find((customList) => customList.transactionFieldID.toLowerCase() === values[INPUT_IDS.TRANSACTION_FIELD_ID].toLowerCase())) {
errors[INPUT_IDS.TRANSACTION_FIELD_ID] = translate('workspace.netsuite.import.importCustomFields.customLists.errors.uniqueTransactionFieldIDError');
@@ -56,6 +56,7 @@ function TransactionFieldIDStep({onNext, isEditing, netSuiteCustomFieldFormValue
enabledWhenOffline
submitFlexEnabled
shouldUseScrollView
+ shouldHideFixErrorsAlert
>
{translate(`workspace.netsuite.import.importCustomFields.customLists.addForm.transactionFieldIDTitle`)}
diff --git a/src/pages/workspace/accounting/netsuite/types.ts b/src/pages/workspace/accounting/netsuite/types.ts
index 608dbadf316e..539518442865 100644
--- a/src/pages/workspace/accounting/netsuite/types.ts
+++ b/src/pages/workspace/accounting/netsuite/types.ts
@@ -74,6 +74,7 @@ type AccordionItem = {
type ExpenseRouteParams = {
expenseType: ValueOf;
+ policyID: string;
};
type CustomFieldSubStepWithPolicy = SubStepProps & {
diff --git a/src/pages/workspace/accounting/nsqs/NSQSSetupPage.tsx b/src/pages/workspace/accounting/nsqs/NSQSSetupPage.tsx
index f3b578b6e064..cba771990413 100644
--- a/src/pages/workspace/accounting/nsqs/NSQSSetupPage.tsx
+++ b/src/pages/workspace/accounting/nsqs/NSQSSetupPage.tsx
@@ -88,6 +88,7 @@ function NSQSSetupPage({policy}: WithPolicyConnectionsProps) {
enabledWhenOffline
shouldValidateOnBlur
shouldValidateOnChange
+ shouldHideFixErrorsAlert
>
{translate('workspace.nsqs.setup.description')}
{
- Category.setWorkspaceCategoryDescriptionHint(policyID, categoryName, commentHint);
+ setWorkspaceCategoryDescriptionHint(policyID, categoryName, commentHint);
Navigation.setNavigationActionToMicrotaskQueue(() => Navigation.goBack(ROUTES.WORKSPACE_CATEGORY_SETTINGS.getRoute(policyID, categoryName)));
}}
submitButtonText={translate('common.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{translate('workspace.rules.categoryRules.descriptionHintDescription', {categoryName})}
diff --git a/src/pages/workspace/categories/CategoryFlagAmountsOverPage.tsx b/src/pages/workspace/categories/CategoryFlagAmountsOverPage.tsx
index dd80757749dd..25508d3a3429 100644
--- a/src/pages/workspace/categories/CategoryFlagAmountsOverPage.tsx
+++ b/src/pages/workspace/categories/CategoryFlagAmountsOverPage.tsx
@@ -11,12 +11,12 @@ import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import usePolicy from '@hooks/usePolicy';
import useThemeStyles from '@hooks/useThemeStyles';
-import * as CurrencyUtils from '@libs/CurrencyUtils';
+import {convertToFrontendAmountAsString, getCurrencySymbol} from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import type {SettingsNavigatorParamList} from '@navigation/types';
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import * as Category from '@userActions/Policy/Category';
+import {setPolicyCategoryMaxAmount} from '@userActions/Policy/Category';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
@@ -45,7 +45,7 @@ function CategoryFlagAmountsOverPage({
const defaultValue =
policyCategoryMaxExpenseAmount === CONST.DISABLED_MAX_EXPENSE_VALUE || !policyCategoryMaxExpenseAmount
? ''
- : CurrencyUtils.convertToFrontendAmountAsString(policyCategoryMaxExpenseAmount, policy?.outputCurrency);
+ : convertToFrontendAmountAsString(policyCategoryMaxExpenseAmount, policy?.outputCurrency);
return (
{
- Category.setPolicyCategoryMaxAmount(policyID, categoryName, maxExpenseAmount, expenseLimitType);
+ setPolicyCategoryMaxAmount(policyID, categoryName, maxExpenseAmount, expenseLimitType);
Navigation.setNavigationActionToMicrotaskQueue(() => Navigation.goBack(ROUTES.WORKSPACE_CATEGORY_SETTINGS.getRoute(policyID, categoryName)));
}}
submitButtonText={translate('workspace.editor.save')}
enabledWhenOffline
submitButtonStyles={styles.ph5}
+ shouldHideFixErrorsAlert
>
{translate('workspace.rules.categoryRules.flagAmountsOverDescription', {categoryName})}
@@ -80,7 +81,7 @@ function CategoryFlagAmountsOverPage({
label={translate('iou.amount')}
InputComponent={AmountForm}
inputID={INPUT_IDS.MAX_EXPENSE_AMOUNT}
- currency={CurrencyUtils.getCurrencySymbol(policy?.outputCurrency ?? CONST.CURRENCY.USD)}
+ currency={getCurrencySymbol(policy?.outputCurrency ?? CONST.CURRENCY.USD)}
defaultValue={defaultValue}
isCurrencyPressable={false}
ref={inputCallbackRef}
diff --git a/src/pages/workspace/categories/CategoryForm.tsx b/src/pages/workspace/categories/CategoryForm.tsx
index f83c1f0594ad..a5b006cc3844 100644
--- a/src/pages/workspace/categories/CategoryForm.tsx
+++ b/src/pages/workspace/categories/CategoryForm.tsx
@@ -72,6 +72,7 @@ function CategoryForm({onSubmit, policyCategories, categoryName, validateEdit}:
validate={validateEdit || validate}
style={[styles.mh5, styles.flex1]}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
) => {
- CompanyCards.updateCompanyCardName(workspaceAccountID, cardID, values[INPUT_IDS.NAME], bank, defaultValue);
+ updateCompanyCardName(workspaceAccountID, cardID, values[INPUT_IDS.NAME], bank, defaultValue);
Navigation.goBack();
};
const validate = (values: FormOnyxValues): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.NAME]);
+ const errors = getFieldRequiredErrors(values, [INPUT_IDS.NAME]);
const length = values.name.length;
if (length > CONST.STANDARD_LENGTH_LIMIT) {
- ErrorUtils.addErrorMessage(errors, INPUT_IDS.NAME, translate('common.error.characterLimitExceedCounter', {length, limit: CONST.STANDARD_LENGTH_LIMIT}));
+ addErrorMessage(errors, INPUT_IDS.NAME, translate('common.error.characterLimitExceedCounter', {length, limit: CONST.STANDARD_LENGTH_LIMIT}));
}
return errors;
};
@@ -72,6 +72,7 @@ function WorkspaceCompanyCardEditCardNamePage({route}: WorkspaceCompanyCardEditC
style={[styles.flex1, styles.mh5]}
enabledWhenOffline
validate={validate}
+ shouldHideFixErrorsAlert
>
): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.CARD_TITLE]);
+ const errors = getFieldRequiredErrors(values, [INPUT_IDS.CARD_TITLE]);
const length = values.cardTitle.length;
if (length > CONST.STANDARD_LENGTH_LIMIT) {
- ErrorUtils.addErrorMessage(errors, INPUT_IDS.CARD_TITLE, translate('common.error.characterLimitExceedCounter', {length, limit: CONST.STANDARD_LENGTH_LIMIT}));
+ addErrorMessage(errors, INPUT_IDS.CARD_TITLE, translate('common.error.characterLimitExceedCounter', {length, limit: CONST.STANDARD_LENGTH_LIMIT}));
}
return errors;
};
const submit = (values: FormOnyxValues) => {
- CompanyCards.setAddNewCompanyCardStepAndData({
+ setAddNewCompanyCardStepAndData({
step: CONST.COMPANY_CARDS.STEP.CARD_DETAILS,
data: {
bankName: values.cardTitle,
@@ -43,7 +43,7 @@ function CardNameStep() {
};
const handleBackButtonPress = () => {
- CompanyCards.setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.CARD_INSTRUCTIONS});
+ setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.CARD_INSTRUCTIONS});
};
return (
@@ -65,6 +65,7 @@ function CardNameStep() {
validate={validate}
style={[styles.mh5, styles.flexGrow1]}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{!!feedProvider && !isStripeFeedProvider ? translate(`workspace.companyCards.addNewCard.feedDetails.${feedProvider}.title`) : ''}
diff --git a/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx b/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx
index 8bc88744e5b8..306df3a48229 100644
--- a/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx
@@ -10,10 +10,10 @@ import TextInput from '@components/TextInput';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
-import * as ErrorUtils from '@libs/ErrorUtils';
-import * as ValidationUtils from '@libs/ValidationUtils';
+import {addErrorMessage} from '@libs/ErrorUtils';
+import {getFieldRequiredErrors} from '@libs/ValidationUtils';
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import * as CompanyCards from '@userActions/CompanyCards';
+import {setAssignCardStepAndData} from '@userActions/CompanyCards';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import INPUT_IDS from '@src/types/form/EditExpensifyCardNameForm';
@@ -32,7 +32,7 @@ function CardNameStep({policyID}: CardNameStepProps) {
const data = assignCard?.data;
const submit = (values: FormOnyxValues) => {
- CompanyCards.setAssignCardStepAndData({
+ setAssignCardStepAndData({
currentStep: CONST.COMPANY_CARD.STEP.CONFIRMATION,
data: {
cardName: values.name,
@@ -42,11 +42,11 @@ function CardNameStep({policyID}: CardNameStepProps) {
};
const validate = (values: FormOnyxValues): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.NAME]);
+ const errors = getFieldRequiredErrors(values, [INPUT_IDS.NAME]);
const length = values.name.length;
if (length > CONST.STANDARD_LENGTH_LIMIT) {
- ErrorUtils.addErrorMessage(errors, INPUT_IDS.NAME, translate('common.error.characterLimitExceedCounter', {length, limit: CONST.STANDARD_LENGTH_LIMIT}));
+ addErrorMessage(errors, INPUT_IDS.NAME, translate('common.error.characterLimitExceedCounter', {length, limit: CONST.STANDARD_LENGTH_LIMIT}));
}
return errors;
@@ -64,7 +64,7 @@ function CardNameStep({policyID}: CardNameStepProps) {
>
CompanyCards.setAssignCardStepAndData({currentStep: CONST.COMPANY_CARD.STEP.CONFIRMATION, isEditing: false})}
+ onBackButtonPress={() => setAssignCardStepAndData({currentStep: CONST.COMPANY_CARD.STEP.CONFIRMATION, isEditing: false})}
/>
{translate('workspace.moreFeatures.companyCards.giveItNameInstruction')}
) => {
- Policy.updateInvoiceCompanyName(policyID, values[INPUT_IDS.COMPANY_NAME]);
+ updateInvoiceCompanyName(policyID, values[INPUT_IDS.COMPANY_NAME]);
Navigation.goBack();
};
const validate = (values: FormOnyxValues): FormInputErrors =>
- ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.COMPANY_NAME]);
+ getFieldRequiredErrors(values, [INPUT_IDS.COMPANY_NAME]);
return (
) => {
const companyWebsite = Str.sanitizeURL(values[INPUT_IDS.COMPANY_WEBSITE], CONST.COMPANY_WEBSITE_DEFAULT_SCHEME);
- Policy.updateInvoiceCompanyWebsite(policyID, companyWebsite);
+ updateInvoiceCompanyWebsite(policyID, companyWebsite);
Navigation.goBack();
};
const validate = (
values: FormOnyxValues,
): FormInputErrors => {
- const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.COMPANY_WEBSITE]);
+ const errors = getFieldRequiredErrors(values, [INPUT_IDS.COMPANY_WEBSITE]);
if (values.companyWebsite) {
const companyWebsite = Str.sanitizeURL(values.companyWebsite, CONST.COMPANY_WEBSITE_DEFAULT_SCHEME);
- if (!ValidationUtils.isValidWebsite(companyWebsite)) {
+ if (!isValidWebsite(companyWebsite)) {
errors.companyWebsite = translate('bankAccount.error.website');
} else {
- const domain = Url.extractUrlDomain(companyWebsite);
+ const domain = extractUrlDomain(companyWebsite);
if (!domain || !Str.isValidDomainName(domain)) {
errors.companyWebsite = translate('iou.invalidDomainError');
- } else if (ValidationUtils.isPublicDomain(domain)) {
+ } else if (isPublicDomain(domain)) {
errors.companyWebsite = translate('iou.publicDomainError');
}
}
@@ -81,6 +80,7 @@ function WorkspaceInvoicingDetailsWebsite({route}: WorkspaceInvoicingDetailsWebs
style={[styles.flex1, styles.mh5]}
enabledWhenOffline
validate={validate}
+ shouldHideFixErrorsAlert
>
diff --git a/src/pages/workspace/perDiem/EditPerDiemSubratePage.tsx b/src/pages/workspace/perDiem/EditPerDiemSubratePage.tsx
index b98adbb423d7..c3fb6d7f677e 100644
--- a/src/pages/workspace/perDiem/EditPerDiemSubratePage.tsx
+++ b/src/pages/workspace/perDiem/EditPerDiemSubratePage.tsx
@@ -91,6 +91,7 @@ function EditPerDiemSubratePage({route}: EditPerDiemSubratePageProps) {
submitButtonText={translate('common.save')}
style={[styles.mh5, styles.flex1]}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{
- PolicyActions.setPolicyAutomaticApprovalLimit(policyID, maxExpenseAutoApprovalAmount);
+ setPolicyAutomaticApprovalLimit(policyID, maxExpenseAutoApprovalAmount);
Navigation.setNavigationActionToMicrotaskQueue(Navigation.goBack);
}}
submitButtonText={translate('common.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
;
function RulesAutoPayReportsUnderPage({route}: RulesAutoPayReportsUnderPageProps) {
- const policyID = route?.params?.policyID ?? '-1';
+ const policyID = route.params.policyID;
const policy = usePolicy(policyID);
const {inputCallbackRef} = useAutoFocusInput();
const {translate} = useLocalize();
const styles = useThemeStyles();
- const currencySymbol = CurrencyUtils.getCurrencySymbol(policy?.outputCurrency ?? CONST.CURRENCY.USD);
+ const currencySymbol = getCurrencySymbol(policy?.outputCurrency ?? CONST.CURRENCY.USD);
const autoPayApprovedReportsUnavailable = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO;
- const defaultValue = CurrencyUtils.convertToFrontendAmountAsString(policy?.autoReimbursement?.limit ?? CONST.POLICY.AUTO_REIMBURSEMENT_DEFAULT_LIMIT_CENTS, policy?.outputCurrency);
+ const defaultValue = convertToFrontendAmountAsString(policy?.autoReimbursement?.limit ?? CONST.POLICY.AUTO_REIMBURSEMENT_DEFAULT_LIMIT_CENTS, policy?.outputCurrency);
const validateLimit = ({maxExpenseAutoPayAmount}: FormOnyxValues) => {
const errors: FormInputErrors = {};
- if (CurrencyUtils.convertToBackendAmount(parseFloat(maxExpenseAutoPayAmount)) > CONST.POLICY.AUTO_REIMBURSEMENT_MAX_LIMIT_CENTS) {
+ if (convertToBackendAmount(parseFloat(maxExpenseAutoPayAmount)) > CONST.POLICY.AUTO_REIMBURSEMENT_MAX_LIMIT_CENTS) {
errors[INPUT_IDS.MAX_EXPENSE_AUTO_PAY_AMOUNT] = translate('workspace.rules.expenseReportRules.autoPayApprovedReportsLimitError', {currency: currencySymbol});
}
return errors;
@@ -65,11 +65,12 @@ function RulesAutoPayReportsUnderPage({route}: RulesAutoPayReportsUnderPageProps
formID={ONYXKEYS.FORMS.RULES_AUTO_PAY_REPORTS_UNDER_MODAL_FORM}
validate={validateLimit}
onSubmit={({maxExpenseAutoPayAmount}) => {
- PolicyActions.setPolicyAutoReimbursementLimit(policyID, maxExpenseAutoPayAmount);
+ setPolicyAutoReimbursementLimit(policyID, maxExpenseAutoPayAmount);
Navigation.setNavigationActionToMicrotaskQueue(Navigation.goBack);
}}
submitButtonText={translate('common.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{
- PolicyActions.setPolicyMaxExpenseAge(policyID, maxExpenseAge);
+ setPolicyMaxExpenseAge(policyID, maxExpenseAge);
Navigation.setNavigationActionToMicrotaskQueue(Navigation.goBack);
}}
submitButtonText={translate('workspace.editor.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{
- PolicyActions.setPolicyMaxExpenseAmount(policyID, maxExpenseAmount);
+ setPolicyMaxExpenseAmount(policyID, maxExpenseAmount);
Navigation.setNavigationActionToMicrotaskQueue(Navigation.goBack);
}}
submitButtonText={translate('workspace.editor.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
;
function RulesRandomReportAuditPage({route}: RulesRandomReportAuditPageProps) {
- const policyID = route?.params?.policyID ?? '-1';
+ const policyID = route.params.policyID;
const policy = usePolicy(policyID);
const {inputCallbackRef} = useAutoFocusInput();
const {translate} = useLocalize();
const styles = useThemeStyles();
- const workflowApprovalsUnavailable = PolicyUtils.getWorkflowApprovalsUnavailable(policy);
+ const workflowApprovalsUnavailable = getWorkflowApprovalsUnavailable(policy);
const defaultValue = Math.round((policy?.autoApproval?.auditRate ?? CONST.POLICY.RANDOM_AUDIT_DEFAULT_PERCENTAGE) * 100);
return (
{
- PolicyActions.setPolicyAutomaticApprovalRate(policyID, auditRatePercentage);
+ setPolicyAutomaticApprovalRate(policyID, auditRatePercentage);
Navigation.setNavigationActionToMicrotaskQueue(Navigation.goBack);
}}
submitButtonText={translate('common.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
{
- PolicyActions.setPolicyMaxExpenseAmountNoReceipt(policyID, maxExpenseAmountNoReceipt);
+ setPolicyMaxExpenseAmountNoReceipt(policyID, maxExpenseAmountNoReceipt);
Navigation.setNavigationActionToMicrotaskQueue(Navigation.goBack);
}}
submitButtonText={translate('workspace.editor.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
PolicyUtils.getTagListName(policyTags, route.params.orderWeight), [policyTags, route.params.orderWeight]);
+ const taglistName = useMemo(() => getTagListName(policyTags, route.params.orderWeight), [policyTags, route.params.orderWeight]);
const {inputCallbackRef} = useAutoFocusInput();
const backTo = route.params.backTo;
const isQuickSettingsFlow = !!backTo;
@@ -58,7 +58,7 @@ function WorkspaceEditTagsPage({route}: WorkspaceEditTagsPageProps) {
const updateTaglistName = useCallback(
(values: FormOnyxValues) => {
if (values[INPUT_IDS.POLICY_TAGS_NAME] !== taglistName) {
- Tag.renamePolicyTaglist(route.params.policyID, {oldName: taglistName, newName: values[INPUT_IDS.POLICY_TAGS_NAME]}, policyTags, route.params.orderWeight);
+ renamePolicyTaglist(route.params.policyID, {oldName: taglistName, newName: values[INPUT_IDS.POLICY_TAGS_NAME]}, policyTags, route.params.orderWeight);
}
goBackToTagsSettings();
},
@@ -87,6 +87,7 @@ function WorkspaceEditTagsPage({route}: WorkspaceEditTagsPageProps) {
validate={validateTagName}
submitButtonText={translate('common.save')}
enabledWhenOffline
+ shouldHideFixErrorsAlert
>
diff --git a/src/pages/workspace/taxes/NamePage.tsx b/src/pages/workspace/taxes/NamePage.tsx
index 963e47ce8566..dd6475812925 100644
--- a/src/pages/workspace/taxes/NamePage.tsx
+++ b/src/pages/workspace/taxes/NamePage.tsx
@@ -90,6 +90,7 @@ function NamePage({
onSubmit={submit}
enabledWhenOffline
validate={validate}
+ shouldHideFixErrorsAlert
>