diff --git a/src/reducer/allCasesSlice.ts b/src/reducer/allCasesSlice.ts index 3aeac36d..4df7be03 100644 --- a/src/reducer/allCasesSlice.ts +++ b/src/reducer/allCasesSlice.ts @@ -12,9 +12,17 @@ import { caseVerdict, ICaseItem, } from '../screens/allCases/interface'; -import { CaseDetail, CONTEXT_TASK_STATUSES } from '../screens/caseDetails/interface'; +import { CaseDetail, CONTEXT_TASK_STATUSES, DOCUMENT_TYPE } from '../screens/caseDetails/interface'; import { addClickstreamEvent } from '../services/clickstreamEventService'; -import { getLoanAccountNumber } from '../components/utlis/commonFunctions'; +import { + checkS3Url, + getLoanAccountNumber, + saveToGlobalDocumentMap, + storeImageLocallyReturnRelativePath, +} from '../components/utlis/commonFunctions'; +import { TDocumentObj } from '../screens/caseDetails/interface'; +import { GlobalDocumentMap } from '../../App'; +import { ISignedRequest, getSignedApi } from '../action/dataActions'; export type ICasesMap = { [key: string]: ICaseItem }; @@ -292,12 +300,94 @@ const allCasesSlice = createSlice({ (task) => task?.taskType === (updatedCurrentTask as string) ); } + let imageUri = ''; + const docsList = updatedCaseDetail.documents; + if (docsList?.length) { + const optimizedSelfieDoc = docsList.find( + (doc) => doc.type === DOCUMENT_TYPE.OPTIMIZED_SELFIE + ); + if (!optimizedSelfieDoc) { + return; + } + imageUri = optimizedSelfieDoc.uri; + } + console.log('imageUri: ', imageUri); state.caseDetails[caseId] = { ...updatedCaseDetail, currentTask, isSynced: true, isNewlyAdded: !isInitialLoad, + imageUri, }; + // (async () => { + // const localImagePath = await storeImageLocallyReturnRelativePath( + // optimizedSelfieDoc.uri + // ); + // // update the docObj with fs path. No more s3 link. + // console.log("localImagePath:::", localImagePath); + // if (localImagePath) { + // // const docObj: TDocumentObj = { + // // ...GlobalDocumentMap[caseId], + // // [DOCUMENT_TYPE.OPTIMIZED_SELFIE]: localImagePath, + // // }; + // state.caseDetails[caseId] = { + // ...updatedCaseDetail, + // imageUri: localImagePath + // }; + // // state.caseDetails[caseId].imageUri = localImagePath; + // // saveToGlobalDocumentMap(caseId, docObj); + // } + // })(); + // } + // const docsList = updatedCaseDetail.documents; + // if (docsList) { + // const optimizedSelfieDoc = docsList.find( + // (doc) => doc.type === DOCUMENT_TYPE.OPTIMIZED_SELFIE + // ); + // if (optimizedSelfieDoc) { + // const { referenceId } = optimizedSelfieDoc; + // if (!referenceId) { + // return; + // } + // const optimizedSelfieUri = optimizedSelfieDoc?.uri; + // async function checkUrl(url: string) { + // const result = await checkS3Url(url); + // if (result) { + // const localImagePath = await storeImageLocallyReturnRelativePath(url); + // if (localImagePath) { + // const docObj: TDocumentObj = { + // ...GlobalDocumentMap[caseId], + // [DOCUMENT_TYPE.OPTIMIZED_SELFIE]: localImagePath, + // }; + // console.log("localImagePath:::", caseId, localImagePath); + // saveToGlobalDocumentMap(caseId, docObj); + // } + // } else { + // const signedRequestPayload: ISignedRequest = [ + // { + // documentReferenceId: referenceId!!, + // caseId, + // caseType, + // }, + // ]; + // const response = await getSignedApi(signedRequestPayload, true); + // const url = response?.imageUrl || ''; + // const localImagePath = await storeImageLocallyReturnRelativePath(url); + // console.log("localImagePath:::", caseId, localImagePath); + // if (localImagePath) { + // const docObj: TDocumentObj = { + // ...GlobalDocumentMap[caseId], + // [DOCUMENT_TYPE.OPTIMIZED_SELFIE]: localImagePath, + // }; + // saveToGlobalDocumentMap(caseId, docObj); + // } + // } + // } + // if (optimizedSelfieUri) { + // checkUrl(optimizedSelfieUri); + // } + // } + // } break; } case FirestoreUpdateTypes.REMOVED: { @@ -525,6 +615,10 @@ const allCasesSlice = createSlice({ } }); }, + setCasesImageUri: (state, action) => { + const { caseId, imageUri } = action.payload; + state.caseDetails[caseId].imageUri = imageUri; + }, }, }); @@ -545,6 +639,7 @@ export const { setVisitPlansUpdating, resetNewVisitedCases, syncCasesByFallback, + setCasesImageUri, } = allCasesSlice.actions; export default allCasesSlice.reducer; diff --git a/src/screens/allCases/CaseItem.tsx b/src/screens/allCases/CaseItem.tsx index b37622a6..80aea812 100644 --- a/src/screens/allCases/CaseItem.tsx +++ b/src/screens/allCases/CaseItem.tsx @@ -39,6 +39,7 @@ const CaseItem: React.FC = ({ caseDetailObj?.isSynced, caseDetailObj?.interactionStatus, caseDetailObj?.caseVerdict, + caseDetailObj?.imageUri, JSON.stringify(caseDetailObj?.currentTask), caseDetailObj?.addressString, ]); diff --git a/src/screens/allCases/CaseItemAvatar.tsx b/src/screens/allCases/CaseItemAvatar.tsx index 7610a857..375895b2 100644 --- a/src/screens/allCases/CaseItemAvatar.tsx +++ b/src/screens/allCases/CaseItemAvatar.tsx @@ -1,11 +1,22 @@ -import React, { memo } from 'react'; +import React, { memo, useEffect, useMemo, useRef, useState } from 'react'; import { StyleSheet, View } from 'react-native'; import Avatar from '../../../RN-UI-LIB/src/components/Avatar'; import UnsyncedIcon from '../../../RN-UI-LIB/src/Icons/UnsyncedIcon'; import { COLORS } from '../../../RN-UI-LIB/src/styles/colors'; import useFetchDocument from '../../hooks/useFetchDocument'; -import { DOCUMENT_TYPE } from '../caseDetails/interface'; +import { DOCUMENT_TYPE, IDocument, TDocumentObj } from '../caseDetails/interface'; import { ICaseItemAvatarCaseDetailObj } from './interface'; +import { + checkS3Url, + findDocumentByDocumentType, + getDocumentList, + saveToGlobalDocumentMap, + storeImageLocallyReturnRelativePath, +} from '../../components/utlis/commonFunctions'; +import { ISignedRequest, getSignedApi } from '../../action/dataActions'; +import { GlobalDocumentMap } from '../../../App'; +import { useAppDispatch } from '../../hooks'; +import { setCasesImageUri } from '../../reducer/allCasesSlice'; interface ICaseItemAvatar { caseDetailObj: ICaseItemAvatarCaseDetailObj; @@ -26,7 +37,11 @@ const CaseItemAvatar: React.FC = ({ enableRetry = true, shouldBatchAvatar = false, }) => { + const lastItemId = useRef(caseDetailObj.caseId); const { isPinned, customerName, isCaseSynced } = caseDetailObj; + const apiInProgressReferenceIds = useRef([]); + + const dispatch = useAppDispatch(); const requiredDocumentTypeList = [DOCUMENT_TYPE.OPTIMIZED_SELFIE]; @@ -34,29 +49,126 @@ const CaseItemAvatar: React.FC = ({ requiredDocumentTypeList.push(DOCUMENT_TYPE.SELFIE); } - const { documentObj, setRetryForUnsignedDocuments, loading } = useFetchDocument( - caseDetailObj, - requiredDocumentTypeList, - true, - shouldBatchAvatar - ); + // const { documentObj, setRetryForUnsignedDocuments, loading } = useFetchDocument( + // caseDetailObj, + // requiredDocumentTypeList, + // true, + // shouldBatchAvatar + // ); const onError = async () => { - if (enableRetry) { - setRetryForUnsignedDocuments(requiredDocumentTypeList); + console.log('error:::::', caseDetailObj.customerName); + for (let retryForDocumentsItem of requiredDocumentTypeList) { + // Doc referenceId => needed to get a signed url of the expired s3 url. + const imageReferenceId = findDocumentByDocumentType( + caseDetailObj?.documentList, + retryForDocumentsItem + )?.referenceId; + + if (!imageReferenceId) { + return; + } + + (async (caseDetail) => { + if (apiInProgressReferenceIds.current.includes(imageReferenceId)) return; + + apiInProgressReferenceIds.current.push(imageReferenceId); + + const signedRequestPayload: ISignedRequest = [ + { + documentReferenceId: imageReferenceId, + caseId: '' + caseDetail.caseId, + caseType: caseDetail.caseType, + }, + ]; + //enableBatching true for listitems + const response = await getSignedApi(signedRequestPayload, enableRetry); + const url = response?.imageUrl; + + if (!url) { + return; + } + + const localImagePath = await storeImageLocallyReturnRelativePath(url); + console.log('localPath: ', caseDetail.customerName, localImagePath); + + if (localImagePath) { + // const docObj: TDocumentObj = { + // ...GlobalDocumentMap[caseDetailObj.caseId], + // [DOCUMENT_TYPE.OPTIMIZED_SELFIE]: localImagePath, + // }; + // saveToGlobalDocumentMap(caseDetailObj.caseId, docObj); + dispatch(setCasesImageUri({ caseId: caseDetail.caseId, imageUri: localImagePath })); + } + })(caseDetailObj); } }; + // const [docList, setDocList] = useState(caseDetailObj.documentList); + const optimizedSelfie = useRef(''); + // const [optimizedSelfie, setOptimizedSelfie] = useState(''); + + // useEffect(() => { + // if(caseDetailObj.caseId !== lastItemId.current) { + // lastItemId.current = caseDetailObj.caseId; + // setDocList(caseDetailObj.documentList); + // } + // }) + + // useEffect(() => { + // if(caseDetailObj.caseId !== lastItemId.current) { + // lastItemId.current = caseDetailObj.caseId; + // optimizedSelfie.current = ''; + // // setDocList(caseDetailObj.documentList); + // } + // const docList = caseDetailObj.documentList || []; + // // if() + // if (docList.length) { + // const optimizedSelfieDoc = findDocumentByDocumentType(docList, DOCUMENT_TYPE.OPTIMIZED_SELFIE); + // const imageReferenceId = optimizedSelfieDoc?.referenceId; + // if (!imageReferenceId) { + // return; + // } + // const optimizedSelfieUri = optimizedSelfieDoc?.uri; + // async function checkUrl(url: string) { + // const result = await checkS3Url(url); + // if (result) { + // optimizedSelfie.current = url; + // // setOptimizedSelfie(url); + // } else { + // const { caseId, caseType } = caseDetailObj; + // const signedRequestPayload: ISignedRequest = [ + // { + // documentReferenceId: imageReferenceId!!, + // caseId, + // caseType + // }, + // ]; + // const response = await getSignedApi(signedRequestPayload, true); + // const url = response?.imageUrl || ''; + // optimizedSelfie.current = url; + // // setOptimizedSelfie(url); + // } + // } + // if (optimizedSelfieUri) { + // checkUrl(optimizedSelfieUri); + // } + // } + // }, []); + + const avatarUri = caseDetailObj.imageUri || ''; //GlobalDocumentMap?.[caseDetailObj.caseId]?.[DOCUMENT_TYPE.OPTIMIZED_SELFIE] || ''; + console.log(`optimizedSelfie: ${caseDetailObj.customerName}`, avatarUri); + return ( {!isCaseSynced ? ( diff --git a/src/screens/allCases/CasesList.tsx b/src/screens/allCases/CasesList.tsx index 8d81d551..4f5c9007 100644 --- a/src/screens/allCases/CasesList.tsx +++ b/src/screens/allCases/CasesList.tsx @@ -9,7 +9,7 @@ import { StyleSheet, View, } from 'react-native'; -import { GenericStyles, SCREEN_WIDTH } from '../../../RN-UI-LIB/src/styles'; +import { GenericStyles, SCREEN_HEIGHT, SCREEN_WIDTH } from '../../../RN-UI-LIB/src/styles'; import { COLORS } from '../../../RN-UI-LIB/src/styles/colors'; import { RootState } from '../../store/store'; import { CaseTypes, ICaseItem, ICaseItemCaseDetailObj } from './interface'; @@ -236,7 +236,11 @@ const CasesList: React.FC = ({ casesList = [], isVisitPlan }) => { onScroll={handleListScroll} renderItem={renderListItem} ListEmptyComponent={listEmptyComponent} - estimatedItemSize={200} + estimatedItemSize={300} + // estimatedListSize={{ + // width: SCREEN_WIDTH, + // height: 100 * 300, + // }} estimatedListSize={{ height: 300, width: SCREEN_WIDTH }} /> ) : ( diff --git a/src/screens/allCases/ListItem.tsx b/src/screens/allCases/ListItem.tsx index 2e2b5294..55e88529 100644 --- a/src/screens/allCases/ListItem.tsx +++ b/src/screens/allCases/ListItem.tsx @@ -130,6 +130,7 @@ const ListItem: React.FC = (props) => { caseId, documentList: getDocumentList(caseListItemDetailObj) || [], caseType: caseType, + imageUri: caseListItemDetailObj?.imageUri || '', }), [ caseType, @@ -137,6 +138,7 @@ const ListItem: React.FC = (props) => { pinRank, caseListItemDetailObj?.customerInfo?.documents, caseListItemDetailObj?.documents, + caseListItemDetailObj?.imageUri, ] ); diff --git a/src/screens/allCases/interface.ts b/src/screens/allCases/interface.ts index c2fd4a98..0608136e 100644 --- a/src/screens/allCases/interface.ts +++ b/src/screens/allCases/interface.ts @@ -313,6 +313,7 @@ export interface ICaseItemAvatarCaseDetailObj extends IFetchDocumentCaseDetailOb isPinned: boolean; isCaseSynced: boolean; customerName: string; + imageUri: string; } export interface ICaseItemCaseDetailObj extends CaseDetail { diff --git a/src/screens/caseDetails/UserDetailsSection.tsx b/src/screens/caseDetails/UserDetailsSection.tsx index cee31582..cf697e66 100644 --- a/src/screens/caseDetails/UserDetailsSection.tsx +++ b/src/screens/caseDetails/UserDetailsSection.tsx @@ -74,6 +74,7 @@ const UserDetailsSection: React.FC = (props) => { caseId: caseDetail?.id, documentList: getDocumentList(caseDetail) || [], caseType: caseDetail?.caseType, + imageUri: caseDetail?.imageUri || '', }), [ caseDetail?.caseType, @@ -81,6 +82,7 @@ const UserDetailsSection: React.FC = (props) => { caseDetail?.pinRank, caseDetail?.customerInfo?.documents, caseDetail?.documents, + caseDetail?.imageUri, ] ); diff --git a/src/screens/caseDetails/interface.ts b/src/screens/caseDetails/interface.ts index a8057496..51125dca 100644 --- a/src/screens/caseDetails/interface.ts +++ b/src/screens/caseDetails/interface.ts @@ -195,6 +195,7 @@ export interface CaseDetail { imageReferenceId?: string; collectionTag?: 'Fresh' | 'Stab'; disbursementAmount?: number; + imageUri?: string; } export interface AddressesGeolocationPayload {