Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Internal QA] [Workspace Feeds] Pull the workspace feed data from different place in domain_member NVP #52268

Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions src/libs/CardUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {TranslationPaths} from '@src/languages/types';
import type {OnyxValues} from '@src/ONYXKEYS';
import ONYXKEYS from '@src/ONYXKEYS';
import type {BankAccountList, Card, CardFeeds, CardList, CompanyCardFeed, PersonalDetailsList, WorkspaceCardsList} from '@src/types/onyx';
import type {CardFeedData} from '@src/types/onyx/CardFeeds';
import type {CompanyFeeds} from '@src/types/onyx/CardFeeds';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type IconAsset from '@src/types/utils/IconAsset';
import localeCompare from './LocaleCompare';
Expand Down Expand Up @@ -242,11 +242,22 @@ function getCardFeedIcon(cardFeed: CompanyCardFeed | typeof CONST.EXPENSIFY_CARD
return Illustrations.AmexCompanyCards;
}

function removeExpensifyCardFromCompanyCards(companyCards?: Record<string, CardFeedData>) {
if (!companyCards) {
function isCustomFeed(feed: CompanyCardFeed): boolean {
return CONST.COMPANY_CARD.FEED_BANK_NAME.MASTER_CARD === feed || CONST.COMPANY_CARD.FEED_BANK_NAME.VISA === feed || CONST.COMPANY_CARD.FEED_BANK_NAME.AMEX === feed;
}

function getCompanyFeeds(cardFeeds: OnyxEntry<CardFeeds>): CompanyFeeds {
return {...cardFeeds?.settings?.companyCards, ...cardFeeds?.settings?.oAuthAccountDetails};
}

function removeExpensifyCardFromCompanyCards(cardFeeds: OnyxEntry<CardFeeds>): CompanyFeeds {
if (!cardFeeds) {
return {};
}
return Object.fromEntries(Object.entries(companyCards).filter(([key]) => key !== CONST.EXPENSIFY_CARD.BANK));

const companyCards = getCompanyFeeds(cardFeeds);

return Object.fromEntries(Object.entries(companyCards).filter(([key]) => key !== CONST.EXPENSIFY_CARD.BANK)) as CompanyFeeds;
}

function getCardFeedName(feedType: CompanyCardFeed): string {
Expand Down Expand Up @@ -315,8 +326,8 @@ const getCorrectStepForSelectedBank = (selectedBank: ValueOf<typeof CONST.COMPAN
return CONST.COMPANY_CARDS.STEP.CARD_TYPE;
};

function getSelectedFeed(lastSelectedFeed: OnyxEntry<CompanyCardFeed>, cardFeeds: OnyxEntry<CardFeeds>): CompanyCardFeed {
const defaultFeed = Object.keys(removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards)).at(0) as CompanyCardFeed;
function getSelectedFeed(lastSelectedFeed: OnyxEntry<CompanyCardFeed>, cardFeeds: OnyxEntry<CardFeeds>): CompanyCardFeed | undefined {
const defaultFeed = Object.keys(removeExpensifyCardFromCompanyCards(cardFeeds)).at(0) as CompanyCardFeed | undefined;
return lastSelectedFeed ?? defaultFeed;
}

Expand All @@ -339,6 +350,8 @@ export {
getCompanyCardNumber,
getCardFeedIcon,
getCardFeedName,
getCompanyFeeds,
isCustomFeed,
getBankCardDetailsImage,
getSelectedFeed,
getCorrectStepForSelectedBank,
Expand Down
2 changes: 1 addition & 1 deletion src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ type SettingsNavigatorParamList = {
};
[SCREENS.WORKSPACE.COMPANY_CARD_DETAILS]: {
policyID: string;
bank: string;
bank: CompanyCardFeed;
cardID: string;
backTo?: Routes;
};
Expand Down
52 changes: 27 additions & 25 deletions src/libs/actions/CompanyCards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
UpdateCompanyCardNameParams,
} from '@libs/API/parameters';
import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import * as CardUtils from '@libs/CardUtils';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as NetworkStore from '@libs/Network/NetworkStore';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
Expand Down Expand Up @@ -121,19 +122,20 @@ function setWorkspaceCompanyCardFeedName(policyID: string, workspaceAccountID: n
API.write(WRITE_COMMANDS.SET_COMPANY_CARD_FEED_NAME, parameters, onyxData);
}

function setWorkspaceCompanyCardTransactionLiability(workspaceAccountID: number, policyID: string, bankName: string, liabilityType: string) {
function setWorkspaceCompanyCardTransactionLiability(workspaceAccountID: number, policyID: string, bankName: CompanyCardFeed, liabilityType: string) {
const authToken = NetworkStore.getAuthToken();
const isCustomFeed = CardUtils.isCustomFeed(bankName);
const feedUpdates = {
[bankName]: {liabilityType},
};

const onyxData: OnyxData = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`,
value: {
settings: {
companyCards: {
[bankName]: {liabilityType},
},
},
settings: isCustomFeed ? {companyCards: feedUpdates} : {oAuthAccountDetails: feedUpdates},
},
},
],
Expand All @@ -149,8 +151,10 @@ function setWorkspaceCompanyCardTransactionLiability(workspaceAccountID: number,
API.write(WRITE_COMMANDS.SET_COMPANY_CARD_TRANSACTION_LIABILITY, parameters, onyxData);
}

function deleteWorkspaceCompanyCardFeed(policyID: string, workspaceAccountID: number, bankName: string) {
function deleteWorkspaceCompanyCardFeed(policyID: string, workspaceAccountID: number, bankName: CompanyCardFeed) {
const authToken = NetworkStore.getAuthToken();
const isCustomFeed = CardUtils.isCustomFeed(bankName);
const feedUpdates = isCustomFeed ? {companyCards: {[bankName]: null}} : {oAuthAccountDetails: {[bankName]: null}};

const onyxData: OnyxData = {
optimisticData: [
Expand All @@ -159,9 +163,7 @@ function deleteWorkspaceCompanyCardFeed(policyID: string, workspaceAccountID: nu
key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`,
value: {
settings: {
companyCards: {
[bankName]: null,
},
...feedUpdates,
companyCardNicknames: {
[bankName]: null,
},
Expand Down Expand Up @@ -288,8 +290,10 @@ function unassignWorkspaceCompanyCard(workspaceAccountID: number, bankName: stri
API.write(WRITE_COMMANDS.UNASSIGN_COMPANY_CARD, parameters, onyxData);
}

function updateWorkspaceCompanyCard(workspaceAccountID: number, cardID: string, bankName: string) {
function updateWorkspaceCompanyCard(workspaceAccountID: number, cardID: string, bankName: CompanyCardFeed) {
const authToken = NetworkStore.getAuthToken();
const isCustomFeed = CardUtils.isCustomFeed(bankName);

const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
Expand Down Expand Up @@ -325,13 +329,7 @@ function updateWorkspaceCompanyCard(workspaceAccountID: number, cardID: string,
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`,
value: {
settings: {
companyCards: {
[bankName]: {
errors: null,
},
},
},
settings: isCustomFeed ? {companyCards: {[bankName]: {errors: null}}} : {oAuthAccountDetails: {[bankName]: {errors: null}}},
},
},
];
Expand Down Expand Up @@ -398,13 +396,17 @@ function updateWorkspaceCompanyCard(workspaceAccountID: number, cardID: string,
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`,
value: {
settings: {
companyCards: {
[bankName]: {
errors: {error: CONST.COMPANY_CARDS.CONNECTION_ERROR},
},
},
},
settings: isCustomFeed
? {
companyCards: {
[bankName]: {errors: {error: CONST.COMPANY_CARDS.CONNECTION_ERROR}},
},
}
: {
oAuthAccountDetails: {
[bankName]: {errors: {error: CONST.COMPANY_CARDS.CONNECTION_ERROR}},
},
},
},
},
];
Expand Down
3 changes: 2 additions & 1 deletion src/pages/workspace/WorkspaceInitialPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import useSingleExecution from '@hooks/useSingleExecution';
import useThemeStyles from '@hooks/useThemeStyles';
import useWaitForNavigation from '@hooks/useWaitForNavigation';
import {isConnectionInProgress} from '@libs/actions/connections';
import * as CardUtils from '@libs/CardUtils';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import getTopmostRouteName from '@libs/Navigation/getTopmostRouteName';
import Navigation from '@libs/Navigation/Navigation';
Expand Down Expand Up @@ -225,7 +226,7 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac
icon: Expensicons.CreditCard,
action: singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(policyID)))),
routeName: SCREENS.WORKSPACE.COMPANY_CARDS,
brickRoadIndicator: PolicyUtils.hasPolicyFeedsError(cardFeeds?.settings?.companyCards ?? {}) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
brickRoadIndicator: PolicyUtils.hasPolicyFeedsError(CardUtils.getCompanyFeeds(cardFeeds)) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/pages/workspace/WorkspaceMoreFeaturesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro
subtitleTranslationKey: 'workspace.moreFeatures.companyCards.subtitle',
isActive: policy?.areCompanyCardsEnabled ?? false,
pendingAction: policy?.pendingFields?.areCompanyCardsEnabled,
disabled: !isEmptyObject(CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards)),
disabled: !isEmptyObject(CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds)),
action: (isEnabled: boolean) => {
if (!policyID) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,16 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS
const [cardFeeds] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`);
const [lastSelectedFeed] = useOnyx(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${policyID}`);
const selectedFeed = CardUtils.getSelectedFeed(lastSelectedFeed, cardFeeds);
const availableCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards);
const companyFeeds = CardUtils.getCompanyFeeds(cardFeeds);
const availableCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds);

const feeds: CardFeedListItem[] = (Object.keys(availableCards) as CompanyCardFeed[]).map((feed) => ({
value: feed,
text: cardFeeds?.settings?.companyCardNicknames?.[feed] ?? CardUtils.getCardFeedName(feed),
keyForList: feed,
isSelected: feed === selectedFeed,
brickRoadIndicator: cardFeeds?.settings?.companyCards?.[feed]?.errors ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
canShowSeveralIndicators: !!cardFeeds?.settings?.companyCards?.[feed]?.errors,
brickRoadIndicator: companyFeeds[feed]?.errors ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
canShowSeveralIndicators: !!companyFeeds[feed]?.errors,
leftElement: (
<Icon
src={CardUtils.getCardFeedIcon(feed)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import * as CardUtils from '@libs/CardUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import Navigation from '@navigation/Navigation';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {CompanyCardFeed} from '@src/types/onyx';
Expand All @@ -39,13 +38,13 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp
const shouldChangeLayout = isMediumScreenWidth || shouldUseNarrowLayout;
const feedName = CardUtils.getCardFeedName(selectedFeed);
const formattedFeedName = translate('workspace.companyCards.feedName', {feedName});
const isCustomFeed =
CONST.COMPANY_CARD.FEED_BANK_NAME.MASTER_CARD === selectedFeed || CONST.COMPANY_CARD.FEED_BANK_NAME.VISA === selectedFeed || CONST.COMPANY_CARD.FEED_BANK_NAME.AMEX === selectedFeed;
const currentFeedData = cardFeeds?.settings?.companyCards?.[selectedFeed] ?? cardFeeds?.settings?.oAuthAccountDetails?.[selectedFeed] ?? {pending: true, errors: {}};
const isCustomFeed = CardUtils.isCustomFeed(selectedFeed);
const companyFeeds = CardUtils.getCompanyFeeds(cardFeeds);
const currentFeedData = companyFeeds?.[selectedFeed];

return (
<OfflineWithFeedback
errors={cardFeeds?.settings?.companyCards?.[selectedFeed]?.errors}
errors={currentFeedData?.errors}
canDismissError={false}
errorRowStyles={styles.ph5}
>
Expand All @@ -65,7 +64,7 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp
<CaretWrapper>
<Text style={styles.textStrong}>{formattedFeedName}</Text>
</CaretWrapper>
{PolicyUtils.hasPolicyFeedsError(cardFeeds?.settings?.companyCards ?? {}, selectedFeed) && (
{PolicyUtils.hasPolicyFeedsError(companyFeeds, selectedFeed) && (
<Icon
src={Expensicons.DotIndicator}
fill={theme.danger}
Expand All @@ -79,8 +78,7 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp
<View style={[styles.flexRow, styles.gap2]}>
<Button
success
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
isDisabled={currentFeedData.pending || !!currentFeedData.errors}
isDisabled={!currentFeedData || !!currentFeedData?.pending || !!currentFeedData?.errors}
onPress={() => Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ASSIGN_CARD.getRoute(policyID, selectedFeed))}
icon={Expensicons.Plus}
text={translate('workspace.companyCards.assignCard')}
Expand Down
10 changes: 5 additions & 5 deletions src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
const selectedFeed = CardUtils.getSelectedFeed(lastSelectedFeed, cardFeeds);
const [cardsList] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`);

const companyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds?.settings?.companyCards);
const companyCards = CardUtils.removeExpensifyCardFromCompanyCards(cardFeeds);
const isLoading = !cardFeeds || !!(cardFeeds.isLoading && !companyCards);
const selectedCompanyCard = companyCards[selectedFeed ?? ''] ?? cardFeeds?.settings?.oAuthAccountDetails?.[selectedFeed ?? ''] ?? null;
const isNoFeed = isEmptyObject(companyCards) && isEmptyObject(cardFeeds?.settings?.oAuthAccountDetails) && !selectedCompanyCard;
const selectedCompanyCard = selectedFeed && companyCards[selectedFeed];
const isNoFeed = isEmptyObject(companyCards) && !selectedCompanyCard;
const isPending = !!selectedCompanyCard?.pending;
const isFeedAdded = !isPending && !isNoFeed;

Expand Down Expand Up @@ -79,10 +79,10 @@ function WorkspaceCompanyCardPage({route}: WorkspaceCompanyCardPageProps) {
includeSafeAreaPaddingBottom
showLoadingAsFirstRender={false}
>
{(isFeedAdded || isPending) && (
{(isFeedAdded || isPending) && !!selectedFeed && (
<WorkspaceCompanyCardsListHeaderButtons
policyID={policyID}
selectedFeed={selectedFeed ?? ''}
selectedFeed={selectedFeed}
/>
)}
{isNoFeed && <WorkspaceCompanyCardPageEmptyState route={route} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ function WorkspaceCompanyCardsSettingsFeedNamePage({
const [lastSelectedFeed] = useOnyx(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${policyID}`);
const [cardFeeds] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`);
const selectedFeed = CardUtils.getSelectedFeed(lastSelectedFeed, cardFeeds);
const feedName = cardFeeds?.settings?.companyCardNicknames?.[selectedFeed] ?? translate('workspace.companyCards.feedName', {feedName: CardUtils.getCardFeedName(selectedFeed)});

const feedName =
selectedFeed && (cardFeeds?.settings?.companyCardNicknames?.[selectedFeed] ?? translate('workspace.companyCards.feedName', {feedName: CardUtils.getCardFeedName(selectedFeed)}));
const validate = useCallback(
(values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_COMPANY_CARD_FEED_NAME>) => {
const errors: FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_COMPANY_CARD_FEED_NAME> = {};
Expand All @@ -58,6 +58,9 @@ function WorkspaceCompanyCardsSettingsFeedNamePage({
);

const submit = ({name}: WorkspaceCompanyCardFeedName) => {
if (!selectedFeed) {
return;
}
CompanyCards.setWorkspaceCompanyCardFeedName(policyID, workspaceAccountID, selectedFeed, name);
Navigation.goBack(ROUTES.WORKSPACE_COMPANY_CARDS_SETTINGS.getRoute(policyID));
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,29 @@ function WorkspaceCompanyCardsSettingsPage({
const [cardFeeds] = useOnyx(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${workspaceAccountID}`);
const [lastSelectedFeed] = useOnyx(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${policyID}`);
const selectedFeed = CardUtils.getSelectedFeed(lastSelectedFeed, cardFeeds);
const feedName = cardFeeds?.settings?.companyCardNicknames?.[selectedFeed] ?? translate('workspace.companyCards.feedName', {feedName: CardUtils.getCardFeedName(selectedFeed)});
const liabilityType = cardFeeds?.settings?.companyCards?.[selectedFeed]?.liabilityType;
const feedName =
selectedFeed && (cardFeeds?.settings?.companyCardNicknames?.[selectedFeed] ?? translate('workspace.companyCards.feedName', {feedName: CardUtils.getCardFeedName(selectedFeed)}));
const companyFeeds = CardUtils.getCompanyFeeds(cardFeeds);
const liabilityType = selectedFeed && companyFeeds[selectedFeed]?.liabilityType;
const isPersonal = liabilityType === CONST.COMPANY_CARDS.DELETE_TRANSACTIONS.ALLOW;

const navigateToChangeFeedName = () => {
Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_SETTINGS_FEED_NAME.getRoute(policyID));
};

const deleteCompanyCardFeed = () => {
if (!selectedFeed) {
return;
}
CompanyCards.deleteWorkspaceCompanyCardFeed(policyID, workspaceAccountID, selectedFeed);
setDeleteCompanyCardConfirmModalVisible(false);
Navigation.setNavigationActionToMicrotaskQueue(Navigation.goBack);
};

const onToggleLiability = (isOn: boolean) => {
if (!selectedFeed) {
return;
}
CompanyCards.setWorkspaceCompanyCardTransactionLiability(
workspaceAccountID,
policyID,
Expand Down Expand Up @@ -102,7 +110,7 @@ function WorkspaceCompanyCardsSettingsPage({
isVisible={deleteCompanyCardConfirmModalVisible}
onConfirm={deleteCompanyCardFeed}
onCancel={() => setDeleteCompanyCardConfirmModalVisible(false)}
title={translate('workspace.moreFeatures.companyCards.removeCardFeedTitle', {feedName})}
title={feedName && translate('workspace.moreFeatures.companyCards.removeCardFeedTitle', {feedName})}
prompt={translate('workspace.moreFeatures.companyCards.removeCardFeedDescription')}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
Expand Down
Loading
Loading