11import type { OnyxCollection , OnyxEntry , ResultMetadata } from 'react-native-onyx' ;
2- import { getCompanyCardFeed , getCompanyFeeds , getSelectedFeed } from '@libs/CardUtils' ;
2+ import { getCompanyCardFeed , getCompanyFeeds , getSelectedFeed , normalizeCardName } from '@libs/CardUtils' ;
33import CONST from '@src/CONST' ;
44import ONYXKEYS from '@src/ONYXKEYS' ;
55import type { CardFeeds , CardList } from '@src/types/onyx' ;
6+ import type Card from '@src/types/onyx/Card' ;
67import type { AssignableCardsList , WorkspaceCardsList } from '@src/types/onyx/Card' ;
78import type { CardFeedsStatusByDomainID , CombinedCardFeeds , CompanyCardFeedWithDomainID , CompanyCardFeedWithNumber , CompanyFeeds } from '@src/types/onyx/CardFeeds' ;
89import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue' ;
@@ -11,6 +12,13 @@ import type {CombinedCardFeed} from './useCardFeeds';
1112import useCardsList from './useCardsList' ;
1213import useOnyx from './useOnyx' ;
1314
15+ type CompanyCardEntry = {
16+ cardName : string ;
17+ encryptedCardNumber : string ;
18+ isAssigned : boolean ;
19+ assignedCard ?: Card ;
20+ } ;
21+
1422type UseCompanyCardsProps = {
1523 policyID : string | undefined ;
1624 feedName ?: CompanyCardFeedWithDomainID ;
@@ -21,7 +29,7 @@ type UseCompanyCardsResult = Partial<{
2129 feedName : CompanyCardFeedWithDomainID ;
2230 cardList : AssignableCardsList ;
2331 assignedCards : CardList ;
24- cardNamesToEncryptedCardNumberMapping : Record < string , string > ;
32+ companyCardEntries : CompanyCardEntry [ ] ;
2533 workspaceCardFeedsStatus : CardFeedsStatusByDomainID ;
2634 allCardFeeds : CombinedCardFeeds ;
2735 companyCardFeeds : CompanyFeeds ;
@@ -39,6 +47,49 @@ type UseCompanyCardsResult = Partial<{
3947 } ;
4048} ;
4149
50+ /**
51+ * Builds a list of card entries by starting from assignedCards (source of truth for assignments),
52+ * then filling in remaining unassigned cards from accountList/cardList.
53+ */
54+ function buildCompanyCardEntries ( accountList : string [ ] | undefined , cardList : AssignableCardsList | undefined , assignedCards : CardList ) : CompanyCardEntry [ ] {
55+ const entries : CompanyCardEntry [ ] = [ ] ;
56+ const coveredNames = new Set < string > ( ) ;
57+ const coveredEncrypted = new Set < string > ( ) ;
58+
59+ // Phase 1: Assigned cards first — these are the source of truth.
60+ for ( const card of Object . values ( assignedCards ) ) {
61+ if ( ! card ?. cardName ) {
62+ continue ;
63+ }
64+ const encryptedCardNumber = card . encryptedCardNumber ?? card . cardName ;
65+ entries . push ( { cardName : card . cardName , encryptedCardNumber, isAssigned : true , assignedCard : card } ) ;
66+ coveredNames . add ( normalizeCardName ( card . cardName ) ) ;
67+ if ( card . encryptedCardNumber ) {
68+ coveredEncrypted . add ( card . encryptedCardNumber ) ;
69+ }
70+ }
71+
72+ // Phase 2: Add remaining unassigned cards. cardList first so its encryptedCardNumber takes precedence.
73+ for ( const [ name , encryptedCardNumber ] of Object . entries ( cardList ?? { } ) ) {
74+ if ( coveredNames . has ( normalizeCardName ( name ) ) || coveredEncrypted . has ( encryptedCardNumber ) ) {
75+ continue ;
76+ }
77+ entries . push ( { cardName : name , encryptedCardNumber, isAssigned : false } ) ;
78+ coveredNames . add ( normalizeCardName ( name ) ) ;
79+ coveredEncrypted . add ( encryptedCardNumber ) ;
80+ }
81+
82+ for ( const name of accountList ?? [ ] ) {
83+ if ( coveredNames . has ( normalizeCardName ( name ) ) ) {
84+ continue ;
85+ }
86+ entries . push ( { cardName : name , encryptedCardNumber : name , isAssigned : false } ) ;
87+ coveredNames . add ( normalizeCardName ( name ) ) ;
88+ }
89+
90+ return entries ;
91+ }
92+
4293function useCompanyCards ( { policyID, feedName : feedNameProp } : UseCompanyCardsProps ) : UseCompanyCardsResult {
4394 // If an empty string is passed, we need to use an invalid key to avoid fetching the whole collection.
4495 // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
@@ -56,14 +107,7 @@ function useCompanyCards({policyID, feedName: feedNameProp}: UseCompanyCardsProp
56107 const selectedFeed = feedName && companyCardFeeds [ feedName ] ;
57108
58109 const { cardList, ...assignedCards } = cardsList ?? { } ;
59- const cardNamesToEncryptedCardNumberMapping : Record < string , string > = { } ;
60-
61- for ( const cardName of selectedFeed ?. accountList ?? [ ] ) {
62- cardNamesToEncryptedCardNumberMapping [ cardName ] = cardName ;
63- }
64- for ( const [ cardName , encryptedCardNumber ] of Object . entries ( cardList ?? { } ) ) {
65- cardNamesToEncryptedCardNumberMapping [ cardName ] = encryptedCardNumber ;
66- }
110+ const companyCardEntries = buildCompanyCardEntries ( selectedFeed ?. accountList , cardList , assignedCards ) ;
67111
68112 const onyxMetadata = {
69113 cardListMetadata,
@@ -86,7 +130,7 @@ function useCompanyCards({policyID, feedName: feedNameProp}: UseCompanyCardsProp
86130 companyCardFeeds,
87131 cardList,
88132 assignedCards,
89- cardNamesToEncryptedCardNumberMapping ,
133+ companyCardEntries ,
90134 workspaceCardFeedsStatus,
91135 selectedFeed,
92136 bankName,
@@ -99,4 +143,4 @@ function useCompanyCards({policyID, feedName: feedNameProp}: UseCompanyCardsProp
99143}
100144
101145export default useCompanyCards ;
102- export type { UseCompanyCardsResult } ;
146+ export type { CompanyCardEntry , UseCompanyCardsResult } ;
0 commit comments