11/* eslint-disable @typescript-eslint/no-explicit-any */
2- import React , { useState , useEffect } from 'react'
2+ import React , { useState , useEffect , useCallback } from 'react'
33import PropTypes from 'prop-types'
4- import { useDispatch } from 'react-redux'
4+ import { useDispatch , useSelector } from 'react-redux'
55
66import { useTokens } from '@kyper/tokenprovider'
77import { Text } from '@kyper/mui'
@@ -19,6 +19,8 @@ import { PrivateAndSecure } from 'src/components/PrivateAndSecure'
1919import { LoadingSpinner } from 'src/components/LoadingSpinner'
2020import { GenericError } from 'src/components/GenericError'
2121import { useApi } from 'src/context/ApiContext'
22+ import { selectConfig } from 'src/redux/reducers/configSlice'
23+ import { instutionSupportRequestedProducts } from 'src/utilities/Institution'
2224
2325interface VerifyExistingMemberProps {
2426 members : MemberResponseType [ ]
@@ -28,56 +30,84 @@ interface VerifyExistingMemberProps {
2830const VerifyExistingMember : React . FC < VerifyExistingMemberProps > = ( props ) => {
2931 useAnalyticsPath ( ...PageviewInfo . CONNECT_VERIFY_EXISTING_MEMBER )
3032 const { api } = useApi ( )
33+ const config = useSelector ( selectConfig )
3134 const dispatch = useDispatch ( )
3235 const { members, onAddNew } = props
3336 const iavMembers = members . filter (
3437 ( member ) => member . verification_is_enabled && member . is_managed_by_user , // Only show user-managed members that support verification
3538 )
36- const [ selectedMember , setSelectedMember ] = useState < MemberResponseType | null > ( null )
37- const [ { isLoadingInstitution, institutionError } , setInstitution ] = useState ( {
38- isLoadingInstitution : false ,
39- institutionError : null ,
40- } )
39+ const [ institutions , setInstitutions ] = useState < Map < string , InstitutionResponseType > > ( new Map ( ) )
40+ const [ loading , setLoading ] = useState ( true )
41+ const [ error , setError ] = useState < Error | null > ( null )
4142
4243 const tokens = useTokens ( )
4344
4445 const styles = getStyles ( tokens )
4546
46- const handleMemberClick = ( selectedMember : MemberResponseType ) => {
47- setSelectedMember ( selectedMember )
48- setInstitution ( ( state ) => ( { ...state , isLoadingInstitution : true } ) )
49- }
47+ const handleMemberClick = useCallback (
48+ ( selectedMember : MemberResponseType ) => {
49+ const institution = institutions . get ( selectedMember . institution_guid )
50+ if ( institution ) {
51+ if ( selectedMember . is_oauth ) {
52+ dispatch ( startOauth ( selectedMember , institution ) )
53+ } else {
54+ dispatch ( verifyExistingConnection ( selectedMember , institution ) )
55+ }
56+ }
57+ } ,
58+ [ dispatch , institutions ] ,
59+ )
5060
5161 useEffect ( ( ) => {
5262 focusElement ( document . getElementById ( 'connect-select-institution' ) )
5363 } , [ ] )
5464
5565 useEffect ( ( ) => {
56- if ( ! isLoadingInstitution || ! selectedMember ) return
57-
58- api
59- . loadInstitutionByGuid ( selectedMember . institution_guid )
60- . then ( ( institution ) => {
61- if ( selectedMember . is_oauth ) {
62- dispatch ( startOauth ( selectedMember , institution ) )
63- } else {
64- dispatch ( verifyExistingConnection ( selectedMember , institution ) )
65- }
66- } )
67- . catch ( ( error ) => {
68- setInstitution ( ( state ) => ( {
69- ...state ,
70- isLoadingInstitution : false ,
71- institutionError : error ,
72- } ) )
73- } )
74- } , [ isLoadingInstitution , selectedMember ] )
75-
76- if ( isLoadingInstitution ) {
66+ const fetchInstitutions = async ( ) => {
67+ try {
68+ const institutionPromises = iavMembers . map ( async ( member ) => {
69+ const institution = await api . loadInstitutionByGuid ( member . institution_guid )
70+ return { guid : member . institution_guid , institution }
71+ } )
72+
73+ const results = await Promise . all ( institutionPromises )
74+
75+ const institutionMap = new Map < string , InstitutionResponseType > ( )
76+ results . forEach ( ( { guid, institution } ) => {
77+ if ( institution ) {
78+ institutionMap . set ( guid , institution )
79+ }
80+ } )
81+ setInstitutions ( institutionMap )
82+ } catch ( err ) {
83+ setError ( err as Error )
84+ } finally {
85+ setLoading ( false )
86+ }
87+ }
88+
89+ if ( iavMembers . length > 0 ) {
90+ fetchInstitutions ( )
91+ } else {
92+ setLoading ( false ) // No members to load
93+ }
94+ } , [ api , iavMembers ] )
95+
96+ const productSupportingMembers = useCallback ( ( ) => {
97+ return iavMembers . filter ( ( member ) => {
98+ const institution = institutions . get ( member . institution_guid )
99+ if ( institution ) {
100+ return instutionSupportRequestedProducts ( config , institution )
101+ }
102+ return false
103+ } )
104+ } , [ config , institutions , iavMembers ] )
105+
106+ if ( loading ) {
77107 return < LoadingSpinner showText = { true } />
78108 }
79109
80- if ( institutionError ) {
110+ if ( error ) {
81111 return (
82112 < GenericError
83113 onAnalyticPageview = { ( ) => { } }
@@ -119,11 +149,11 @@ const VerifyExistingMember: React.FC<VerifyExistingMemberProps> = (props) => {
119149 { _n (
120150 '%1 Connected institution' ,
121151 '%1 Connected institutions' ,
122- iavMembers . length ,
123- iavMembers . length ,
152+ productSupportingMembers ( ) . length ,
153+ productSupportingMembers ( ) . length ,
124154 ) }
125155 </ Text >
126- { iavMembers . map ( ( member ) => {
156+ { productSupportingMembers ( ) . map ( ( member ) => {
127157 return (
128158 < UtilityRow
129159 borderType = "none"
0 commit comments