Merge branch 'master' into TP-53768_deploy

This commit is contained in:
Anshuman Rai
2024-05-08 15:11:07 +05:30
committed by GitHub
10 changed files with 214 additions and 93 deletions

View File

@@ -49,7 +49,8 @@ const AnswerRender: React.FC<IAnswerRender> = (props) => {
const data = useAppSelector((state) => state.case.caseForm?.[caseId]?.[journey]);
const caseType = useAppSelector((state) => state.allCases.caseDetails[caseId]?.caseType);
const templateData = useAppSelector((state) => state.case.templateData[caseType]);
const { mobileNumbers } = useMobileNumbers(caseId);
const mobileNumbers =
useAppSelector((state) => state?.telephoneNumbers?.telephoneNumbers?.[caseId]) || [];
const getPhoneNumberStringFromNumber = memoize((phoneNumber: string) => {
return getPhoneNumberString(mobileNumbers?.find((a) => a.number === phoneNumber));
});

View File

@@ -528,6 +528,7 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
emiData={emiData}
loading={isLoading}
bottomSheetHeight={6.2}
isLanView
/>
</SafeAreaView>
</Layout>

View File

@@ -20,6 +20,7 @@ const EmiBreakup: React.FC<IEmiBreakup> = ({ emiData, lanLevelView }) => {
heldUntil,
waiverOrHoldAmount,
action,
refundedAmount = 0,
} = emiData || {};
const paidAmountGreaterThanZero = totalDueAmountPaid > 0;
const waivedOrHoldAmountGreaterThanZero = waiverOrHoldAmount > 0;
@@ -109,13 +110,20 @@ const EmiBreakup: React.FC<IEmiBreakup> = ({ emiData, lanLevelView }) => {
</Text>
</View>
<View style={[GenericStyles.row, GenericStyles.spaceBetween]}>
<Text>To pay</Text>
<Text>{refundedAmount > 0 ? 'To be refunded' : 'To pay'}</Text>
<Text
dark
bold
style={[totalDueAmountUnpaid > 0 ? GenericStyles.textRed : {}, GenericStyles.fw700]}
style={[
refundedAmount > 0
? GenericStyles.textGreen
: totalDueAmountUnpaid > 0
? GenericStyles.textRed
: {},
GenericStyles.fw700,
]}
>
{formatAmount(totalDueAmountUnpaid)}
{formatAmount(refundedAmount > 0 ? refundedAmount : totalDueAmountUnpaid)}
</Text>
</View>
</View>

View File

@@ -19,6 +19,7 @@ interface IEmiBreakupBottomSheet {
emiData: IEmiItem | null;
loading?: boolean;
bottomSheetHeight?: number;
isLanView?: boolean;
}
const EmiBreakupBottomSheet: React.FC<IEmiBreakupBottomSheet> = (props) => {
@@ -27,6 +28,7 @@ const EmiBreakupBottomSheet: React.FC<IEmiBreakupBottomSheet> = (props) => {
emiData,
loading = false,
bottomSheetHeight = 5.5,
isLanView,
setOpenBottomSheet,
} = props;
const { emiNumber } = emiData || {};
@@ -61,7 +63,7 @@ const EmiBreakupBottomSheet: React.FC<IEmiBreakupBottomSheet> = (props) => {
>
{emiData ? (
<View style={GenericStyles.p16}>
<EmiBreakup emiData={emiData} lanLevelView={true} />
<EmiBreakup emiData={emiData} lanLevelView={isLanView} />
</View>
) : null}
</SuspenseLoader>

View File

@@ -1,25 +1,11 @@
import { StyleSheet, View } from 'react-native';
import { View } from 'react-native';
import React from 'react';
import { GenericStyles } from '@rn-ui-lib/styles';
import Text from '@rn-ui-lib/components/Text';
import { formatAmount } from '@rn-ui-lib/utils/amount';
import { EmiFeeActions, IEmiItem } from './interfaces';
import { COLORS } from '@rn-ui-lib/colors';
interface IFeeWaiveInfoBanner {
emiData: IEmiItem;
}
import { IFeeWaiveInfoBanner } from './interfaces';
import FeeWaiveInfoText from './FeeWaiveInfoText';
const FeeWaiveInfoBanner: React.FC<IFeeWaiveInfoBanner> = ({ emiData }) => {
const {
maxWaivableAmount,
totalDueWaivedAmount,
totalDueAmountUnpaid,
action,
waiverOrHoldAmount,
isMaxWaived,
} = emiData || {};
const textStyle = isMaxWaived ? GenericStyles.textGreen : GenericStyles.textBlue;
const { isMaxWaived } = emiData || {};
const backgroundStyle = isMaxWaived
? GenericStyles.greenBackground
: GenericStyles.blueBackground;
@@ -28,68 +14,9 @@ const FeeWaiveInfoBanner: React.FC<IFeeWaiveInfoBanner> = ({ emiData }) => {
<View
style={[backgroundStyle, GenericStyles.row, GenericStyles.alignCenter, GenericStyles.p12]}
>
{isMaxWaived ? (
<Text small style={textStyle}>
Max {totalDueWaivedAmount > 0 ? 'waive' : 'hold'} of{' '}
<Text small style={[GenericStyles.fw700, textStyle]}>
{formatAmount(waiverOrHoldAmount)}
</Text>{' '}
is applied
</Text>
) : action === EmiFeeActions.ADJUST ? (
<View>
<Text small style={textStyle}>
You can waive / hold {waiverOrHoldAmount <= 0 ? 'maximum of ' : null}
<Text small style={[GenericStyles.fw700, textStyle]}>
{formatAmount(maxWaivableAmount)}{' '}
</Text>
{waiverOrHoldAmount > 0 ? 'more ' : ''}
from penalty
</Text>
<View style={[GenericStyles.row, GenericStyles.alignCenter, GenericStyles.ml8]}>
<View style={styles.blueDot} />
<Text style={[textStyle, GenericStyles.fontSize12, GenericStyles.ml4]}>
Amount less than{' '}
<Text small style={[GenericStyles.fw700, textStyle, GenericStyles.fontSize12]}>
{formatAmount(totalDueAmountUnpaid)}
</Text>{' '}
will be held
</Text>
</View>
<View style={[GenericStyles.row, GenericStyles.alignCenter, GenericStyles.ml8]}>
<View style={styles.blueDot} />
<Text style={[textStyle, GenericStyles.fontSize12, GenericStyles.ml4]}>
Amount{maxWaivableAmount === totalDueAmountUnpaid ? '' : ' greater than or'} equal to{' '}
<Text small style={[GenericStyles.fw700, textStyle, GenericStyles.fontSize12]}>
{formatAmount(totalDueAmountUnpaid)}
</Text>{' '}
will be instantly waived
</Text>
</View>
</View>
) : (
<Text small style={textStyle}>
You can {action === EmiFeeActions.WAIVE ? 'waive' : 'hold'}{' '}
{waiverOrHoldAmount <= 0 ? 'maximum of ' : null}
<Text small style={[GenericStyles.fw700, textStyle]}>
{formatAmount(maxWaivableAmount)}{' '}
</Text>
{waiverOrHoldAmount > 0 ? 'more ' : ''}
from penalty
</Text>
)}
<FeeWaiveInfoText emiData={emiData} />
</View>
);
};
const styles = StyleSheet.create({
blueDot: {
height: 4,
width: 4,
borderRadius: 2,
backgroundColor: COLORS.TEXT.BLUE,
marginTop: 1,
},
});
export default FeeWaiveInfoBanner;

View File

@@ -0,0 +1,115 @@
import { StyleSheet, View } from 'react-native';
import React from 'react';
import Text from '@rn-ui-lib/components/Text';
import { GenericStyles } from '@rn-ui-lib/styles';
import { formatAmount } from '@rn-ui-lib/utils/amount';
import { EmiFeeActions, IFeeWaiveInfoText } from './interfaces';
import { COLORS } from '@rn-ui-lib/colors';
const FeeWaiveInfoText: React.FC<IFeeWaiveInfoText> = ({ emiData }) => {
const {
maxWaivableAmount,
totalDueWaivedAmount,
totalDueAmountUnpaid,
action,
waiverOrHoldAmount,
isMaxWaived,
refundedAmount,
maxRefundableAmount,
} = emiData || {};
const textStyle = isMaxWaived ? GenericStyles.textGreen : GenericStyles.textBlue;
if (isMaxWaived) {
if (refundedAmount > 0) {
return (
<Text small style={textStyle}>
Max waive of{' '}
<Text small style={[GenericStyles.fw700, textStyle]}>
{formatAmount((totalDueWaivedAmount || 0) + refundedAmount)}
</Text>{' '}
is applied.{' '}
{totalDueWaivedAmount > 0 ? (
<>
<Text small style={[GenericStyles.fw700, textStyle]}>
{formatAmount(totalDueWaivedAmount)}
</Text>{' '}
is waived instantly,{' '}
</>
) : (
''
)}
<Text small style={[GenericStyles.fw700, textStyle]}>
{formatAmount(refundedAmount)}
</Text>{' '}
will be refunded.
</Text>
);
}
return (
<Text small style={textStyle}>
Max {totalDueWaivedAmount > 0 ? 'waive' : 'hold'} of{' '}
<Text small style={[GenericStyles.fw700, textStyle]}>
{formatAmount(waiverOrHoldAmount)}
</Text>{' '}
is applied
</Text>
);
}
if (action === EmiFeeActions.ADJUST) {
return (
<View>
<Text small style={textStyle}>
You can waive / hold {waiverOrHoldAmount <= 0 ? 'maximum of ' : null}
<Text small style={[GenericStyles.fw700, textStyle]}>
{formatAmount(maxWaivableAmount)}{' '}
</Text>
{waiverOrHoldAmount > 0 ? 'more ' : ''}
from penalty
</Text>
<View style={[GenericStyles.row, GenericStyles.ml8]}>
<View style={styles.blueDot} />
<Text style={[textStyle, GenericStyles.fontSize12, GenericStyles.ml4]}>
Amount less than{' '}
<Text small style={[GenericStyles.fw700, textStyle, GenericStyles.fontSize12]}>
{formatAmount(totalDueAmountUnpaid)}
</Text>{' '}
will be held
</Text>
</View>
<View style={[GenericStyles.row, GenericStyles.ml8]}>
<View style={styles.blueDot} />
<Text style={[textStyle, GenericStyles.fontSize12, GenericStyles.ml4]}>
Amount{maxWaivableAmount === totalDueAmountUnpaid ? '' : ' greater than or'} equal to{' '}
<Text small style={[GenericStyles.fw700, textStyle, GenericStyles.fontSize12]}>
{formatAmount(totalDueAmountUnpaid)}
</Text>{' '}
will be instantly waived
</Text>
</View>
</View>
);
}
return (
<Text small style={textStyle}>
You can {action === EmiFeeActions.WAIVE ? 'waive' : 'hold'}{' '}
{waiverOrHoldAmount <= 0 ? 'maximum of ' : null}
<Text small style={[GenericStyles.fw700, textStyle]}>
{formatAmount(maxWaivableAmount)}{' '}
</Text>
{waiverOrHoldAmount > 0 ? 'more ' : ''}
from penalty. {maxRefundableAmount ? 'Amount will be refunded to the customer.' : ''}
</Text>
);
};
const styles = StyleSheet.create({
blueDot: {
height: 4,
width: 4,
borderRadius: 2,
backgroundColor: COLORS.TEXT.BLUE,
marginTop: 10,
},
});
export default FeeWaiveInfoText;

View File

@@ -8,6 +8,7 @@ import { formatAmount } from '@rn-ui-lib/utils/amount';
import { addClickstreamEvent } from '@services/clickstreamEventService';
import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants';
import { IEmiItem } from './interfaces';
import InfoSolidSmallIcon from '@rn-ui-lib/icons/InfoSolidSmallIcon';
interface PartialPaidFeeAdjusmentModal {
waivedAmount: number;
@@ -22,7 +23,7 @@ const PartialPaidFeeAdjusmentModal: React.FC<PartialPaidFeeAdjusmentModal> = ({
closeModal,
confirmAdjustment,
}) => {
const { totalDueAmountUnpaid } = emiData || {};
const { totalDueAmountUnpaid, isColendingFlow } = emiData || {};
const adjustmentAmount = waivedAmount - totalDueAmountUnpaid;
const waivedInstantlyAmount = totalDueAmountUnpaid;
@@ -35,7 +36,7 @@ const PartialPaidFeeAdjusmentModal: React.FC<PartialPaidFeeAdjusmentModal> = ({
}, []);
return (
<View style={GenericStyles.p16}>
<View style={[GenericStyles.p16]}>
<Text>
You're waiving <Text style={GenericStyles.textGreen}>{formatAmount(waivedAmount)}</Text>
</Text>
@@ -58,13 +59,25 @@ const PartialPaidFeeAdjusmentModal: React.FC<PartialPaidFeeAdjusmentModal> = ({
</View>
<View style={GenericStyles.ml16}>
<Text style={[GenericStyles.fontSize13, styles.labelText]} light>
Adjusted to next EMI
{isColendingFlow ? 'To be refunded' : 'Adjusted to next EMI'}
</Text>
<Text style={[GenericStyles.fontSize16, GenericStyles.fw700]} dark>
{formatAmount(adjustmentAmount)}
</Text>
</View>
</View>
{isColendingFlow && (
<View style={styles.refundInfoBox}>
<View style={styles.infoIcon}>
<InfoSolidSmallIcon />
</View>
<View style={styles.topArrow} />
<Text small style={GenericStyles.textBlue}>
Navi customer support team will connect with the customer within 2 business days for the
refund. Customer need not reach out to Navi.
</Text>
</View>
)}
<View style={GenericStyles.row}>
<Button
title="Cancel"
@@ -91,6 +104,30 @@ const styles = StyleSheet.create({
pv7: {
paddingVertical: 7,
},
refundInfoBox: {
flexDirection: 'row',
backgroundColor: COLORS.BACKGROUND.BLUE,
padding: 12,
borderRadius: 8,
marginTop: 18,
},
topArrow: {
width: 0,
height: 0,
borderLeftWidth: 10,
borderRightWidth: 10,
borderBottomWidth: 10,
borderLeftColor: 'transparent',
borderRightColor: 'transparent',
borderBottomColor: COLORS.BACKGROUND.BLUE,
position: 'absolute',
top: -10,
right: 70,
},
infoIcon: {
marginTop: 4,
marginRight: 6,
},
});
export default PartialPaidFeeAdjusmentModal;

View File

@@ -53,6 +53,9 @@ export interface IEmiItem {
action: EmiFeeActions | null;
maxAmountAlreadyWaived: boolean;
showInfoIcon: boolean;
isColendingFlow: boolean;
refundedAmount: number;
maxRefundableAmount: number;
}
export const emiTypes = {
@@ -140,11 +143,19 @@ export enum EmiFeeActions {
export interface IEmiBreakup {
emiData: IEmiItem;
lanLevelView: boolean;
lanLevelView?: boolean;
}
export const PenaltyWaivedLabelMap = {
[EmiFeeActions.ADJUST]: 'Penalty waived / held',
[EmiFeeActions.WAIVE]: 'Penalty waived',
[EmiFeeActions.HOLD]: 'Penalty held',
};
};
export interface IFeeWaiveInfoText {
emiData: IEmiItem;
}
export interface IFeeWaiveInfoBanner {
emiData: IEmiItem;
}

View File

@@ -57,14 +57,23 @@ export const feeWaiverHistorySectionList = (
};
const getEmiFeeAction = (emiItem: IEmiItem): EmiFeeActions | null => {
const { maxWaivableAmount, totalDueAmountUnpaid, status, totalDuePenalty, isWaivable } =
emiItem || {};
const {
maxWaivableAmount,
totalDueAmountUnpaid,
status,
totalDuePenalty,
isWaivable,
maxRefundableAmount,
} = emiItem || {};
if (!totalDuePenalty) {
return null;
}
if (status === EmiSelectedTab.PAID && isWaivable) {
return EmiFeeActions.WAIVE;
}
if (maxRefundableAmount > 0) {
return EmiFeeActions.ADJUST;
}
const canAmountBeAdjusted = maxWaivableAmount >= totalDueAmountUnpaid;
if (status === EmiSelectedTab.UNPAID) {
if (canAmountBeAdjusted) {
@@ -77,17 +86,27 @@ const getEmiFeeAction = (emiItem: IEmiItem): EmiFeeActions | null => {
};
export const feeWaiveTransformedEmiData = (emiItem: IEmiItem): IEmiItem => {
const { totalDueHoldAmount, totalDueWaivedAmount, isWaivable, maxAmountAlreadyWaived } =
emiItem || {};
const {
totalDueHoldAmount,
totalDueWaivedAmount,
isWaivable,
maxAmountAlreadyWaived,
refundedAmount,
maxRefundableAmount,
maxWaivableAmount,
} = emiItem || {};
const waiverOrHoldAmount = totalDueHoldAmount || totalDueWaivedAmount || 0;
const action = getEmiFeeAction(emiItem);
const showInfoIcon = Boolean(action && !isWaivable && !maxAmountAlreadyWaived);
const isColendingFlow = refundedAmount > 0 || maxRefundableAmount > 0;
return {
...emiItem,
waiverOrHoldAmount,
isMaxWaived: !isWaivable,
action,
showInfoIcon,
isColendingFlow,
maxWaivableAmount: (maxRefundableAmount || 0) + maxWaivableAmount,
};
};