TP-38645 | Show Documents On Customer Profile Screen

This commit is contained in:
yashmantri
2023-09-13 14:13:20 +05:30
parent bb73aef672
commit 330eb8e1d3
16 changed files with 652 additions and 146 deletions

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import {
AppState,
LogBox,
@@ -38,6 +38,7 @@ import {
import usePolling from './src/hooks/usePolling';
import { MILLISECONDS_IN_A_SECOND } from './RN-UI-LIB/src/utlis/common';
import analytics from '@react-native-firebase/analytics';
import ScreenshotBlocker from './src/components/utlis/ScreenshotBlocker';
initSentry();
@@ -112,6 +113,10 @@ function App() {
active: true,
});
useEffect(() => {
ScreenshotBlocker.unblockScreenshots();
}, []);
React.useEffect(() => {
askForPermissions();
const appStateChange = AppState.addEventListener('change', async (change) => {

View File

@@ -135,6 +135,12 @@ def VERSION_CODE = 83
def VERSION_NAME = "2.3.10"
android {
packagingOptions {
pickFirst 'lib/x86/libc++_shared.so'
pickFirst 'lib/x86_64/libc++_shared.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
}
ndkVersion rootProject.ext.ndkVersion
compileSdkVersion rootProject.ext.compileSdkVersion
@@ -217,10 +223,18 @@ android {
}
signingConfigs {
debug {
if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
storeFile file(MYAPP_UPLOAD_STORE_FILE)
storePassword MYAPP_UPLOAD_STORE_PASSWORD
keyAlias MYAPP_UPLOAD_KEY_ALIAS
keyPassword MYAPP_UPLOAD_KEY_PASSWORD
}
else {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
release {
if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {

View File

@@ -37,6 +37,7 @@ public class MainApplication extends Application implements ReactApplication {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
packages.add(new DeviceUtilsModulePackage());
packages.add(new ScreenshotBlockerModulePackage());
return packages;
}

View File

@@ -0,0 +1,59 @@
package com.avapp;
import android.app.Activity;
import android.view.WindowManager;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import android.os.Handler;
import android.os.Looper;
public class ScreenshotBlockerModule extends ReactContextBaseJavaModule {
private ReactApplicationContext reactContext;
public ScreenshotBlockerModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}
@Override
public String getName() {
return "ScreenshotBlocker";
}
@ReactMethod
public void blockScreenshots() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
Activity activity = getCurrentActivity();
@Override
public void run() {
if (activity != null) {
activity.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
);
}
}
});
}
@ReactMethod
public void unblockScreenshots() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
Activity activity = getCurrentActivity();
@Override
public void run() {
if (activity != null) {
activity.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_SECURE
);
}
}
});
}
}

View File

@@ -0,0 +1,28 @@
package com.avapp;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ScreenshotBlockerModulePackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new ScreenshotBlockerModule(reactContext));
return modules;
}
}

View File

@@ -67,6 +67,7 @@
"react-native-gzip": "1.0.0",
"react-native-image-picker": "4.10.2",
"react-native-pager-view": "6.1.2",
"react-native-pdf": "^6.7.1",
"react-native-permissions": "3.6.1",
"react-native-qrcode-svg": "^6.2.0",
"react-native-safe-area-context": "4.4.1",

View File

@@ -0,0 +1,5 @@
import { NativeModules } from 'react-native';
const { ScreenshotBlocker } = NativeModules;
export default ScreenshotBlocker;

View File

@@ -32,6 +32,7 @@ import Notifications from '../notifications';
import RegisterPayments from '../registerPayements/RegisterPayments';
import TodoList from '../todoList/TodoList';
import UngroupedAddressContainer from '../addressGeolocation/UngroupedAddressContainer';
import PDFFullScreen from '../caseDetails/PDFFullScreen';
const Stack = createNativeStackNavigator();
@@ -170,6 +171,16 @@ const ProtectedRouter = () => {
}}
listeners={getScreenFocusListenerObj}
/>
<Stack.Screen
name={'pdfFull'}
component={PDFFullScreen}
options={{
header: () => null,
animationDuration: SCREEN_ANIMATION_DURATION,
animation: 'none',
}}
listeners={getScreenFocusListenerObj}
/>
<Stack.Screen
name={PageRouteEnum.PAYMENTS}
component={RegisterPayments}

