diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml index ed42d15f..8e042777 100644 --- a/.github/workflows/pr-review.yml +++ b/.github/workflows/pr-review.yml @@ -1,9 +1,6 @@ name: Code Critic PR Review on: - pull_request: - types: [opened, reopened, ready_for_review] - branches: [master] issue_comment: types: [created] diff --git a/android/app/build.gradle b/android/app/build.gradle index aeaae7b5..915c47a4 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -134,8 +134,8 @@ def reactNativeArchitectures() { return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] } -def VERSION_CODE = 185 -def VERSION_NAME = "2.12.9" +def VERSION_CODE = 186 +def VERSION_NAME = "2.12.10" android { ndkVersion rootProject.ext.ndkVersion diff --git a/package.json b/package.json index 3b2acde1..ab75388b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "AV_APP", - "version": "2.12.9", - "buildNumber": "185", + "version": "2.12.10", + "buildNumber": "186", "private": true, "scripts": { "android:dev": "yarn move:dev && react-native run-android", diff --git a/src/common/Constants.ts b/src/common/Constants.ts index add4d060..d2fd3918 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -758,9 +758,9 @@ export const CLICKSTREAM_EVENT_NAMES = { name: 'FA_DOCUMENT_WHATSAPP_SHARE_CLICKED', description: 'FA_DOCUMENT_WHATSAPP_SHARE_CLICKED', }, - FA_DOCUMENT_WHATSAPP_SHARE_SUCCESS: { - name: 'FA_DOCUMENT_WHATSAPP_SHARE_SUCCESS', - description: 'FA_DOCUMENT_WHATSAPP_SHARE_SUCCESS', + FA_DOCUMENT_NAVI_WHATSAPP_SHARE_SUCCESS: { + name: 'FA_DOCUMENT_NAVI_WHATSAPP_SHARE_SUCCESS', + description: 'FA_DOCUMENT_NAVI_WHATSAPP_SHARE_SUCCESS', }, FA_DOCUMENT_WHATSAPP_SHARE_FAILED: { name: 'FA_DOCUMENT_WHATSAPP_SHARE_FAILED', diff --git a/src/components/utlis/apiHelper.ts b/src/components/utlis/apiHelper.ts index 091d1581..0a78bad9 100644 --- a/src/components/utlis/apiHelper.ts +++ b/src/components/utlis/apiHelper.ts @@ -93,6 +93,7 @@ export enum ApiKeys { FETCH_DOCUMENT_SPECIFIC_LANGUAGE = 'FETCH_DOCUMENT_SPECIFIC_LANGUAGE', SEND_COMMUNICATION_NAVI_ACCOUNT = 'SEND_COMMUNICATION_NAVI_ACCOUNT', SYNC_CALL_FEEDBACK_NUDGE_DETAILS = 'SYNC_CALL_FEEDBACK_NUDGE_DETAILS', + GENERATE_DYNAMIC_DOCUMENT = 'GENERATE_DYNAMIC_DOCUMENT', } export const API_URLS: Record = {} as Record; @@ -178,6 +179,7 @@ API_URLS[ApiKeys.FETCH_CUSTOMER_DOCUMENTS] = '/documents/{loanAccountNumber}'; API_URLS[ApiKeys.FETCH_AGENT_DOCUMENTS] = '/documents/agent'; API_URLS[ApiKeys.FETCH_DOCUMENT_SPECIFIC_LANGUAGE] = '/documents/language/{loanAccountNumber}'; API_URLS[ApiKeys.SEND_COMMUNICATION_NAVI_ACCOUNT] = '/navi-communications/{loanAccountNumber}'; +API_URLS[ApiKeys.GENERATE_DYNAMIC_DOCUMENT] = '/documents/generate/{loanAccountNumber}'; export const API_STATUS_CODE = { OK: 200, diff --git a/src/components/utlis/commonFunctions.ts b/src/components/utlis/commonFunctions.ts index 8e24044d..3361fc0b 100644 --- a/src/components/utlis/commonFunctions.ts +++ b/src/components/utlis/commonFunctions.ts @@ -14,6 +14,7 @@ import { getPrefixBase64Image, LocalStorageKeys, MimeType, + NAVI_AGENCY_CODE, } from '../../common/Constants'; import NetInfo from '@react-native-community/netinfo'; import Clipboard from '@react-native-clipboard/clipboard'; @@ -44,6 +45,7 @@ import { import { addClickstreamEvent } from '@services/clickstreamEventService'; import { ITelephoneNumbers } from '@reducers/telephoneNumbersSlice'; import { ISignedRequest, getSignedApi } from '@actions/dataActions'; +import axiosInstance, { ApiKeys, getApiUrl } from './apiHelper'; const fs = ReactNativeBlobUtil.fs; @@ -590,3 +592,71 @@ export const handleDownloadPdfDocument = async (document: IDocumentItem | IDocum logError(error as Error); }); }; + +export const fetchDynamicallyGeneratedDoc = async (lan: string, documentType: string) => { + return axiosInstance + .post( + getApiUrl(ApiKeys.GENERATE_DYNAMIC_DOCUMENT, { loanAccountNumber: lan }), + { + documentGenerationType: documentType, + }, + { + headers: { + donotHandleError: true, + }, + } + ) + .then((res) => { + if (res?.data) { + return res?.data; + } + }) + .catch(() => { + toast({ + text1: `Cannot generate ${documentType} for LAN: ${lan}`, + type: 'error', + }); + }); +}; + +export const downloadDynamicallyGeneratedDoc = async ( + lan: string, + caseId: string, + documentType: string +) => { + fetchDynamicallyGeneratedDoc(lan, documentType) + .then((res) => { + if (res?.uri) { + handleDownloadPdfDocument(res, caseId); + } + }) + .catch(() => { + toast({ + text1: `Cannot download ${documentType} for LAN: ${lan}`, + type: 'error', + }); + }); +}; + +export const shareDynamicallyGeneratedDoc = async ( + lan: string, + caseId: string, + documentType: string +) => { + fetchDynamicallyGeneratedDoc(lan, documentType) + .then((res) => { + if (res?.uri) { + handleSharePdfDocument(res, caseId); + } + }) + .catch(() => { + toast({ + text1: `Cannot share ${documentType} for LAN: ${lan}`, + type: 'error', + }); + }); +}; + +export const checkExternalAgency = (agencyName: string, agencyCode: string) => { + return (agencyName && agencyCode !== NAVI_AGENCY_CODE); +} diff --git a/src/screens/Profile/AgentIdCard.tsx b/src/screens/Profile/AgentIdCard.tsx index aef83db8..632e5919 100644 --- a/src/screens/Profile/AgentIdCard.tsx +++ b/src/screens/Profile/AgentIdCard.tsx @@ -1,14 +1,10 @@ import { Pressable, SafeAreaView, StyleSheet, View } from 'react-native'; import React, { useEffect, useMemo, useState } from 'react'; -import NaviLogoWithTextIcon from '../../../RN-UI-LIB/src/Icons/NaviLogoWithTextIcon'; import Avatar from '../../../RN-UI-LIB/src/components/Avatar'; import { GenericStyles } from '../../../RN-UI-LIB/src/styles'; import Text from '../../../RN-UI-LIB/src/components/Text'; -import Heading from '../../../RN-UI-LIB/src/components/Heading'; import { COLORS } from '../../../RN-UI-LIB/src/styles/colors'; import { useAppDispatch, useAppSelector } from '../../hooks'; -import { BUSINESS_DATE_FORMAT, dateFormat } from '../../../RN-UI-LIB/src/utlis/dates'; -import { NAVI_AGENCY_CODE } from '../../common/Constants'; import Layout from '@screens/layout/Layout'; import NavigationHeader from '@rn-ui-lib/components/NavigationHeader'; import { goBack, popToScreen } from '@components/utlis/navigationUtlis'; @@ -19,6 +15,8 @@ import RetryIcon from '@assets/icons/RetryIcon'; import ScreenshotBlocker from '@components/utlis/ScreenshotBlocker'; import { getSelfieDocument } from '@actions/profileActions'; import { setShouldHideTabBar } from '@reducers/commonSlice'; +import AgentIdCardDetails from './AgentIdCardDetails'; +import { checkExternalAgency } from '@components/utlis/commonFunctions'; const PAGE_TITLE = 'Agent ID card'; @@ -72,32 +70,19 @@ const AgentIdCard = () => { - const { - originalImageUri, - optimizedImageUri, - agentName, - agentPhone, - agencyName, - agentEmail, - agencyCode, - employeeId, - } = useAppSelector((state) => ({ - originalImageUri: state.profile.originalImageUri, - agentName: state.user.user?.name!!, - agentPhone: state.user.user?.phoneNumber, - agencyName: state.profile.agencyName, - agentEmail: state.user.user?.emailId, - agencyCode: state.profile.agencyCode, - employeeId: state.user?.employeeId, - optimizedImageUri: state.profile.optimizedImageUri, - })); + const originalImageUri = useAppSelector((state) => state.profile.originalImageUri); + const optimizedImageUri = useAppSelector((state) => state.profile.optimizedImageUri); + const agentName = useAppSelector((state) => state.user.user?.name!!); + const agencyName = useAppSelector((state) => state.profile?.agencyName); + const agencyCode = useAppSelector((state) => state.profile?.agencyCode); + const showRetry = useMemo(() => { return !originalImageUri && !optimizedImageUri; }, [optimizedImageUri, originalImageUri]); - const isExternalAgency = (agencyName && agencyCode !== NAVI_AGENCY_CODE); + const isExternalAgency = useMemo(() => checkExternalAgency(agencyName, agencyCode), [agencyName, agencyCode]); const loaderConf = useMemo(()=>{ return [ @@ -110,9 +95,6 @@ const AgentIdCard = () => { ] },[]) - - - return ( @@ -154,50 +136,9 @@ const AgentIdCard = () => { )) || null} ) : ( - <> - - {isExternalAgency ? ( - <> - - in association with - - - {agencyName} - - - ) : null} - - Valid as of {dateFormat(new Date(todaysDate), BUSINESS_DATE_FORMAT)} - - - - {'Debt Management Executive'} - - - {agentName} - - - - {agentEmail} - - - {' | '} - - - {agentPhone} - - - - {employeeId ? - - {'Emp ID '} - - - {employeeId} - - : null} - - + )} @@ -214,16 +155,8 @@ const styles = StyleSheet.create({ borderWidth: 3, borderColor: COLORS.BORDER.PRIMARY, }, - flexContainer : { - display:'flex', - flexDirection:'row', - }, - greyColor: { - color: COLORS.TEXT.GREY, - }, - darkBlueColor: { - color: COLORS.TEXT.DARK_BLUE, - }, + + lineLoader: { borderRadius: 20, }, @@ -233,10 +166,6 @@ const styles = StyleSheet.create({ mt70: { marginTop: 70, }, - avatarMargin: { - alignItems: 'center', - marginTop: 310, - }, retryContainer: { marginTop: 30, }, diff --git a/src/screens/Profile/AgentIdCardDetails.tsx b/src/screens/Profile/AgentIdCardDetails.tsx new file mode 100644 index 00000000..2eb01e1a --- /dev/null +++ b/src/screens/Profile/AgentIdCardDetails.tsx @@ -0,0 +1,84 @@ +import { checkExternalAgency } from '@components/utlis/commonFunctions'; +import { useAppSelector } from '@hooks'; +import { COLORS } from '@rn-ui-lib/colors'; +import Heading from '@rn-ui-lib/components/Heading'; +import Text from '@rn-ui-lib/components/Text'; +import NaviLogoWithTextIcon from '@rn-ui-lib/icons/NaviLogoWithTextIcon'; +import { GenericStyles } from '@rn-ui-lib/styles'; +import { BUSINESS_DATE_FORMAT, dateFormat } from '@rn-ui-lib/utils/dates'; +import { useMemo } from 'react'; +import { View } from 'react-native'; +import { StyleSheet } from 'react-native'; + +interface IAgentCardDetails { + todaysDate: Date; +} + +const AgentIdCardDetails = ({ + todaysDate, +}: IAgentCardDetails) => { + + const agentName = useAppSelector((state) => state.user.user?.name!!); + const agentPhone = useAppSelector((state) => state.user.user?.phoneNumber); + const agencyName = useAppSelector((state) => state.profile?.agencyName); + const agentEmail = useAppSelector((state) => state.user.user?.emailId); + const agencyCode = useAppSelector((state) => state.profile?.agencyCode); + const employeeId = useAppSelector((state) => state.user?.employeeId); + const isExternalAgency = useMemo(() => checkExternalAgency(agencyName, agencyCode), [agencyName, agencyCode]); + + return ( + <> + + {isExternalAgency ? ( + <> + + in association with + + + {agencyName} + + + ) : null} + + Valid as of {dateFormat(new Date(todaysDate), BUSINESS_DATE_FORMAT)} + + + {'Debt Management Executive'} + + {agentName} + + + {agentEmail} + {' | '} + {agentPhone} + + + {employeeId ? ( + + {'Emp ID '} + {employeeId} + + ) : null} + + + ); +}; + +export default AgentIdCardDetails; + +const styles = StyleSheet.create({ + flexContainer: { + display: 'flex', + flexDirection: 'row', + }, + greyColor: { + color: COLORS.TEXT.GREY, + }, + darkBlueColor: { + color: COLORS.TEXT.DARK_BLUE, + }, + avatarMargin: { + alignItems: 'center', + marginTop: 310, + }, +}); diff --git a/src/screens/Profile/MyDocuments.tsx b/src/screens/Profile/MyDocuments.tsx index 189f0ac9..d4200d6b 100644 --- a/src/screens/Profile/MyDocuments.tsx +++ b/src/screens/Profile/MyDocuments.tsx @@ -53,11 +53,7 @@ const MyDocuments = () => { documentType: document?.documentKey, }) navigateToScreen(CaseDetailStackEnum.PDF_FULL, { - pdfUri: document?.uri, - referenceId: document?.documentRefId, - cacheFileKey: document?.documentRefId, - unSignedUri: document?.unsignedUri, - screenName: `${document?.documentName} PDF viewer`, + document: document }); }; diff --git a/src/screens/allCases/utils.ts b/src/screens/allCases/utils.ts index 2004f0e8..3e5c4ca3 100644 --- a/src/screens/allCases/utils.ts +++ b/src/screens/allCases/utils.ts @@ -1,5 +1,5 @@ import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants'; -import { getDistanceFromLatLonInKm } from '@components/utlis/commonFunctions'; +import { getDistanceFromLatLonInKm, isFunction } from '@components/utlis/commonFunctions'; import { IGeoLocation } from '@interfaces/addressGeolocation.types'; import { addClickstreamEvent } from '@services/clickstreamEventService'; import { @@ -223,9 +223,12 @@ export const updateNearbyCasesListAndLocation = ( return; }; -export const getCustomerDocuments = async (loanAccountNumber: string) => -{ +export const getCustomerDocuments = async ( + loanAccountNumber: string, + setIsDocumentsLoading?: (val: boolean) => void +) => { if (!loanAccountNumber) return; + isFunction(setIsDocumentsLoading) && setIsDocumentsLoading(true); const url = getApiUrl(ApiKeys.FETCH_CUSTOMER_DOCUMENTS, { loanAccountNumber }); await axiosInstance .get(url) @@ -247,6 +250,9 @@ export const getCustomerDocuments = async (loanAccountNumber: string) => }) .catch((err) => { logError(err); + }) + .finally(() => { + isFunction(setIsDocumentsLoading) && setIsDocumentsLoading(false); }); }; diff --git a/src/screens/caseDetails/CollectionCaseDetail.tsx b/src/screens/caseDetails/CollectionCaseDetail.tsx index 87b98c1a..051c2008 100644 --- a/src/screens/caseDetails/CollectionCaseDetail.tsx +++ b/src/screens/caseDetails/CollectionCaseDetail.tsx @@ -61,17 +61,6 @@ const CollectionCaseDetails: React.FC = (props) => { }; }, [caseId]); - const fetchCustomerDocuments = (loanAccountNumber: string) => { - setIsDocumentsLoading(true); - try { - getCustomerDocuments(loanAccountNumber); - } catch (error: GenericType) { - logError(error as Error); - } finally { - setIsDocumentsLoading(false); - } - }; - useEffect(() => { if (!loanAccountNumber) { return; @@ -83,7 +72,6 @@ const CollectionCaseDetails: React.FC = (props) => { [UnifiedCaseDetailsTypes.FEEDBACKS, UnifiedCaseDetailsTypes.ADDRESS_AND_GEOLOCATIONS] ) ); - fetchCustomerDocuments(loanAccountNumber); } }, [caseDetail]); @@ -126,7 +114,7 @@ const CollectionCaseDetails: React.FC = (props) => { - + = (props) => { const { route: { - params: { caseDetail, isDocumentsLoading }, + params: { caseDetail }, }, } = props; const [errorModalImage, setErrorModalImage] = useState(false); @@ -58,10 +57,13 @@ const CustomerProfile: React.FC = (props) => { const [retry, setRetry] = useState(true); const [errorCount, setErrorCount] = useState(0); const [isHighQualityImageLoaded, setIsHighQualityImageLoaded] = useState(false); - const [documentsLoading, setDocumentsLoading] = useState(false); const [showLoadingState, setShowLoadingState] = useState(false); + const [isDocumentsLoading, setIsDocumentsLoading] = React.useState(false); const agentId = useAppSelector((state) => state?.user?.user?.referenceId); + const documentsData = useAppSelector((state) => state?.documentsSlice?.documentsData); + + const loanAccountNumber = caseDetail?.loanAccountNumber; const { startTimer, isActive, clearTimer } = useTimeout(() => { setLoading(false); }, DELAY_FOR_PAINTING_IMAGE); @@ -77,7 +79,6 @@ const CustomerProfile: React.FC = (props) => { false, false ); - const [documentData, setDocumentData] = useState>([]); const getImageURI = () => { if (!isOnline) { @@ -94,29 +95,16 @@ const CustomerProfile: React.FC = (props) => { ); }; + const { mobileNumbers } = useMobileNumbers(caseDetail?.caseReferenceId); + useEffect(() => { - if (caseDetail) { - setDocumentsLoading(true); - const docList: IDocument[] = getDocumentList(caseDetail) || []; - const docPromises: Promise[] = []; - CUSTOMER_PROFILE_DOCS.forEach((documentType) => { - const document = findDocumentByDocumentType(docList, documentType); - if (document) { - const docPromise = getDocumentDetails(document); - if (docPromise) docPromises.push(docPromise); - } - }); - Promise.all(docPromises) - .then((docs: Array) => { - const documents = docs?.filter( - (document: DocumentDetail | null) => document - ) as Array; - setDocumentData(documents); - }) - .catch(() => {}) - .finally(() => setDocumentsLoading(false)); + if (isOnline && loanAccountNumber) { + getCustomerDocuments( + loanAccountNumber, + documentsData?.[loanAccountNumber] ? noop : setIsDocumentsLoading + ); } - }, [caseDetail]); + }, []); const onLoadStart = () => { setLoading(true); diff --git a/src/screens/caseDetails/DocumentDataItem.tsx b/src/screens/caseDetails/DocumentDataItem.tsx index d95b1f80..a1ff0f01 100644 --- a/src/screens/caseDetails/DocumentDataItem.tsx +++ b/src/screens/caseDetails/DocumentDataItem.tsx @@ -64,13 +64,9 @@ const DocumentDataItem: React.FC = ({ } ); navigateToScreen('pdfFull', { - pdfUri: document?.uri, - referenceId: documentRefId, - cacheFileKey: documentRefId + caseId, - unSignedUri: unsignedUri, caseId, + loanAccountNumber: lan, document: document, - screenName: `${documentName} PDF viewer`, showDownloadButton: downloadable, }); }; diff --git a/src/screens/caseDetails/DocumentImageComponent.tsx b/src/screens/caseDetails/DocumentImageComponent.tsx index c1f4d4d3..02a93737 100644 --- a/src/screens/caseDetails/DocumentImageComponent.tsx +++ b/src/screens/caseDetails/DocumentImageComponent.tsx @@ -57,8 +57,6 @@ const DocumentImageComponent = (props: DocumentImageComponentProps) => { }); }; - useS3UrlCheck(uri, documentRefId, caseId, caseType, unsignedUri, setImageUrl, setIsValidating); - return ( <> diff --git a/src/screens/caseDetails/DocumentListItem.tsx b/src/screens/caseDetails/DocumentListItem.tsx index 1a2dc81a..5188e426 100644 --- a/src/screens/caseDetails/DocumentListItem.tsx +++ b/src/screens/caseDetails/DocumentListItem.tsx @@ -8,7 +8,7 @@ import DownloadOutlineIcon from '@rn-ui-lib/icons/DownloadOutlineIcon'; import { IDocumentItem } from './interface'; import { useAppSelector } from '@hooks'; import ShareAndDownloadJourney, { DocumentJourneyType } from './ShareAndDownloadJourney'; -import { handleDownloadPdfDocument } from '@components/utlis/commonFunctions'; +import { downloadDynamicallyGeneratedDoc, handleDownloadPdfDocument } from '@components/utlis/commonFunctions'; import { addClickstreamEvent } from '@services/clickstreamEventService'; import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants'; import DownloadBoldIcon from '@rn-ui-lib/icons/DownloadBoldIcon'; @@ -20,7 +20,7 @@ interface IDocumentListItem { } const DocumentListItem: React.FC = ({ lan, caseId, document }) => { - const { shareable, downloadable, multiLingual } = document || {}; + const { shareable, downloadable, multiLingual, documentKey, dynamicallyGenerated } = document || {}; const agentId = useAppSelector((state) => state.user.user?.referenceId!); const [isShareBottomSheetVisible, setIsShareBottomSheetVisible] = React.useState(false); const [isDownloadBottomSheetVisible, setIsDownloadBottomSheetVisible] = @@ -34,6 +34,11 @@ const DocumentListItem: React.FC = ({ lan, caseId, document } documentName: document?.documentKey, }) + + if(dynamicallyGenerated) { + downloadDynamicallyGeneratedDoc(lan, caseId, documentKey); + return; + } if(!multiLingual) { handleDownloadPdfDocument(document, caseId); return; diff --git a/src/screens/caseDetails/DocumentTabs.tsx b/src/screens/caseDetails/DocumentTabs.tsx index ae346e57..6c57c405 100644 --- a/src/screens/caseDetails/DocumentTabs.tsx +++ b/src/screens/caseDetails/DocumentTabs.tsx @@ -9,6 +9,7 @@ import { ActivityIndicator, StyleSheet } from 'react-native'; import { COLORS } from '@rn-ui-lib/colors'; import { addClickstreamEvent } from '@services/clickstreamEventService'; import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants'; +import { AGENT_TAB_KEY, AGENT_TAB_NAME } from './constants'; interface IDocumentTabs { @@ -21,12 +22,12 @@ interface IDocumentTabs { const DocumentTabs: React.FC = ({ lan, caseId, isDocumentsLoading, scrollByOffset }) => { const documentsData = useAppSelector((state) => state?.documentsSlice?.documentsData); - const data = documentsData[lan]; + const data = documentsData?.[lan]; const agentsData = useAppSelector((state) => state?.documentsSlice?.agentDocumentsData); - const [DOCUMENTS_TABS, SET_DOCUMENT_TABS] = useState([]); + const [documentTabs, setDocumentTabs] = useState([]); const [documentsList, setDocumentsList] = useState([]); - const [selectedTab, setSelectedTab] = useState(DOCUMENTS_TABS?.[0]?.key || ''); + const [selectedTab, setSelectedTab] = useState(documentTabs?.[0]?.key || ''); useEffect(() => { const docTabs: Tab[] = []; @@ -50,10 +51,10 @@ const DocumentTabs: React.FC = ({ lan, caseId, isDocumentsLoading agentsData && docTabs.push({ - key: 'AGENT', - label: 'Agent', + key: AGENT_TAB_KEY, + label: AGENT_TAB_NAME, }); - SET_DOCUMENT_TABS(docTabs); + setDocumentTabs(docTabs); if (agentsData) { agentsData?.forEach((doc: IDocumentItem) => { @@ -64,8 +65,8 @@ const DocumentTabs: React.FC = ({ lan, caseId, isDocumentsLoading }, [data, agentsData]); useEffect(() => { - setSelectedTab(DOCUMENTS_TABS?.[0]?.key || ''); - }, [DOCUMENTS_TABS]); + setSelectedTab(documentTabs?.[0]?.key || ''); + }, [documentTabs]); const handleTabChange = (tabKey: string) => { addClickstreamEvent( @@ -89,7 +90,7 @@ const DocumentTabs: React.FC = ({ lan, caseId, isDocumentsLoading ) : ( <> ; } const PDFDownload = (props: IPDFDownload) => { - const { document, caseId, style={} } = props + const { document, lan, caseId, style={} } = props const handlePDFDocumentDownload = () =>{ + if(document?.dynamicallyGenerated){ + downloadDynamicallyGeneratedDoc(lan, caseId, document?.documentKey); + return; + } handleDownloadPdfDocument(document, caseId); } diff --git a/src/screens/caseDetails/PDFFullScreen.tsx b/src/screens/caseDetails/PDFFullScreen.tsx index a361d6e8..1ebed418 100644 --- a/src/screens/caseDetails/PDFFullScreen.tsx +++ b/src/screens/caseDetails/PDFFullScreen.tsx @@ -1,9 +1,7 @@ import React, { useEffect, useState } from 'react'; import { ActivityIndicator, - Pressable, SafeAreaView, - ScrollView, StyleSheet, View, useWindowDimensions, @@ -16,42 +14,34 @@ import { COLORS } from '../../../RN-UI-LIB/src/styles/colors'; import { goBack } from '../../components/utlis/navigationUtlis'; import Text from '../../../RN-UI-LIB/src/components/Text'; import PdfRendererView from 'react-native-pdf-renderer'; -import { CaseAllocationType } from '../allCases/interface'; -import useS3UrlCheck from '../../hooks/useS3UrlCheck'; import { toast } from '@rn-ui-lib/components/toast'; -import { handleSharePdfDocument } from '@components/utlis/commonFunctions'; +import { + fetchDynamicallyGeneratedDoc, + handleSharePdfDocument, +} from '@components/utlis/commonFunctions'; import { calculateBottomSheetHeight, sendCommunicationViaNaviAccount, } from '@screens/allCases/utils'; -import { IDocumentItem } from './interface'; +import { IDocument, IDocumentItem } from './interface'; import { DOCUMENT_NOT_AVAILABLE } from '@constants/Global'; import { NAVI_ACCOUNT_SHARE_CHANNELS, ShareVia } from './constants'; import PDFScreenShareJourneyBottomSheet from './PDFScreenShareJourneyBottomSheet'; import { addClickstreamEvent } from '@services/clickstreamEventService'; import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants'; -import { ITelephoneNumbers } from '@reducers/telephoneNumbersSlice'; -import useMobileNumbers from '@hooks/useMobileNumbers'; import { logError } from '@components/utlis/errorUtils'; import { GenericType } from '@common/GenericTypes'; -import DownloadSolidIcon from '@rn-ui-lib/icons/DownloadSolidIcon'; import PDFDownload from './PDFDownload'; +import { useAppSelector } from '@hooks'; interface IPdfFullScreen { route: { params: { - pdfUri: string; - referenceId: string; - cacheFileKey: string; - screenName: string; - caseId: string; - caseType: CaseAllocationType; - unSignedUri: string; + caseId?: string; loanAccountNumber?: string; - document?: IDocumentItem; + document: IDocumentItem; showShareBottomsheet?: boolean; showDownloadButton?: boolean; - handleDownloadPDF?: () => void; }; }; } @@ -60,22 +50,20 @@ const PDFFullScreen: React.FC = (props) => { const { route: { params: { - pdfUri, - referenceId, - cacheFileKey, - screenName, - caseId, - caseType, - unSignedUri, + caseId = '', + loanAccountNumber, document, showShareBottomsheet = false, - handleDownloadPDF, showDownloadButton = false, - loanAccountNumber, }, }, } = props; + const mobileNumbers = + useAppSelector((state) => state?.telephoneNumbers?.telephoneNumbers?.[caseId]) || []; + const { uri: pdfUri, documentName: screenName } = document || {}; + const referenceId = document?.documentRefId || document?.referenceId; + const cacheFileKey = referenceId + caseId; const [isLoading, setIsLoading] = useState(false); const [pdfFilePath, setPdfFilePath] = useState(''); const [error, setError] = useState(false); @@ -89,11 +77,10 @@ const PDFFullScreen: React.FC = (props) => { return calculateBottomSheetHeight(mobileNumbers?.length || 0); }; - useS3UrlCheck(pdfUri, referenceId, caseId, caseType, unSignedUri, setPdfUrl, setIsValidating); - useEffect(() => { addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_PDF_VIEWER_OPENED, { agentId: referenceId, + lan: loanAccountNumber, documentRefId: document?.documentRefId, documentType: document?.documentKey, }); @@ -109,8 +96,6 @@ const PDFFullScreen: React.FC = (props) => { goBack(); }; - const { mobileNumbers } = useMobileNumbers(caseId); - useEffect(() => { setIsBottomSheetVisible(showShareBottomsheet && !isLoading && !error); }, [showShareBottomsheet, isLoading, error]); @@ -152,16 +137,22 @@ const PDFFullScreen: React.FC = (props) => { setIsLoading(true); setError(false); try { - await RNFS.mkdir(cacheDirectory); - const exists = await RNFS.exists(cacheFilePath); + let highQualityResponse; + if (document?.dynamicallyGenerated) { + const doc = await fetchDynamicallyGeneratedDoc(loanAccountNumber, document?.documentKey); + highQualityResponse = await RNFetchBlob.fetch('GET', doc?.uri); + } else { + await RNFS.mkdir(cacheDirectory); + const exists = await RNFS.exists(cacheFilePath); - if (exists) { - setPdfFilePath(cacheFilePath); - setIsLoading(false); - setError(false); - return; + if (exists) { + setPdfFilePath(cacheFilePath); + setIsLoading(false); + setError(false); + return; + } + highQualityResponse = await RNFetchBlob.fetch('GET', pdfUrl); } - const highQualityResponse = await RNFetchBlob.fetch('GET', pdfUrl); if (highQualityResponse.respInfo.status !== 200) { setIsLoading(false); @@ -189,7 +180,9 @@ const PDFFullScreen: React.FC = (props) => { title={screenName} icon={Icon.back} rightActionable={ - showDownloadButton ? : null + showDownloadButton ? ( + + ) : null } /> {pdfFilePath && ( diff --git a/src/screens/caseDetails/PDFScreenShareJourneyBottomSheet.tsx b/src/screens/caseDetails/PDFScreenShareJourneyBottomSheet.tsx index 02aa1dd4..a1b6f081 100644 --- a/src/screens/caseDetails/PDFScreenShareJourneyBottomSheet.tsx +++ b/src/screens/caseDetails/PDFScreenShareJourneyBottomSheet.tsx @@ -76,7 +76,7 @@ const PDFScreenShareJourneyBottomSheet = ({ ]} > - {!shareVia ? 'Share via' : 'Share document on'} + {shareVia ? 'Share via' : 'Share document on'} diff --git a/src/screens/caseDetails/ShareAndDownloadJourney.tsx b/src/screens/caseDetails/ShareAndDownloadJourney.tsx index 0c995e14..9ceb51dd 100644 --- a/src/screens/caseDetails/ShareAndDownloadJourney.tsx +++ b/src/screens/caseDetails/ShareAndDownloadJourney.tsx @@ -50,9 +50,9 @@ export const ShareAndDownloadJourney = ({ isDownloadBottomSheetVisible, setIsDownloadBottomSheetVisible, }: IShareAndDownloadJourney) => { - const { agentId } = useAppSelector((state) => ({ - agentId: state.user.user?.referenceId!, - })); + const agentId = useAppSelector((state) => state.user.user?.referenceId!); + const mobileNumbers = + useAppSelector((state) => state?.telephoneNumbers?.telephoneNumbers?.[caseId]) || []; const { shareablePersonalAccount = false, languagesAvailable = [] } = document || {}; const getBottomSheetHeightCalculation = ( @@ -67,11 +67,6 @@ export const ShareAndDownloadJourney = ({ return calculateBottomSheetHeight(mobileNumbers?.length || 0); }; - - const {mobileNumbers} = useMobileNumbers(caseId); - - - const fetchMultiLingualDocument = async (documentName: string, language: string) => { try{ const multiLingualDoc = await getDocumentInSpecificLanguage(lan, documentName, language).then((res) => { @@ -134,7 +129,7 @@ export const ShareAndDownloadJourney = ({ ); } addClickstreamEvent( - CLICKSTREAM_EVENT_NAMES.FA_DOCUMENT_WHATSAPP_SHARE_SUCCESS, + CLICKSTREAM_EVENT_NAMES.FA_DOCUMENT_NAVI_WHATSAPP_SHARE_SUCCESS, { lan: lan, caseId: caseId, diff --git a/src/screens/caseDetails/ShareJourneyBottomSheet.tsx b/src/screens/caseDetails/ShareJourneyBottomSheet.tsx index 864cee15..52e59802 100644 --- a/src/screens/caseDetails/ShareJourneyBottomSheet.tsx +++ b/src/screens/caseDetails/ShareJourneyBottomSheet.tsx @@ -18,6 +18,7 @@ import { ITelephoneNumbers } from '@reducers/telephoneNumbersSlice'; import { getBorderBottomColor, getShareMessage } from './utils/documentUtils'; import { toast } from '@rn-ui-lib/components/toast'; import { ToastMessages } from '@screens/allCases/constants'; +import { shareDynamicallyGeneratedDoc } from '@components/utlis/commonFunctions'; interface IShareJourneyBottomSheet { loanAccountNumber: string; @@ -56,6 +57,7 @@ export const ShareJourneyBottomSheet = ({ multiLingual = false, shareablePersonalAccount = false, languagesAvailable = [], + dynamicallyGenerated = false, } = document || {}; const resetBottomSheet = () => { @@ -68,21 +70,13 @@ export const ShareJourneyBottomSheet = ({ documentKey: string, language: string ) => { - await fetchMultiLingualDocument(documentKey, language).then((res) => { - const doc = res; - if(doc){ + fetchMultiLingualDocument(documentKey, language).then((res) => { + if(res){ navigateToScreen('pdfFull', { - pdfUri: doc?.uri, - referenceId: doc?.referenceId, - cacheFileKey: doc?.referenceId + caseId, - unSignedUri: doc?.unSignedUri, caseId, loanAccountNumber, - screenName: `${doc?.type} PDF viewer`, - document: doc, + document: res, showShareBottomsheet: true, - handleDownloadPDF: handleDownloadPDF, - phoneNumberOptions: phoneNumberOptions, }); } else { toast({ @@ -111,6 +105,11 @@ export const ShareJourneyBottomSheet = ({ }) setShareVia(option); if (option === ShareVia.PERSONAL_ACCOUNT) { + if(dynamicallyGenerated) { + shareDynamicallyGeneratedDoc(loanAccountNumber, caseId, documentKey); + resetBottomSheet(); + return; + } handleSharePDF(document, option); resetBottomSheet(); } @@ -121,6 +120,7 @@ export const ShareJourneyBottomSheet = ({ lan: loanAccountNumber, agentId: agentId, language: phoneNumberRefId, + document: documentKey, }) handleSharePDF(document, ShareVia.NAVI_ACCOUNT, phoneNumberRefId); resetBottomSheet(); @@ -166,7 +166,7 @@ export const ShareJourneyBottomSheet = ({ ]} > - {getShareMessage(isLanguageNotSelectedForMultilingualDocument, !shareVia)} + {getShareMessage(isLanguageNotSelectedForMultilingualDocument, !shareVia, documentName)} { @@ -229,7 +229,7 @@ export const ShareJourneyBottomSheet = ({ })} ) : ( - + {phoneNumberOptions?.map((option, index) => { const borderBottomColor = getBorderBottomColor(index, phoneNumberOptions.length); return ( diff --git a/src/screens/caseDetails/interface.ts b/src/screens/caseDetails/interface.ts index fb679dc2..e64d1129 100644 --- a/src/screens/caseDetails/interface.ts +++ b/src/screens/caseDetails/interface.ts @@ -425,6 +425,7 @@ export interface IDocumentItem { shareablePersonalAccount: boolean; multiLingual: boolean; languagesAvailable: string[]; + dynamicallyGenerated: boolean; } export interface IDocumentTabItem { diff --git a/src/screens/caseDetails/utils/VKYCVideo.tsx b/src/screens/caseDetails/utils/VKYCVideo.tsx index 2b8855cd..db9fdf74 100644 --- a/src/screens/caseDetails/utils/VKYCVideo.tsx +++ b/src/screens/caseDetails/utils/VKYCVideo.tsx @@ -7,8 +7,6 @@ const VKYCVideo = ({ document, caseId, caseType }: any) => { const { uri, unsignedUri, documentRefId } = document; const [videoUrl, setVideoUrl] = useState(uri); - useS3UrlCheck(uri, documentRefId, caseId, caseType, unsignedUri, setVideoUrl); - return ( { +export const getShareMessage = (isLanguageNotSelectedForMultilingualDocument: boolean, shareVia: boolean, documentName: string) => { if (isLanguageNotSelectedForMultilingualDocument) { return 'Select language for sharing'; } - if (!shareVia) { - return 'Share via'; + if (shareVia) { + return `Share ${documentName} via`; } - return 'Share document on'; + return `Share ${documentName} on`; }; export const getBorderBottomColor = (index: number, length: number) => { diff --git a/src/services/clickstreamEventService.ts b/src/services/clickstreamEventService.ts index 1b4b97d8..a3a39d70 100644 --- a/src/services/clickstreamEventService.ts +++ b/src/services/clickstreamEventService.ts @@ -101,12 +101,15 @@ export const addClickstreamEvent = async ( const getPayload = async (events: IClickstreamEvent[]) => { const { agentId, deviceId } = events[events.length - 1]; return { - app: { name: APP_NAME }, + app: { name: APP_NAME, version: getAppVersion() }, events, metadata: { agentId: agentId || (await getItem('agentId')), deviceId: deviceId || (await getItem('deviceId')), }, + device: { + device_id: deviceId || (await getItem('deviceId')), + }, client_ts: new Date().getTime(), source: APP_NAME, user: { @@ -163,7 +166,7 @@ export const sendApiToClickstreamEvent = ( const url = response?.config?.url; const statusCode = response?.status; if (url) { - const apiKey = getKeyByValue(url, API_URLS); + const apiKey = getKeyByValue(url, API_URLS); if (apiKey && DISABLE_API_EVENTS_URL.indexOf(apiKey) === -1) { const eventName = getEventNameFromAPIKey(apiKey, isSuccess); addClickstreamEvent(