TP-20465 | Detail page fixes (#159)

This commit is contained in:
Himanshu Kansal
2023-03-17 16:40:54 +05:30
committed by GitHub Enterprise
parent 11af3d2a5f
commit 11ae25b2ad
13 changed files with 154 additions and 65 deletions

View File

@@ -18,6 +18,7 @@ import {
} from '../reducer/repaymentsSlice';
import { AxiosResponse } from 'axios';
import { setAddresses, setAddressLoading } from '../reducer/addressSlice';
import { IFeedback } from '../types/feedback.types';
// TODO: Need to add respective interfaces instead of any
interface IUnifiedData {
@@ -81,8 +82,9 @@ const setUnifiedData =
);
}
if (queryParams[UnifiedCaseDetailsTypes.FEEDBACKS]) {
// todo: data is coming as feedback.data
dispatch(
setFeedbackHistory({ loanAccountNumber, feedbacks }),
setFeedbackHistory({ loanAccountNumber, feedbacks: feedbacks?.data as IFeedback[] }),
);
}
if (queryParams[UnifiedCaseDetailsTypes.REPAYMENTS]) {
@@ -113,7 +115,7 @@ export const getCaseUnifiedData =
const promise = axiosInstance.get(url);
promisesList.push(promise);
});
Promise.allSettled(promisesList).then(res => {
Promise.allSettled?.(promisesList).then(res => {
dispatch(setUnifiedData(queryParams, loanAccountNumbers, res));
}).finally(() => {
dispatch(setEmiScheduleLoading({isLoading:false, loanAccountNumbers}));

View File

@@ -5,22 +5,22 @@ import axiosInstance, {
import { logError } from '../components/utlis/errorUtils';
interface IPastFeedbacks {
account_number: string,
page_no: number,
page_size: number,
customerRecahble: boolean,
loan_account_number: string,
page_no: number,
page_size: number,
customerRecahble: boolean,
}
export const getPastFeedbacks =
(queryParamsPayload: IPastFeedbacks) => {
const url = getApiUrl(ApiKeys.PAST_FEEDBACK);
return axiosInstance
.post(url, {}, {
.get(url, {
params: queryParamsPayload
})
.then(response => {
if (response?.data) {
return response.data;
if (response?.data?.data?.length) {
return response.data.data;
}
throw response;
})

View File

@@ -46,8 +46,7 @@ API_URLS[ApiKeys.NEW_ADDRESS] = '/addresses';
API_URLS[ApiKeys.GET_SIGNED_URL] = '/cases/get-signed-urls';
API_URLS[ApiKeys.CASE_UNIFIED_DETAILS] = '/collection-cases/unified-details/{loanAccountNumber}';
API_URLS[ApiKeys.EMI_SCHEDULES] = '/collection-cases/emi-schedules';
API_URLS[ApiKeys.PAST_FEEDBACK] = '/field-app/feedbacks';
API_URLS[ApiKeys.PAST_FEEDBACK] = '/feedback';
export const API_STATUS_CODE = {
OK: 200,

View File

@@ -1,8 +1,8 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { IFeedback } from '../types/feedback.types';
interface IFeedbackHistoryState {
//TODO: update interface of FeedbackHistory instead of any
[loanAccountNumber: string] : {data : any, isLoading: boolean, timestamp: string };
[loanAccountNumber: string] : { data : IFeedback[], isLoading: boolean, timestamp: string };
}
const initialState: IFeedbackHistoryState = {};

View File

@@ -33,7 +33,7 @@ const AddressContainer: React.FC<IAddressContainer> = ({addressList}) => {
<View>
{
addressList.map((address: AddressL1Details) => (
<Accordion accordionStyle={{paddingVertical: 28}}
<Accordion accordionStyle={{paddingVertical: 28, paddingHorizontal: 16 }}
accordionHeader={<AddressItem key={address?.addressDTO?.externalReferenceId}
addressItem={address?.addressDTO}
geoLocationList={address.matchingGeoLocations}

View File

@@ -98,8 +98,7 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = props => {
} = caseDetail;
const feedbackList: IFeedback[] = useAppSelector(
(state: RootState) =>
state.feedbackHistory?.data?.[loanAccountNumber as string],
(state: RootState) => state.feedbackHistory?.[loanAccountNumber as string]?.data,
);
const [showCallingBottomSheet, setShowCallingBottomSheet] =
@@ -416,7 +415,7 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = props => {
GenericStyles.pb16,
]}>
<View style={GenericStyles.row}>
<View style={{ flexBasis: '65%' }}>
<View style={{ flexBasis: '60%' }}>
<Text
style={[
styles.textContainer,
@@ -426,10 +425,10 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = props => {
</Text>
</View>
{feedbackList?.length ? (
<View style={[{ flexBasis: '35%' }]}>
<View style={[{ flexBasis: '40%' }]}>
<TouchableOpacity
activeOpacity={0.7}
onPress={console.log}
onPress={() => handleRouting(PageRouteEnum.PAST_FEEDBACK_DETAIL)}
style={GenericStyles.flex20}>
<Text
style={[

View File

@@ -1,8 +1,86 @@
import React from 'react'
import { ImageBackground, StyleSheet, 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 { BUSINESS_DATE_FORMAT, BUSINESS_TIME_FORMAT, dateFormat } from '../../../../RN-UI-LIB/src/utlis/dates'
import { sanitizeString } from '../../../components/utlis/commonFunctions'
import { AnswerType, IAnswerView, OPTION_TAG } from '../../../types/feedback.types'
const getAnswerText = (answer: IAnswerView) => {
switch (answer?.answerType) {
case AnswerType.OPTIONS:
return sanitizeString(answer.optionText);
case AnswerType.TEXT:
return sanitizeString(answer.inputText);
case AnswerType.DATE:
return sanitizeString(dateFormat(new Date(answer.inputDate as string), BUSINESS_DATE_FORMAT))
case AnswerType.TIME:
return sanitizeString(dateFormat(new Date(answer.inputDate as string), BUSINESS_TIME_FORMAT))
case AnswerType.AMOUNT:
return `${answer.inputAmount}`;
default:
return sanitizeString()
}
}
interface IFeedbackDetailAnswerContainer {
answerList: IAnswerView[]
}
const FeedbackDetailAnswerContainer: React.FC<IFeedbackDetailAnswerContainer> = ({ answerList }) => {
const imageAnswerList = answerList.filter(answer => answer.questionTag === OPTION_TAG.IMAGE_UPLOAD);
export default function FeedbackDetailAnswerContainer() {
return (
<Text>FeedbackDetailAnswerContainer</Text>
<View style={[styles.container]}>
{
imageAnswerList.map(image => (
<ImageBackground
style={styles.image}
imageStyle={styles.br8}
source={{
uri: image.inputText,
}} />
))
}
{
answerList.filter(answer => answer.questionTag !== OPTION_TAG.IMAGE_UPLOAD).map((answerItem) => (
<View style={[GenericStyles.row, GenericStyles.spaceBetween, GenericStyles.mv8]}>
<Text style={[{ width: '50%' }, styles.textContainer, styles.questionText]}>{
(answerItem.questionKey ? answerItem.questionName : answerItem.questionText) || '--'}</Text>
<Text style={[styles.textContainer, styles.answerText]}>{getAnswerText(answerItem)}</Text>
</View>
))
}
</View>
)
}
const styles = StyleSheet.create({
container: {
padding: 16,
backgroundColor: COLORS.TEXT.GREY_LIGHT,
},
textContainer: {
fontSize: 12,
lineHeight: 18,
fontWeight: '400',
},
questionText: {
color: COLORS.TEXT.LIGHT
},
answerText: {
color: COLORS.TEXT.DARK
},
br8:{
borderRadius: 8
},
image: {
width: '100%',
height: 350,
resizeMode: 'contain',
},
});
export default FeedbackDetailAnswerContainer;

View File

@@ -1,6 +1,7 @@
import React, { useEffect, useState } from 'react'
import { ScrollView, StyleSheet, View } from 'react-native';
import { Dimensions, ScrollView, StyleSheet, View } from 'react-native';
import Accordion from '../../../../RN-UI-LIB/src/components/accordian/Accordian';
import FullScreenLoader from '../../../../RN-UI-LIB/src/components/FullScreenLoader';
import NavigationHeader from '../../../../RN-UI-LIB/src/components/NavigationHeader';
import Text from '../../../../RN-UI-LIB/src/components/Text';
import { GenericStyles, getShadowStyle } from '../../../../RN-UI-LIB/src/styles';
@@ -17,7 +18,7 @@ import FeedbackDetailAnswerContainer from './FeedbackDetailAnswerContainer';
import FeedbackDetailItem from './FeedbackDetailItem';
const PAGE_TITLE = 'All feedbacks';
const SCROLL_LAYOUT_OFFSET = -10;
const SCROLL_LAYOUT_OFFSET = 10;
interface IFeedbackDetailContainer {
route: {
@@ -35,28 +36,33 @@ const FeedbackDetailContainer: React.FC<IFeedbackDetailContainer> = ({ route: ro
const isOnline = useIsOnline();
const [feedbackList, setFeedbackList] = useState<IFeedback[]>([]);
const feedbackListFromCache = useAppSelector(
(state: RootState) => state.feedbackHistory?.data?.[loanAccountNumber],
(state: RootState) => state.feedbackHistory?.[loanAccountNumber as string]?.data,
)
const [feedbackList, setFeedbackList] = useState<IFeedback[]>([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
if(isOnline) {
setLoading(true);
getPastFeedbacks({
account_number: loanAccountNumber,
loan_account_number: loanAccountNumber,
page_no: 0,
page_size: 100,
customerRecahble: false,
}).then((res: IFeedback[]) => {
if (res) {
setFeedbackList(res);
if (res?.length) {
return setFeedbackList(res);
}
throw res;
})
.catch(err => {
logError(err);
setFeedbackList(feedbackListFromCache);
logError(err);
})
.finally(() => {
setLoading(false);
})
} else {
setFeedbackList(feedbackListFromCache);
@@ -79,45 +85,43 @@ const FeedbackDetailContainer: React.FC<IFeedbackDetailContainer> = ({ route: ro
return (
<View>
<FullScreenLoader loading={loading} />
<NavigationHeader title={PAGE_TITLE} onBack={goBack} />
<ScrollView ref={x => setRef(x)}>
<View style={styles.container}>
{
feedbackList.map((feedback: IFeedback, index) => (
<View
key={index}
onLayout={(event) => {
const layout = event.nativeEvent.layout;
if (!dataSourceCord && feedback.referenceId === activeFeedbackReferenceId) {
setDataSourceCord(layout.y + SCROLL_LAYOUT_OFFSET)
}
}}>
<Accordion accordionStyle={[GenericStyles.p16, getShadowStyle(4)]}
isActive={feedback.referenceId === activeFeedbackReferenceId}
accordionHeader={<FeedbackDetailItem
key={feedback.referenceId}
feedbackItem={feedback}
/>}
customExpandUi={{ whenCollapsed: <Text style={styles.accordionExpandBtn}>View more</Text>, whenExpanded: <Text style={styles.accordionExpandBtn}>View less</Text> }}
>
<View>
<FeedbackDetailAnswerContainer />
</View>
</Accordion>
</View>
))
}
</View>
</ScrollView>
<ScrollView style={styles.container} ref={x => setRef(x)}>
{
feedbackList.map((feedback: IFeedback, index) => (
<View
key={index}
onLayout={(event) => {
const layout = event.nativeEvent.layout;
if (!dataSourceCord && feedback.referenceId === activeFeedbackReferenceId) {
setDataSourceCord(layout.y + SCROLL_LAYOUT_OFFSET)
}
}}>
<Accordion accordionStyle={[GenericStyles.pv12, getShadowStyle(4)]}
isActive={feedback.referenceId === activeFeedbackReferenceId}
accordionHeader={<FeedbackDetailItem
key={feedback.referenceId}
feedbackItem={feedback}
/>}
customExpandUi={{ whenCollapsed: <Text style={styles.accordionExpandBtn}>View more</Text>, whenExpanded: <Text style={styles.accordionExpandBtn}>View less</Text> }}
>
<FeedbackDetailAnswerContainer answerList={feedback.answerViews} />
</Accordion>
</View>
))
}
</ScrollView>
</View>
)
}
const styles = StyleSheet.create({
container: {
paddingVertical: 20,
paddingTop: 20,
paddingHorizontal: 16,
backgroundColor: COLORS.BACKGROUND.PRIMARY,
height: (Dimensions.get('window').height - 56)
},
accordionExpandBtn: {
fontSize: 13,

View File

@@ -29,9 +29,9 @@ const FeedbackDetailItem = ({ feedbackItem }: IFeedbackDetailItem) => {
const getBottomSheetHeight = getDynamicBottomSheetHeightPercentageFn();
return (
<View style={GenericStyles.columnDirection}>
<View style={[GenericStyles.columnDirection, GenericStyles.ph16]}>
<Text numberOfLines={1} ellipsizeMode="tail" style={[styles.textContainer, styles.cardBoldTitle, GenericStyles.pb4]}>
{sanitizeString(InteractionStatuses[feedbackItem.interactionStatus])}
{sanitizeString(feedbackItem.interactionStatus)}
</Text>
<Text numberOfLines={1} ellipsizeMode="tail" style={[styles.textContainer, styles.cardFooterText, GenericStyles.fontSize12]}>
{sanitizeString(dateFormat(new Date(feedbackItem.createdAt), BUSINESS_DATE_FORMAT))}

View File

@@ -77,7 +77,7 @@ const FeedbackListContainer: React.FC<IFeedbackListContainer> = ({ loanAccountNu
const isOnline = useIsOnline();
const feedbackList: IFeedback[] = useAppSelector(
(state: RootState) => state.feedbackHistory?.data?.[loanAccountNumber],
(state: RootState) => state.feedbackHistory?.[loanAccountNumber as string]?.data,
);
const handleRetryEvent = () => {

View File

@@ -40,7 +40,7 @@ const FeedbackListItem: React.FC<IFeedbackListItem> = ({ feedbackItem, loanAccou
<View style={{ flexBasis: '95%' }}>
<Text
style={styles.textHeading}>
{sanitizeString(InteractionStatuses[feedbackItem.interactionStatus])}
{sanitizeString(feedbackItem.interactionStatus)}
</Text>
<Text
style={styles.subText}>

View File

@@ -11,18 +11,25 @@ export enum AnswerType {
REMINDER = 'REMINDER',
}
export enum OPTION_TAG {
COMMENTS = 'COMMENTS',
IMAGE_UPLOAD = 'IMAGE_UPLOAD',
}
export interface IAnswerView {
interactionId?: number;
referenceId?: string;
questionReferenceId?: string;
questionName?: string;
questionText?: string;
questionKey?: string;
answerType?: AnswerType;
optionReferenceId?: string;
optionText?: string;
inputAmount?: number;
inputDate?: string;
inputText?: string;
questionTag?: OPTION_TAG;
}
export enum FEEDBACK_TYPE {