TP-20464 | Feedback Unified Case API integration + CaseDetailPages Feedback listing added (#148)

* TP-21355 batch case details API

* TP-21355 | Aman C | batch case details API

* TP-21355 | Aman C | batch api fix

* TP-20464 | Feedback Unified Case API integration + CaseDetailPages Feedback listing added

Co-authored-by: Aman Chaturvedi <aman.chaturvedi@navi.com>
Co-authored-by: kunalsharma <kunal.sharma@navi.com>
This commit is contained in:
Himanshu Kansal
2023-03-16 14:09:59 +05:30
committed by GitHub Enterprise
parent 5195918f04
commit aed6c9d525
6 changed files with 352 additions and 2 deletions

View File

@@ -0,0 +1,58 @@
import * as React from "react"
import Svg, { Path } from "react-native-svg"
const NoFeedbackIcon: React.FC = () => {
return (
<Svg
width={92}
height={69}
viewBox="0 0 92 69"
fill="none"
>
<Path
d="M79.652 14.525l-.522.461v40.18c0 .78-.632 1.417-1.416 1.417H55.665L1.369 13.754a1.41 1.41 0 011.043-.461h75.297c.37 0 .697.143.946.37h.01l.987.862z"
fill="#DBDBDB"
stroke="#12183E"
strokeWidth={0.349419}
strokeLinejoin="round"
/>
<Path
d="M55.665 56.583H15.808L1.923 68 1 67.197V14.705c0-.364.263-.896.49-1.057l54.17 42.935h.005z"
fill="#545454"
stroke="#12183E"
strokeWidth={0.349419}
strokeMiterlimit={10}
/>
<Path
d="M78.636 57.388H16.73L1.922 68.002V15.51c0-.78.632-1.416 1.417-1.416h75.297c.78 0 1.416.632 1.416 1.416v40.462c0 .78-.632 1.416-1.416 1.416z"
fill="#fff"
stroke="#12183E"
strokeWidth={0.349419}
strokeLinejoin="round"
/>
<Path
d="M48.542 25.965H12.12c-.51 0-.923.353-.923.79v4.407c0 .436.414.79.923.79h36.422c.51 0 .923-.354.923-.79v-4.408c0-.436-.413-.79-.923-.79zM69.85 40H12.12c-.51 0-.923.353-.923.79v4.407c0 .436.414.79.923.79h57.73c.51 0 .922-.354.922-.79V40.79c0-.436-.413-.789-.923-.789z"
fill="#F1F1F1"
stroke="#12183E"
strokeWidth={0.349419}
strokeLinejoin="round"
/>
<Path
d="M74.263 35.527c9.535 0 17.264-7.73 17.264-17.264C91.527 8.73 83.797 1 74.263 1 64.73 1 57 8.73 57 18.263c0 9.535 7.73 17.264 17.263 17.264z"
fill="#fff"
stroke="#12183E"
strokeWidth={0.349419}
strokeLinejoin="round"
/>
<Path
d="M73.992 20.965a1.314 1.314 0 001.304-1.208l.708-8.693a1 1 0 00-.048-.4.98.98 0 00-.538-.58.992.992 0 00-.398-.084h-2.032a.992.992 0 00-.936.663.948.948 0 00-.048.401l.709 8.692a1.308 1.308 0 001.273 1.208h.005zM73.99 25.278a1.4 1.4 0 110-2.8 1.4 1.4 0 010 2.8z"
fill="#F98600"
stroke="#12183E"
strokeWidth={0.26992}
strokeMiterlimit={10}
/>
</Svg>
)
}
export default NoFeedbackIcon;

View File

@@ -34,4 +34,4 @@ export const {
setFeedbackHistoryLoading
} = FeedbackHistorySlice.actions;
export default FeedbackHistorySlice.reducer;
export default FeedbackHistorySlice.reducer;

View File

@@ -5,6 +5,7 @@ import {
SafeAreaView,
ScrollView,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native';
import Button from '../../../RN-UI-LIB/src/components/Button';
@@ -25,6 +26,10 @@ import PhoneNumberSelectionBottomSheet from './journeyStepper/PhoneNumberSelecti
import { PageRouteEnum } from '../../../ProtectedRouter';
import { CaseAllocationType, TaskTitleUIMapping } from '../allCases/interface';
import { _map } from '../../../RN-UI-LIB/src/utlis/common';
import FeedbackListContainer from './feedback/FeedbackListContainer';
import { RootState } from '../../store/store';
import { IFeedback } from '../../types/feedback.types';
import { setFeedbackHistory } from '../../reducer/feedbackHistorySlice';
interface ICaseDetails {
route: {
@@ -51,7 +56,11 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = props => {
],
);
const { addressString, phoneNumbers, currentOutstandingEmi } = caseDetail;
const { addressString, phoneNumbers, currentOutstandingEmi, loanAccountNumber } = caseDetail;
const feedbackList: IFeedback[] = useAppSelector(
(state: RootState) => state.feedbackHistory?.data?.[loanAccountNumber as string],
);
const [showCallingBottomSheet, setShowCallingBottomSheet] =
React.useState(false);
@@ -274,6 +283,50 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = props => {
}
/>
</View>
<View
style={[
GenericStyles.whiteBackground,
styles.secondSection,
getShadowStyle(2),
GenericStyles.mt16,
GenericStyles.pv24,
]}>
<View
style={[
GenericStyles.row,
GenericStyles.alignCenter,
GenericStyles.ph24,
GenericStyles.pb16
]}>
<View style={GenericStyles.row}>
<View style={{ flexBasis: '65%' }}>
<Text
style={[
styles.textContainer,
GenericStyles.fontSize14,
]}>
Feedbacks
</Text>
</View>
{
feedbackList?.length ? (
<View style={[{ flexBasis: '35%' }]}>
<TouchableOpacity
activeOpacity={0.7}
onPress={console.log}
style={GenericStyles.flex20}>
<Text style={[styles.textContainer, styles.feedbackBtn]}>
Open all feedbacks
</Text>
</TouchableOpacity>
</View>
) : null
}
</View>
</View>
<View style={[GenericStyles.borderTop]} />
<FeedbackListContainer loanAccountNumber={caseDetail?.loanAccountNumber as string} />
</View>
</Animated.View>
</ScrollView>
<View
@@ -405,6 +458,15 @@ export const styles = StyleSheet.create({
position: 'absolute',
left: '30%',
},
textContainer: {
fontSize: 13,
lineHeight: 18,
color: COLORS.TEXT.LIGHT
},
feedbackBtn: {
fontWeight: '500',
color: COLORS.TEXT.BLUE
},
});
export default CollectionCaseDetails;

View File

@@ -0,0 +1,127 @@
import React, { useEffect, useState } from 'react'
import { StyleSheet, TouchableOpacity, View } 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';
import { IFeedback } from '../../../types/feedback.types';
import { GenericFunctionArgs } from '../../../common/GenericTypes';
import Heading from '../../../../RN-UI-LIB/src/components/Heading';
import LoadingIcon from '../../../../RN-UI-LIB/src/Icons/LoadingIcon';
import FeedbackListItem from './FeedbackListItem';
import { useAppDispatch, useAppSelector } from '../../../hooks';
import useIsOnline from '../../../hooks/useIsOnline';
import NoFeedbackIcon from '../../../assets/icons/NoFeedbackIcon';
import { RootState } from '../../../store/store';
import OfflineIcon from '../../../../RN-UI-LIB/src/Icons/OfflineIcon';
import { getCaseUnifiedData, UnifiedCaseDetailsTypes } from '../../../action/caseApiActions';
interface IFeedbackListContainer {
loanAccountNumber: string,
}
interface IOfflineFeedbackListContainer {
handleRetryEvent: GenericFunctionArgs;
}
const NoFeedbackFoundContainer: React.FC = () => (
<View>
<View style={[GenericStyles.centerAligned, styles.noFeedbackContainer]}>
<NoFeedbackIcon />
<View style={[GenericStyles.mt24]}>
<Heading
dark
bold
type="h3"
style={GenericStyles.centerAlignedText}>
No feedbacks recorded
</Heading>
</View>
</View>
</View>
);
const OfflineFeedbackListContainer: React.FC<IOfflineFeedbackListContainer> = ({ handleRetryEvent }) => (
<View>
<View style={[GenericStyles.centerAligned, styles.noFeedbackContainer]}>
<OfflineIcon />
<View style={[GenericStyles.mt24]}>
<Heading
dark
bold
type="h3"
style={GenericStyles.centerAlignedText}>
You seem to be offline!
</Heading>
<Text>Go back online to view this page</Text>
<TouchableOpacity
activeOpacity={0.7}
onPress={handleRetryEvent}
style={[GenericStyles.row, GenericStyles.pt12, GenericStyles.centerAligned]}>
<Text style={[GenericStyles.p12]}>
<LoadingIcon fillColor={COLORS.BASE.BLUE} />
</Text>
<Text style={[styles.textContainer, styles.retryBtn]}>
Retry
</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
const FeedbackListContainer: React.FC<IFeedbackListContainer> = ({ loanAccountNumber }) => {
const [retryBtnToggle, setRetryBtnToggle] = useState(false);
const dispatch = useAppDispatch();
const isOnline = useIsOnline();
const feedbackList: IFeedback[] = useAppSelector(
(state: RootState) => state.feedbackHistory?.data?.[loanAccountNumber],
);
const handleRetryEvent = () => {
setRetryBtnToggle(retryBtnToggle => !retryBtnToggle);
}
useEffect(() => {
if (isOnline || !feedbackList) {
dispatch(getCaseUnifiedData([loanAccountNumber], [UnifiedCaseDetailsTypes.FEEDBACKS]))
}
}, [isOnline, retryBtnToggle, feedbackList]);
if (!isOnline && !feedbackList) {
return <OfflineFeedbackListContainer handleRetryEvent={handleRetryEvent} />
}
if (!feedbackList?.length) {
return <NoFeedbackFoundContainer />
}
return (
<View>
{
feedbackList.map((feedbackItem: IFeedback, idx: number) => (
<FeedbackListItem feedbackItem={feedbackItem} showHorizontalLine={++idx !== feedbackList.length} />
))
}
</View>
)
};
const styles = StyleSheet.create({
textContainer: {
fontSize: 14,
lineHeight: 20,
paddingVertical: 8
},
noFeedbackContainer: {
paddingVertical: 50
},
retryBtn: {
fontSize: 16,
color: COLORS.BASE.BLUE
}
});
export default FeedbackListContainer;

View File

@@ -0,0 +1,63 @@
import React from 'react'
import { StyleSheet, TouchableOpacity, View } from 'react-native';
import Text from '../../../../RN-UI-LIB/src/components/Text'
import Chevron from '../../../../RN-UI-LIB/src/Icons/Chevron';
import { GenericStyles } from '../../../../RN-UI-LIB/src/styles';
import { COLORS } from '../../../../RN-UI-LIB/src/styles/colors';
import { BUSINESS_DATE_FORMAT, dateFormat } from '../../../../RN-UI-LIB/src/utlis/dates';
import { sanitizeString } from '../../../components/utlis/commonFunctions';
import { IFeedback } from '../../../types/feedback.types'
import { InteractionStatuses } from '../../allCases/interface';
interface IFeedbackListItem {
feedbackItem: IFeedback,
showHorizontalLine?: boolean,
}
const FeedbackListItem: React.FC<IFeedbackListItem> = ({ feedbackItem, showHorizontalLine = true }) => {
return (
<View style={[
GenericStyles.ph24,
GenericStyles.pt12
]}>
<TouchableOpacity
activeOpacity={0.7}
onPress={console.log}
style={[GenericStyles.row, GenericStyles.alignCenter, showHorizontalLine && GenericStyles.pb16 ]}
>
<View style={{ flexBasis: '95%' }}>
<Text
style={styles.textHeading}>
{sanitizeString(InteractionStatuses[feedbackItem.interactionStatus])}
</Text>
<Text
style={styles.subText}>
{sanitizeString(`${dateFormat(new Date(feedbackItem?.createdAt), BUSINESS_DATE_FORMAT)}`)}
</Text>
</View>
<Chevron />
</TouchableOpacity >
{
showHorizontalLine ? (
<View style={[GenericStyles.borderTop, GenericStyles.w100]} />
) : null
}
</View>
)
}
const styles = StyleSheet.create({
textHeading: {
fontSize: 14,
lineHeight: 20,
paddingBottom: 4,
color: COLORS.TEXT.DARK
},
subText: {
fontSize: 12,
lineHeight: 18,
color: COLORS.TEXT.LIGHT
}
});
export default FeedbackListItem;

View File

@@ -0,0 +1,40 @@
import { GenericType } from "../common/GenericTypes";
import { Address, InteractionStatuses } from "../screens/allCases/interface";
export enum AnswerType {
TEXT = 'TEXT',
DATE = 'DATE',
TIME = 'TIME',
AMOUNT = 'AMOUNT',
OPTIONS = 'OPTIONS',
REMINDER = 'REMINDER',
}
export interface IAnswerView {
interactionId?: number;
referenceId?: string;
questionReferenceId?: string;
questionName?: string;
questionText?: string;
answerType?: AnswerType;
optionReferenceId?: string;
optionText?: string;
inputAmount?: number;
inputDate?: string;
inputText?: string;
}
export interface IFeedback {
[x: string]: any;
referenceId: string;
type: string;
accountNumber: string;
createdAt: string;
metadata: GenericType;
sourceType: string;
answerViews: IAnswerView[];
imageUrls: string[];
agentReferenceId: string
source: Address | GenericType;
interactionStatus: InteractionStatuses;
}