Merge branch 'master' into TP-53768_deploy
This commit is contained in:
Submodule RN-UI-LIB updated: c8321d615a...b479209834
@@ -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));
|
||||
});
|
||||
|
||||
@@ -528,6 +528,7 @@ const CollectionCaseDetails: React.FC<ICaseDetails> = (props) => {
|
||||
emiData={emiData}
|
||||
loading={isLoading}
|
||||
bottomSheetHeight={6.2}
|
||||
isLanView
|
||||
/>
|
||||
</SafeAreaView>
|
||||
</Layout>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
115
src/screens/emiSchedule/FeeWaiveInfoText.tsx
Normal file
115
src/screens/emiSchedule/FeeWaiveInfoText.tsx
Normal 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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user