From 2252b39e76212263ead41b2eb56da26fe4191262 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Wed, 20 Sep 2023 14:00:08 +0530 Subject: [PATCH 01/26] Inserted share button in ui AT ALL FEEDBACKS --- RN-UI-LIB | 2 +- android/app/google-services.json | 73 ++++++++++--------- .../icons/WhatsAppFeedbackShareIcon.tsx | 11 +++ .../feedback/FeedbackDetailItem.tsx | 47 +++++++++--- 4 files changed, 84 insertions(+), 49 deletions(-) create mode 100644 src/assets/icons/WhatsAppFeedbackShareIcon.tsx diff --git a/RN-UI-LIB b/RN-UI-LIB index 4c7f4f68..5b77f75c 160000 --- a/RN-UI-LIB +++ b/RN-UI-LIB @@ -1 +1 @@ -Subproject commit 4c7f4f6880d96bffa856e04d7b2b4d383e42c5cf +Subproject commit 5b77f75cb69fc7c8ed7d8a3acc84be1eb6564c64 diff --git a/android/app/google-services.json b/android/app/google-services.json index 9d2a90ba..1df006c6 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -1,39 +1,40 @@ { - "project_info": { - "project_number": "60755663443", - "project_id": "address-verification-app", - "storage_bucket": "address-verification-app.appspot.com" - }, - "client": [ - { - "client_info": { - "mobilesdk_app_id": "1:60755663443:android:988149d3da3c00d38584a6", - "android_client_info": { - "package_name": "com.avapp" - } - }, - "oauth_client": [ - { - "client_id": "60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyA70_d2M2ke-Mu0OHGZ6iZilBbD6A-_z0c" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com", - "client_type": 3 - } - ] - } + "project_info": { + "project_number": "60755663443", + "project_id": "address-verification-app", + "storage_bucket": "address-verification-app.appspot.com", + "firebase_url": "https://address-verification-app-default-rtdb.firebaseio.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:60755663443:android:4a948ee9d0b4e3098584a6", + "android_client_info": { + "package_name": "com.avapp" + } + }, + "oauth_client": [ + { + "client_id": "60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyA70_d2M2ke-Mu0OHGZ6iZilBbD6A-_z0c" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "60755663443-40k0fbrbbqv4ci4hrjlbrphab5fj387b.apps.googleusercontent.com", + "client_type": 3 + } + ] } } - ], - "configuration_version": "1" - } \ No newline at end of file + } + ], + "configuration_version": "1" +} diff --git a/src/assets/icons/WhatsAppFeedbackShareIcon.tsx b/src/assets/icons/WhatsAppFeedbackShareIcon.tsx new file mode 100644 index 00000000..10067e6f --- /dev/null +++ b/src/assets/icons/WhatsAppFeedbackShareIcon.tsx @@ -0,0 +1,11 @@ +import * as React from 'react'; +import Svg, { Path, SvgProps } from 'react-native-svg'; +const SvgComponent = (props: SvgProps) => ( + + + +); +export default SvgComponent; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index bcb5e69c..d21749bb 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -16,6 +16,8 @@ import { FEEDBACK_TYPE } from '../../../types/feedback.types'; import CallIcon from '../../../../RN-UI-LIB/src/Icons/CallIcon'; import { addClickstreamEvent } from '../../../services/clickstreamEventService'; import { CLICKSTREAM_EVENT_NAMES } from '../../../common/Constants'; +import IconLabel from '../../../common/IconLabel'; +import WhatsAppFeedbackShareIcon from '../../../assets/icons/WhatsAppIcon'; interface IFeedbackDetailItem { feedbackItem: IFeedback; @@ -93,19 +95,34 @@ const FeedbackDetailItem = ({ feedbackItem, isExpanded }: IFeedbackDetailItem) = {feedbackItem.metadata?.interactionLatitude && FIELD_FEEDBACKS.includes(feedbackItem.type) ? ( - - openGeolocation( - feedbackItem.metadata?.interactionLatitude, - feedbackItem.metadata?.interactionLongitude - ) - } - style={[GenericStyles.row, GenericStyles.pv12]} - > - Open map - + <> + + + openGeolocation( + feedbackItem.metadata?.interactionLatitude, + feedbackItem.metadata?.interactionLongitude + ) + } + style={[GenericStyles.row, GenericStyles.pv12]} + > + Open map + + + ) : null} + + + } + textStyle={{ color: COLORS.BASE.BLUE }} + /> + ); }; @@ -129,6 +146,12 @@ const styles = StyleSheet.create({ }, geolocationBtn: { color: COLORS.BASE.BLUE, + marginRight: 20, + }, + container: { + flexDirection: 'row', + alignItems: 'center', + marginTop: 20, }, }); From 35653c07f1154c88a7df0f61867fcdf3bfa5c0ce Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Wed, 20 Sep 2023 22:38:29 +0530 Subject: [PATCH 02/26] Added Share button and text template send to WhatsApp --- .../feedback/FeedbackDetailItem.tsx | 73 ++++++++++++++++--- 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index d21749bb..7d12e5eb 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -1,5 +1,5 @@ import React, { ReactNode } from 'react'; -import { View, StyleSheet, TouchableOpacity, Linking } from 'react-native'; +import { View, StyleSheet, TouchableOpacity, Linking, Share } from 'react-native'; 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'; @@ -19,6 +19,8 @@ import { CLICKSTREAM_EVENT_NAMES } from '../../../common/Constants'; import IconLabel from '../../../common/IconLabel'; import WhatsAppFeedbackShareIcon from '../../../assets/icons/WhatsAppIcon'; +const BUSINESS_DATE_FORMAT_WITH_TIME = 'YYYY-MM-DD HH:mm:ss'; + interface IFeedbackDetailItem { feedbackItem: IFeedback; isExpanded: boolean; @@ -49,6 +51,57 @@ const openGeolocation = (latitude: string, longitude: string) => { return Linking.openURL(geolocationUrl); }; +function getLocationLink(latitude: string, longitude: string): string { + const link = `https://www.google.com/maps?q=${encodeURIComponent(`${latitude},${longitude}`)}`; + return link; +} + +const sendToWhatsapp = (feedbackItem: IFeedback) => { + var message = ''; + message += 'Feedback Type: ' + sanitizeString(feedbackItem.type) + '\n\n'; + message += 'Disposition: ' + sanitizeString(feedbackItem.interactionStatus) + '\n\n'; + message += + 'Feedback Date and Time: ' + + sanitizeString(dateFormat(new Date(feedbackItem.createdAt), 'DD MMM YYYY, HH:mm A')) + + '\n\n'; + { + feedbackItem.metadata?.interactionLatitude && + feedbackItem.metadata?.interactionLongitude && + FIELD_FEEDBACKS.includes(feedbackItem.type) + ? (message += + 'Location: ' + + sanitizeString( + getLocationLink( + feedbackItem.metadata?.interactionLatitude, + feedbackItem.metadata?.interactionLongitude + ) + ) + + '\n\n') + : null; + } + const imageUrl = 'https://via.placeholder.com/150'; + message = encodeURIComponent(message); + const url = `whatsapp://send?text=${message}`; + // Linking.canOpenURL(url) + // .then(isInstalled => { + // if (!isInstalled) { + // console.log(message); + // console.log(url); + // console.error('WhatsApp is not installed on this device.'); + // } else { + // console.log(message); + // return Linking.openURL(url); + // } + // }) + // .catch(error => console.error('An error occurred', error)); + // Linking.openURL(url); + Share.share({ + title: 'Agent Feedback', + message, + url: imageUrl, + }); +}; + const FeedbackDetailItem = ({ feedbackItem, isExpanded }: IFeedbackDetailItem) => { return ( @@ -109,20 +162,16 @@ const FeedbackDetailItem = ({ feedbackItem, isExpanded }: IFeedbackDetailItem) = > Open map + sendToWhatsapp(feedbackItem)}> + } + textStyle={{ color: COLORS.BASE.BLUE }} + /> + ) : null} - - - } - textStyle={{ color: COLORS.BASE.BLUE }} - /> - ); }; From 49da019c5c01cfe899899b80b7253e0a1bd46f50 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Thu, 21 Sep 2023 13:03:59 +0530 Subject: [PATCH 03/26] Tried adding image send --- package.json | 3 +- .../feedback/FeedbackDetailItem.tsx | 76 +++++++++++++------ yarn.lock | 20 +++++ 3 files changed, 74 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index ccc82a6b..e92b0be2 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,8 @@ "react-native-webview": "12.0.2", "react-redux": "8.0.5", "redux": "4.2.0", - "redux-persist": "6.0.0" + "redux-persist": "6.0.0", + "rn-fetch-blob": "^0.12.0" }, "devDependencies": { "@babel/core": "7.12.9", diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index 7d12e5eb..e4bc7b27 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -9,7 +9,12 @@ import { dateFormat, } from '../../../../RN-UI-LIB/src/utlis/dates'; import { getGoogleMapUrl, sanitizeString } from '../../../components/utlis/commonFunctions'; -import { FIELD_FEEDBACKS, ICallingFeedback, IFeedback } from '../../../types/feedback.types'; +import { + FIELD_FEEDBACKS, + ICallingFeedback, + IFeedback, + OPTION_TAG, +} from '../../../types/feedback.types'; import { Address as IAddress } from '../interface'; import MapIcon from '../../../../RN-UI-LIB/src/Icons/MapIcon'; import { FEEDBACK_TYPE } from '../../../types/feedback.types'; @@ -18,8 +23,7 @@ import { addClickstreamEvent } from '../../../services/clickstreamEventService'; import { CLICKSTREAM_EVENT_NAMES } from '../../../common/Constants'; import IconLabel from '../../../common/IconLabel'; import WhatsAppFeedbackShareIcon from '../../../assets/icons/WhatsAppIcon'; - -const BUSINESS_DATE_FORMAT_WITH_TIME = 'YYYY-MM-DD HH:mm:ss'; +import RNFetchBlob from 'rn-fetch-blob'; interface IFeedbackDetailItem { feedbackItem: IFeedback; @@ -79,27 +83,51 @@ const sendToWhatsapp = (feedbackItem: IFeedback) => { '\n\n') : null; } - const imageUrl = 'https://via.placeholder.com/150'; - message = encodeURIComponent(message); - const url = `whatsapp://send?text=${message}`; - // Linking.canOpenURL(url) - // .then(isInstalled => { - // if (!isInstalled) { - // console.log(message); - // console.log(url); - // console.error('WhatsApp is not installed on this device.'); - // } else { - // console.log(message); - // return Linking.openURL(url); - // } - // }) - // .catch(error => console.error('An error occurred', error)); - // Linking.openURL(url); - Share.share({ - title: 'Agent Feedback', - message, - url: imageUrl, - }); + const imagesList = feedbackItem.answerViews.filter( + (answer) => answer.questionTag === OPTION_TAG.IMAGE_UPLOAD + ); + var imageUri = ''; + if (imagesList.length > 0) { + imageUri = imagesList[0].inputText ? imagesList[0].inputText : ''; + } + + let imagePath = ''; + RNFetchBlob.config({ + fileCache: true, + }) + .fetch('GET', imageUri) + .then((resp) => { + imagePath = resp.path(); + return resp.readFile('base64'); + }) + .then((base64Data) => { + var imageUrl = 'data:image/png;base64,' + base64Data; + + const encodedMessage = encodeURIComponent(message); + const encodedImageUri = encodeURIComponent(imageUrl); + var url = `whatsapp://send?text=${encodedMessage}`; + if (encodedImageUri !== '') { + url += `&media=${encodedImageUri}`; + } + // Linking.canOpenURL(url) + // .then(isInstalled => { + // if (!isInstalled) { + // console.log(message); + // console.log(url); + // console.error('WhatsApp is not installed on this device.'); + // } else { + // console.log(message); + // return Linking.openURL(url); + // } + // }) + // .catch(error => console.error('An error occurred', error)); + console.log(message); + console.log(imageUri); + console.log(imageUrl); + console.log(url); + Linking.openURL(url); + return RNFetchBlob.fs.unlink(imagePath); + }); }; const FeedbackDetailItem = ({ feedbackItem, isExpanded }: IFeedbackDetailItem) => { diff --git a/yarn.lock b/yarn.lock index 2f13bddd..da0c193e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4700,6 +4700,18 @@ glob@5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" +glob@7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" + integrity sha512-f8c0rE8JiCxpa52kWPAOa3ZaYEnzofDzCQLCn3Vdk0Z5OVLq3BsRFJI4S4ykpeVW6QMGBUkMeUpoEgWnMTnw5Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -8226,6 +8238,14 @@ rimraf@~2.6.2: dependencies: glob "^7.1.3" +rn-fetch-blob@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/rn-fetch-blob/-/rn-fetch-blob-0.12.0.tgz#ec610d2f9b3f1065556b58ab9c106eeb256f3cba" + integrity sha512-+QnR7AsJ14zqpVVUbzbtAjq0iI8c9tCg49tIoKO2ezjzRunN7YL6zFSFSWZm6d+mE/l9r+OeDM3jmb2tBb2WbA== + dependencies: + base-64 "0.1.0" + glob "7.0.6" + route-recognizer@^0.3.3: version "0.3.4" resolved "https://registry.yarnpkg.com/route-recognizer/-/route-recognizer-0.3.4.tgz#39ab1ffbce1c59e6d2bdca416f0932611e4f3ca3" From 60c3b106cf26b463aab101c05b4c0e73c400e9a7 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Thu, 21 Sep 2023 18:10:22 +0530 Subject: [PATCH 04/26] Photo getting shared with text on WhatsApp --- package.json | 1 + .../feedback/FeedbackDetailItem.tsx | 29 +++++++++++++------ yarn.lock | 5 ++++ 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index e92b0be2..daf8f1ef 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "react-native-qrcode-svg": "^6.2.0", "react-native-safe-area-context": "4.4.1", "react-native-screens": "3.18.2", + "react-native-share": "^9.4.1", "react-native-svg": "^13.9.0", "react-native-tab-view": "3.3.2", "react-native-toast-message": "2.1.5", diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index e4bc7b27..d1c8ab26 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -1,5 +1,5 @@ import React, { ReactNode } from 'react'; -import { View, StyleSheet, TouchableOpacity, Linking, Share } from 'react-native'; +import { View, StyleSheet, TouchableOpacity, Linking } from 'react-native'; 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'; @@ -24,6 +24,7 @@ import { CLICKSTREAM_EVENT_NAMES } from '../../../common/Constants'; import IconLabel from '../../../common/IconLabel'; import WhatsAppFeedbackShareIcon from '../../../assets/icons/WhatsAppIcon'; import RNFetchBlob from 'rn-fetch-blob'; +import Share from 'react-native-share'; interface IFeedbackDetailItem { feedbackItem: IFeedback; @@ -86,6 +87,7 @@ const sendToWhatsapp = (feedbackItem: IFeedback) => { const imagesList = feedbackItem.answerViews.filter( (answer) => answer.questionTag === OPTION_TAG.IMAGE_UPLOAD ); + console.log(imagesList, 'imagesList'); var imageUri = ''; if (imagesList.length > 0) { imageUri = imagesList[0].inputText ? imagesList[0].inputText : ''; @@ -96,11 +98,11 @@ const sendToWhatsapp = (feedbackItem: IFeedback) => { fileCache: true, }) .fetch('GET', imageUri) - .then((resp) => { + .then((resp: any) => { imagePath = resp.path(); return resp.readFile('base64'); }) - .then((base64Data) => { + .then((base64Data: any) => { var imageUrl = 'data:image/png;base64,' + base64Data; const encodedMessage = encodeURIComponent(message); @@ -109,6 +111,21 @@ const sendToWhatsapp = (feedbackItem: IFeedback) => { if (encodedImageUri !== '') { url += `&media=${encodedImageUri}`; } + console.log(message); + console.log(imageUri); + console.log(imageUrl); + console.log(url); + //Linking.openURL(url); + let shareImage = { + title: 'Agent Feedback', + message: message, + url: imageUrl, + social: Share.Social.WHATSAPP, + }; + //console.log(shareImage); + Share.open(shareImage); + return RNFetchBlob.fs.unlink(imagePath); + // Linking.canOpenURL(url) // .then(isInstalled => { // if (!isInstalled) { @@ -121,12 +138,6 @@ const sendToWhatsapp = (feedbackItem: IFeedback) => { // } // }) // .catch(error => console.error('An error occurred', error)); - console.log(message); - console.log(imageUri); - console.log(imageUrl); - console.log(url); - Linking.openURL(url); - return RNFetchBlob.fs.unlink(imagePath); }); }; diff --git a/yarn.lock b/yarn.lock index da0c193e..138c81b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7820,6 +7820,11 @@ react-native-screens@3.18.2: react-freeze "^1.0.0" warn-once "^0.1.0" +react-native-share@^9.4.1: + version "9.4.1" + resolved "https://registry.yarnpkg.com/react-native-share/-/react-native-share-9.4.1.tgz#1b6d96015009e3878bfc4346940602c1cffff525" + integrity sha512-jm4qA5J5+ytWA8UFg6s8iEfdZYGPW+t5oreSuzrPt0assjvBUlFaoqYGGwGR5RJ8BIpjzOJYvx/c9MjXB4ApUg== + react-native-svg@^13.9.0: version "13.9.0" resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-13.9.0.tgz#8df8a690dd00362601f074dec5d3a86dd0f99c7f" From f8fd8a724fe6484f479638d18d9a3f1e1a606026 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Thu, 21 Sep 2023 19:27:37 +0530 Subject: [PATCH 05/26] Some CSS features added --- src/assets/icons/ChevronDown.tsx | 28 +++++++++++++++++++ src/assets/icons/ChevronUp.tsx | 28 +++++++++++++++++++ .../feedback/FeedbackDetailItem.tsx | 2 +- 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/assets/icons/ChevronDown.tsx create mode 100644 src/assets/icons/ChevronUp.tsx diff --git a/src/assets/icons/ChevronDown.tsx b/src/assets/icons/ChevronDown.tsx new file mode 100644 index 00000000..d9f0db95 --- /dev/null +++ b/src/assets/icons/ChevronDown.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import Svg, { Rect, Mask, Path, G } from 'react-native-svg'; + +const ChevronDown = (props) => ( + + + + + + + + + +); +export default ChevronDown; diff --git a/src/assets/icons/ChevronUp.tsx b/src/assets/icons/ChevronUp.tsx new file mode 100644 index 00000000..7bc95ccc --- /dev/null +++ b/src/assets/icons/ChevronUp.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import Svg, { Rect, Mask, Path, G } from 'react-native-svg'; + +const ChevronUp = (props) => ( + + + + + + + + + +); +export default ChevronUp; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index d1c8ab26..44439a18 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -226,7 +226,7 @@ const styles = StyleSheet.create({ }, cardLightTitle: { fontWeight: '400', - color: '#BCBCBC', + color: '#585757', }, cardFooterText: { fontWeight: '400', From 504f4588dbfd7402998fdfbf36918897f186a714 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Fri, 22 Sep 2023 17:35:26 +0530 Subject: [PATCH 06/26] sharing as per whatsapp figma --- .../java/com/avapp/DeviceUtilsModule.java | 39 ++++ package.json | 1 + src/assets/icons/ChevronDown.tsx | 1 - src/constants/icons/ExpandAccordian.ts | 2 + src/constants/icons/ShrinkAccordian.ts | 2 + .../caseDetails/CollectionCaseDetail.tsx | 4 +- .../feedback/FeedbackDetailContainer.tsx | 35 ++- .../feedback/FeedbackDetailItem.tsx | 201 +++++++++++------- .../feedback/FeedbackListContainer.tsx | 24 ++- .../caseDetails/feedback/FeedbackListItem.tsx | 4 + yarn.lock | 5 + 11 files changed, 228 insertions(+), 90 deletions(-) create mode 100644 src/constants/icons/ExpandAccordian.ts create mode 100644 src/constants/icons/ShrinkAccordian.ts diff --git a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java index 56c69465..f05a1756 100644 --- a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java +++ b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java @@ -21,6 +21,9 @@ import org.json.JSONObject; import java.util.List; +import android.net.Uri; +import android.util.Log; + public class DeviceUtilsModule extends ReactContextBaseJavaModule implements ActivityEventListener { private ReactApplicationContext RNContext; @@ -77,4 +80,40 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act promise.reject( err); } } + + // @ReactMethod + // public void sendFeedbackToWhatsapp(String encodedMessage, String encodedImageUri, String mimeType) { + // log.d("Native Function is called"); + // log.d("sendFeedbackToWhatsapp", encodedMessage, encodedImageUri, mimeType); + // Intent sendIntent = new Intent(); + // sendIntent.setAction(Intent.ACTION_SEND); + // sendIntent.putExtra(Intent.EXTRA_TEXT, encodedMessage); + // sendIntent.setType(mimeType); + // sendIntent.putExtra(Intent.EXTRA_STREAM, encodedImageUri); + + // sendIntent.setPackage("com.whatsapp"); + // startActivity(sendIntent); + // return; + // } + + @ReactMethod + public void sendFeedbackToWhatsapp(String encodedMessage, String encodedImageUri, String mimeType) { + Log.d("Native Function called","string eg"); + + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, encodedMessage); + sendIntent.setType(mimeType); + + // Convert the encodedImageUri to a URI and set it as an EXTRA_STREAM + Uri uri = Uri.parse(encodedImageUri); + sendIntent.putExtra(Intent.EXTRA_STREAM, uri); + + sendIntent.setPackage("com.whatsapp"); + + // Start the activity + getCurrentActivity().startActivity(sendIntent); + return; + } + } diff --git a/package.json b/package.json index daf8f1ef..93284aee 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "react-native-qrcode-svg": "^6.2.0", "react-native-safe-area-context": "4.4.1", "react-native-screens": "3.18.2", + "react-native-send-intent": "^1.3.0", "react-native-share": "^9.4.1", "react-native-svg": "^13.9.0", "react-native-tab-view": "3.3.2", diff --git a/src/assets/icons/ChevronDown.tsx b/src/assets/icons/ChevronDown.tsx index d9f0db95..06080164 100644 --- a/src/assets/icons/ChevronDown.tsx +++ b/src/assets/icons/ChevronDown.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import Svg, { Rect, Mask, Path, G } from 'react-native-svg'; - const ChevronDown = (props) => ( diff --git a/src/constants/icons/ExpandAccordian.ts b/src/constants/icons/ExpandAccordian.ts new file mode 100644 index 00000000..388254fd --- /dev/null +++ b/src/constants/icons/ExpandAccordian.ts @@ -0,0 +1,2 @@ +export const expandAccordianPath = + 'M8.466 1.233a.63.63 0 0 0-.183.465.63.63 0 0 0 .183.465l3.057 3.055a.587.587 0 0 0 .216.141.742.742 0 0 0 .25.041c.088 0 .171-.013.249-.04.077-.029.15-.076.216-.142l3.073-3.072a.609.609 0 0 0 .183-.448.637.637 0 0 0-.2-.465.63.63 0 0 0-.465-.183.63.63 0 0 0-.465.183l-2.592 2.59-2.608-2.607a.61.61 0 0 0-.449-.182.638.638 0 0 0-.465.199Z'; diff --git a/src/constants/icons/ShrinkAccordian.ts b/src/constants/icons/ShrinkAccordian.ts new file mode 100644 index 00000000..cbd78f0f --- /dev/null +++ b/src/constants/icons/ShrinkAccordian.ts @@ -0,0 +1,2 @@ +export const shrinkAccordianPath = + 'M8.466 13.767a.63.63 0 0 1-.183-.465.63.63 0 0 1 .183-.465l3.057-3.055a.587.587 0 0 1 .216-.141.742.742 0 0 1 .25-.041c.088 0 .171.013.249.04.077.029.15.076.216.142l3.073 3.072a.609.609 0 0 1 .183.448.637.637 0 0 1-.2.465.63.63 0 0 1-.465.183.63.63 0 0 1-.465-.183l-2.592-2.59-2.608 2.607a.61.61 0 0 1-.449.182.638.638 0 0 1-.465-.199Z'; diff --git a/src/screens/caseDetails/CollectionCaseDetail.tsx b/src/screens/caseDetails/CollectionCaseDetail.tsx index fbeb55c8..bdba53f3 100644 --- a/src/screens/caseDetails/CollectionCaseDetail.tsx +++ b/src/screens/caseDetails/CollectionCaseDetail.tsx @@ -206,8 +206,9 @@ const CollectionCaseDetails: React.FC = (props) => { const commonParams = { loanAccountNumber: caseDetail.loanAccountNumber, customerReferenceId: caseDetail.customerReferenceId, - caseId, + caseId: caseId, }; + console.log(caseId); navigateToScreen(route, { ...params, ...commonParams }); }; @@ -454,6 +455,7 @@ const CollectionCaseDetails: React.FC = (props) => { diff --git a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx index 3a19a0db..9ed3ce77 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx @@ -4,6 +4,7 @@ import Accordion from '../../../../RN-UI-LIB/src/components/accordian/Accordian' import NavigationHeader from '../../../../RN-UI-LIB/src/components/NavigationHeader'; import Text from '../../../../RN-UI-LIB/src/components/Text'; import { GenericStyles, SCREEN_HEIGHT, getShadowStyle } from '../../../../RN-UI-LIB/src/styles'; +import Chevron from '../../../../RN-UI-LIB/src/Icons/Chevron'; import { COLORS } from '../../../../RN-UI-LIB/src/styles/colors'; import { getPastFeedbacks, getPastFeedbacksOnAddresses } from '../../../action/feedbackActions'; import { GenericType } from '../../../common/GenericTypes'; @@ -25,6 +26,8 @@ import { setFeedbackHistoryLoading } from '../../../reducer/feedbackHistorySlice import SuspenseLoader from '../../../../RN-UI-LIB/src/components/suspense_loader/SuspenseLoader'; import LineLoader from '../../../../RN-UI-LIB/src/components/suspense_loader/LineLoader'; import NoPastFeedbackIcon from '../../../assets/icons/NoPastFeedbackIcon'; +import { expandAccordianPath } from '../../../constants/icons/ExpandAccordian'; +import { shrinkAccordianPath } from '../../../constants/icons/ShrinkAccordian'; const FEEDBACK_PAGE_TITLE = 'All feedbacks'; const ADDRESS_FEEDBACK_PAGE_TITLE = 'Address feedback'; @@ -32,6 +35,22 @@ const ADDRESS_FEEDBACK_PAGE_TITLE = 'Address feedback'; const SCROLL_LAYOUT_OFFSET = 10; const FEEDBACK_PER_PAGE = 5; +const shrinkAccordianProps = { + width: 24, + height: 24, + fillColor: '#0276FE', + rotateY: 0, + path: shrinkAccordianPath, +}; + +const expandAccordianProps = { + width: 24, + height: 24, + fillColor: '#0276FE', + rotateY: 0, + path: expandAccordianPath, +}; + interface IFeedbackDetailContainer { route: { params: { @@ -39,15 +58,24 @@ interface IFeedbackDetailContainer { addressReferenceIds?: string[]; addressText?: string; activeFeedbackReferenceId?: string; + caseID: string; }; }; } const FeedbackDetailContainer: React.FC = ({ route: routeParams }) => { const { - params: { loanAccountNumber, activeFeedbackReferenceId, addressReferenceIds, addressText }, + params: { + loanAccountNumber, + activeFeedbackReferenceId, + addressReferenceIds, + addressText, + caseID, + }, } = routeParams; + console.log({ routeParams }); + const isPastFeedbackOnAddress = addressText || addressReferenceIds?.length; const [isExpanded, setIsExpanded] = useState(false); @@ -221,11 +249,12 @@ const FeedbackDetailContainer: React.FC = ({ route: ro key={feedback.referenceId} feedbackItem={feedback} isExpanded={isExpanded} + caseID={caseID} /> } customExpandUi={{ - whenCollapsed: View more, - whenExpanded: View less, + whenCollapsed: , + whenExpanded: , }} onExpanded={(value) => { setIsExpanded(value); diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index 44439a18..d58960bf 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -1,5 +1,5 @@ import React, { ReactNode } from 'react'; -import { View, StyleSheet, TouchableOpacity, Linking } from 'react-native'; +import { View, StyleSheet, TouchableOpacity, Linking, Platform, NativeModules } from 'react-native'; 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'; @@ -25,17 +25,21 @@ import IconLabel from '../../../common/IconLabel'; import WhatsAppFeedbackShareIcon from '../../../assets/icons/WhatsAppIcon'; import RNFetchBlob from 'rn-fetch-blob'; import Share from 'react-native-share'; +import { useAppSelector } from '../../../hooks'; +import { InteractionStatuses } from '../../allCases/interface'; +const { DeviceUtilsModule } = NativeModules; interface IFeedbackDetailItem { feedbackItem: IFeedback; isExpanded: boolean; + caseID: string; } const feedbackTypeIcon: Record = { - FIELD_VISIT: , - INHOUSE_FIELD_VISIT: , - SELF_CALL: , - CALL_BRIDGE: , + FIELD_VISIT: , + INHOUSE_FIELD_VISIT: , + SELF_CALL: , + CALL_BRIDGE: , }; const getAddress = (address?: IAddress) => { @@ -61,14 +65,26 @@ function getLocationLink(latitude: string, longitude: string): string { return link; } -const sendToWhatsapp = (feedbackItem: IFeedback) => { - var message = ''; - message += 'Feedback Type: ' + sanitizeString(feedbackItem.type) + '\n\n'; - message += 'Disposition: ' + sanitizeString(feedbackItem.interactionStatus) + '\n\n'; +const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any) => { + var message = '*Visit Feedback for* ' + sanitizeString(caseDetails?.customerName) + '\n'; message += - 'Feedback Date and Time: ' + - sanitizeString(dateFormat(new Date(feedbackItem.createdAt), 'DD MMM YYYY, HH:mm A')) + - '\n\n'; + sanitizeString(dateFormat(new Date(feedbackItem.createdAt), 'DD MMM YYYY | HH:mm A')) + '\n\n'; + message += 'LAN: ' + sanitizeString(caseDetails?.loanAccountNumber); + message += '| DPD Bucket: ' + sanitizeString(caseDetails?.dpdBucket) + '\n\n'; + message += 'Disposition: ' + sanitizeString(feedbackItem.interactionStatus); + console.log('PRIIIIIIIINTINGGGGGGGGGGGGGGGG'); + console.log(feedbackItem); + const ptpDate = feedbackItem.answerViews.filter((answer) => answer.questionName === 'PTP Date'); + if (ptpDate.length > 0) { + message += ' for ' + sanitizeString(ptpDate[0].inputDate) + '\n\n'; + } + const answerList = feedbackItem.answerViews.filter( + (answer) => answer.questionName === 'Comments' + ); + if (answerList.length > 0) { + message += 'Comments: ' + sanitizeString(answerList[0].inputText) + '\n\n'; + } + { feedbackItem.metadata?.interactionLatitude && feedbackItem.metadata?.interactionLongitude && @@ -116,6 +132,7 @@ const sendToWhatsapp = (feedbackItem: IFeedback) => { console.log(imageUrl); console.log(url); //Linking.openURL(url); + ////////////////////////////////////////////////////////////// let shareImage = { title: 'Agent Feedback', message: message, @@ -123,9 +140,9 @@ const sendToWhatsapp = (feedbackItem: IFeedback) => { social: Share.Social.WHATSAPP, }; //console.log(shareImage); - Share.open(shareImage); - return RNFetchBlob.fs.unlink(imagePath); - + //Share.open(shareImage); + //return RNFetchBlob.fs.unlink(imagePath); + //////////////////////////////////////////////////////////////// // Linking.canOpenURL(url) // .then(isInstalled => { // if (!isInstalled) { @@ -138,80 +155,112 @@ const sendToWhatsapp = (feedbackItem: IFeedback) => { // } // }) // .catch(error => console.error('An error occurred', error)); + + // const sendIntent = Platform.select({ + // ios: null, + // android: { + // action: 'android.intent.action.SEND', + // intentType: 'text/plain', + // extras: { + // 'android.intent.extra.TEXT': encodedMessage, + // 'android.intent.extra.STREAM': encodedImageUri, + // 'android.intent.extra.SUBJECT': 'Subject', + // }, + // packageName: 'com.whatsapp', + // }, + // }); + + // return Linking.openURL(sendIntent); + const mimeType = 'image/*'; + console.log(DeviceUtilsModule); + DeviceUtilsModule.sendFeedbackToWhatsApp(message, imageUri, mimeType); }); }; -const FeedbackDetailItem = ({ feedbackItem, isExpanded }: IFeedbackDetailItem) => { +const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseID }: IFeedbackDetailItem) => { + const caseDetails = useAppSelector((state) => state.allCases.caseDetails[caseID]); return ( - - - {feedbackTypeIcon[feedbackItem.type] ? ( - {feedbackTypeIcon[feedbackItem.type]} - ) : null} + console.log(caseID), + console.log(caseDetails), + ( + + + {feedbackTypeIcon[feedbackItem.type] ? ( + {feedbackTypeIcon[feedbackItem.type]} + ) : null} + + {sanitizeString(feedbackItem.interactionStatus)} + + - {sanitizeString(feedbackItem.interactionStatus)} + {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_DATE_FORMAT))} +   ●   + {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_TIME_FORMAT))} + + + {FIELD_FEEDBACKS.includes(feedbackItem.type) + ? sanitizeString(getAddress(feedbackItem.source as IAddress)) + : sanitizeString( + [ + (feedbackItem.source as ICallingFeedback)?.recipientNumber, + feedbackItem.sourceText ? `(${feedbackItem.sourceText})` : '', + ].join(' ') + )} - - - {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_DATE_FORMAT))} -   ●   - {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_TIME_FORMAT))} - - - - {FIELD_FEEDBACKS.includes(feedbackItem.type) - ? sanitizeString(getAddress(feedbackItem.source as IAddress)) - : sanitizeString( - [ - (feedbackItem.source as ICallingFeedback)?.recipientNumber, - feedbackItem.sourceText ? `(${feedbackItem.sourceText})` : '', - ].join(' ') - )} - - {feedbackItem.metadata?.interactionLatitude && FIELD_FEEDBACKS.includes(feedbackItem.type) ? ( - <> - - - openGeolocation( - feedbackItem.metadata?.interactionLatitude, - feedbackItem.metadata?.interactionLongitude - ) - } - style={[GenericStyles.row, GenericStyles.pv12]} - > - Open map - - sendToWhatsapp(feedbackItem)}> - } - textStyle={{ color: COLORS.BASE.BLUE }} - /> - - - - ) : null} - + {feedbackItem.metadata?.interactionLatitude && + FIELD_FEEDBACKS.includes(feedbackItem.type) ? ( + <> + + + openGeolocation( + feedbackItem.metadata?.interactionLatitude, + feedbackItem.metadata?.interactionLongitude + ) + } + style={[GenericStyles.row, GenericStyles.pv12]} + > + Open map + + sendToWhatsapp(feedbackItem, caseDetails)} + > + } + textStyle={{ color: COLORS.BASE.BLUE }} + /> + + + + ) : null} + + ) ); }; diff --git a/src/screens/caseDetails/feedback/FeedbackListContainer.tsx b/src/screens/caseDetails/feedback/FeedbackListContainer.tsx index 721f983b..485087e8 100644 --- a/src/screens/caseDetails/feedback/FeedbackListContainer.tsx +++ b/src/screens/caseDetails/feedback/FeedbackListContainer.tsx @@ -18,6 +18,7 @@ import { getCaseUnifiedData, UnifiedCaseDetailsTypes } from '../../../action/cas interface IFeedbackListContainer { loanAccountNumber: string; feedbackList: (IFeedback | IUnSyncedFeedbackItem)[]; + caseID: string; } interface IOfflineFeedbackListContainer { @@ -66,6 +67,7 @@ const OfflineFeedbackListContainer: React.FC = ({ const FeedbackListContainer: React.FC = ({ loanAccountNumber, feedbackList, + caseID, }) => { const [retryBtnCount, setRetryBtnCount] = useState(0); @@ -91,15 +93,19 @@ const FeedbackListContainer: React.FC = ({ } return ( - - {feedbackList.map((feedbackItem: IFeedback | IUnSyncedFeedbackItem, idx: number) => ( - - ))} - + console.log(caseID), + ( + + {feedbackList.map((feedbackItem: IFeedback | IUnSyncedFeedbackItem, idx: number) => ( + + ))} + + ) ); }; diff --git a/src/screens/caseDetails/feedback/FeedbackListItem.tsx b/src/screens/caseDetails/feedback/FeedbackListItem.tsx index 3b7c06a7..8a8a3184 100644 --- a/src/screens/caseDetails/feedback/FeedbackListItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackListItem.tsx @@ -15,11 +15,13 @@ interface IFeedbackListItem { feedbackItem: IFeedback | IUnSyncedFeedbackItem; showHorizontalLine?: boolean; loanAccountNumber: string; + caseID: string; } const FeedbackListItem: React.FC = ({ feedbackItem, loanAccountNumber, + caseID, showHorizontalLine = true, }) => { const handleRouting = (route: PageRouteEnum, params: object | undefined = undefined) => { @@ -27,7 +29,9 @@ const FeedbackListItem: React.FC = ({ const commonParams = { loanAccountNumber, activeFeedbackReferenceId: (feedbackItem as IFeedback).referenceId, + caseID: caseID, }; + console.log(caseID); navigateToScreen(route, { ...params, ...commonParams }); }; diff --git a/yarn.lock b/yarn.lock index 138c81b8..305e30da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7820,6 +7820,11 @@ react-native-screens@3.18.2: react-freeze "^1.0.0" warn-once "^0.1.0" +react-native-send-intent@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/react-native-send-intent/-/react-native-send-intent-1.3.0.tgz#d8c7898827da1b8b10e25a645ce6802d1a0b440c" + integrity sha512-ODTX7BHITFxdcAL0K2iHfa3qVYnqG8GPcv1NbLBNC1DyCaOSJiiGtVH6Kc5YBqzQ8+1pV9uN5nfQ5wyFgiq74g== + react-native-share@^9.4.1: version "9.4.1" resolved "https://registry.yarnpkg.com/react-native-share/-/react-native-share-9.4.1.tgz#1b6d96015009e3878bfc4346940602c1cffff525" From 10cd908b46eff7c33eb3c02f1d72161613bc512e Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Fri, 22 Sep 2023 21:15:08 +0530 Subject: [PATCH 07/26] Bridge developed --- .../java/com/avapp/Base64ToContentUri.java | 91 +++++++++++++++++++ .../java/com/avapp/DeviceUtilsModule.java | 78 +++++++++++++--- .../feedback/FeedbackDetailItem.tsx | 6 +- 3 files changed, 158 insertions(+), 17 deletions(-) create mode 100644 android/app/src/main/java/com/avapp/Base64ToContentUri.java diff --git a/android/app/src/main/java/com/avapp/Base64ToContentUri.java b/android/app/src/main/java/com/avapp/Base64ToContentUri.java new file mode 100644 index 00000000..0a835c21 --- /dev/null +++ b/android/app/src/main/java/com/avapp/Base64ToContentUri.java @@ -0,0 +1,91 @@ +package com.avapp; + + + +import android.annotation.SuppressLint; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.media.MediaScannerConnection; +import android.net.Uri; +import android.os.Environment; +import android.provider.MediaStore; +import android.util.Base64; +import android.util.Log; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Base64ToContentUri { + + public static Uri getUriFromBase64(Context context, String base64Image) { + // Decode base64 string to bitmap + Bitmap bitmap = decodeBase64ToBitmap(base64Image); + + // Save the bitmap to a file and get the content URI for that file + return saveBitmapAsImage(context, bitmap); + } + + private static Bitmap decodeBase64ToBitmap(String base64Image) { + byte[] decodedBytes = Base64.decode(base64Image, Base64.DEFAULT); + return BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length); + } + + private static Uri saveBitmapAsImage(Context context, Bitmap bitmap) { + File imagesDir = new File(Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_DCIM), "YourAppImages"); + if (!imagesDir.exists()) { + if (!imagesDir.mkdirs()) { + Log.e("Base64ToContentUri", "Failed to create directory"); + return null; + } + } + + String fileName = System.currentTimeMillis() + ".jpg"; + File imageFile = new File(imagesDir, fileName); + + try (OutputStream fOut = new FileOutputStream(imageFile)) { + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut); + fOut.flush(); + } catch (IOException e) { + Log.e("Base64ToContentUri", "Failed to save image file: " + e.getMessage()); + return null; + } + + // Update the media store to include the image + MediaScannerConnection.scanFile(context, new String[]{imageFile.getAbsolutePath()}, null, null); + + // Return the content URI for the saved image + return getImageContentUri(context, imageFile); + } + + private static Uri getImageContentUri(Context context, File imageFile) { + String filePath = imageFile.getAbsolutePath(); + Cursor cursor = context.getContentResolver().query( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + new String[]{MediaStore.Images.Media._ID}, + MediaStore.Images.Media.DATA + "=? ", + new String[]{filePath}, null); + + if (cursor != null && cursor.moveToFirst()) { + @SuppressLint("Range") int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID)); + cursor.close(); + return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id); + } else { + if (imageFile.exists()) { + ContentValues values = new ContentValues(); + values.put(MediaStore.Images.Media.DATA, filePath); + return context.getContentResolver().insert( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + } else { + return null; + } + } + } +} + diff --git a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java index f05a1756..3874cea7 100644 --- a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java +++ b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java @@ -15,6 +15,10 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import android.content.pm.PackageInfo; +import android.os.Environment; +import android.util.Base64; +import android.widget.Toast; + import org.json.JSONArray; import org.json.JSONObject; @@ -23,7 +27,9 @@ import java.util.List; import android.net.Uri; import android.util.Log; - +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; public class DeviceUtilsModule extends ReactContextBaseJavaModule implements ActivityEventListener { private ReactApplicationContext RNContext; @@ -96,24 +102,66 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act // return; // } - @ReactMethod - public void sendFeedbackToWhatsapp(String encodedMessage, String encodedImageUri, String mimeType) { - Log.d("Native Function called","string eg"); + private static File convertBase64ToFile(Context context,String base64Data) { + try { + // Convert Base64 to byte array + byte[] decodedBytes = Base64.decode(base64Data, Base64.DEFAULT); - Intent sendIntent = new Intent(); - sendIntent.setAction(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_TEXT, encodedMessage); - sendIntent.setType(mimeType); + // Create a temporary file to store the Base64 data - // Convert the encodedImageUri to a URI and set it as an EXTRA_STREAM - Uri uri = Uri.parse(encodedImageUri); - sendIntent.putExtra(Intent.EXTRA_STREAM, uri); + File outputDir = context.getCacheDir(); + File file = File.createTempFile("temp_image", ".jpg", outputDir); - sendIntent.setPackage("com.whatsapp"); + // Write the byte array to the file + FileOutputStream fos = new FileOutputStream(file); + fos.write(decodedBytes); + fos.flush(); + fos.close(); - // Start the activity - getCurrentActivity().startActivity(sendIntent); - return; + return file; + } catch (IOException e) { + Log.e("ShareUtils", "Failed to convert Base64 to file: " + e.getMessage()); + return null; + } } + @ReactMethod + public void sendFeedbackToWhatsapp(String encodedMessage, String encodedImageUri, String mimeType) { + Log.d("Native Function called","string eg"); + + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, encodedMessage); + sendIntent.setType("image/*"); + + File imageFile = convertBase64ToFile(getReactApplicationContext(),encodedImageUri); + Uri fileUri = Uri.fromFile(imageFile); + + + //Uri imageUri = Base64ToContentUri.getUriFromBase64(getReactApplicationContext(), encodedImageUri); + + + + + // Convert the encodedImageUri to a URI and set it as an EXTRA_STREAM + //Uri uri = Uri.parse(encodedImageUri); + sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); + Log.d("base64 data", fileUri.toString()); + + sendIntent.setPackage("com.whatsapp"); + + // Start the activity + getCurrentActivity().startActivity(sendIntent); + return; + } + + @ReactMethod + public String helloWorld() { + Log.d("debug", "hello world called"); + Toast.makeText(getReactApplicationContext(), "Hello from Native Module!", Toast.LENGTH_SHORT).show(); + return "hello"; + } + + + } diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index d58960bf..66218964 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -119,7 +119,7 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any) => { return resp.readFile('base64'); }) .then((base64Data: any) => { - var imageUrl = 'data:image/png;base64,' + base64Data; + var imageUrl = base64Data; const encodedMessage = encodeURIComponent(message); const encodedImageUri = encodeURIComponent(imageUrl); @@ -173,7 +173,9 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any) => { // return Linking.openURL(sendIntent); const mimeType = 'image/*'; console.log(DeviceUtilsModule); - DeviceUtilsModule.sendFeedbackToWhatsApp(message, imageUri, mimeType); + DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType); + + // DeviceUtilsModule.helloWorld(); }); }; From 5ecc1b47f1cd82af62efd00f796d15a2eba5159e Mon Sep 17 00:00:00 2001 From: Varnit Goyal Date: Sat, 23 Sep 2023 17:03:42 +0530 Subject: [PATCH 08/26] TP-00000| fixed whatsapp intent --- android/app/src/main/AndroidManifest.xml | 11 +++ .../java/com/avapp/Base64ToContentUri.java | 91 ------------------- .../java/com/avapp/DeviceUtilsModule.java | 48 +++------- 3 files changed, 23 insertions(+), 127 deletions(-) delete mode 100644 android/app/src/main/java/com/avapp/Base64ToContentUri.java diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 4815e009..b85cb2e2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -55,6 +55,16 @@ + + + + + diff --git a/android/app/src/main/java/com/avapp/Base64ToContentUri.java b/android/app/src/main/java/com/avapp/Base64ToContentUri.java deleted file mode 100644 index 0a835c21..00000000 --- a/android/app/src/main/java/com/avapp/Base64ToContentUri.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.avapp; - - - -import android.annotation.SuppressLint; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.media.MediaScannerConnection; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.util.Base64; -import android.util.Log; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -public class Base64ToContentUri { - - public static Uri getUriFromBase64(Context context, String base64Image) { - // Decode base64 string to bitmap - Bitmap bitmap = decodeBase64ToBitmap(base64Image); - - // Save the bitmap to a file and get the content URI for that file - return saveBitmapAsImage(context, bitmap); - } - - private static Bitmap decodeBase64ToBitmap(String base64Image) { - byte[] decodedBytes = Base64.decode(base64Image, Base64.DEFAULT); - return BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length); - } - - private static Uri saveBitmapAsImage(Context context, Bitmap bitmap) { - File imagesDir = new File(Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_DCIM), "YourAppImages"); - if (!imagesDir.exists()) { - if (!imagesDir.mkdirs()) { - Log.e("Base64ToContentUri", "Failed to create directory"); - return null; - } - } - - String fileName = System.currentTimeMillis() + ".jpg"; - File imageFile = new File(imagesDir, fileName); - - try (OutputStream fOut = new FileOutputStream(imageFile)) { - bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut); - fOut.flush(); - } catch (IOException e) { - Log.e("Base64ToContentUri", "Failed to save image file: " + e.getMessage()); - return null; - } - - // Update the media store to include the image - MediaScannerConnection.scanFile(context, new String[]{imageFile.getAbsolutePath()}, null, null); - - // Return the content URI for the saved image - return getImageContentUri(context, imageFile); - } - - private static Uri getImageContentUri(Context context, File imageFile) { - String filePath = imageFile.getAbsolutePath(); - Cursor cursor = context.getContentResolver().query( - MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - new String[]{MediaStore.Images.Media._ID}, - MediaStore.Images.Media.DATA + "=? ", - new String[]{filePath}, null); - - if (cursor != null && cursor.moveToFirst()) { - @SuppressLint("Range") int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID)); - cursor.close(); - return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id); - } else { - if (imageFile.exists()) { - ContentValues values = new ContentValues(); - values.put(MediaStore.Images.Media.DATA, filePath); - return context.getContentResolver().insert( - MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); - } else { - return null; - } - } - } -} - diff --git a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java index 3874cea7..c94373dc 100644 --- a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java +++ b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java @@ -8,6 +8,7 @@ import android.content.pm.PackageManager; import android.location.LocationManager; import androidx.annotation.Nullable; +import androidx.core.content.FileProvider; import com.facebook.react.bridge.ActivityEventListener; import com.facebook.react.bridge.Promise; @@ -17,7 +18,6 @@ import com.facebook.react.bridge.ReactMethod; import android.content.pm.PackageInfo; import android.os.Environment; import android.util.Base64; -import android.widget.Toast; import org.json.JSONArray; @@ -86,22 +86,6 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act promise.reject( err); } } - - // @ReactMethod - // public void sendFeedbackToWhatsapp(String encodedMessage, String encodedImageUri, String mimeType) { - // log.d("Native Function is called"); - // log.d("sendFeedbackToWhatsapp", encodedMessage, encodedImageUri, mimeType); - // Intent sendIntent = new Intent(); - // sendIntent.setAction(Intent.ACTION_SEND); - // sendIntent.putExtra(Intent.EXTRA_TEXT, encodedMessage); - // sendIntent.setType(mimeType); - // sendIntent.putExtra(Intent.EXTRA_STREAM, encodedImageUri); - - // sendIntent.setPackage("com.whatsapp"); - // startActivity(sendIntent); - // return; - // } - private static File convertBase64ToFile(Context context,String base64Data) { try { // Convert Base64 to byte array @@ -110,7 +94,10 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act // Create a temporary file to store the Base64 data File outputDir = context.getCacheDir(); - File file = File.createTempFile("temp_image", ".jpg", outputDir); + + + + File file = File.createTempFile("temp_image", ".jpg", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)); // Write the byte array to the file FileOutputStream fos = new FileOutputStream(file); @@ -127,26 +114,21 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act @ReactMethod public void sendFeedbackToWhatsapp(String encodedMessage, String encodedImageUri, String mimeType) { - Log.d("Native Function called","string eg"); Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, encodedMessage); - sendIntent.setType("image/*"); + sendIntent.setType(mimeType); + sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); File imageFile = convertBase64ToFile(getReactApplicationContext(),encodedImageUri); - Uri fileUri = Uri.fromFile(imageFile); + Uri fileUri = FileProvider.getUriForFile(getReactApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", new File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + imageFile.getName() + ) + ); - - //Uri imageUri = Base64ToContentUri.getUriFromBase64(getReactApplicationContext(), encodedImageUri); - - - - - // Convert the encodedImageUri to a URI and set it as an EXTRA_STREAM - //Uri uri = Uri.parse(encodedImageUri); sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); - Log.d("base64 data", fileUri.toString()); sendIntent.setPackage("com.whatsapp"); @@ -155,12 +137,6 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act return; } - @ReactMethod - public String helloWorld() { - Log.d("debug", "hello world called"); - Toast.makeText(getReactApplicationContext(), "Hello from Native Module!", Toast.LENGTH_SHORT).show(); - return "hello"; - } From e56b728439c3f0e17d095aefdbdb2a254d328aa2 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Mon, 25 Sep 2023 11:00:53 +0530 Subject: [PATCH 09/26] Image and text are shareable --- .../caseDetails/CollectionCaseDetail.tsx | 3 +- .../feedback/FeedbackDetailContainer.tsx | 260 +++++++++--------- .../feedback/FeedbackDetailItem.tsx | 50 +++- .../feedback/FeedbackListContainer.tsx | 8 +- .../caseDetails/feedback/FeedbackListItem.tsx | 8 +- 5 files changed, 182 insertions(+), 147 deletions(-) diff --git a/src/screens/caseDetails/CollectionCaseDetail.tsx b/src/screens/caseDetails/CollectionCaseDetail.tsx index bdba53f3..3185620a 100644 --- a/src/screens/caseDetails/CollectionCaseDetail.tsx +++ b/src/screens/caseDetails/CollectionCaseDetail.tsx @@ -208,6 +208,7 @@ const CollectionCaseDetails: React.FC = (props) => { customerReferenceId: caseDetail.customerReferenceId, caseId: caseId, }; + console.log('Handle Routing for Open all feedbacks'); console.log(caseId); navigateToScreen(route, { ...params, ...commonParams }); }; @@ -455,7 +456,7 @@ const CollectionCaseDetails: React.FC = (props) => { diff --git a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx index 9ed3ce77..f1e2ec9f 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx @@ -58,7 +58,7 @@ interface IFeedbackDetailContainer { addressReferenceIds?: string[]; addressText?: string; activeFeedbackReferenceId?: string; - caseID: string; + caseId: string; }; }; } @@ -70,10 +70,11 @@ const FeedbackDetailContainer: React.FC = ({ route: ro activeFeedbackReferenceId, addressReferenceIds, addressText, - caseID, + caseId, }, } = routeParams; + console.log('Feedback Detail Container '); console.log({ routeParams }); const isPastFeedbackOnAddress = addressText || addressReferenceIds?.length; @@ -191,132 +192,143 @@ const FeedbackDetailContainer: React.FC = ({ route: ro }; return ( - - - - } - style={[GenericStyles.ph16, GenericStyles.mt16]} - ref={(x) => setRef(x)} - > - - {[...Array(8).keys()].map(() => ( - - ))} - - } + console.log('Case ID before passing is: ' + routeParams.params.caseId), + ( + + + + } + style={[GenericStyles.ph16, GenericStyles.mt16]} + ref={(x) => setRef(x)} > - - {feedbackList?.length ? ( + - {isPastFeedbackOnAddress ? ( - - - Feedback for - - - {addressText} - - - ) : null} - {feedbackList.map((feedback: IFeedback, index) => ( - { - const layout = event.nativeEvent.layout; - if (!dataSourceCord && feedback.referenceId === activeFeedbackReferenceId) { - setDataSourceCord(layout.y + SCROLL_LAYOUT_OFFSET); - } - }} - > - - } - customExpandUi={{ - whenCollapsed: , - whenExpanded: , - }} - onExpanded={(value) => { - setIsExpanded(value); + {[...Array(8).keys()].map(() => ( + + ))} + + } + > + + {feedbackList?.length ? ( + <> + {isPastFeedbackOnAddress ? ( + + + Feedback for + + + {addressText} + + + ) : null} + {feedbackList.map((feedback: IFeedback, index) => ( + { + const layout = event.nativeEvent.layout; + if ( + !dataSourceCord && + feedback.referenceId === activeFeedbackReferenceId + ) { + setDataSourceCord(layout.y + SCROLL_LAYOUT_OFFSET); + } }} > - - - - ))} - - handlePageChangeClickstream( - page, - CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_NEXT_PAGE_CLICKED - ) - } - onPrevPage={(page) => - handlePageChangeClickstream( - page, - CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_PREV_PAGE_CLICKED - ) - } - onFirstPage={(page) => - handlePageChangeClickstream( - page, - CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_FIRST_PAGE_CLICKED - ) - } - onLastPage={(page) => - handlePageChangeClickstream( - page, - CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_LAST_PAGE_CLICKED - ) - } - /> - - ) : ( - - - - No previous feedback found - - - )} - - - - - + + } + customExpandUi={{ + whenCollapsed: , + whenExpanded: , + }} + onExpanded={(value) => { + setIsExpanded(value); + }} + > + + + + ))} + + handlePageChangeClickstream( + page, + CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_NEXT_PAGE_CLICKED + ) + } + onPrevPage={(page) => + handlePageChangeClickstream( + page, + CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_PREV_PAGE_CLICKED + ) + } + onFirstPage={(page) => + handlePageChangeClickstream( + page, + CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_FIRST_PAGE_CLICKED + ) + } + onLastPage={(page) => + handlePageChangeClickstream( + page, + CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_LAST_PAGE_CLICKED + ) + } + /> + + ) : ( + + + + No previous feedback found + + + )} + + + + + + ) ); }; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index 66218964..12f4d973 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -8,7 +8,11 @@ import { BUSINESS_TIME_FORMAT, dateFormat, } from '../../../../RN-UI-LIB/src/utlis/dates'; -import { getGoogleMapUrl, sanitizeString } from '../../../components/utlis/commonFunctions'; +import { + getGoogleMapUrl, + getLoanAccountNumber, + sanitizeString, +} from '../../../components/utlis/commonFunctions'; import { FIELD_FEEDBACKS, ICallingFeedback, @@ -27,12 +31,14 @@ import RNFetchBlob from 'rn-fetch-blob'; import Share from 'react-native-share'; import { useAppSelector } from '../../../hooks'; import { InteractionStatuses } from '../../allCases/interface'; +import { EmiSelectedTab } from '../../emiSchedule/EmiScheduleTab'; +import { getFilteredData } from '../../emiSchedule/utils'; const { DeviceUtilsModule } = NativeModules; interface IFeedbackDetailItem { feedbackItem: IFeedback; isExpanded: boolean; - caseID: string; + caseId: string; } const feedbackTypeIcon: Record = { @@ -65,24 +71,34 @@ function getLocationLink(latitude: string, longitude: string): string { return link; } -const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any) => { - var message = '*Visit Feedback for* ' + sanitizeString(caseDetails?.customerName) + '\n'; +const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: any) => { + var message = '*Visit Feedback for ' + sanitizeString(caseDetails?.customerName) + '*\n'; message += - sanitizeString(dateFormat(new Date(feedbackItem.createdAt), 'DD MMM YYYY | HH:mm A')) + '\n\n'; + '_' + + sanitizeString(dateFormat(new Date(feedbackItem.createdAt), 'DD MMM, YYYY | HH:mm A')) + + '_\n\n'; message += 'LAN: ' + sanitizeString(caseDetails?.loanAccountNumber); - message += '| DPD Bucket: ' + sanitizeString(caseDetails?.dpdBucket) + '\n\n'; + message += '| DPD Bucket: ' + sanitizeString(caseDetails?.dpdBucket); + console.log(filteredData); + message += '| EMI: ' + filteredData?.[0]?.totalOverDueAmount + '\n\n'; message += 'Disposition: ' + sanitizeString(feedbackItem.interactionStatus); - console.log('PRIIIIIIIINTINGGGGGGGGGGGGGGGG'); - console.log(feedbackItem); + // console.log('PRIIIIIIIINTINGGGGGGGGGGGGGGGG'); + // console.log(feedbackItem); const ptpDate = feedbackItem.answerViews.filter((answer) => answer.questionName === 'PTP Date'); if (ptpDate.length > 0) { message += ' for ' + sanitizeString(ptpDate[0].inputDate) + '\n\n'; + } else { + message += '\n\n'; } + + message += 'Remarks: '; const answerList = feedbackItem.answerViews.filter( (answer) => answer.questionName === 'Comments' ); if (answerList.length > 0) { - message += 'Comments: ' + sanitizeString(answerList[0].inputText) + '\n\n'; + message += sanitizeString(answerList[0].inputText) + '\n\n'; + } else { + message += 'N.A.\n\n'; } { @@ -179,10 +195,16 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any) => { }); }; -const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseID }: IFeedbackDetailItem) => { - const caseDetails = useAppSelector((state) => state.allCases.caseDetails[caseID]); +const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetailItem) => { + const caseDetails = useAppSelector((state) => state.allCases.caseDetails[caseId]); + const emiEcheduleData = + useAppSelector((state) => state.emiSchedule?.[getLoanAccountNumber(caseDetails)]) || {}; + const { data: emiData, isLoading } = emiEcheduleData; + const filteredData = getFilteredData(emiData, EmiSelectedTab.UNPAID); + return ( - console.log(caseID), + console.log('In feedback detail item'), + console.log(caseId), console.log(caseDetails), ( @@ -218,7 +240,7 @@ const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseID }: IFeedbackDetai {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_TIME_FORMAT))} @@ -250,7 +272,7 @@ const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseID }: IFeedbackDetai sendToWhatsapp(feedbackItem, caseDetails)} + onPress={() => sendToWhatsapp(feedbackItem, caseDetails, filteredData)} > = ({ const FeedbackListContainer: React.FC = ({ loanAccountNumber, feedbackList, - caseID, + caseId, }) => { const [retryBtnCount, setRetryBtnCount] = useState(0); @@ -93,7 +93,7 @@ const FeedbackListContainer: React.FC = ({ } return ( - console.log(caseID), + console.log(caseId), ( {feedbackList.map((feedbackItem: IFeedback | IUnSyncedFeedbackItem, idx: number) => ( @@ -101,7 +101,7 @@ const FeedbackListContainer: React.FC = ({ feedbackItem={feedbackItem} loanAccountNumber={loanAccountNumber} showHorizontalLine={++idx !== feedbackList.length} - caseID={caseID} + caseId={caseId} /> ))} diff --git a/src/screens/caseDetails/feedback/FeedbackListItem.tsx b/src/screens/caseDetails/feedback/FeedbackListItem.tsx index 8a8a3184..9e658f67 100644 --- a/src/screens/caseDetails/feedback/FeedbackListItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackListItem.tsx @@ -15,13 +15,13 @@ interface IFeedbackListItem { feedbackItem: IFeedback | IUnSyncedFeedbackItem; showHorizontalLine?: boolean; loanAccountNumber: string; - caseID: string; + caseId: string; } const FeedbackListItem: React.FC = ({ feedbackItem, loanAccountNumber, - caseID, + caseId, showHorizontalLine = true, }) => { const handleRouting = (route: PageRouteEnum, params: object | undefined = undefined) => { @@ -29,9 +29,9 @@ const FeedbackListItem: React.FC = ({ const commonParams = { loanAccountNumber, activeFeedbackReferenceId: (feedbackItem as IFeedback).referenceId, - caseID: caseID, + caseId: caseId, }; - console.log(caseID); + console.log(caseId); navigateToScreen(route, { ...params, ...commonParams }); }; From c502cd96343425e0bf4e61b8050e08587d48cf04 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Mon, 25 Sep 2023 16:54:03 +0530 Subject: [PATCH 10/26] Accordian content fit to card width --- src/assets/icons/ChevronDown.tsx | 72 +++++++++++++------ .../feedback/FeedbackDetailContainer.tsx | 8 +-- .../feedback/FeedbackDetailItem.tsx | 15 ++-- src/screens/emiSchedule/EmiScheduleTab.tsx | 3 +- 4 files changed, 64 insertions(+), 34 deletions(-) diff --git a/src/assets/icons/ChevronDown.tsx b/src/assets/icons/ChevronDown.tsx index 06080164..80112095 100644 --- a/src/assets/icons/ChevronDown.tsx +++ b/src/assets/icons/ChevronDown.tsx @@ -1,27 +1,53 @@ -import * as React from 'react'; -import Svg, { Rect, Mask, Path, G } from 'react-native-svg'; -const ChevronDown = (props) => ( - - - ( +// +// +// +// +// +// +// +// +// ) +// export default ChevronDown + +import React from 'react'; +import Svg, { Path } from 'react-native-svg'; +import { COLORS } from '../../../RN-UI-LIB/src/styles/colors'; +import { IconProps } from '../../../RN-UI-LIB/src/Icons/types'; + +const ChevronDown: React.FC = (props) => { + const { fillColor = COLORS.TEXT.LIGHT, size = 16, rotateX = 0 } = props; + return ( + - - - - - -); + + ); +}; + export default ChevronDown; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx index f1e2ec9f..1b4b6025 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx @@ -263,10 +263,10 @@ const FeedbackDetailContainer: React.FC = ({ route: ro caseId={caseId} /> } - customExpandUi={{ - whenCollapsed: , - whenExpanded: , - }} + // customExpandUi={{ + // whenCollapsed: , + // whenExpanded: , + // }} onExpanded={(value) => { setIsExpanded(value); }} diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index 12f4d973..afaa7248 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -42,8 +42,8 @@ interface IFeedbackDetailItem { } const feedbackTypeIcon: Record = { - FIELD_VISIT: , - INHOUSE_FIELD_VISIT: , + FIELD_VISIT: , + INHOUSE_FIELD_VISIT: , SELF_CALL: , CALL_BRIDGE: , }; @@ -72,6 +72,8 @@ function getLocationLink(latitude: string, longitude: string): string { } const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: any) => { + console.log('Printing filtered data'); + console.log(filteredData); var message = '*Visit Feedback for ' + sanitizeString(caseDetails?.customerName) + '*\n'; message += '_' + @@ -197,15 +199,18 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetailItem) => { const caseDetails = useAppSelector((state) => state.allCases.caseDetails[caseId]); - const emiEcheduleData = - useAppSelector((state) => state.emiSchedule?.[getLoanAccountNumber(caseDetails)]) || {}; - const { data: emiData, isLoading } = emiEcheduleData; + const emiEcheduleData = useAppSelector( + (state) => state.emiSchedule?.[getLoanAccountNumber(caseDetails)] + ); + const { data: emiData } = emiEcheduleData; const filteredData = getFilteredData(emiData, EmiSelectedTab.UNPAID); return ( console.log('In feedback detail item'), console.log(caseId), console.log(caseDetails), + console.log(emiData), + console.log(filteredData), ( diff --git a/src/screens/emiSchedule/EmiScheduleTab.tsx b/src/screens/emiSchedule/EmiScheduleTab.tsx index 3cf7670c..4736273f 100644 --- a/src/screens/emiSchedule/EmiScheduleTab.tsx +++ b/src/screens/emiSchedule/EmiScheduleTab.tsx @@ -39,8 +39,7 @@ const EmiScheduleTab: React.FC = (props) => { const [selectedTab, setSelectedTab] = useState(EmiSelectedTab.UNPAID); const emiEcheduleData = useAppSelector((state) => state.emiSchedule?.[loanAccountNumber]) || {}; const { data: emiData, isLoading } = emiEcheduleData; - const filteredData = - selectedTab !== EmiSelectedTab.ALL ? getFilteredData(emiData, selectedTab) : emiData; + const filteredData = getFilteredData(emiData, selectedTab); return ( Date: Mon, 25 Sep 2023 18:36:14 +0530 Subject: [PATCH 11/26] TP-36682 | Shri Prakash Bajpai | WhatsApp Share implemented --- src/assets/icons/ChevronDown.tsx | 119 +++++++++++++----- src/assets/icons/ChevronUp.tsx | 105 ++++++++++++---- .../feedback/FeedbackDetailContainer.tsx | 10 +- .../feedback/FeedbackDetailItem.tsx | 1 + 4 files changed, 178 insertions(+), 57 deletions(-) diff --git a/src/assets/icons/ChevronDown.tsx b/src/assets/icons/ChevronDown.tsx index 80112095..e6301ca6 100644 --- a/src/assets/icons/ChevronDown.tsx +++ b/src/assets/icons/ChevronDown.tsx @@ -1,53 +1,112 @@ // import * as React from "react" -// import Svg, { Mask, Path, G } from "react-native-svg" -// const ChevronDown = (props) => ( -// +// import Svg, { Rect, Mask, Path, G } from "react-native-svg" + +// const ChevronDown = () => ( +// +// // -// +// // // // // // + // ) -// export default ChevronDown +// export default ChevronDown; -import React from 'react'; -import Svg, { Path } from 'react-native-svg'; -import { COLORS } from '../../../RN-UI-LIB/src/styles/colors'; -import { IconProps } from '../../../RN-UI-LIB/src/Icons/types'; - -const ChevronDown: React.FC = (props) => { - const { fillColor = COLORS.TEXT.LIGHT, size = 16, rotateX = 0 } = props; +import * as React from 'react'; +import Svg, { Mask, Path, G } from 'react-native-svg'; +const ChevronDown = () => { return ( - + ); }; - export default ChevronDown; + +// import React from 'react'; +// import Svg, { Path } from 'react-native-svg'; +// import { COLORS } from '../../../RN-UI-LIB/src/styles/colors'; +// import { IconProps } from '../../../RN-UI-LIB/src/Icons/types'; + +// const ChevronDown: React.FC = (props) => { +// const { fillColor = COLORS.TEXT.LIGHT, size = 16, rotateX = 0 } = props; +// return ( +// +// +// +// ); +// }; + +// export default ChevronDown; + +// import * as React from 'react'; +// import Svg, { Path } from 'react-native-svg'; +// import { IconProps } from './types'; + +// interface IChevron extends IconProps { +// width?: number; +// height?: number; +// } + +// const ChevronDown: React.FC = (props) => { +// const { width = 5, height = 8} = props; +// const rotateY = 180; +// return ( +// +// +// +// ); +// }; + +// export default ChevronDown; + +// import * as React from 'react'; +// import ArrowSolidDownIcon from '../../../RN-UI-LIB/src/Icons/ArrowSolidDownIcon'; +// import { View } from 'react-native'; + +// const ChevronDown = () => { +// return ( +// +// +// +// ); +// }; +// export default ChevronDown; diff --git a/src/assets/icons/ChevronUp.tsx b/src/assets/icons/ChevronUp.tsx index 7bc95ccc..a257be2a 100644 --- a/src/assets/icons/ChevronUp.tsx +++ b/src/assets/icons/ChevronUp.tsx @@ -1,28 +1,87 @@ import * as React from 'react'; -import Svg, { Rect, Mask, Path, G } from 'react-native-svg'; - -const ChevronUp = (props) => ( - - - - - - +import Svg, { Mask, Path, G } from 'react-native-svg'; +const ChevronUp = () => { + return ( + - - -); + + ); +}; export default ChevronUp; + +// import * as React from 'react'; +// import Svg, { Rect, Mask, Path, G } from 'react-native-svg'; + +// const ChevronUp = (props) => ( +// +// +// +// +// +// +// +// +// +// ); +// export default ChevronUp; + +// import * as React from 'react'; +// import Svg, { Path } from 'react-native-svg'; +// import { IconProps } from '../../../RN-UI-LIB/src/Icons/types'; + +// interface IChevron extends IconProps { +// width?: number; +// height?: number; +// } +// // by default Right Chevron +// const ChevronUp: React.FC = (props) => { +// const { width = 5, height = 8} = props; +// return ( +// +// +// +// ); +// }; + +// export default ChevronUp; + +// import * as React from 'react'; +// import ArrowSolidDownIcon from '../../../RN-UI-LIB/src/Icons/ArrowSolidDownIcon'; +// import { View } from 'react-native'; + +// const ChevronUp = ( ) => { +// return ( +// +// +// +// ); +// }; + +// export default ChevronUp; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx index 1b4b6025..e170e209 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx @@ -28,6 +28,8 @@ import LineLoader from '../../../../RN-UI-LIB/src/components/suspense_loader/Lin import NoPastFeedbackIcon from '../../../assets/icons/NoPastFeedbackIcon'; import { expandAccordianPath } from '../../../constants/icons/ExpandAccordian'; import { shrinkAccordianPath } from '../../../constants/icons/ShrinkAccordian'; +import ChevronDown from '../../../assets/icons/ChevronDown'; +import ChevronUp from '../../../assets/icons/ChevronUp'; const FEEDBACK_PAGE_TITLE = 'All feedbacks'; const ADDRESS_FEEDBACK_PAGE_TITLE = 'Address feedback'; @@ -263,10 +265,10 @@ const FeedbackDetailContainer: React.FC = ({ route: ro caseId={caseId} /> } - // customExpandUi={{ - // whenCollapsed: , - // whenExpanded: , - // }} + customExpandUi={{ + whenCollapsed: , + whenExpanded: , + }} onExpanded={(value) => { setIsExpanded(value); }} diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index afaa7248..a0e1ed9c 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -192,6 +192,7 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: const mimeType = 'image/*'; console.log(DeviceUtilsModule); DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType); + RNFetchBlob.fs.unlink(imagePath); // DeviceUtilsModule.helloWorld(); }); From b183dfd83f6c3c8fba66b2ffd9888ddb65d13733 Mon Sep 17 00:00:00 2001 From: Varnit Goyal Date: Mon, 25 Sep 2023 18:36:30 +0530 Subject: [PATCH 12/26] TP-00000 | merged to master --- RN-UI-LIB | 2 +- android/app/src/main/AndroidManifest.xml | 6 +++- .../main/java/com/avapp/AlarmReceiver.java | 16 ++++++++++ .../main/java/com/avapp/AlarmScheduler.java | 32 +++++++++++++++++++ .../ForegroundServiceBroadcastReciever.java | 22 +++++++++++++ .../src/main/java/com/avapp/MainActivity.java | 14 +++++++- 6 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 android/app/src/main/java/com/avapp/AlarmReceiver.java create mode 100644 android/app/src/main/java/com/avapp/AlarmScheduler.java create mode 100644 android/app/src/main/java/com/avapp/ForegroundServiceBroadcastReciever.java diff --git a/RN-UI-LIB b/RN-UI-LIB index 5b77f75c..4c7f4f68 160000 --- a/RN-UI-LIB +++ b/RN-UI-LIB @@ -1 +1 @@ -Subproject commit 5b77f75cb69fc7c8ed7d8a3acc84be1eb6564c64 +Subproject commit 4c7f4f6880d96bffa856e04d7b2b4d383e42c5cf diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b85cb2e2..b5c3d67a 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -30,6 +30,7 @@ -> + 21 -> lollipop 28 -> - + + + = Build.VERSION_CODES.M) { + alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTimeMillis, pendingIntent); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + alarmManager.setExact(AlarmManager.RTC_WAKEUP, alarmTimeMillis, pendingIntent); + // alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, intervalMillis, repeatMillis,pendingIntent); + } else { + alarmManager.set(AlarmManager.RTC_WAKEUP, alarmTimeMillis, pendingIntent); + //alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarmTimeMillis, repeatMillis, pendingIntent); + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/avapp/ForegroundServiceBroadcastReciever.java b/android/app/src/main/java/com/avapp/ForegroundServiceBroadcastReciever.java new file mode 100644 index 00000000..d9df5097 --- /dev/null +++ b/android/app/src/main/java/com/avapp/ForegroundServiceBroadcastReciever.java @@ -0,0 +1,22 @@ +package com.avapp; + + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + + +public class ForegroundServiceBroadcastReciever extends BroadcastReceiver { + public static final String ACTION_CUSTOM_DESTROY = "com.avapp.ACTION_FOREGROUND_SERVICE_DESTROYED"; + + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction() != null && intent.getAction().equals(ACTION_CUSTOM_DESTROY)) { + // Handle the broadcast here + String extraData = intent.getStringExtra("key"); + Log.d("BROADCAST_RECEIVED", "broadcast received when service destroyed"); + // Do something with the extra data + } + } +} diff --git a/android/app/src/main/java/com/avapp/MainActivity.java b/android/app/src/main/java/com/avapp/MainActivity.java index 9ac0a557..a6c02035 100644 --- a/android/app/src/main/java/com/avapp/MainActivity.java +++ b/android/app/src/main/java/com/avapp/MainActivity.java @@ -3,10 +3,17 @@ package com.avapp; import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivityDelegate; import com.facebook.react.ReactRootView; + +import android.content.IntentFilter; import android.os.Bundle; public class MainActivity extends ReactActivity { + private ForegroundServiceBroadcastReciever receiver; + public static final String ACTION_CUSTOM_DESTROY = "com.avapp.ACTION_FOREGROUND_SERVICE_DESTROYED"; + + + /** * Returns the name of the main component registered from JavaScript. This is used to schedule * rendering of the component. @@ -20,7 +27,12 @@ public class MainActivity extends ReactActivity { // https://github.com/software-mansion/react-native-screens#android @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(null); + super.onCreate(null); + receiver = new ForegroundServiceBroadcastReciever(); + IntentFilter filter = new IntentFilter(ACTION_CUSTOM_DESTROY); + registerReceiver(receiver, filter); + AlarmScheduler.scheduleRepeatingAlarm(this); // 'this' is the context + } From 7cd4d27b94b3691596f45f63b788bf1cbbca5413 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Mon, 25 Sep 2023 21:04:40 +0530 Subject: [PATCH 13/26] Whatsapp feddback share done --- src/components/utlis/commonFunctions.ts | 1 + .../caseDetails/feedback/FeedbackDetailItem.tsx | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/utlis/commonFunctions.ts b/src/components/utlis/commonFunctions.ts index caf22894..8edfb657 100644 --- a/src/components/utlis/commonFunctions.ts +++ b/src/components/utlis/commonFunctions.ts @@ -217,6 +217,7 @@ export function isNullOrUndefined(val: any): boolean { export const getLoanAccountNumber = (caseDetail: CaseDetail) => { const { loanAccountNumber, loanDetails } = caseDetail ?? {}; + console.log(loanAccountNumber, loanDetails?.loanAccountNumber); return loanAccountNumber ?? loanDetails?.loanAccountNumber ?? ''; }; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index a0e1ed9c..36010659 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -203,15 +203,16 @@ const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetai const emiEcheduleData = useAppSelector( (state) => state.emiSchedule?.[getLoanAccountNumber(caseDetails)] ); - const { data: emiData } = emiEcheduleData; + const { data: emiData } = emiEcheduleData || {}; const filteredData = getFilteredData(emiData, EmiSelectedTab.UNPAID); return ( console.log('In feedback detail item'), - console.log(caseId), - console.log(caseDetails), - console.log(emiData), - console.log(filteredData), + console.log({ caseId }), + console.log({ caseDetails }), + console.log({ emiEcheduleData }), + console.log({ emiData }), + console.log({ filteredData }), ( From 3c8becdc94b03c8f50fe19b294a0d25e473db2b7 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Tue, 26 Sep 2023 02:59:55 +0530 Subject: [PATCH 14/26] Adjusted Chevron colour --- src/assets/icons/ChevronDown.tsx | 2 +- src/assets/icons/ChevronUp.tsx | 2 +- .../feedback/FeedbackDetailContainer.tsx | 4 ++++ .../feedback/FeedbackDetailItem.tsx | 23 +++++++++++++++++-- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/assets/icons/ChevronDown.tsx b/src/assets/icons/ChevronDown.tsx index e6301ca6..81a26a44 100644 --- a/src/assets/icons/ChevronDown.tsx +++ b/src/assets/icons/ChevronDown.tsx @@ -32,7 +32,7 @@ const ChevronDown = () => { ); diff --git a/src/assets/icons/ChevronUp.tsx b/src/assets/icons/ChevronUp.tsx index a257be2a..61087e3d 100644 --- a/src/assets/icons/ChevronUp.tsx +++ b/src/assets/icons/ChevronUp.tsx @@ -5,7 +5,7 @@ const ChevronUp = () => { ); diff --git a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx index e170e209..b930f48a 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx @@ -30,6 +30,10 @@ import { expandAccordianPath } from '../../../constants/icons/ExpandAccordian'; import { shrinkAccordianPath } from '../../../constants/icons/ShrinkAccordian'; import ChevronDown from '../../../assets/icons/ChevronDown'; import ChevronUp from '../../../assets/icons/ChevronUp'; +import { getLoanAccountNumber } from '../../../components/utlis/commonFunctions'; +import { UnifiedCaseDetailsTypes, getCaseUnifiedData } from '../../../action/caseApiActions'; +import { getFilteredData } from '../../emiSchedule/utils'; +import { EmiSelectedTab } from '../../emiSchedule/EmiScheduleTab'; const FEEDBACK_PAGE_TITLE = 'All feedbacks'; const ADDRESS_FEEDBACK_PAGE_TITLE = 'Address feedback'; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index 36010659..3b236acf 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -29,10 +29,11 @@ import IconLabel from '../../../common/IconLabel'; import WhatsAppFeedbackShareIcon from '../../../assets/icons/WhatsAppIcon'; import RNFetchBlob from 'rn-fetch-blob'; import Share from 'react-native-share'; -import { useAppSelector } from '../../../hooks'; +import { useAppDispatch, useAppSelector } from '../../../hooks'; import { InteractionStatuses } from '../../allCases/interface'; import { EmiSelectedTab } from '../../emiSchedule/EmiScheduleTab'; import { getFilteredData } from '../../emiSchedule/utils'; +import { UnifiedCaseDetailsTypes, getCaseUnifiedData } from '../../../action/caseApiActions'; const { DeviceUtilsModule } = NativeModules; interface IFeedbackDetailItem { @@ -199,10 +200,27 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: }; const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetailItem) => { + const dispatch = useAppDispatch(); const caseDetails = useAppSelector((state) => state.allCases.caseDetails[caseId]); - const emiEcheduleData = useAppSelector( + var emiEcheduleData = useAppSelector( (state) => state.emiSchedule?.[getLoanAccountNumber(caseDetails)] ); + + if (emiEcheduleData.data === undefined) { + console.log('Fetching API'); + async () => { + await dispatch( + getCaseUnifiedData( + [getLoanAccountNumber(caseDetails)], + [UnifiedCaseDetailsTypes.EMI_SCHEDULE, UnifiedCaseDetailsTypes.REPAYMENTS] + ) + ); + }; + emiEcheduleData = useAppSelector( + (state) => state.emiSchedule?.[getLoanAccountNumber(caseDetails)] + ); + } + const { data: emiData } = emiEcheduleData || {}; const filteredData = getFilteredData(emiData, EmiSelectedTab.UNPAID); @@ -213,6 +231,7 @@ const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetai console.log({ emiEcheduleData }), console.log({ emiData }), console.log({ filteredData }), + console.log({ feedbackItem }), ( From 618c4bb39435d1055b475df44a06a242e9df9da7 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Tue, 26 Sep 2023 13:54:32 +0530 Subject: [PATCH 15/26] EMI amount also shared --- .../addressGeolocation/AddressContainer.tsx | 5 +-- .../feedback/FeedbackDetailItem.tsx | 36 +++++++++++-------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/screens/addressGeolocation/AddressContainer.tsx b/src/screens/addressGeolocation/AddressContainer.tsx index 1b590448..6b3afec3 100644 --- a/src/screens/addressGeolocation/AddressContainer.tsx +++ b/src/screens/addressGeolocation/AddressContainer.tsx @@ -56,11 +56,12 @@ const AddressContainer: React.FC = ({ return ( - {filterNearMetaAddresses({ + {/* {filterNearMetaAddresses({ metaAddresses: groupedAddressList, maximumDistance: MAXIMUM_ALLOWED_DISTANCE_FOR_GROUPED_ADDRESSES, currentLocationCoordinates: currentGeolocationCoordinates, - })?.map((groupedAddress: IGroupedAddressesItem, index: number) => { + })?. */} + {groupedAddressList?.map((groupedAddress: IGroupedAddressesItem, index: number) => { const lastFeedbackForAddress = addressFeedbacks.find( (addressFeedback) => addressFeedback?.addressReferenceId === groupedAddress?.metaAddress?.id diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index 3b236acf..f7213f51 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -1,4 +1,4 @@ -import React, { ReactNode } from 'react'; +import React, { ReactNode, useEffect, useState } from 'react'; import { View, StyleSheet, TouchableOpacity, Linking, Platform, NativeModules } from 'react-native'; import Text from '../../../../RN-UI-LIB/src/components/Text'; import { GenericStyles } from '../../../../RN-UI-LIB/src/styles'; @@ -73,8 +73,9 @@ function getLocationLink(latitude: string, longitude: string): string { } const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: any) => { - console.log('Printing filtered data'); - console.log(filteredData); + console.log('Printing casedetails in sendToWhatsapp'); + console.log({ caseDetails }); + console.log(caseDetails?.outstandingEmiDetails?.[0]?.emiAmount); var message = '*Visit Feedback for ' + sanitizeString(caseDetails?.customerName) + '*\n'; message += '_' + @@ -83,7 +84,7 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: message += 'LAN: ' + sanitizeString(caseDetails?.loanAccountNumber); message += '| DPD Bucket: ' + sanitizeString(caseDetails?.dpdBucket); console.log(filteredData); - message += '| EMI: ' + filteredData?.[0]?.totalOverDueAmount + '\n\n'; + message += '| EMI: ' + caseDetails?.outstandingEmiDetails?.[0]?.emiAmount + '\n\n'; message += 'Disposition: ' + sanitizeString(feedbackItem.interactionStatus); // console.log('PRIIIIIIIINTINGGGGGGGGGGGGGGGG'); // console.log(feedbackItem); @@ -199,27 +200,34 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: }); }; +// const useEmiEcheduleData = (caseDetails: any) => { +// const [apiCalled, setApiCalled] = useState(false); + +// return emiEcheduleData; +// }; + const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetailItem) => { - const dispatch = useAppDispatch(); const caseDetails = useAppSelector((state) => state.allCases.caseDetails[caseId]); + var emiEcheduleData = useAppSelector( (state) => state.emiSchedule?.[getLoanAccountNumber(caseDetails)] ); + const dispatch = useAppDispatch(); - if (emiEcheduleData.data === undefined) { - console.log('Fetching API'); - async () => { - await dispatch( + useEffect(() => { + if (emiEcheduleData?.data === undefined) { + console.log('Fetching API'); + + const apiFetchedData = dispatch( getCaseUnifiedData( [getLoanAccountNumber(caseDetails)], [UnifiedCaseDetailsTypes.EMI_SCHEDULE, UnifiedCaseDetailsTypes.REPAYMENTS] ) ); - }; - emiEcheduleData = useAppSelector( - (state) => state.emiSchedule?.[getLoanAccountNumber(caseDetails)] - ); - } + + console.log({ apiFetchedData }); + } + }, []); const { data: emiData } = emiEcheduleData || {}; const filteredData = getFilteredData(emiData, EmiSelectedTab.UNPAID); From bf9c4eaf4c6e5bb191d44b82998d78d5cd6c3c75 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Wed, 27 Sep 2023 16:46:47 +0530 Subject: [PATCH 16/26] TP36628 | WhatsApp Feedback Share --- RN-UI-LIB | 2 +- android/app/src/main/AndroidManifest.xml | 11 ++ .../java/com/avapp/DeviceUtilsModule.java | 61 +++++++-- .../addressGeolocation/AddressContainer.tsx | 5 +- src/screens/allCases/constants.ts | 3 + .../feedback/FeedbackDetailContainer.tsx | 7 +- .../feedback/FeedbackDetailItem.tsx | 120 +++++++----------- 7 files changed, 121 insertions(+), 88 deletions(-) diff --git a/RN-UI-LIB b/RN-UI-LIB index 5b77f75c..4c7f4f68 160000 --- a/RN-UI-LIB +++ b/RN-UI-LIB @@ -1 +1 @@ -Subproject commit 5b77f75cb69fc7c8ed7d8a3acc84be1eb6564c64 +Subproject commit 4c7f4f6880d96bffa856e04d7b2b4d383e42c5cf diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b85cb2e2..60ee6722 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -30,6 +30,17 @@ -> + + + + + + + + + + + 21 -> lollipop 28 -> packages = packageManager.getInstalledPackages(PackageManager.GET_META_DATA); + for (PackageInfo packageInfo : packages) { + String appName = packageInfo.applicationInfo.loadLabel(packageManager).toString(); + String packageName = packageInfo.packageName; + int versionCode = packageInfo.versionCode; + String versionName = packageInfo.versionName; + + if(packageName.equals("com.whatsapp")){ + return true; + } + } + return false; + } + + @ReactMethod + public void sendFeedbackToWhatsapp(String encodedMessage, String encodedImageUri, String mimeType, Promise promise) { + + try{ Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, encodedMessage); sendIntent.setType(mimeType); sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - File imageFile = convertBase64ToFile(getReactApplicationContext(),encodedImageUri); - Uri fileUri = FileProvider.getUriForFile(getReactApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", new File( - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), - imageFile.getName() - ) - ); - - sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); + if(encodedImageUri != null) { + File imageFile = convertBase64ToFile(getReactApplicationContext(), encodedImageUri); + Uri fileUri = FileProvider.getUriForFile(getReactApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", new File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + imageFile.getName() + ) + ); + sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); + } sendIntent.setPackage("com.whatsapp"); + Log.d("Reached if","reached if"); + + + PackageManager pm = getCurrentActivity().getPackageManager(); + if(isWhatsAppInstalled()){ + getCurrentActivity().startActivity(sendIntent); + promise.resolve(true); + } else { + promise.resolve(false); + } + + }catch (Error e){ + promise.reject(e); + } - // Start the activity - getCurrentActivity().startActivity(sendIntent); return; } diff --git a/src/screens/addressGeolocation/AddressContainer.tsx b/src/screens/addressGeolocation/AddressContainer.tsx index 6b3afec3..1b590448 100644 --- a/src/screens/addressGeolocation/AddressContainer.tsx +++ b/src/screens/addressGeolocation/AddressContainer.tsx @@ -56,12 +56,11 @@ const AddressContainer: React.FC = ({ return ( - {/* {filterNearMetaAddresses({ + {filterNearMetaAddresses({ metaAddresses: groupedAddressList, maximumDistance: MAXIMUM_ALLOWED_DISTANCE_FOR_GROUPED_ADDRESSES, currentLocationCoordinates: currentGeolocationCoordinates, - })?. */} - {groupedAddressList?.map((groupedAddress: IGroupedAddressesItem, index: number) => { + })?.map((groupedAddress: IGroupedAddressesItem, index: number) => { const lastFeedbackForAddress = addressFeedbacks.find( (addressFeedback) => addressFeedback?.addressReferenceId === groupedAddress?.metaAddress?.id diff --git a/src/screens/allCases/constants.ts b/src/screens/allCases/constants.ts index fee142c9..ec1d1c1d 100644 --- a/src/screens/allCases/constants.ts +++ b/src/screens/allCases/constants.ts @@ -77,6 +77,9 @@ export const ToastMessages = { CASES_DELETION_DISABLED: 'Case deletion is disabled during the generation of visit plan', GEOLOCATION_COORDINATES_INCORRECT: 'Geolocation not found', IMAGE_UPLOAD_SUCCESS: 'Your ID card has been sent for approval', + WHATSAPP_FEEDBACK_SHARE_SUCCESS: 'Feedback shared successfully via WhatsApp', + WHATSAPP_FEEDBACK_SHARE_FAILURE: 'Feedback sharing failed via WhatsApp', + WHATSAPP_NOT_INSTALLED: 'WhatsApp is not installed on your device', }; export enum BOTTOM_TAB_ROUTES { diff --git a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx index b930f48a..e3684101 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx @@ -253,8 +253,9 @@ const FeedbackDetailContainer: React.FC = ({ route: ro > answer.questionName === 'PTP Date'); if (ptpDate.length > 0) { message += ' for ' + sanitizeString(ptpDate[0].inputDate) + '\n\n'; @@ -110,7 +111,7 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: feedbackItem.metadata?.interactionLongitude && FIELD_FEEDBACKS.includes(feedbackItem.type) ? (message += - 'Location: ' + + 'Location of feedback: ' + sanitizeString( getLocationLink( feedbackItem.metadata?.interactionLatitude, @@ -135,77 +136,42 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: }) .fetch('GET', imageUri) .then((resp: any) => { - imagePath = resp.path(); - return resp.readFile('base64'); + if (resp.info().status !== 200) { + return ''; + } else { + imagePath = resp.path(); + return resp.readFile('base64'); + } }) .then((base64Data: any) => { var imageUrl = base64Data; - const encodedMessage = encodeURIComponent(message); - const encodedImageUri = encodeURIComponent(imageUrl); - var url = `whatsapp://send?text=${encodedMessage}`; - if (encodedImageUri !== '') { - url += `&media=${encodedImageUri}`; - } - console.log(message); - console.log(imageUri); - console.log(imageUrl); - console.log(url); - //Linking.openURL(url); - ////////////////////////////////////////////////////////////// - let shareImage = { - title: 'Agent Feedback', - message: message, - url: imageUrl, - social: Share.Social.WHATSAPP, - }; - //console.log(shareImage); - //Share.open(shareImage); - //return RNFetchBlob.fs.unlink(imagePath); - //////////////////////////////////////////////////////////////// - // Linking.canOpenURL(url) - // .then(isInstalled => { - // if (!isInstalled) { - // console.log(message); - // console.log(url); - // console.error('WhatsApp is not installed on this device.'); - // } else { - // console.log(message); - // return Linking.openURL(url); - // } - // }) - // .catch(error => console.error('An error occurred', error)); - - // const sendIntent = Platform.select({ - // ios: null, - // android: { - // action: 'android.intent.action.SEND', - // intentType: 'text/plain', - // extras: { - // 'android.intent.extra.TEXT': encodedMessage, - // 'android.intent.extra.STREAM': encodedImageUri, - // 'android.intent.extra.SUBJECT': 'Subject', - // }, - // packageName: 'com.whatsapp', - // }, - // }); - - // return Linking.openURL(sendIntent); const mimeType = 'image/*'; console.log(DeviceUtilsModule); - DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType); + DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType) + .then((res: any) => { + console.log(res); + res + ? toast({ + text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_SUCCESS, + type: 'success', + }) + : toast({ + text1: ToastMessages.WHATSAPP_NOT_INSTALLED, + type: 'error', + }); + }) + .catch((err: any) => { + console.log(err); + toast({ + text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_FAILURE, + type: 'error', + }); + }); RNFetchBlob.fs.unlink(imagePath); - - // DeviceUtilsModule.helloWorld(); }); }; -// const useEmiEcheduleData = (caseDetails: any) => { -// const [apiCalled, setApiCalled] = useState(false); - -// return emiEcheduleData; -// }; - const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetailItem) => { const caseDetails = useAppSelector((state) => state.allCases.caseDetails[caseId]); @@ -241,7 +207,7 @@ const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetai console.log({ filteredData }), console.log({ feedbackItem }), ( - + {feedbackTypeIcon[feedbackItem.type] ? ( {feedbackTypeIcon[feedbackItem.type]} @@ -270,11 +236,12 @@ const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetai ]} > {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_DATE_FORMAT))} -   ●   + {/*   ●   */} + {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_TIME_FORMAT))} @@ -300,13 +267,14 @@ const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetai feedbackItem.metadata?.interactionLongitude ) } - style={[GenericStyles.row, GenericStyles.pv12]} + style={[GenericStyles.row, styles.BtnPadding]} > Open map sendToWhatsapp(feedbackItem, caseDetails, filteredData)} + style={[GenericStyles.row, styles.BtnPadding]} > Date: Wed, 27 Sep 2023 19:20:14 +0530 Subject: [PATCH 17/26] Manifest updated --- android/app/src/main/AndroidManifest.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 60ee6722..1799bd6d 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -31,13 +31,13 @@ -> - + - + From 2b540a26bde349db0f302514b46d66cd082c6487 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Wed, 27 Sep 2023 23:38:41 +0530 Subject: [PATCH 18/26] Toast modified --- .../caseDetails/feedback/FeedbackDetailItem.tsx | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index 6e90163f..f2a68fb3 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -151,15 +151,12 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType) .then((res: any) => { console.log(res); - res - ? toast({ - text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_SUCCESS, - type: 'success', - }) - : toast({ - text1: ToastMessages.WHATSAPP_NOT_INSTALLED, - type: 'error', - }); + if (!res) { + toast({ + text1: ToastMessages.WHATSAPP_NOT_INSTALLED, + type: 'error', + }); + } }) .catch((err: any) => { console.log(err); From 7b34ee13a8944e5d6f4180b3af425e049b69d4d5 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Thu, 28 Sep 2023 02:01:56 +0530 Subject: [PATCH 19/26] Handled unable to fetch image case --- RN-UI-LIB | 2 +- .../src/main/java/com/avapp/DeviceUtilsModule.java | 14 +++++++++----- .../caseDetails/feedback/FeedbackDetailItem.tsx | 10 ++++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/RN-UI-LIB b/RN-UI-LIB index 4c7f4f68..5b77f75c 160000 --- a/RN-UI-LIB +++ b/RN-UI-LIB @@ -1 +1 @@ -Subproject commit 4c7f4f6880d96bffa856e04d7b2b4d383e42c5cf +Subproject commit 5b77f75cb69fc7c8ed7d8a3acc84be1eb6564c64 diff --git a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java index 5e5c13b5..2c043519 100644 --- a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java +++ b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java @@ -142,10 +142,15 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, encodedMessage); - sendIntent.setType(mimeType); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - if(encodedImageUri != null) { + if(encodedImageUri.equals("")) { + Log.d("encodedImageUri", "Null String"); + sendIntent.setType("text/plain"); + + } else { + Log.d("encodedImageUri", encodedImageUri); + sendIntent.setType(mimeType); + sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); File imageFile = convertBase64ToFile(getReactApplicationContext(), encodedImageUri); Uri fileUri = FileProvider.getUriForFile(getReactApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), @@ -158,8 +163,7 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act sendIntent.setPackage("com.whatsapp"); Log.d("Reached if","reached if"); - - PackageManager pm = getCurrentActivity().getPackageManager(); + Log.d("sendIntent", sendIntent.toString()); if(isWhatsAppInstalled()){ getCurrentActivity().startActivity(sendIntent); promise.resolve(true); diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index f2a68fb3..dc0b1cbf 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -70,7 +70,7 @@ const openGeolocation = (latitude: string, longitude: string) => { }; function getLocationLink(latitude: string, longitude: string): string { - const link = `https://www.google.com/maps?q=${encodeURIComponent(`${latitude},${longitude}`)}`; + const link = 'https://www.google.com/maps/search/?api=1&query=' + latitude + ',' + longitude; return link; } @@ -84,14 +84,15 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: sanitizeString(dateFormat(new Date(feedbackItem.createdAt), 'DD MMM, YYYY | HH:mm A')) + '_\n\n'; message += 'LAN: ' + sanitizeString(caseDetails?.loanAccountNumber); - message += ' | DPD Bucket: ' + sanitizeString(caseDetails?.dpdBucket); + message += '\nDPD Bucket: ' + sanitizeString(caseDetails?.dpdBucket); console.log(filteredData); - message += ' | EMI: ' + caseDetails?.outstandingEmiDetails?.[0]?.emiAmount + '\n\n'; + message += '\nEMI: ' + caseDetails?.outstandingEmiDetails?.[0]?.emiAmount + '\n\n'; message += 'Disposition: ' + sanitizeString(feedbackItem.interactionStatus); const ptpDate = feedbackItem.answerViews.filter((answer) => answer.questionName === 'PTP Date'); if (ptpDate.length > 0) { - message += ' for ' + sanitizeString(ptpDate[0].inputDate) + '\n\n'; + message += + ' for ' + sanitizeString(dateFormat(new Date(ptpDate[0].inputDate), 'DD MMM, YYYY')) + '\n\n'; } else { message += '\n\n'; } @@ -147,6 +148,7 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: var imageUrl = base64Data; const mimeType = 'image/*'; + console.log({ message }); console.log(DeviceUtilsModule); DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType) .then((res: any) => { From b6a0f04e9bb374e3d5c69cb1b0e54a1a579e3b0c Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Thu, 28 Sep 2023 02:34:21 +0530 Subject: [PATCH 20/26] Cleaned code --- .../java/com/avapp/DeviceUtilsModule.java | 28 +- src/assets/icons/ChevronDown.tsx | 99 ------ src/assets/icons/ChevronUp.tsx | 74 ----- .../caseDetails/CollectionCaseDetail.tsx | 2 - .../feedback/FeedbackDetailContainer.tsx | 288 ++++++++---------- .../feedback/FeedbackDetailItem.tsx | 253 +++++++-------- .../feedback/FeedbackListContainer.tsx | 23 +- .../caseDetails/feedback/FeedbackListItem.tsx | 1 - 8 files changed, 247 insertions(+), 521 deletions(-) diff --git a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java index 2c043519..683377c7 100644 --- a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java +++ b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java @@ -94,23 +94,13 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act } private static File convertBase64ToFile(Context context,String base64Data) { try { - // Convert Base64 to byte array byte[] decodedBytes = Base64.decode(base64Data, Base64.DEFAULT); - - // Create a temporary file to store the Base64 data - File outputDir = context.getCacheDir(); - - - File file = File.createTempFile("temp_image", ".jpg", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)); - - // Write the byte array to the file FileOutputStream fos = new FileOutputStream(file); fos.write(decodedBytes); fos.flush(); fos.close(); - return file; } catch (IOException e) { Log.e("ShareUtils", "Failed to convert Base64 to file: " + e.getMessage()); @@ -123,11 +113,7 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act List packages = packageManager.getInstalledPackages(PackageManager.GET_META_DATA); for (PackageInfo packageInfo : packages) { - String appName = packageInfo.applicationInfo.loadLabel(packageManager).toString(); String packageName = packageInfo.packageName; - int versionCode = packageInfo.versionCode; - String versionName = packageInfo.versionName; - if(packageName.equals("com.whatsapp")){ return true; } @@ -136,22 +122,19 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act } @ReactMethod - public void sendFeedbackToWhatsapp(String encodedMessage, String encodedImageUri, String mimeType, Promise promise) { + public void sendFeedbackToWhatsapp(String message, String imageUrl, String mimeType, Promise promise) { try{ Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_TEXT, encodedMessage); + sendIntent.putExtra(Intent.EXTRA_TEXT, message); - if(encodedImageUri.equals("")) { - Log.d("encodedImageUri", "Null String"); + if(imageUrl.equals("")) { sendIntent.setType("text/plain"); - } else { - Log.d("encodedImageUri", encodedImageUri); sendIntent.setType(mimeType); sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - File imageFile = convertBase64ToFile(getReactApplicationContext(), encodedImageUri); + File imageFile = convertBase64ToFile(getReactApplicationContext(), imageUrl); Uri fileUri = FileProvider.getUriForFile(getReactApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), imageFile.getName() @@ -161,9 +144,6 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act } sendIntent.setPackage("com.whatsapp"); - Log.d("Reached if","reached if"); - - Log.d("sendIntent", sendIntent.toString()); if(isWhatsAppInstalled()){ getCurrentActivity().startActivity(sendIntent); promise.resolve(true); diff --git a/src/assets/icons/ChevronDown.tsx b/src/assets/icons/ChevronDown.tsx index 81a26a44..91bd8a91 100644 --- a/src/assets/icons/ChevronDown.tsx +++ b/src/assets/icons/ChevronDown.tsx @@ -1,30 +1,3 @@ -// import * as React from "react" -// import Svg, { Rect, Mask, Path, G } from "react-native-svg" - -// const ChevronDown = () => ( -// -// -// -// -// -// -// -// -// - -// ) -// export default ChevronDown; - import * as React from 'react'; import Svg, { Mask, Path, G } from 'react-native-svg'; const ChevronDown = () => { @@ -38,75 +11,3 @@ const ChevronDown = () => { ); }; export default ChevronDown; - -// import React from 'react'; -// import Svg, { Path } from 'react-native-svg'; -// import { COLORS } from '../../../RN-UI-LIB/src/styles/colors'; -// import { IconProps } from '../../../RN-UI-LIB/src/Icons/types'; - -// const ChevronDown: React.FC = (props) => { -// const { fillColor = COLORS.TEXT.LIGHT, size = 16, rotateX = 0 } = props; -// return ( -// -// -// -// ); -// }; - -// export default ChevronDown; - -// import * as React from 'react'; -// import Svg, { Path } from 'react-native-svg'; -// import { IconProps } from './types'; - -// interface IChevron extends IconProps { -// width?: number; -// height?: number; -// } - -// const ChevronDown: React.FC = (props) => { -// const { width = 5, height = 8} = props; -// const rotateY = 180; -// return ( -// -// -// -// ); -// }; - -// export default ChevronDown; - -// import * as React from 'react'; -// import ArrowSolidDownIcon from '../../../RN-UI-LIB/src/Icons/ArrowSolidDownIcon'; -// import { View } from 'react-native'; - -// const ChevronDown = () => { -// return ( -// -// -// -// ); -// }; -// export default ChevronDown; diff --git a/src/assets/icons/ChevronUp.tsx b/src/assets/icons/ChevronUp.tsx index 61087e3d..5c77ab77 100644 --- a/src/assets/icons/ChevronUp.tsx +++ b/src/assets/icons/ChevronUp.tsx @@ -11,77 +11,3 @@ const ChevronUp = () => { ); }; export default ChevronUp; - -// import * as React from 'react'; -// import Svg, { Rect, Mask, Path, G } from 'react-native-svg'; - -// const ChevronUp = (props) => ( -// -// -// -// -// -// -// -// -// -// ); -// export default ChevronUp; - -// import * as React from 'react'; -// import Svg, { Path } from 'react-native-svg'; -// import { IconProps } from '../../../RN-UI-LIB/src/Icons/types'; - -// interface IChevron extends IconProps { -// width?: number; -// height?: number; -// } -// // by default Right Chevron -// const ChevronUp: React.FC = (props) => { -// const { width = 5, height = 8} = props; -// return ( -// -// -// -// ); -// }; - -// export default ChevronUp; - -// import * as React from 'react'; -// import ArrowSolidDownIcon from '../../../RN-UI-LIB/src/Icons/ArrowSolidDownIcon'; -// import { View } from 'react-native'; - -// const ChevronUp = ( ) => { -// return ( -// -// -// -// ); -// }; - -// export default ChevronUp; diff --git a/src/screens/caseDetails/CollectionCaseDetail.tsx b/src/screens/caseDetails/CollectionCaseDetail.tsx index 3185620a..c879bb92 100644 --- a/src/screens/caseDetails/CollectionCaseDetail.tsx +++ b/src/screens/caseDetails/CollectionCaseDetail.tsx @@ -208,8 +208,6 @@ const CollectionCaseDetails: React.FC = (props) => { customerReferenceId: caseDetail.customerReferenceId, caseId: caseId, }; - console.log('Handle Routing for Open all feedbacks'); - console.log(caseId); navigateToScreen(route, { ...params, ...commonParams }); }; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx index e3684101..adefe9a9 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx @@ -4,7 +4,6 @@ import Accordion from '../../../../RN-UI-LIB/src/components/accordian/Accordian' import NavigationHeader from '../../../../RN-UI-LIB/src/components/NavigationHeader'; import Text from '../../../../RN-UI-LIB/src/components/Text'; import { GenericStyles, SCREEN_HEIGHT, getShadowStyle } from '../../../../RN-UI-LIB/src/styles'; -import Chevron from '../../../../RN-UI-LIB/src/Icons/Chevron'; import { COLORS } from '../../../../RN-UI-LIB/src/styles/colors'; import { getPastFeedbacks, getPastFeedbacksOnAddresses } from '../../../action/feedbackActions'; import { GenericType } from '../../../common/GenericTypes'; @@ -26,14 +25,8 @@ import { setFeedbackHistoryLoading } from '../../../reducer/feedbackHistorySlice import SuspenseLoader from '../../../../RN-UI-LIB/src/components/suspense_loader/SuspenseLoader'; import LineLoader from '../../../../RN-UI-LIB/src/components/suspense_loader/LineLoader'; import NoPastFeedbackIcon from '../../../assets/icons/NoPastFeedbackIcon'; -import { expandAccordianPath } from '../../../constants/icons/ExpandAccordian'; -import { shrinkAccordianPath } from '../../../constants/icons/ShrinkAccordian'; import ChevronDown from '../../../assets/icons/ChevronDown'; import ChevronUp from '../../../assets/icons/ChevronUp'; -import { getLoanAccountNumber } from '../../../components/utlis/commonFunctions'; -import { UnifiedCaseDetailsTypes, getCaseUnifiedData } from '../../../action/caseApiActions'; -import { getFilteredData } from '../../emiSchedule/utils'; -import { EmiSelectedTab } from '../../emiSchedule/EmiScheduleTab'; const FEEDBACK_PAGE_TITLE = 'All feedbacks'; const ADDRESS_FEEDBACK_PAGE_TITLE = 'Address feedback'; @@ -41,22 +34,6 @@ const ADDRESS_FEEDBACK_PAGE_TITLE = 'Address feedback'; const SCROLL_LAYOUT_OFFSET = 10; const FEEDBACK_PER_PAGE = 5; -const shrinkAccordianProps = { - width: 24, - height: 24, - fillColor: '#0276FE', - rotateY: 0, - path: shrinkAccordianPath, -}; - -const expandAccordianProps = { - width: 24, - height: 24, - fillColor: '#0276FE', - rotateY: 0, - path: expandAccordianPath, -}; - interface IFeedbackDetailContainer { route: { params: { @@ -80,9 +57,6 @@ const FeedbackDetailContainer: React.FC = ({ route: ro }, } = routeParams; - console.log('Feedback Detail Container '); - console.log({ routeParams }); - const isPastFeedbackOnAddress = addressText || addressReferenceIds?.length; const [isExpanded, setIsExpanded] = useState(false); @@ -198,144 +172,138 @@ const FeedbackDetailContainer: React.FC = ({ route: ro }; return ( - console.log('Case ID before passing is: ' + routeParams.params.caseId), - ( - - - - } - style={[GenericStyles.ph16, GenericStyles.mt16]} - ref={(x) => setRef(x)} + + + + } + style={[GenericStyles.ph16, GenericStyles.mt16]} + ref={(x) => setRef(x)} + > + + {[...Array(8).keys()].map(() => ( + + ))} + + } > - + {feedbackList?.length ? ( <> - {[...Array(8).keys()].map(() => ( - - ))} - - } - > - - {feedbackList?.length ? ( - <> - {isPastFeedbackOnAddress ? ( - - - Feedback for - - - {addressText} - - - ) : null} - {feedbackList.map((feedback: IFeedback, index) => ( - { - const layout = event.nativeEvent.layout; - if ( - !dataSourceCord && - feedback.referenceId === activeFeedbackReferenceId - ) { - setDataSourceCord(layout.y + SCROLL_LAYOUT_OFFSET); - } + {isPastFeedbackOnAddress ? ( + + + Feedback for + + + {addressText} + + + ) : null} + {feedbackList.map((feedback: IFeedback, index) => ( + { + const layout = event.nativeEvent.layout; + if (!dataSourceCord && feedback.referenceId === activeFeedbackReferenceId) { + setDataSourceCord(layout.y + SCROLL_LAYOUT_OFFSET); + } + }} + > + + } + customExpandUi={{ + whenCollapsed: , + whenExpanded: , + }} + onExpanded={(value) => { + setIsExpanded(value); }} > - - } - customExpandUi={{ - whenCollapsed: , - whenExpanded: , - }} - onExpanded={(value) => { - setIsExpanded(value); - }} - > - - - - ))} - - handlePageChangeClickstream( - page, - CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_NEXT_PAGE_CLICKED - ) - } - onPrevPage={(page) => - handlePageChangeClickstream( - page, - CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_PREV_PAGE_CLICKED - ) - } - onFirstPage={(page) => - handlePageChangeClickstream( - page, - CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_FIRST_PAGE_CLICKED - ) - } - onLastPage={(page) => - handlePageChangeClickstream( - page, - CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_LAST_PAGE_CLICKED - ) - } - /> - - ) : ( - - - - No previous feedback found - - - )} - - - - - - ) + + + + ))} + + handlePageChangeClickstream( + page, + CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_NEXT_PAGE_CLICKED + ) + } + onPrevPage={(page) => + handlePageChangeClickstream( + page, + CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_PREV_PAGE_CLICKED + ) + } + onFirstPage={(page) => + handlePageChangeClickstream( + page, + CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_FIRST_PAGE_CLICKED + ) + } + onLastPage={(page) => + handlePageChangeClickstream( + page, + CLICKSTREAM_EVENT_NAMES.FA_VIEW_PAST_FEEDBACK_LAST_PAGE_CLICKED + ) + } + /> + + ) : ( + + + + No previous feedback found + + + )} + + + + + ); }; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index dc0b1cbf..a5c370f8 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -19,7 +19,7 @@ import { IFeedback, OPTION_TAG, } from '../../../types/feedback.types'; -import { Address as IAddress } from '../interface'; +import { CaseDetail, Address as IAddress } from '../interface'; import MapIcon from '../../../../RN-UI-LIB/src/Icons/MapIcon'; import { FEEDBACK_TYPE } from '../../../types/feedback.types'; import CallIcon from '../../../../RN-UI-LIB/src/Icons/CallIcon'; @@ -28,9 +28,7 @@ import { CLICKSTREAM_EVENT_NAMES } from '../../../common/Constants'; import IconLabel from '../../../common/IconLabel'; import WhatsAppFeedbackShareIcon from '../../../assets/icons/WhatsAppIcon'; import RNFetchBlob from 'rn-fetch-blob'; -import Share from 'react-native-share'; import { useAppDispatch, useAppSelector } from '../../../hooks'; -import { InteractionStatuses } from '../../allCases/interface'; import { EmiSelectedTab } from '../../emiSchedule/EmiScheduleTab'; import { getFilteredData } from '../../emiSchedule/utils'; import { UnifiedCaseDetailsTypes, getCaseUnifiedData } from '../../../action/caseApiActions'; @@ -74,10 +72,7 @@ function getLocationLink(latitude: string, longitude: string): string { return link; } -const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: any) => { - console.log('Printing casedetails in sendToWhatsapp'); - console.log({ caseDetails }); - console.log(caseDetails?.outstandingEmiDetails?.[0]?.emiAmount); +const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail) => { var message = '*Visit Feedback for ' + sanitizeString(caseDetails?.customerName) + '*\n'; message += '_' + @@ -85,7 +80,6 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: '_\n\n'; message += 'LAN: ' + sanitizeString(caseDetails?.loanAccountNumber); message += '\nDPD Bucket: ' + sanitizeString(caseDetails?.dpdBucket); - console.log(filteredData); message += '\nEMI: ' + caseDetails?.outstandingEmiDetails?.[0]?.emiAmount + '\n\n'; message += 'Disposition: ' + sanitizeString(feedbackItem.interactionStatus); @@ -122,170 +116,133 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: any, filteredData: '\n\n') : null; } + const imagesList = feedbackItem.answerViews.filter( (answer) => answer.questionTag === OPTION_TAG.IMAGE_UPLOAD ); - console.log(imagesList, 'imagesList'); - var imageUri = ''; + + var imageUrl = ''; + const mimeType = 'image/*'; if (imagesList.length > 0) { + var imageUri = ''; imageUri = imagesList[0].inputText ? imagesList[0].inputText : ''; - } - - let imagePath = ''; - RNFetchBlob.config({ - fileCache: true, - }) - .fetch('GET', imageUri) - .then((resp: any) => { - if (resp.info().status !== 200) { - return ''; - } else { - imagePath = resp.path(); - return resp.readFile('base64'); - } + let imagePath = ''; + RNFetchBlob.config({ + fileCache: true, }) - .then((base64Data: any) => { - var imageUrl = base64Data; - - const mimeType = 'image/*'; - console.log({ message }); - console.log(DeviceUtilsModule); - DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType) - .then((res: any) => { - console.log(res); - if (!res) { + .fetch('GET', imageUri) + .then((resp: any) => { + if (resp.info().status !== 200) { + return ''; + } else { + imagePath = resp.path(); + return resp.readFile('base64'); + } + }) + .then((base64Data: any) => { + imageUrl = base64Data; + DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType) + .then((res: any) => { + if (!res) { + toast({ + text1: ToastMessages.WHATSAPP_NOT_INSTALLED, + type: 'error', + }); + } + }) + .catch((err: any) => { toast({ - text1: ToastMessages.WHATSAPP_NOT_INSTALLED, + text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_FAILURE, type: 'error', }); - } - }) - .catch((err: any) => { - console.log(err); - toast({ - text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_FAILURE, - type: 'error', }); - }); - RNFetchBlob.fs.unlink(imagePath); - }); + RNFetchBlob.fs.unlink(imagePath); + }); + } else { + DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType); + } }; const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetailItem) => { const caseDetails = useAppSelector((state) => state.allCases.caseDetails[caseId]); - - var emiEcheduleData = useAppSelector( - (state) => state.emiSchedule?.[getLoanAccountNumber(caseDetails)] - ); - const dispatch = useAppDispatch(); - - useEffect(() => { - if (emiEcheduleData?.data === undefined) { - console.log('Fetching API'); - - const apiFetchedData = dispatch( - getCaseUnifiedData( - [getLoanAccountNumber(caseDetails)], - [UnifiedCaseDetailsTypes.EMI_SCHEDULE, UnifiedCaseDetailsTypes.REPAYMENTS] - ) - ); - - console.log({ apiFetchedData }); - } - }, []); - - const { data: emiData } = emiEcheduleData || {}; - const filteredData = getFilteredData(emiData, EmiSelectedTab.UNPAID); - return ( - console.log('In feedback detail item'), - console.log({ caseId }), - console.log({ caseDetails }), - console.log({ emiEcheduleData }), - console.log({ emiData }), - console.log({ filteredData }), - console.log({ feedbackItem }), - ( - - - {feedbackTypeIcon[feedbackItem.type] ? ( - {feedbackTypeIcon[feedbackItem.type]} - ) : null} - - {sanitizeString(feedbackItem.interactionStatus)} - - + + + {feedbackTypeIcon[feedbackItem.type] ? ( + {feedbackTypeIcon[feedbackItem.type]} + ) : null} - {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_DATE_FORMAT))} - {/*   ●   */} - - {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_TIME_FORMAT))} + {sanitizeString(feedbackItem.interactionStatus)} - - {FIELD_FEEDBACKS.includes(feedbackItem.type) - ? sanitizeString(getAddress(feedbackItem.source as IAddress)) - : sanitizeString( - [ - (feedbackItem.source as ICallingFeedback)?.recipientNumber, - feedbackItem.sourceText ? `(${feedbackItem.sourceText})` : '', - ].join(' ') - )} - - - {feedbackItem.metadata?.interactionLatitude && - FIELD_FEEDBACKS.includes(feedbackItem.type) ? ( - <> - - - openGeolocation( - feedbackItem.metadata?.interactionLatitude, - feedbackItem.metadata?.interactionLongitude - ) - } - style={[GenericStyles.row, styles.BtnPadding]} - > - Open map - - sendToWhatsapp(feedbackItem, caseDetails, filteredData)} - style={[GenericStyles.row, styles.BtnPadding]} - > - } - textStyle={{ color: COLORS.BASE.BLUE }} - /> - - - - ) : null} - ) + + {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_DATE_FORMAT))} + + {sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_TIME_FORMAT))} + + + {FIELD_FEEDBACKS.includes(feedbackItem.type) + ? sanitizeString(getAddress(feedbackItem.source as IAddress)) + : sanitizeString( + [ + (feedbackItem.source as ICallingFeedback)?.recipientNumber, + feedbackItem.sourceText ? `(${feedbackItem.sourceText})` : '', + ].join(' ') + )} + + + {feedbackItem.metadata?.interactionLatitude && FIELD_FEEDBACKS.includes(feedbackItem.type) ? ( + <> + + + openGeolocation( + feedbackItem.metadata?.interactionLatitude, + feedbackItem.metadata?.interactionLongitude + ) + } + style={[GenericStyles.row, styles.BtnPadding]} + > + Open map + + sendToWhatsapp(feedbackItem, caseDetails)} + style={[GenericStyles.row, styles.BtnPadding]} + > + } + textStyle={{ color: COLORS.BASE.BLUE }} + /> + + + + ) : null} + ); }; diff --git a/src/screens/caseDetails/feedback/FeedbackListContainer.tsx b/src/screens/caseDetails/feedback/FeedbackListContainer.tsx index 1bc7c43e..31565c4a 100644 --- a/src/screens/caseDetails/feedback/FeedbackListContainer.tsx +++ b/src/screens/caseDetails/feedback/FeedbackListContainer.tsx @@ -93,19 +93,16 @@ const FeedbackListContainer: React.FC = ({ } return ( - console.log(caseId), - ( - - {feedbackList.map((feedbackItem: IFeedback | IUnSyncedFeedbackItem, idx: number) => ( - - ))} - - ) + + {feedbackList.map((feedbackItem: IFeedback | IUnSyncedFeedbackItem, idx: number) => ( + + ))} + ); }; diff --git a/src/screens/caseDetails/feedback/FeedbackListItem.tsx b/src/screens/caseDetails/feedback/FeedbackListItem.tsx index 9e658f67..f7fc51c5 100644 --- a/src/screens/caseDetails/feedback/FeedbackListItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackListItem.tsx @@ -31,7 +31,6 @@ const FeedbackListItem: React.FC = ({ activeFeedbackReferenceId: (feedbackItem as IFeedback).referenceId, caseId: caseId, }; - console.log(caseId); navigateToScreen(route, { ...params, ...commonParams }); }; From ad36d426547ab5f78ffeb38a974e33bdfbb885f7 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Thu, 28 Sep 2023 12:54:00 +0530 Subject: [PATCH 21/26] TP-36682 | Added Clickstream events to WhatsApp share --- .../java/com/avapp/DeviceUtilsModule.java | 85 +++++++++++-------- src/common/Constants.ts | 9 ++ src/components/utlis/commonFunctions.ts | 7 ++ .../feedback/FeedbackDetailItem.tsx | 56 +++++++++--- 4 files changed, 112 insertions(+), 45 deletions(-) diff --git a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java index 683377c7..bd29cb29 100644 --- a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java +++ b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java @@ -1,5 +1,10 @@ package com.avapp; +import static android.app.Activity.RESULT_CANCELED; +import static android.app.Activity.RESULT_OK; + +import static com.imagepicker.Utils.deleteFile; + import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -12,6 +17,7 @@ import androidx.annotation.Nullable; import androidx.core.content.FileProvider; import com.facebook.react.bridge.ActivityEventListener; +import com.facebook.react.bridge.BaseActivityEventListener; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -35,12 +41,17 @@ import android.widget.Toast; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -public class DeviceUtilsModule extends ReactContextBaseJavaModule implements ActivityEventListener { +public class DeviceUtilsModule extends ReactContextBaseJavaModule { private ReactApplicationContext RNContext; + private File imageFile; + + private int WHATSAPP_SHARE_REQUEST_CODE = 12345; + public DeviceUtilsModule(@Nullable ReactApplicationContext reactContext){ super(reactContext); RNContext = reactContext; + reactContext.addActivityEventListener(mActivityEventListener); } @Override @@ -48,15 +59,22 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act return "DeviceUtilsModule"; } - @Override - public void onActivityResult(Activity activity, int i, int i1, @Nullable Intent intent) { + private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() { + @Override + public void onActivityResult(Activity activity, int i, int i1, @Nullable Intent intent) { + if(i1 != RESULT_CANCELED) { + if (i == WHATSAPP_SHARE_REQUEST_CODE) { + deleteFile(Uri.fromFile(imageFile)); + } + } + } - } + @Override + public void onNewIntent(Intent intent) { - @Override - public void onNewIntent(Intent intent) { + } + }; - } @ReactMethod public void isLocationEnabled (Promise promise) { @@ -85,7 +103,6 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act mainObject.put("packageName", packageInfo.packageName); mainObject.put("appDetails", appObject); jsonArray.put(mainObject); - Log.d("from inbuilt", jsonArray.toString()); } promise.resolve( jsonArray.toString()); }catch (Exception err){ @@ -125,33 +142,33 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule implements Act public void sendFeedbackToWhatsapp(String message, String imageUrl, String mimeType, Promise promise) { try{ - Intent sendIntent = new Intent(); - sendIntent.setAction(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_TEXT, message); + if(isWhatsAppInstalled()){ + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, message); - if(imageUrl.equals("")) { - sendIntent.setType("text/plain"); - } else { - sendIntent.setType(mimeType); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - File imageFile = convertBase64ToFile(getReactApplicationContext(), imageUrl); - Uri fileUri = FileProvider.getUriForFile(getReactApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", new File( - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), - imageFile.getName() - ) - ); - sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); - } - - sendIntent.setPackage("com.whatsapp"); - if(isWhatsAppInstalled()){ - getCurrentActivity().startActivity(sendIntent); - promise.resolve(true); - } else { - promise.resolve(false); - } - - }catch (Error e){ + if(imageUrl.equals("")) { + sendIntent.setType("text/plain"); + sendIntent.setPackage("com.whatsapp"); + getCurrentActivity().startActivity(sendIntent); + } else { + sendIntent.setType(mimeType); + sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + imageFile = convertBase64ToFile(getReactApplicationContext(), imageUrl); + Uri fileUri = FileProvider.getUriForFile(getReactApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", new File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + imageFile.getName() + ) + ); + sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); + sendIntent.setPackage("com.whatsapp"); + getCurrentActivity().startActivityForResult(sendIntent, WHATSAPP_SHARE_REQUEST_CODE); + } + promise.resolve(true); + } else { + promise.resolve(false); + } + } catch (Error e){ promise.reject(e); } diff --git a/src/common/Constants.ts b/src/common/Constants.ts index 8cf8ca88..d4a33e2b 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -427,6 +427,15 @@ export const CLICKSTREAM_EVENT_NAMES = { name: 'FA_UNIFIED_ENTITY_REQUEST_FAILED', description: 'FA_UNIFIED_ENTITY_REQUEST_FAILED', }, + FA_SHARE_FEEDBACK_CLICKED: { + name: 'FA_SHARE_FEEDBACK_CLICKED', + description: + 'When user clicks on share feedback on case details screen for any of the filled feedback', + }, + FA_SHARE_SUCCESSFUL: { + name: 'FA_SHARE_SUCCESSFUL', + description: 'When user is redirected to WhatsApp after clicking on share feedback', + }, // Notifications FA_NOTIFICATION_ICON_CLICK: { diff --git a/src/components/utlis/commonFunctions.ts b/src/components/utlis/commonFunctions.ts index 8edfb657..e87ccd4f 100644 --- a/src/components/utlis/commonFunctions.ts +++ b/src/components/utlis/commonFunctions.ts @@ -369,3 +369,10 @@ export function getDistanceFromLatLonInKm( const distance = 2 * Math.atan2(Math.sqrt(intermediateResult), Math.sqrt(1 - intermediateResult)); return EARTH_RADIUS * distance; } + +export function insertCommasinAmount(amount: any) { + const reversedAmount = amount?.toString().split('').reverse().join(''); + const groups = reversedAmount?.match(/.{1,3}/g); + const result = groups?.join(',').split('').reverse().join(''); + return result; +} diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index a5c370f8..e2dc7048 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -11,6 +11,7 @@ import { import { getGoogleMapUrl, getLoanAccountNumber, + insertCommasinAmount, sanitizeString, } from '../../../components/utlis/commonFunctions'; import { @@ -72,16 +73,24 @@ function getLocationLink(latitude: string, longitude: string): string { return link; } -const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail) => { - var message = '*Visit Feedback for ' + sanitizeString(caseDetails?.customerName) + '*\n'; +const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail, agentId: string) => { + console.log(caseDetails?.id, agentId); + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SHARE_FEEDBACK_CLICKED, { + caseId: caseDetails?.id, + agentId: agentId, + }); + var message = '*Visit Feedback* for ' + sanitizeString(caseDetails?.customerName) + '\n'; message += '_' + - sanitizeString(dateFormat(new Date(feedbackItem.createdAt), 'DD MMM, YYYY | HH:mm A')) + + sanitizeString(dateFormat(new Date(feedbackItem.createdAt), 'DD MMM, YYYY | HH:mm a')) + '_\n\n'; - message += 'LAN: ' + sanitizeString(caseDetails?.loanAccountNumber); - message += '\nDPD Bucket: ' + sanitizeString(caseDetails?.dpdBucket); - message += '\nEMI: ' + caseDetails?.outstandingEmiDetails?.[0]?.emiAmount + '\n\n'; - message += 'Disposition: ' + sanitizeString(feedbackItem.interactionStatus); + message += '*LAN*: ' + sanitizeString(caseDetails?.loanAccountNumber); + message += '\n*DPD Bucket*: ' + sanitizeString(caseDetails?.dpdBucket); + message += + '\n*EMI Amount*: ₹' + + insertCommasinAmount(caseDetails?.outstandingEmiDetails?.[0]?.emiAmount) + + '\n\n'; + message += '*Disposition*: ' + sanitizeString(feedbackItem.interactionStatus); const ptpDate = feedbackItem.answerViews.filter((answer) => answer.questionName === 'PTP Date'); if (ptpDate.length > 0) { @@ -91,7 +100,7 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail) => { message += '\n\n'; } - message += 'Remarks: '; + message += '*Remarks*: '; const answerList = feedbackItem.answerViews.filter( (answer) => answer.questionName === 'Comments' ); @@ -106,7 +115,7 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail) => { feedbackItem.metadata?.interactionLongitude && FIELD_FEEDBACKS.includes(feedbackItem.type) ? (message += - 'Location of feedback: ' + + '*Location of feedback*: ' + sanitizeString( getLocationLink( feedbackItem.metadata?.interactionLatitude, @@ -148,6 +157,11 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail) => { text1: ToastMessages.WHATSAPP_NOT_INSTALLED, type: 'error', }); + } else { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SHARE_SUCCESSFUL, { + caseId: caseDetails?.id, + agentId: agentId, + }); } }) .catch((err: any) => { @@ -159,12 +173,32 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail) => { RNFetchBlob.fs.unlink(imagePath); }); } else { - DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType); + DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType) + .then((res: any) => { + if (!res) { + toast({ + text1: ToastMessages.WHATSAPP_NOT_INSTALLED, + type: 'error', + }); + } else { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SHARE_SUCCESSFUL, { + caseId: caseDetails?.id, + agentId: agentId, + }); + } + }) + .catch((err: any) => { + toast({ + text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_FAILURE, + type: 'error', + }); + }); } }; const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetailItem) => { const caseDetails = useAppSelector((state) => state.allCases.caseDetails[caseId]); + const { agentId } = useAppSelector((state) => ({ agentId: state.user.user?.referenceId!! })); return ( @@ -230,7 +264,7 @@ const FeedbackDetailItem = ({ feedbackItem, isExpanded, caseId }: IFeedbackDetai sendToWhatsapp(feedbackItem, caseDetails)} + onPress={() => sendToWhatsapp(feedbackItem, caseDetails, agentId)} style={[GenericStyles.row, styles.BtnPadding]} > Date: Thu, 28 Sep 2023 13:13:55 +0530 Subject: [PATCH 22/26] TP-36682 | Added Clickstream events to WhatsApp share and cleaned code --- android/app/src/main/java/com/avapp/DeviceUtilsModule.java | 1 + src/screens/caseDetails/feedback/FeedbackDetailItem.tsx | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java index bd29cb29..062b9134 100644 --- a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java +++ b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java @@ -26,6 +26,7 @@ import android.content.pm.PackageInfo; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Environment; +import android.os.Handler; import android.util.Base64; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index e2dc7048..bc0207c7 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -74,7 +74,6 @@ function getLocationLink(latitude: string, longitude: string): string { } const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail, agentId: string) => { - console.log(caseDetails?.id, agentId); addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SHARE_FEEDBACK_CLICKED, { caseId: caseDetails?.id, agentId: agentId, From 4f5ed89dd5dfca4971545feab4c88465637b48fc Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Thu, 28 Sep 2023 14:59:01 +0530 Subject: [PATCH 23/26] Emi tab changes revereted --- RN-UI-LIB | 2 +- src/screens/emiSchedule/EmiScheduleTab.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/RN-UI-LIB b/RN-UI-LIB index 4c7f4f68..5b77f75c 160000 --- a/RN-UI-LIB +++ b/RN-UI-LIB @@ -1 +1 @@ -Subproject commit 4c7f4f6880d96bffa856e04d7b2b4d383e42c5cf +Subproject commit 5b77f75cb69fc7c8ed7d8a3acc84be1eb6564c64 diff --git a/src/screens/emiSchedule/EmiScheduleTab.tsx b/src/screens/emiSchedule/EmiScheduleTab.tsx index 4736273f..3cf7670c 100644 --- a/src/screens/emiSchedule/EmiScheduleTab.tsx +++ b/src/screens/emiSchedule/EmiScheduleTab.tsx @@ -39,7 +39,8 @@ const EmiScheduleTab: React.FC = (props) => { const [selectedTab, setSelectedTab] = useState(EmiSelectedTab.UNPAID); const emiEcheduleData = useAppSelector((state) => state.emiSchedule?.[loanAccountNumber]) || {}; const { data: emiData, isLoading } = emiEcheduleData; - const filteredData = getFilteredData(emiData, selectedTab); + const filteredData = + selectedTab !== EmiSelectedTab.ALL ? getFilteredData(emiData, selectedTab) : emiData; return ( Date: Thu, 28 Sep 2023 20:24:35 +0530 Subject: [PATCH 24/26] uat done --- src/screens/caseDetails/feedback/FeedbackDetailItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index bc0207c7..81d816d7 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -90,7 +90,7 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail, agentI insertCommasinAmount(caseDetails?.outstandingEmiDetails?.[0]?.emiAmount) + '\n\n'; message += '*Disposition*: ' + sanitizeString(feedbackItem.interactionStatus); - + console.log(feedbackItem); const ptpDate = feedbackItem.answerViews.filter((answer) => answer.questionName === 'PTP Date'); if (ptpDate.length > 0) { message += From 3500f9f513b1b11d0e07a866a42eb052fa340a55 Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Fri, 29 Sep 2023 16:19:36 +0530 Subject: [PATCH 25/26] Comments resolved --- android/app/src/main/AndroidManifest.xml | 4 - .../main/java/com/avapp/AlarmReceiver.java | 16 --- .../main/java/com/avapp/AlarmScheduler.java | 32 ----- .../ForegroundServiceBroadcastReciever.java | 22 ---- .../src/main/java/com/avapp/MainActivity.java | 19 --- package.json | 4 +- src/components/utlis/commonFunctions.ts | 1 - .../feedback/FeedbackDetailItem.tsx | 119 ++++++++---------- 8 files changed, 51 insertions(+), 166 deletions(-) delete mode 100644 android/app/src/main/java/com/avapp/AlarmReceiver.java delete mode 100644 android/app/src/main/java/com/avapp/AlarmScheduler.java delete mode 100644 android/app/src/main/java/com/avapp/ForegroundServiceBroadcastReciever.java diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ff2d3d1d..dbaef9b9 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -30,7 +30,6 @@ -> - @@ -71,9 +70,6 @@ android:resource="@xml/provider_paths" /> - - - = Build.VERSION_CODES.M) { - alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, alarmTimeMillis, pendingIntent); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - alarmManager.setExact(AlarmManager.RTC_WAKEUP, alarmTimeMillis, pendingIntent); - // alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, intervalMillis, repeatMillis,pendingIntent); - } else { - alarmManager.set(AlarmManager.RTC_WAKEUP, alarmTimeMillis, pendingIntent); - //alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarmTimeMillis, repeatMillis, pendingIntent); - } - } -} \ No newline at end of file diff --git a/android/app/src/main/java/com/avapp/ForegroundServiceBroadcastReciever.java b/android/app/src/main/java/com/avapp/ForegroundServiceBroadcastReciever.java deleted file mode 100644 index d9df5097..00000000 --- a/android/app/src/main/java/com/avapp/ForegroundServiceBroadcastReciever.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.avapp; - - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.util.Log; - - -public class ForegroundServiceBroadcastReciever extends BroadcastReceiver { - public static final String ACTION_CUSTOM_DESTROY = "com.avapp.ACTION_FOREGROUND_SERVICE_DESTROYED"; - - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getAction() != null && intent.getAction().equals(ACTION_CUSTOM_DESTROY)) { - // Handle the broadcast here - String extraData = intent.getStringExtra("key"); - Log.d("BROADCAST_RECEIVED", "broadcast received when service destroyed"); - // Do something with the extra data - } - } -} diff --git a/android/app/src/main/java/com/avapp/MainActivity.java b/android/app/src/main/java/com/avapp/MainActivity.java index a6c02035..db8a3e5d 100644 --- a/android/app/src/main/java/com/avapp/MainActivity.java +++ b/android/app/src/main/java/com/avapp/MainActivity.java @@ -9,11 +9,6 @@ import android.os.Bundle; public class MainActivity extends ReactActivity { - private ForegroundServiceBroadcastReciever receiver; - public static final String ACTION_CUSTOM_DESTROY = "com.avapp.ACTION_FOREGROUND_SERVICE_DESTROYED"; - - - /** * Returns the name of the main component registered from JavaScript. This is used to schedule * rendering of the component. @@ -23,20 +18,6 @@ public class MainActivity extends ReactActivity { return "AVAPP"; } - - // https://github.com/software-mansion/react-native-screens#android - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(null); - receiver = new ForegroundServiceBroadcastReciever(); - IntentFilter filter = new IntentFilter(ACTION_CUSTOM_DESTROY); - registerReceiver(receiver, filter); - AlarmScheduler.scheduleRepeatingAlarm(this); // 'this' is the context - - } - - - /** * Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and * you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer diff --git a/package.json b/package.json index 93284aee..d047413e 100644 --- a/package.json +++ b/package.json @@ -72,8 +72,6 @@ "react-native-qrcode-svg": "^6.2.0", "react-native-safe-area-context": "4.4.1", "react-native-screens": "3.18.2", - "react-native-send-intent": "^1.3.0", - "react-native-share": "^9.4.1", "react-native-svg": "^13.9.0", "react-native-tab-view": "3.3.2", "react-native-toast-message": "2.1.5", @@ -83,7 +81,7 @@ "react-redux": "8.0.5", "redux": "4.2.0", "redux-persist": "6.0.0", - "rn-fetch-blob": "^0.12.0" + "rn-fetch-blob": "0.12.0" }, "devDependencies": { "@babel/core": "7.12.9", diff --git a/src/components/utlis/commonFunctions.ts b/src/components/utlis/commonFunctions.ts index e87ccd4f..d7e058e2 100644 --- a/src/components/utlis/commonFunctions.ts +++ b/src/components/utlis/commonFunctions.ts @@ -217,7 +217,6 @@ export function isNullOrUndefined(val: any): boolean { export const getLoanAccountNumber = (caseDetail: CaseDetail) => { const { loanAccountNumber, loanDetails } = caseDetail ?? {}; - console.log(loanAccountNumber, loanDetails?.loanAccountNumber); return loanAccountNumber ?? loanDetails?.loanAccountNumber ?? ''; }; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx index 81d816d7..48792ff2 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailItem.tsx @@ -10,7 +10,6 @@ import { } from '../../../../RN-UI-LIB/src/utlis/dates'; import { getGoogleMapUrl, - getLoanAccountNumber, insertCommasinAmount, sanitizeString, } from '../../../components/utlis/commonFunctions'; @@ -29,10 +28,7 @@ import { CLICKSTREAM_EVENT_NAMES } from '../../../common/Constants'; import IconLabel from '../../../common/IconLabel'; import WhatsAppFeedbackShareIcon from '../../../assets/icons/WhatsAppIcon'; import RNFetchBlob from 'rn-fetch-blob'; -import { useAppDispatch, useAppSelector } from '../../../hooks'; -import { EmiSelectedTab } from '../../emiSchedule/EmiScheduleTab'; -import { getFilteredData } from '../../emiSchedule/utils'; -import { UnifiedCaseDetailsTypes, getCaseUnifiedData } from '../../../action/caseApiActions'; +import { useAppSelector } from '../../../hooks'; import { toast } from '../../../../RN-UI-LIB/src/components/toast'; import { ToastMessages } from '../../allCases/constants'; const { DeviceUtilsModule } = NativeModules; @@ -73,25 +69,49 @@ function getLocationLink(latitude: string, longitude: string): string { return link; } +const sendToWhatsappNative = ( + message: string, + imageUrl: string, + mimeType: string, + caseDetails: CaseDetail, + agentId: string +) => { + DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType) + .then((res: any) => { + if (!res) { + toast({ + text1: ToastMessages.WHATSAPP_NOT_INSTALLED, + type: 'error', + }); + } else { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SHARE_SUCCESSFUL, { + caseId: caseDetails?.id, + agentId: agentId, + }); + } + }) + .catch((err: any) => { + toast({ + text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_FAILURE, + type: 'error', + }); + }); +}; + const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail, agentId: string) => { addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SHARE_FEEDBACK_CLICKED, { caseId: caseDetails?.id, agentId: agentId, }); - var message = '*Visit Feedback* for ' + sanitizeString(caseDetails?.customerName) + '\n'; - message += - '_' + - sanitizeString(dateFormat(new Date(feedbackItem.createdAt), 'DD MMM, YYYY | HH:mm a')) + - '_\n\n'; - message += '*LAN*: ' + sanitizeString(caseDetails?.loanAccountNumber); - message += '\n*DPD Bucket*: ' + sanitizeString(caseDetails?.dpdBucket); - message += - '\n*EMI Amount*: ₹' + - insertCommasinAmount(caseDetails?.outstandingEmiDetails?.[0]?.emiAmount) + - '\n\n'; - message += '*Disposition*: ' + sanitizeString(feedbackItem.interactionStatus); - console.log(feedbackItem); - const ptpDate = feedbackItem.answerViews.filter((answer) => answer.questionName === 'PTP Date'); + + var message = `*Visit Feedback* for ${sanitizeString(caseDetails?.customerName)} +_${sanitizeString(dateFormat(new Date(feedbackItem?.createdAt), 'DD MMM, YYYY | HH:mm a.'))}_\n +*LAN*: ${sanitizeString(caseDetails?.loanAccountNumber)} +*DPD Bucket*: ${sanitizeString(caseDetails?.dpdBucket)} +*EMI Amount*: ₹${insertCommasinAmount(caseDetails?.outstandingEmiDetails?.[0]?.emiAmount)}\n +*Disposition*: ${sanitizeString(feedbackItem?.interactionStatus)}`; + + const ptpDate = feedbackItem?.answerViews.filter((answer) => answer.questionName === 'PTP Date'); if (ptpDate.length > 0) { message += ' for ' + sanitizeString(dateFormat(new Date(ptpDate[0].inputDate), 'DD MMM, YYYY')) + '\n\n'; @@ -100,40 +120,39 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail, agentI } message += '*Remarks*: '; - const answerList = feedbackItem.answerViews.filter( + const answerList = feedbackItem?.answerViews?.filter( (answer) => answer.questionName === 'Comments' ); if (answerList.length > 0) { - message += sanitizeString(answerList[0].inputText) + '\n\n'; + message += sanitizeString(answerList[0]?.inputText) + '\n\n'; } else { message += 'N.A.\n\n'; } { - feedbackItem.metadata?.interactionLatitude && - feedbackItem.metadata?.interactionLongitude && - FIELD_FEEDBACKS.includes(feedbackItem.type) + feedbackItem?.metadata?.interactionLatitude && + feedbackItem?.metadata?.interactionLongitude && + FIELD_FEEDBACKS.includes(feedbackItem?.type) ? (message += '*Location of feedback*: ' + sanitizeString( getLocationLink( - feedbackItem.metadata?.interactionLatitude, - feedbackItem.metadata?.interactionLongitude + feedbackItem?.metadata?.interactionLatitude, + feedbackItem?.metadata?.interactionLongitude ) ) + '\n\n') : null; } - const imagesList = feedbackItem.answerViews.filter( + const imagesList = feedbackItem?.answerViews.filter( (answer) => answer.questionTag === OPTION_TAG.IMAGE_UPLOAD ); - var imageUrl = ''; const mimeType = 'image/*'; if (imagesList.length > 0) { var imageUri = ''; - imageUri = imagesList[0].inputText ? imagesList[0].inputText : ''; + imageUri = imagesList[0]?.inputText ? imagesList[0].inputText : ''; let imagePath = ''; RNFetchBlob.config({ fileCache: true, @@ -149,49 +168,11 @@ const sendToWhatsapp = (feedbackItem: IFeedback, caseDetails: CaseDetail, agentI }) .then((base64Data: any) => { imageUrl = base64Data; - DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType) - .then((res: any) => { - if (!res) { - toast({ - text1: ToastMessages.WHATSAPP_NOT_INSTALLED, - type: 'error', - }); - } else { - addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SHARE_SUCCESSFUL, { - caseId: caseDetails?.id, - agentId: agentId, - }); - } - }) - .catch((err: any) => { - toast({ - text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_FAILURE, - type: 'error', - }); - }); + sendToWhatsappNative(message, imageUrl, mimeType, caseDetails, agentId); RNFetchBlob.fs.unlink(imagePath); }); } else { - DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType) - .then((res: any) => { - if (!res) { - toast({ - text1: ToastMessages.WHATSAPP_NOT_INSTALLED, - type: 'error', - }); - } else { - addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SHARE_SUCCESSFUL, { - caseId: caseDetails?.id, - agentId: agentId, - }); - } - }) - .catch((err: any) => { - toast({ - text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_FAILURE, - type: 'error', - }); - }); + sendToWhatsappNative(message, imageUrl, mimeType, caseDetails, agentId); } }; From 704b2840d76208ae3f0c795080f9c927bc6944ff Mon Sep 17 00:00:00 2001 From: ShriPrakashBajpai Date: Tue, 3 Oct 2023 19:31:36 +0530 Subject: [PATCH 26/26] Comments resolved v2 --- .../java/com/avapp/DeviceUtilsModule.java | 60 ++++++++++--------- src/assets/icons/ChevronDown.tsx | 7 ++- src/assets/icons/ChevronUp.tsx | 7 ++- src/components/utlis/DeviceUtils.ts | 7 +++ src/components/utlis/commonFunctions.ts | 2 +- src/constants/icons/ExpandAccordian.ts | 2 - src/constants/icons/ShrinkAccordian.ts | 2 - .../feedback/FeedbackDetailContainer.tsx | 1 - .../feedback/FeedbackDetailItem.tsx | 44 +++++++------- yarn.lock | 12 +--- 10 files changed, 70 insertions(+), 74 deletions(-) delete mode 100644 src/constants/icons/ExpandAccordian.ts delete mode 100644 src/constants/icons/ShrinkAccordian.ts diff --git a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java index 062b9134..71da3d39 100644 --- a/android/app/src/main/java/com/avapp/DeviceUtilsModule.java +++ b/android/app/src/main/java/com/avapp/DeviceUtilsModule.java @@ -31,6 +31,7 @@ import android.util.Base64; import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; import java.util.List; @@ -141,38 +142,39 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule { @ReactMethod public void sendFeedbackToWhatsapp(String message, String imageUrl, String mimeType, Promise promise) { - try{ - if(isWhatsAppInstalled()){ - Intent sendIntent = new Intent(); - sendIntent.setAction(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_TEXT, message); - - if(imageUrl.equals("")) { - sendIntent.setType("text/plain"); - sendIntent.setPackage("com.whatsapp"); - getCurrentActivity().startActivity(sendIntent); - } else { - sendIntent.setType(mimeType); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - imageFile = convertBase64ToFile(getReactApplicationContext(), imageUrl); - Uri fileUri = FileProvider.getUriForFile(getReactApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", new File( - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), - imageFile.getName() - ) - ); - sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); - sendIntent.setPackage("com.whatsapp"); - getCurrentActivity().startActivityForResult(sendIntent, WHATSAPP_SHARE_REQUEST_CODE); - } - promise.resolve(true); - } else { - promise.resolve(false); + if(!isWhatsAppInstalled()){ + promise.reject("errorCode", "1"); + return; } - } catch (Error e){ - promise.reject(e); - } + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, message); + + if(imageUrl.equals("")) { + sendIntent.setType("text/plain"); + sendIntent.setPackage("com.whatsapp"); + getCurrentActivity().startActivity(sendIntent); + } else { + sendIntent.setType(mimeType); + sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + imageFile = convertBase64ToFile(getReactApplicationContext(), imageUrl); + Uri fileUri = FileProvider.getUriForFile(getReactApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", new File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + imageFile.getName() + ) + ); + sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); + sendIntent.setPackage("com.whatsapp"); + getCurrentActivity().startActivityForResult(sendIntent, WHATSAPP_SHARE_REQUEST_CODE); + } + promise.resolve(true); + return; + + } catch (Error e){ + promise.reject("errorCode","2"); + } return; } diff --git a/src/assets/icons/ChevronDown.tsx b/src/assets/icons/ChevronDown.tsx index 91bd8a91..ce42c6ba 100644 --- a/src/assets/icons/ChevronDown.tsx +++ b/src/assets/icons/ChevronDown.tsx @@ -1,11 +1,12 @@ import * as React from 'react'; import Svg, { Mask, Path, G } from 'react-native-svg'; -const ChevronDown = () => { +const ChevronDown = (props) => { + const { fillColor = '#969696', size = 24 } = props; return ( - + ); diff --git a/src/assets/icons/ChevronUp.tsx b/src/assets/icons/ChevronUp.tsx index 5c77ab77..e4e5ba08 100644 --- a/src/assets/icons/ChevronUp.tsx +++ b/src/assets/icons/ChevronUp.tsx @@ -1,11 +1,12 @@ import * as React from 'react'; import Svg, { Mask, Path, G } from 'react-native-svg'; -const ChevronUp = () => { +const ChevronUp = (props) => { + const { fillColor = '#969696', size = 24 } = props; return ( - + ); diff --git a/src/components/utlis/DeviceUtils.ts b/src/components/utlis/DeviceUtils.ts index 5443d7d7..926d85a3 100644 --- a/src/components/utlis/DeviceUtils.ts +++ b/src/components/utlis/DeviceUtils.ts @@ -7,3 +7,10 @@ export const locationEnabled = (): Promise => DeviceUtilsModule.isLocat // returns array of all the installed packages. export const getAllInstalledApp = (): Promise => DeviceUtilsModule.getAllInstalledApp(); + +// sends feedback data to whatsapp. +export const sendFeedbackToWhatsapp = ( + message: string, + imageUrl: string, + mimeType: string +): Promise => DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType); diff --git a/src/components/utlis/commonFunctions.ts b/src/components/utlis/commonFunctions.ts index d7e058e2..993f96cd 100644 --- a/src/components/utlis/commonFunctions.ts +++ b/src/components/utlis/commonFunctions.ts @@ -369,7 +369,7 @@ export function getDistanceFromLatLonInKm( return EARTH_RADIUS * distance; } -export function insertCommasinAmount(amount: any) { +export function insertCommasinAmount(amount: number | undefined) { const reversedAmount = amount?.toString().split('').reverse().join(''); const groups = reversedAmount?.match(/.{1,3}/g); const result = groups?.join(',').split('').reverse().join(''); diff --git a/src/constants/icons/ExpandAccordian.ts b/src/constants/icons/ExpandAccordian.ts deleted file mode 100644 index 388254fd..00000000 --- a/src/constants/icons/ExpandAccordian.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const expandAccordianPath = - 'M8.466 1.233a.63.63 0 0 0-.183.465.63.63 0 0 0 .183.465l3.057 3.055a.587.587 0 0 0 .216.141.742.742 0 0 0 .25.041c.088 0 .171-.013.249-.04.077-.029.15-.076.216-.142l3.073-3.072a.609.609 0 0 0 .183-.448.637.637 0 0 0-.2-.465.63.63 0 0 0-.465-.183.63.63 0 0 0-.465.183l-2.592 2.59-2.608-2.607a.61.61 0 0 0-.449-.182.638.638 0 0 0-.465.199Z'; diff --git a/src/constants/icons/ShrinkAccordian.ts b/src/constants/icons/ShrinkAccordian.ts deleted file mode 100644 index cbd78f0f..00000000 --- a/src/constants/icons/ShrinkAccordian.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const shrinkAccordianPath = - 'M8.466 13.767a.63.63 0 0 1-.183-.465.63.63 0 0 1 .183-.465l3.057-3.055a.587.587 0 0 1 .216-.141.742.742 0 0 1 .25-.041c.088 0 .171.013.249.04.077.029.15.076.216.142l3.073 3.072a.609.609 0 0 1 .183.448.637.637 0 0 1-.2.465.63.63 0 0 1-.465.183.63.63 0 0 1-.465-.183l-2.592-2.59-2.608 2.607a.61.61 0 0 1-.449.182.638.638 0 0 1-.465-.199Z'; diff --git a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx index adefe9a9..78186917 100644 --- a/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx +++ b/src/screens/caseDetails/feedback/FeedbackDetailContainer.tsx @@ -230,7 +230,6 @@ const FeedbackDetailContainer: React.FC = ({ route: ro isActive={feedback.referenceId === activeFeedbackReferenceId} touchableDelay={50} touchableOpacity={0.8} - touchableArea={{ top: 400, bottom: 400, left: 400, right: 400 }} accordionHeader={ = { - FIELD_VISIT: , - INHOUSE_FIELD_VISIT: , - SELF_CALL: , - CALL_BRIDGE: , + FIELD_VISIT: , + INHOUSE_FIELD_VISIT: , + SELF_CALL: , + CALL_BRIDGE: , }; const getAddress = (address?: IAddress) => { @@ -76,25 +76,25 @@ const sendToWhatsappNative = ( caseDetails: CaseDetail, agentId: string ) => { - DeviceUtilsModule.sendFeedbackToWhatsapp(message, imageUrl, mimeType) - .then((res: any) => { - if (!res) { + sendFeedbackToWhatsapp(message, imageUrl, mimeType) + .then((res: boolean) => { + addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SHARE_SUCCESSFUL, { + caseId: caseDetails?.id, + agentId: agentId, + }); + }) + .catch((err: Error) => { + if (err.message === '1') { toast({ text1: ToastMessages.WHATSAPP_NOT_INSTALLED, type: 'error', }); } else { - addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_SHARE_SUCCESSFUL, { - caseId: caseDetails?.id, - agentId: agentId, + toast({ + text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_FAILURE, + type: 'error', }); } - }) - .catch((err: any) => { - toast({ - text1: ToastMessages.WHATSAPP_FEEDBACK_SHARE_FAILURE, - type: 'error', - }); }); }; @@ -154,7 +154,7 @@ _${sanitizeString(dateFormat(new Date(feedbackItem?.createdAt), 'DD MMM, YYYY | var imageUri = ''; imageUri = imagesList[0]?.inputText ? imagesList[0].inputText : ''; let imagePath = ''; - RNFetchBlob.config({ + ReactNativeBlobUtil.config({ fileCache: true, }) .fetch('GET', imageUri) @@ -169,7 +169,7 @@ _${sanitizeString(dateFormat(new Date(feedbackItem?.createdAt), 'DD MMM, YYYY | .then((base64Data: any) => { imageUrl = base64Data; sendToWhatsappNative(message, imageUrl, mimeType, caseDetails, agentId); - RNFetchBlob.fs.unlink(imagePath); + ReactNativeBlobUtil.fs.unlink(imagePath); }); } else { sendToWhatsappNative(message, imageUrl, mimeType, caseDetails, agentId); @@ -271,7 +271,7 @@ const styles = StyleSheet.create({ }, cardLightTitle: { fontWeight: '400', - color: '#585757', + color: COLORS.TEXT.BLACK, }, cardFooterText: { fontWeight: '400', @@ -287,7 +287,7 @@ const styles = StyleSheet.create({ marginTop: 0, }, bullet: { - color: '#CACED5', + color: COLORS.TEXT.GREY_1, }, BtnPadding: { paddingTop: 8, diff --git a/yarn.lock b/yarn.lock index 305e30da..cf3cbdc7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7820,16 +7820,6 @@ react-native-screens@3.18.2: react-freeze "^1.0.0" warn-once "^0.1.0" -react-native-send-intent@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/react-native-send-intent/-/react-native-send-intent-1.3.0.tgz#d8c7898827da1b8b10e25a645ce6802d1a0b440c" - integrity sha512-ODTX7BHITFxdcAL0K2iHfa3qVYnqG8GPcv1NbLBNC1DyCaOSJiiGtVH6Kc5YBqzQ8+1pV9uN5nfQ5wyFgiq74g== - -react-native-share@^9.4.1: - version "9.4.1" - resolved "https://registry.yarnpkg.com/react-native-share/-/react-native-share-9.4.1.tgz#1b6d96015009e3878bfc4346940602c1cffff525" - integrity sha512-jm4qA5J5+ytWA8UFg6s8iEfdZYGPW+t5oreSuzrPt0assjvBUlFaoqYGGwGR5RJ8BIpjzOJYvx/c9MjXB4ApUg== - react-native-svg@^13.9.0: version "13.9.0" resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-13.9.0.tgz#8df8a690dd00362601f074dec5d3a86dd0f99c7f" @@ -8248,7 +8238,7 @@ rimraf@~2.6.2: dependencies: glob "^7.1.3" -rn-fetch-blob@^0.12.0: +rn-fetch-blob@0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/rn-fetch-blob/-/rn-fetch-blob-0.12.0.tgz#ec610d2f9b3f1065556b58ab9c106eeb256f3cba" integrity sha512-+QnR7AsJ14zqpVVUbzbtAjq0iI8c9tCg49tIoKO2ezjzRunN7YL6zFSFSWZm6d+mE/l9r+OeDM3jmb2tBb2WbA==