Skip to content

Commit

Permalink
Merge pull request Expensify#51588 from rushatgabhane/copilot-error-r…
Browse files Browse the repository at this point in the history
…efactor
  • Loading branch information
dangrous authored Nov 4, 2024
2 parents d046e88 + 0e7a689 commit fcb4a5b
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 49 deletions.
7 changes: 4 additions & 3 deletions src/components/AccountSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function AccountSwitcher() {
}

const delegatePersonalDetails = PersonalDetailsUtils.getPersonalDetailByEmail(delegateEmail);
const error = ErrorUtils.getLatestErrorField(account?.delegatedAccess, 'connect');
const error = ErrorUtils.getLatestError(account?.delegatedAccess?.errorFields?.disconnect);

return [
createBaseMenuItem(delegatePersonalDetails, error, {
Expand All @@ -105,8 +105,9 @@ function AccountSwitcher() {

const delegatorMenuItems: PopoverMenuItem[] = delegators
.filter(({email}) => email !== currentUserPersonalDetails.login)
.map(({email, role, errorFields}) => {
const error = ErrorUtils.getLatestErrorField({errorFields}, 'connect');
.map(({email, role}) => {
const errorFields = account?.delegatedAccess?.errorFields ?? {};
const error = ErrorUtils.getLatestError(errorFields?.connect?.[email]);
const personalDetails = PersonalDetailsUtils.getPersonalDetailByEmail(email);
return createBaseMenuItem(personalDetails, error, {
badgeText: translate('delegate.role', {role}),
Expand Down
10 changes: 10 additions & 0 deletions src/libs/ErrorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,15 @@ function getLatestErrorFieldForAnyField<TOnyxData extends OnyxDataWithErrorField
return latestErrorFields.reduce((acc, error) => Object.assign(acc, error), {});
}

function getLatestError(errors?: Errors): Errors {
if (!errors || Object.keys(errors).length === 0) {
return {};
}

const key = Object.keys(errors).sort().reverse().at(0) ?? '';
return {[key]: getErrorMessageWithTranslationData(errors[key])};
}

/**
* Method used to attach already translated message
* @param errors - An object containing current errors in the form
Expand Down Expand Up @@ -198,6 +207,7 @@ export {
getLatestErrorFieldForAnyField,
getLatestErrorMessage,
getLatestErrorMessageField,
getLatestError,
getMicroSecondOnyxErrorWithTranslationKey,
getMicroSecondOnyxErrorWithMessage,
getMicroSecondOnyxErrorObject,
Expand Down
87 changes: 59 additions & 28 deletions src/libs/actions/Delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ function connect(email: string) {
key: ONYXKEYS.ACCOUNT,
value: {
delegatedAccess: {
delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {...delegator, errorFields: {connect: null}} : delegator)),
errorFields: {
connect: {
[email]: null,
},
},
},
},
},
Expand All @@ -59,7 +63,11 @@ function connect(email: string) {
key: ONYXKEYS.ACCOUNT,
value: {
delegatedAccess: {
delegators: delegatedAccess.delegators.map((delegator) => (delegator.email === email ? {...delegator, errorFields: undefined} : delegator)),
errorFields: {
connect: {
[email]: null,
},
},
},
},
},
Expand All @@ -71,9 +79,11 @@ function connect(email: string) {
key: ONYXKEYS.ACCOUNT,
value: {
delegatedAccess: {
delegators: delegatedAccess.delegators.map((delegator) =>
delegator.email === email ? {...delegator, errorFields: {connect: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('delegate.genericError')}} : delegator,
),
errorFields: {
connect: {
[email]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('delegate.genericError'),
},
},
},
},
},
Expand Down Expand Up @@ -112,7 +122,7 @@ function disconnect() {
key: ONYXKEYS.ACCOUNT,
value: {
delegatedAccess: {
errorFields: {connect: null},
errorFields: {disconnect: null},
},
},
},
Expand All @@ -136,7 +146,7 @@ function disconnect() {
key: ONYXKEYS.ACCOUNT,
value: {
delegatedAccess: {
errorFields: {connect: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('delegate.genericError')},
errorFields: {disconnect: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('delegate.genericError')},
},
},
},
Expand Down Expand Up @@ -190,7 +200,6 @@ function addDelegate(email: string, role: DelegateRole, validateCode: string) {
: {
...delegate,
isLoading: true,
errorFields: {addDelegate: null},
pendingFields: {email: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, role: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD},
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
Expand All @@ -204,7 +213,6 @@ function addDelegate(email: string, role: DelegateRole, validateCode: string) {
email,
role,
isLoading: true,
errorFields: {addDelegate: null},
pendingFields: {email: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, role: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD},
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
Expand All @@ -218,6 +226,11 @@ function addDelegate(email: string, role: DelegateRole, validateCode: string) {
value: {
delegatedAccess: {
delegates: optimisticDelegateData(),
errorFields: {
addDelegate: {
[email]: null,
},
},
},
isLoading: true,
},
Expand All @@ -233,7 +246,6 @@ function addDelegate(email: string, role: DelegateRole, validateCode: string) {
: {
...delegate,
isLoading: false,
errorFields: {addDelegate: null},
pendingAction: null,
pendingFields: {email: null, role: null},
optimisticAccountID: undefined,
Expand All @@ -247,7 +259,6 @@ function addDelegate(email: string, role: DelegateRole, validateCode: string) {
{
email,
role,
errorFields: {addDelegate: null},
isLoading: false,
pendingAction: null,
pendingFields: {email: null, role: null},
Expand All @@ -263,6 +274,11 @@ function addDelegate(email: string, role: DelegateRole, validateCode: string) {
value: {
delegatedAccess: {
delegates: successDelegateData(),
errorFields: {
addDelegate: {
[email]: null,
},
},
},
isLoading: false,
},
Expand All @@ -278,7 +294,6 @@ function addDelegate(email: string, role: DelegateRole, validateCode: string) {
: {
...delegate,
isLoading: false,
errorFields: {addDelegate: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('contacts.genericFailureMessages.validateSecondaryLogin')},
},
) ?? []
);
Expand All @@ -289,9 +304,6 @@ function addDelegate(email: string, role: DelegateRole, validateCode: string) {
{
email,
role,
errorFields: {
addDelegate: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('contacts.genericFailureMessages.validateSecondaryLogin'),
},
isLoading: false,
pendingFields: {email: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, role: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD},
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
Expand Down Expand Up @@ -328,11 +340,15 @@ function removeDelegate(email: string) {
key: ONYXKEYS.ACCOUNT,
value: {
delegatedAccess: {
errorFields: {
removeDelegate: {
[email]: null,
},
},
delegates: delegatedAccess.delegates?.map((delegate) =>
delegate.email === email
? {
...delegate,
errorFields: {removeDelegate: null},
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
pendingFields: {email: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, role: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE},
}
Expand Down Expand Up @@ -361,13 +377,15 @@ function removeDelegate(email: string) {
key: ONYXKEYS.ACCOUNT,
value: {
delegatedAccess: {
errorFields: {
removeDelegate: {
[email]: null,
},
},
delegates: delegatedAccess.delegates?.map((delegate) =>
delegate.email === email
? {
...delegate,
errorFields: {
removeDelegate: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('delegate.genericError'),
},
pendingAction: null,
pendingFields: undefined,
}
Expand All @@ -383,14 +401,18 @@ function removeDelegate(email: string) {
API.write(WRITE_COMMANDS.REMOVE_DELEGATE, parameters, {optimisticData, successData, failureData});
}

function clearAddDelegateErrors(email: string, fieldName: string) {
function clearDelegateErrorsByField(email: string, fieldName: string) {
if (!delegatedAccess?.delegates) {
return;
}

Onyx.merge(ONYXKEYS.ACCOUNT, {
delegatedAccess: {
delegates: delegatedAccess.delegates.map((delegate) => (delegate.email !== email ? delegate : {...delegate, errorFields: {...delegate.errorFields, [fieldName]: null}})),
errorFields: {
[fieldName]: {
[email]: null,
},
},
},
});
}
Expand Down Expand Up @@ -422,12 +444,16 @@ function updateDelegateRole(email: string, role: DelegateRole, validateCode: str
key: ONYXKEYS.ACCOUNT,
value: {
delegatedAccess: {
errorFields: {
updateDelegateRole: {
[email]: null,
},
},
delegates: delegatedAccess.delegates.map((delegate) =>
delegate.email === email
? {
...delegate,
role,
errorFields: {updateDelegateRole: null},
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
pendingFields: {role: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
isLoading: true,
Expand All @@ -445,12 +471,16 @@ function updateDelegateRole(email: string, role: DelegateRole, validateCode: str
key: ONYXKEYS.ACCOUNT,
value: {
delegatedAccess: {
errorFields: {
updateDelegateRole: {
[email]: null,
},
},
delegates: delegatedAccess.delegates.map((delegate) =>
delegate.email === email
? {
...delegate,
role,
errorFields: {updateDelegateRole: null},
pendingAction: null,
pendingFields: {role: null},
isLoading: false,
Expand All @@ -472,9 +502,6 @@ function updateDelegateRole(email: string, role: DelegateRole, validateCode: str
delegate.email === email
? {
...delegate,
errorFields: {
updateDelegateRole: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('delegate.genericError'),
},
isLoading: false,
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
pendingFields: {role: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
Expand Down Expand Up @@ -502,12 +529,16 @@ function updateDelegateRoleOptimistically(email: string, role: DelegateRole) {
key: ONYXKEYS.ACCOUNT,
value: {
delegatedAccess: {
errorFields: {
updateDelegateRole: {
[email]: null,
},
},
delegates: delegatedAccess.delegates.map((delegate) =>
delegate.email === email
? {
...delegate,
role,
errorFields: {updateDelegateRole: null},
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
pendingFields: {role: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
}
Expand Down Expand Up @@ -568,7 +599,7 @@ export {
clearDelegatorErrors,
addDelegate,
requestValidationCode,
clearAddDelegateErrors,
clearDelegateErrorsByField,
removePendingDelegate,
restoreDelegateSession,
isConnectedAsDelegate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ function DelegateMagicCodeModal({login, role, onClose, isValidateCodeActionModal
const [account] = useOnyx(ONYXKEYS.ACCOUNT);

const currentDelegate = account?.delegatedAccess?.delegates?.find((d) => d.email === login);
const validateLoginError = ErrorUtils.getLatestErrorField(currentDelegate, 'addDelegate');
const addDelegateErrors = account?.delegatedAccess?.errorFields?.addDelegate?.[login];
const validateLoginError = ErrorUtils.getLatestError(addDelegateErrors);

useEffect(() => {
if (!currentDelegate || !!currentDelegate.pendingFields?.email || !!currentDelegate.errorFields?.addDelegate) {
if (!currentDelegate || !!currentDelegate.pendingFields?.email || !!addDelegateErrors) {
return;
}

// Dismiss modal on successful magic code verification
Navigation.navigate(ROUTES.SETTINGS_SECURITY);
}, [login, currentDelegate, role]);
}, [login, currentDelegate, role, addDelegateErrors]);

const onBackButtonPress = () => {
onClose?.();
Expand All @@ -42,7 +43,7 @@ function DelegateMagicCodeModal({login, role, onClose, isValidateCodeActionModal
if (!validateLoginError) {
return;
}
Delegate.clearAddDelegateErrors(currentDelegate?.email ?? '', 'addDelegate');
Delegate.clearDelegateErrorsByField(currentDelegate?.email ?? '', 'addDelegate');
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ function UpdateDelegateMagicCodePage({route}: UpdateDelegateMagicCodePageProps)
const validateCodeFormRef = useRef<ValidateCodeFormHandle>(null);

const currentDelegate = account?.delegatedAccess?.delegates?.find((d) => d.email === login);
const updateDelegateErrors = account?.delegatedAccess?.errorFields?.addDelegate?.[login];

useEffect(() => {
if (!currentDelegate || !!currentDelegate.pendingFields?.role || !!currentDelegate.errorFields?.updateDelegateRole) {
if (!currentDelegate || !!currentDelegate.pendingFields?.role || !!updateDelegateErrors) {
return;
}

// Dismiss modal on successful magic code verification
Navigation.dismissModal();
}, [login, currentDelegate, role]);
}, [login, currentDelegate, role, updateDelegateErrors]);

const onBackButtonPress = () => {
Navigation.goBack(ROUTES.SETTINGS_UPDATE_DELEGATE_ROLE.getRoute(login, role));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ function BaseValidateCodeForm({autoComplete = 'one-time-code', innerRef = () =>
const focusTimeoutRef = useRef<NodeJS.Timeout | null>(null);

const currentDelegate = account?.delegatedAccess?.delegates?.find((d) => d.email === delegate);
const validateLoginError = ErrorUtils.getLatestErrorField(currentDelegate, 'updateDelegateRole');
const errorFields = account?.delegatedAccess?.errorFields ?? {};
const validateLoginError = ErrorUtils.getLatestError(errorFields.updateDelegateRole?.[currentDelegate?.email ?? '']);

const shouldDisableResendValidateCode = !!isOffline || currentDelegate?.isLoading;

Expand Down Expand Up @@ -127,7 +128,7 @@ function BaseValidateCodeForm({autoComplete = 'one-time-code', innerRef = () =>
setValidateCode(text);
setFormError({});
if (validateLoginError) {
Delegate.clearAddDelegateErrors(currentDelegate?.email ?? '', 'updateDelegateRole');
Delegate.clearDelegateErrorsByField(currentDelegate?.email ?? '', 'updateDelegateRole');
}
},
[currentDelegate?.email, validateLoginError],
Expand Down
Loading

0 comments on commit fcb4a5b

Please sign in to comment.