View File

@@ -41,6 +41,8 @@ import { addClickstreamEvent } from '../../services/clickstreamEventService';
import { getLoanAccountNumber } from '../../components/utlis/commonFunctions';
import EmiBreakupBottomSheet from '../emiSchedule/EmiBreakupBottomSheet';
import { CollectionCaseWidgetId } from '../../types/template.types';
import { useFocusEffect } from '@react-navigation/native';
import ScreenshotBlocker from '../../components/utlis/ScreenshotBlocker';
interface ICaseDetails {
route: {
@@ -221,6 +223,10 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
});
};
useFocusEffect(() => {
ScreenshotBlocker.unblockScreenshots();
});
return (
<Layout>
<SafeAreaView style={[GenericStyles.fill, GenericStyles.whiteBackground]}>

View File

@@ -1,25 +1,25 @@
import { ActivityIndicator, Pressable, ScrollView, StyleSheet, View } from 'react-native';
import { ScrollView, StyleSheet, View } from 'react-native';
import React, { useEffect, useState } from 'react';
import { SafeAreaView } from 'react-native-safe-area-context';
import { GenericStyles, SCREEN_WIDTH } from '../../../RN-UI-LIB/src/styles';
import { COLORS } from '../../../RN-UI-LIB/src/styles/colors';
import RNFastImage from '../../../RN-UI-LIB/src/components/FastImage';
import NavigationHeader, { Icon } from '../../../RN-UI-LIB/src/components/NavigationHeader';
import { CaseDetail, DOCUMENT_TYPE, IDocument } from './interface';
import { CaseDetail, DocumentDetail, DOCUMENT_TYPE, IDocument } from './interface';
import useIsOnline from '../../hooks/useIsOnline';
import useFetchDocument from '../../hooks/useFetchDocument';
import {
RELATIVE_PATH_PREFIX,
checkS3Url,
findDocumentByDocumentType,
getDocumentList,
} from '../../components/utlis/commonFunctions';
import { goBack, navigateToScreen } from '../../components/utlis/navigationUtlis';
import Text from '../../../RN-UI-LIB/src/components/Text';
import { ISignedRequest, getSignedApi } from '../../action/dataActions';
import { useTimeout } from 'react-native-toast-message/lib/src/hooks';
import { DELAY_FOR_PAINTING_IMAGE } from '../../common/Constants';
import { isNullOrEmptyString } from '../../../RN-UI-LIB/src/utlis/common';
import { goBack } from '../../components/utlis/navigationUtlis';
import SuspenseLoader from '../../../RN-UI-LIB/src/components/suspense_loader/SuspenseLoader';
import LineLoader from '../../../RN-UI-LIB/src/components/suspense_loader/LineLoader';
import ScreenshotBlocker from '../../components/utlis/ScreenshotBlocker';
import { useFocusEffect } from '@react-navigation/native';
import DocumentImageComponent from './DocumentImageComponent';
import DocumentDetails from './DocumentDetails';
import { getDocumentDetails } from './utils/documentUtils';
interface ICustomerProfile {
route: {
@@ -35,12 +35,9 @@ const CustomerProfile: React.FC<ICustomerProfile> = (props) => {
params: { caseDetail },
},
} = props;
const [errorModalImage, setErrorModalImage] = useState<boolean>(false);
const [loading, setLoading] = useState(true);
const { startTimer, isActive, clearTimer } = useTimeout(() => {
setLoading(false);
}, DELAY_FOR_PAINTING_IMAGE);
const isOnline = useIsOnline();
const [isDocumentsLoading, setIsDocumentsLoading] = useState(false);
const { documentObj, setRetryForUnsignedDocuments } = useFetchDocument(
{
caseId: caseDetail?.id,
@@ -51,45 +48,7 @@ const CustomerProfile: React.FC<ICustomerProfile> = (props) => {
false,
false
);
const [vkycUri, setVkycUri] = useState<string>();
const [showVkyc, setShowVkyc] = useState<boolean>(false);
const updateVkycVideo = (uri: string) => {
setVkycUri(uri);
};
useEffect(() => {
if (caseDetail) {
const docList: IDocument[] = getDocumentList(caseDetail) || [];
const vkycDoc = findDocumentByDocumentType(docList, DOCUMENT_TYPE.VKYC_VIDEO);
if (!vkycDoc?.referenceId) {
return;
}
setShowVkyc(true);
const vkycUri = vkycDoc?.uri;
async function checkUrl(url: string) {
const result = await checkS3Url(url);
if (result) {
setVkycUri(url);
} else {
const imageReferenceId = vkycDoc?.referenceId!!;
const signedRequestPayload: ISignedRequest = [
{
documentReferenceId: imageReferenceId,
caseId: caseDetail.id,
caseType: caseDetail.caseType,
},
];
const response = await getSignedApi(signedRequestPayload);
const url = response?.imageUrl || '';
setVkycUri(url);
}
}
if (vkycUri) {
checkUrl(vkycUri);
}
}
}, [caseDetail]);
const [documentData, setDocumentData] = useState<Array<DocumentDetail>>([]);
const getImageURI = () => {
if (!isOnline) {
@@ -106,72 +65,75 @@ const CustomerProfile: React.FC<ICustomerProfile> = (props) => {
);
};
const handleVkycPress = () => {
navigateToScreen('vkycFull', {
vkycUri,
});
};
useEffect(() => {
if (caseDetail) {
const docList: IDocument[] = getDocumentList(caseDetail) || [];
const docPromises: Promise<DocumentDetail | null>[] = [];
// TODO: Add Driver License Enum
const updatedDocList = [
DOCUMENT_TYPE.VKYC_VIDEO,
DOCUMENT_TYPE.AADHAR,
DOCUMENT_TYPE.PAN,
DOCUMENT_TYPE.AADHAR_PHOTO,
];
updatedDocList.forEach((documentType) => {
const document = findDocumentByDocumentType(docList, documentType);
if (document) {
const docPromise = getDocumentDetails(document, caseDetail.id, caseDetail.caseType);
if (docPromise) docPromises.push(docPromise);
}
});
const onLoadStart = () => {
setLoading(true);
setErrorModalImage(false);
};
const onLoadEnd = () => {
// added this to show loader for the image is getting painted on screen
startTimer();
};
setIsDocumentsLoading(true);
Promise.all(docPromises)
.then((docs: Array<DocumentDetail | null>) => {
const documents = docs?.filter(
(document: DocumentDetail | null) => document
) as Array<DocumentDetail>;
setDocumentData(documents);
setIsDocumentsLoading(false);
})
.catch(() => {
setIsDocumentsLoading(false);
});
}
}, [caseDetail]);
const onLoad = () => {
clearTimer();
setLoading(false);
setErrorModalImage(false);
};
useFocusEffect(() => {
ScreenshotBlocker.blockScreenshots();
});
const imageUri = getImageURI();
return (
<SafeAreaView style={[GenericStyles.fill, styles.container, GenericStyles.whiteBackground]}>
<NavigationHeader title="Customer profile" onBack={() => goBack()} icon={Icon.close} />
<ScrollView>
<View style={GenericStyles.centerAlignedRow}>
<View style={styles.imageContainer}>
<RNFastImage
style={styles.imageStyle}
source={{ uri: imageUri }}
resizeMode="contain"
onError={() => {
setRetryForUnsignedDocuments([DOCUMENT_TYPE.SELFIE]);
setErrorModalImage(true);
}}
onLoadStart={onLoadStart}
onLoad={onLoad}
onLoadEnd={onLoadEnd}
<DocumentImageComponent
docType={DOCUMENT_TYPE.SELFIE}
url={imageUri}
setRetryForUnsignedDocuments={setRetryForUnsignedDocuments}
/>
{loading ? (
<Text style={[styles.loadingText]} bold>
{!isNullOrEmptyString(imageUri) ? 'Loading Image...' : 'No Image Found'}
</Text>
) : errorModalImage ? (
<Text style={[styles.errorText]} bold>
Error loading image
</Text>
) : null}
</View>
</View>
{showVkyc ? (
<View style={styles.vkyc}>
<Text bold dark>
VKYC video
</Text>
{vkycUri ? (
<Pressable onPress={handleVkycPress}>
<Text style={styles.openVideoTxt}>Open video</Text>
</Pressable>
) : (
<ActivityIndicator color={COLORS.BASE.BLUE} />
)}
</View>
) : null}
{/* <Accordion title="VKYC Video" content={<VKYCVideo />} /> */}
<SuspenseLoader
loading={isDocumentsLoading}
fallBack={
<View style={GenericStyles.ph16}>
{[...Array(4).keys()].map(() => (
<LineLoader
width="100%"
height={50}
style={[GenericStyles.br6, GenericStyles.mb20]}
/>
))}
</View>
}
>
<DocumentDetails documentData={documentData} />
</SuspenseLoader>
</ScrollView>
</SafeAreaView>
);
@@ -190,37 +152,7 @@ const styles = StyleSheet.create({
borderWidth: 1,
borderColor: COLORS.BORDER.GREY,
},
imageStyle: {
height: '100%',
},
container: {
position: 'relative',
},
errorText: {
position: 'absolute',
top: '50%',
textAlign: 'center',
width: '100%',
color: COLORS.TEXT.RED,
},
loadingText: {
position: 'absolute',
top: '50%',
textAlign: 'center',
width: '100%',
},
vkyc: {
marginHorizontal: 16,
paddingHorizontal: 12,
paddingVertical: 18,
borderRadius: 4,
borderWidth: 1,
borderColor: COLORS.BORDER.GREY,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
openVideoTxt: {
color: COLORS.TEXT.BLUE,
},
});

View File

@@ -0,0 +1,131 @@
import React, { useState } from 'react';
import { Pressable, StyleSheet, View } from 'react-native';
import WebView from 'react-native-webview';
import Accordion from '../../../RN-UI-LIB/src/components/accordian/Accordian';
import Text from '../../../RN-UI-LIB/src/components/Text';
import ArrowSolidDownIcon from '../../../RN-UI-LIB/src/Icons/ArrowSolidDownIcon';
import { GenericStyles, getShadowStyle } from '../../../RN-UI-LIB/src/styles';
import { COLORS } from '../../../RN-UI-LIB/src/styles/colors';
import { navigateToScreen } from '../../components/utlis/navigationUtlis';
import DocumentImageComponent from './DocumentImageComponent';
import { DocumentDetail } from './interface';
import { vkycHtml } from './vkycTemplate';
interface DocumentDetails {
documentData: Array<DocumentDetail>;
}
const DocumentDetails = (props: DocumentDetails) => {
const { documentData } = props;
const [isExpanded, setIsExpanded] = useState<boolean>(false);
const handleOpenPdfPress = (url: string) => {
// TODO: Dynamic Url
navigateToScreen('pdfFull', {
pdfUri: 'https://www.africau.edu/images/default/sample.pdf',
});
};
return (
<View style={GenericStyles.ph16}>
{documentData.map((item: any) =>
item.docContentType !== 'pdf' ? (
<Accordion
accordionStyle={styles.accordionStyles}
isActive={isExpanded}
touchableDelay={50}
touchableOpacity={0.8}
accordionHeader={
<View style={styles.headerWrapper}>
{item?.icon}
<Text style={GenericStyles.pl6}>{item?.title}</Text>
</View>
}
customExpandUi={{
whenCollapsed: (
<View style={styles.accordionExpandBtn}>
<ArrowSolidDownIcon />
</View>
),
whenExpanded: (
<View style={[styles.accordionExpandBtn, styles.rotateBtn]}>
<ArrowSolidDownIcon />
</View>
),
}}
onExpanded={(value) => {
setIsExpanded(value);
}}
>
<View style={styles.accordionContentWrapper}>
{item.docContentType === 'video' ? (
<WebView
source={{ html: vkycHtml(item.url) }}
style={{ flex: 1 }}
allowsFullscreenVideo={true}
mediaPlaybackRequiresUserAction={false}
/>
) : (
<DocumentImageComponent docType={item.docType} url={item.url} />
)}
</View>
</Accordion>
) : (
<View
style={[
styles.accordionStyles,
GenericStyles.row,
GenericStyles.justifyContentSpaceBetween,
{ marginBottom: 12, backgroundColor: COLORS.TEXT.WHITE, paddingHorizontal: 16 },
]}
>
<View style={[styles.headerWrapper, { paddingHorizontal: 0 }]}>
{item?.icon}
<Text style={GenericStyles.pl6}>{item?.title}</Text>
</View>
<Pressable onPress={() => handleOpenPdfPress(item.url)}>
<Text style={styles.openPdfTxt}>Open PDF</Text>
</Pressable>
</View>
)
)}
</View>
);
};
const styles = StyleSheet.create({
openPdfTxt: {
color: COLORS.TEXT.BLUE,
},
accordionExpandBtn: {
fontSize: 13,
marginTop: 8,
fontWeight: '500',
lineHeight: 20,
color: COLORS.TEXT.BLUE,
paddingRight: 16,
},
accordionContentWrapper: {
backgroundColor: '#F7F7F7',
borderBottomLeftRadius: 8,
borderBottomRightRadius: 8,
height: 250,
padding: 16,
},
rotateBtn: { transform: [{ rotateX: '180deg' }], marginTop: 0 },
headerWrapper: {
...GenericStyles.alignCenter,
...GenericStyles.row,
...GenericStyles.ph16,
...GenericStyles.mb12,
},
accordionStyles: {
...GenericStyles.pt12,
...GenericStyles.br8,
...getShadowStyle(4),
paddingHorizontal: 0,
marginBottom: 16,
},
});
export default DocumentDetails;

View File

@@ -0,0 +1,116 @@
import React, { useState } from 'react';
import { StyleSheet } from 'react-native';
import { useTimeout } from 'react-native-toast-message/lib/src/hooks';
import RNFastImage from '../../../RN-UI-LIB/src/components/FastImage';
import Text from '../../../RN-UI-LIB/src/components/Text';
import { GenericStyles } from '../../../RN-UI-LIB/src/styles';
import { COLORS } from '../../../RN-UI-LIB/src/styles/colors';
import { isNullOrEmptyString } from '../../../RN-UI-LIB/src/utlis/common';
import { DELAY_FOR_PAINTING_IMAGE } from '../../common/Constants';
import { DOCUMENT_TYPE } from './interface';
interface DocumentImageComponentProps {
docType: DOCUMENT_TYPE;
url: string;
setRetryForUnsignedDocuments?: React.Dispatch<React.SetStateAction<DOCUMENT_TYPE[]>>;
}
const DocumentImageComponent = (props: DocumentImageComponentProps) => {
const { docType, url, setRetryForUnsignedDocuments } = props;
const [errorModalImage, setErrorModalImage] = useState({
[DOCUMENT_TYPE.SELFIE]: false,
[DOCUMENT_TYPE.AADHAR]: false,
[DOCUMENT_TYPE.PAN]: false,
});
const [loading, setLoading] = useState({
[DOCUMENT_TYPE.SELFIE]: true,
[DOCUMENT_TYPE.AADHAR]: true,
[DOCUMENT_TYPE.PAN]: true,
});
const { startTimer, isActive, clearTimer } = useTimeout(() => {
setLoading({
[DOCUMENT_TYPE.SELFIE]: false,
[DOCUMENT_TYPE.AADHAR]: false,
[DOCUMENT_TYPE.PAN]: false,
});
}, DELAY_FOR_PAINTING_IMAGE);
const onLoadStart = (docType: DOCUMENT_TYPE) => {
setLoading({
...loading,
[docType]: true,
});
setErrorModalImage({
...errorModalImage,
[docType]: false,
});
};
const onLoadEnd = () => {
// added this to show loader for the image is getting painted on screen
startTimer();
};
const onLoad = (docType: DOCUMENT_TYPE) => {
clearTimer();
setLoading({
...loading,
[docType]: false,
});
setErrorModalImage({
...errorModalImage,
[docType]: false,
});
};
return (
<>
<RNFastImage
style={styles.imageStyle}
source={{ uri: url }}
resizeMode="contain"
onError={() => {
setRetryForUnsignedDocuments?.([docType]);
setErrorModalImage({
...errorModalImage,
[docType]: true,
});
}}
onLoadStart={() => onLoadStart(docType)}
onLoad={() => onLoad(docType)}
onLoadEnd={onLoadEnd}
/>
{loading[docType] ? (
<Text style={[styles.loadingText]} bold>
{!isNullOrEmptyString(url) ? 'Loading Image...' : 'No Image Found'}
</Text>
) : errorModalImage[docType] ? (
<Text style={[styles.errorText]} bold>
Error loading image
</Text>
) : null}
</>
);
};
const styles = StyleSheet.create({
imageStyle: {
height: '100%',
},
errorText: {
...GenericStyles.absolute,
top: '50%',
textAlign: 'center',
width: '100%',
color: COLORS.TEXT.RED,
},
loadingText: {
...GenericStyles.absolute,
top: '50%',
textAlign: 'center',
width: '100%',
},
});
export default DocumentImageComponent;

View File

@@ -0,0 +1,74 @@
import { Dimensions, StyleSheet, View } from 'react-native';
import React, { useState } from 'react';
import { GenericStyles } from '../../../RN-UI-LIB/src/styles';
import NavigationHeader, { Icon } from '../../../RN-UI-LIB/src/components/NavigationHeader';
import { goBack } from '../../components/utlis/navigationUtlis';
import Pdf from 'react-native-pdf';
import Text from '../../../RN-UI-LIB/src/components/Text';
import { COLORS } from '../../../RN-UI-LIB/src/styles/colors';
interface ICustomerProfile {
route: {
params: {
pdfUri: string;
};
};
}
const PDFFullScreen: React.FC<ICustomerProfile> = (props) => {
const {
route: {
params: { pdfUri },
},
} = props;
const [error, setError] = useState(false);
return (
<View style={GenericStyles.fill}>
<NavigationHeader onBack={goBack} title="Aadhar PDF viewer" icon={Icon.close} />
<View style={styles.container}>
<Pdf
trustAllCerts={false}
source={{ uri: pdfUri }}
renderActivityIndicator={() => {
return !error ? (
<Text>Loading...</Text>
) : (
<Text style={[styles.errorText]} bold>
Error loading pdf
</Text>
);
}}
onError={() => {
setError(true);
}}
style={styles.pdf}
/>
</View>
</View>
);
};
export default PDFFullScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
margin: 12,
},
pdf: {
flex: 1,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
errorText: {
...GenericStyles.absolute,
top: '50%',
textAlign: 'center',
width: '100%',
color: COLORS.TEXT.RED,
},
});

View File

@@ -139,6 +139,9 @@ export enum DOCUMENT_TYPE {
SELFIE = 'SELFIE',
OPTIMIZED_SELFIE = 'OPTIMIZED_SELFIE',
VKYC_VIDEO = 'VKYC_VIDEO',
PAN = 'PAN',
AADHAR = 'AADHAR',
AADHAR_PHOTO = 'aadhar_photo',
}
export type TDocumentObj = {
@@ -151,6 +154,14 @@ export interface IDocument {
type: DOCUMENT_TYPE;
}
export interface DocumentDetail {
icon: React.ReactNode;
title: string;
docType: DOCUMENT_TYPE;
docContentType: string;
url: string;
}
export enum FeedbackStatus {
ATTEMPTED = 'ATTEMPTED',
NOT_ATTEMPTED = 'NOT_ATTEMPTED',

View File

@@ -0,0 +1,90 @@
import ImageIcon from '../../../../RN-UI-LIB/src/Icons/ImageIcon';
import PdfIcon from '../../../../RN-UI-LIB/src/Icons/PdfIcon';
import VideoIcon from '../../../../RN-UI-LIB/src/Icons/VideoIcon';
import { getSignedApi, ISignedRequest } from '../../../action/dataActions';
import { checkS3Url } from '../../../components/utlis/commonFunctions';
import { CaseAllocationType } from '../../allCases/interface';
import { DOCUMENT_TYPE, IDocument } from '../interface';
async function checkUrlData(
url: string,
referenceId: string,
caseId: string,
caseType: CaseAllocationType
) {
const result = await checkS3Url(url);
if (result) {
return url;
} else {
const signedRequestPayload: ISignedRequest = [
{
documentReferenceId: referenceId!!,
caseId: caseId,
caseType: caseType,
},
];
const response = await getSignedApi(signedRequestPayload);
const url = response?.imageUrl || '';
return url;
}
}
export const getDocumentDetails = async (
document: IDocument,
caseId: string,
caseType: CaseAllocationType
) => {
if (!document.referenceId) {
return null;
}
if (document?.uri) {
try {
const imageUrl = await checkUrlData(document.uri, document.referenceId, caseId, caseType);
if (!imageUrl) return null;
// TODO: Make Dynamic Based on Content type from firestore and add DL Case
switch (document.type) {
case DOCUMENT_TYPE.VKYC_VIDEO:
return {
icon: <VideoIcon />,
title: 'VKYC video',
docType: DOCUMENT_TYPE.VKYC_VIDEO,
docContentType: 'video',
url: imageUrl,
};
case DOCUMENT_TYPE.PAN:
return {
icon: <ImageIcon />,
title: 'Pan details',
docType: DOCUMENT_TYPE.PAN,
docContentType: 'image',
url: imageUrl,
};
case DOCUMENT_TYPE.AADHAR:
return {
icon: <PdfIcon />,
title: 'Aadhar details',
docType: DOCUMENT_TYPE.AADHAR,
docContentType: 'pdf',
url: imageUrl,
};
case DOCUMENT_TYPE.AADHAR_PHOTO:
return {
icon: <ImageIcon />,
title: 'Aadhar photo',
docType: DOCUMENT_TYPE.AADHAR_PHOTO,
docContentType: 'image',
url: imageUrl,
};
default:
break;
}
} catch (error) {
return null;
}
}
return null;
};

View File

@@ -1658,16 +1658,16 @@
resolved "https://registry.yarnpkg.com/@react-native/assets/-/assets-1.0.0.tgz#c6f9bf63d274bafc8e970628de24986b30a55c8e"
integrity sha512-KrwSpS1tKI70wuKl68DwJZYEvXktDHdZMG0k2AXD/rJVSlB23/X2CB2cutVR0HwNMJIal9HOUOBB2rVfa6UGtQ==
"@react-native/normalize-color@*", "@react-native/normalize-color@^2.0.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-2.1.0.tgz#939b87a9849e81687d3640c5efa2a486ac266f91"
integrity sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA==
"@react-native/normalize-color@2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-2.0.0.tgz#da955909432474a9a0fe1cbffc66576a0447f567"
integrity sha512-Wip/xsc5lw8vsBlmY2MO/gFLp3MvuZ2baBZjDeTjjndMgM0h5sxz7AZR62RDPGgstp8Np7JzjvVqVT7tpFZqsw==
"@react-native/normalize-color@^2.0.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-2.1.0.tgz#939b87a9849e81687d3640c5efa2a486ac266f91"
integrity sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA==
"@react-native/polyfills@2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@react-native/polyfills/-/polyfills-2.0.0.tgz#4c40b74655c83982c8cf47530ee7dc13d957b6aa"
@@ -3339,6 +3339,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
shebang-command "^2.0.0"
which "^2.0.1"
crypto-js@^3.2.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.3.0.tgz#846dd1cce2f68aacfa156c8578f926a609b7976b"
integrity sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==
css-select@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6"
@@ -3404,7 +3409,7 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
dayjs@^1.11.9:
dayjs@1.11.9:
version "1.11.9"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.9.tgz#9ca491933fadd0a60a2c19f6c237c03517d71d1a"
integrity sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==
@@ -3551,6 +3556,15 @@ depd@2.0.0:
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
deprecated-react-native-prop-types@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-2.3.0.tgz#c10c6ee75ff2b6de94bb127f142b814e6e08d9ab"
integrity sha512-pWD0voFtNYxrVqvBMYf5gq3NA2GCpfodS1yNynTPc93AYA/KEMGeWDqqeUB6R2Z9ZofVhks2aeJXiuQqKNpesA==
dependencies:
"@react-native/normalize-color" "*"
invariant "*"
prop-types "*"
destroy@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
@@ -5045,7 +5059,7 @@ internal-slot@^1.0.3:
has "^1.0.3"
side-channel "^1.0.4"
invariant@2.2.4, invariant@^2.2.2, invariant@^2.2.4:
invariant@*, invariant@2.2.4, invariant@^2.2.2, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
@@ -7528,7 +7542,7 @@ prompts@^2.0.1, prompts@^2.4.0:
kleur "^3.0.3"
sisteransi "^1.0.5"
prop-types@15.8.1, prop-types@^15.7.2, prop-types@^15.8.0, prop-types@^15.8.1:
prop-types@*, prop-types@15.8.1, prop-types@^15.7.2, prop-types@^15.8.0, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@@ -7762,6 +7776,14 @@ react-native-pager-view@6.1.2:
resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.1.2.tgz#3522079b9a9d6634ca5e8d153bc0b4d660254552"
integrity sha512-qs2KSFc+7N7B+UZ6SG2sTvCkppagm5fVyRclv1KFKc7lDtrhXLzN59tXJw575LDP/dRJoXsNwqUAhZJdws6ABQ==
react-native-pdf@^6.7.1:
version "6.7.1"
resolved "https://registry.yarnpkg.com/react-native-pdf/-/react-native-pdf-6.7.1.tgz#198b8ec3e8f1025ceb43ddfc6bc5b422521c4411"
integrity sha512-zszQygtNBYoUfEtP/fV7zhzGeohDlUksh2p3OzshLrxdY9mw7Tm5VXAxYq4d8HsomRJUbFlJ7rHaTU9AQL800g==
dependencies:
crypto-js "^3.2.0"
deprecated-react-native-prop-types "^2.3.0"
react-native-permissions@3.6.1:
version "3.6.1"
resolved "https://registry.yarnpkg.com/react-native-permissions/-/react-native-permissions-3.6.1.tgz#73adcc1cef8cd57a9ef167b4507405f4ff5749c4"