Skip to content

Commit

Permalink
Merge pull request #52268 from callstack-internal/VickyStash/feature/…
Browse files Browse the repository at this point in the history
…52251-get-all-feeds-data

[Internal QA] [Workspace Feeds] Pull the workspace feed data from different place in domain_member NVP
  • Loading branch information
mountiny authored Nov 14, 2024
2 parents d1df397 + 7649ded commit 4e0bbeb
Show file tree
Hide file tree
Showing 14 changed files with 332 additions and 116 deletions.
33 changes: 28 additions & 5 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 {CompanyCardNicknames, 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 @@ -243,10 +243,20 @@ 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, CONST.COMPANY_CARD.FEED_BANK_NAME.VISA, CONST.COMPANY_CARD.FEED_BANK_NAME.AMEX].some((value) => value === feed);
}

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

function removeExpensifyCardFromCompanyCards(cardFeeds: OnyxEntry<CardFeeds>): CompanyFeeds {
if (!cardFeeds) {
return {};
}

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

Expand Down Expand Up @@ -283,6 +293,16 @@ const getBankCardDetailsImage = (bank: ValueOf<typeof CONST.COMPANY_CARDS.BANKS>
return iconMap[bank];
};

function getCustomOrFormattedFeedName(feed?: CompanyCardFeed, companyCardNicknames?: CompanyCardNicknames): string | undefined {
if (!feed) {
return;
}

const customFeedName = companyCardNicknames?.[feed];
const formattedFeedName = Localize.translateLocal('workspace.companyCards.feedName', {feedName: getCardFeedName(feed)});
return customFeedName ?? formattedFeedName;
}

// We will simplify the logic below once we have #50450 #50451 implemented
const getCorrectStepForSelectedBank = (selectedBank: ValueOf<typeof CONST.COMPANY_CARDS.BANKS>) => {
const banksWithFeedType = [
Expand Down Expand Up @@ -316,8 +336,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 @@ -340,8 +360,11 @@ export {
getCompanyCardNumber,
getCardFeedIcon,
getCardFeedName,
getCompanyFeeds,
isCustomFeed,
getBankCardDetailsImage,
getSelectedFeed,
getCorrectStepForSelectedBank,
getCustomOrFormattedFeedName,
removeExpensifyCardFromCompanyCards,
};
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
44 changes: 19 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 = {[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,
},
...(isCustomFeed ? {companyCards: feedUpdates} : {oAuthAccountDetails: feedUpdates}),
companyCardNicknames: {
[bankName]: null,
},
Expand Down Expand Up @@ -309,8 +311,12 @@ 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 optimisticFeedUpdates = {[bankName]: {errors: null}};
const failureFeedUpdates = {[bankName]: {errors: {error: CONST.COMPANY_CARDS.CONNECTION_ERROR}}};

const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
Expand Down Expand Up @@ -346,13 +352,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: optimisticFeedUpdates} : {oAuthAccountDetails: optimisticFeedUpdates},
},
},
];
Expand Down Expand Up @@ -419,13 +419,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: {error: CONST.COMPANY_CARDS.CONNECTION_ERROR},
},
},
},
settings: isCustomFeed ? {companyCards: failureFeedUpdates} : {oAuthAccountDetails: failureFeedUpdates},
},
},
];
Expand Down
5 changes: 4 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 @@ -220,12 +221,14 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac
}

if (featureStates?.[CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED]) {
const hasPolicyFeedsError = PolicyUtils.hasPolicyFeedsError(CardUtils.getCompanyFeeds(cardFeeds));

protectedCollectPolicyMenuItems.push({
translationKey: 'workspace.common.companyCards',
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: hasPolicyFeedsError ? 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
12 changes: 6 additions & 6 deletions src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ 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 isPending = !!selectedCompanyCard?.pending;
const selectedFeedData = selectedFeed && companyCards[selectedFeed];
const isNoFeed = isEmptyObject(companyCards) && !selectedFeedData;
const isPending = !!selectedFeedData?.pending;
const isFeedAdded = !isPending && !isNoFeed;

const fetchCompanyCards = useCallback(() => {
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 @@ -43,7 +43,7 @@ function WorkspaceCompanyCardsSettingsFeedNamePage({
const [lastSelectedFeed, lastSelectedFeedResult] = useOnyx(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${policyID}`);
const [cardFeeds, cardFeedsResult] = 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 = CardUtils.getCustomOrFormattedFeedName(selectedFeed, cardFeeds?.settings?.companyCardNicknames);

const validate = useCallback(
(values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_COMPANY_CARD_FEED_NAME>) => {
Expand All @@ -60,7 +60,9 @@ function WorkspaceCompanyCardsSettingsFeedNamePage({
);

const submit = ({name}: WorkspaceCompanyCardFeedName) => {
CompanyCards.setWorkspaceCompanyCardFeedName(policyID, workspaceAccountID, selectedFeed, name);
if (selectedFeed) {
CompanyCards.setWorkspaceCompanyCardFeedName(policyID, workspaceAccountID, selectedFeed, name);
}
Navigation.goBack(ROUTES.WORKSPACE_COMPANY_CARDS_SETTINGS.getRoute(policyID));
};

Expand Down
Loading

0 comments on commit 4e0bbeb

Please sign in to comment.