TP-111|Kunal|HRC EMI CARD revamp (#1003)

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp

* TP-111|Kunal|HRC EMI CARD revamp
This commit is contained in:
Kunal Sharma
2024-06-17 19:44:45 +05:30
committed by GitHub
parent 7d98592d95
commit bdaaf99f27
8 changed files with 431 additions and 114 deletions

View File

@@ -0,0 +1,45 @@
import * as React from 'react';
const HourglassIconV2 = () => (
<svg xmlns="http://www.w3.org/2000/svg" width={14} height={14} viewBox="0 0 14 14" fill="none">
<path
d="M2.918 1.483h8.164M2.918 12.529h8.164"
stroke="#0276FE"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path d="m7 9.163 1.44 1.44h1.681v-.48a3.12 3.12 0 1 0-6.243 0v.48H5.56z" fill="#fff" />
<path d="M8.44 10.604 7 9.164l-1.441 1.44h-1.68v1.92h6.242v-1.92z" fill="#0276FE" />
<path
d="M8.44 10.604 7 9.164l-1.441 1.44h-1.68v1.92h6.242v-1.92z"
stroke="#0276FE"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M10.121 3.884V1.483H3.878v2.4c0 .697.234 1.374.664 1.921h4.914a3.1 3.1 0 0 0 .665-1.92"
fill="#fff"
/>
<path
d="M10.121 3.884V1.483H3.878v2.4c0 .697.234 1.374.664 1.921h4.914a3.1 3.1 0 0 0 .665-1.92"
stroke="#0276FE"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path d="M4.542 5.805a3.115 3.115 0 0 0 4.915 0z" fill="#fff" />
<path
d="M4.542 5.805a3.115 3.115 0 0 0 4.915 0z"
fill="#0276FE"
stroke="#0276FE"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="m7 9.163 1.44 1.44h1.681v-.48a3.12 3.12 0 1 0-6.243 0v.48H5.56z"
stroke="#0276FE"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
export default HourglassIconV2;

View File

@@ -12,7 +12,8 @@ import {
useMergeRefs,
FloatingPortal,
FloatingArrow,
hide
hide,
useTransitionStyles
} from '@floating-ui/react';
import type { Placement } from '@floating-ui/react';
import { arrow } from '@floating-ui/dom';
@@ -31,6 +32,8 @@ interface PopperOptions {
openOnClick?: boolean;
mainAxisOffset?: number;
crossAxisOffset?: number;
disableCloseOnOutsideClick?: boolean;
transform?: boolean;
}
interface PopperContentProps {
@@ -62,7 +65,9 @@ export function usePopper({
hiddenPadding = 16,
openOnClick = true,
mainAxisOffset = 9,
crossAxisOffset = 9
crossAxisOffset = 9,
disableCloseOnOutsideClick = false,
transform = true
}: PopperOptions = {}) {
const [uncontrolledOpen, setUncontrolledOpen] = React.useState(initialOpen);
@@ -74,6 +79,7 @@ export function usePopper({
open,
onOpenChange: setOpen,
whileElementsMounted: autoUpdate,
transform,
middleware: [
offset({
mainAxis: mainAxisOffset,
@@ -98,7 +104,10 @@ export function usePopper({
const click = useClick(context, {
enabled: controlledOpen == null
});
const dismiss = useDismiss(context);
const dismiss = useDismiss(context, {
outsidePress: !disableCloseOnOutsideClick,
escapeKey: !disableCloseOnOutsideClick
});
const role = useRole(context, { role: 'popper' });
const defaultInteractions = [dismiss, role];
@@ -182,11 +191,14 @@ export const PopperTrigger = React.forwardRef<HTMLElement, PopperTriggerProps>(
export const PopperContent = React.forwardRef<HTMLDivElement, PopperContentProps>(
function PopperContent(
{ style, headerText, iconRequired = true, noHeader = false, onClose, ...props },
{ style, headerText, iconRequired = true, noHeader = false, onClose, className, ...props },
propRef
) {
const context = usePopperContext();
const ref = useMergeRefs([context.refs.setFloating, propRef]);
const transition = useTransitionStyles(context?.context, {
duration: 500
});
const referenceHidden = context?.middlewareData?.hide?.escaped;
@@ -204,41 +216,45 @@ export const PopperContent = React.forwardRef<HTMLDivElement, PopperContentProps
return (
<FloatingPortal>
<div
ref={ref}
style={{
...context.floatingStyles,
...style,
visibility: referenceHidden ? 'hidden' : 'visible'
}}
{...context.getFloatingProps(props)}
>
{!noHeader ? (
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: '12px'
}}
>
<div>{headerText}</div>
{transition?.isMounted && (
<div
ref={ref}
style={{
...context?.floatingStyles,
...style,
...transition?.styles,
visibility: referenceHidden ? 'hidden' : 'visible'
}}
className={className}
{...context?.getFloatingProps(props)}
>
{!noHeader ? (
<div
style={{ cursor: 'pointer' }}
onClick={() => {
if (onClose) onClose();
context.setOpen(false);
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: '12px'
}}
>
{iconRequired && <CloseIcon />}
<div>{headerText}</div>
<div
style={{ cursor: 'pointer' }}
onClick={() => {
if (onClose) onClose();
context?.setOpen(false);
}}
>
{iconRequired && <CloseIcon />}
</div>
</div>
</div>
) : null}
{typeof props.children === 'function'
? props?.children({ closePopper: closePopper, openPopper: openPopper })
: props.children}
<FloatingArrow context={context} ref={context?.arrowRef} fill={arrowColor} />
</div>
) : null}
{typeof props.children === 'function'
? props?.children({ closePopper: closePopper, openPopper: openPopper })
: props.children}
<FloatingArrow context={context} ref={context?.arrowRef} fill={arrowColor} />
</div>
)}
</FloatingPortal>
);
}

View File

@@ -274,3 +274,22 @@
margin-top: 0;
margin-bottom: 0;
}
:global {
.penaltyPopperWrapper {
display: flex;
flex-direction: column;
background-color: var(--green-dark);
padding: 4px 8px;
border-radius: 4px;
color: var(--text-primary);
font-family: Inter;
font-size: 13px;
font-style: normal;
font-weight: 500;
line-height: 20px;
letter-spacing: -0.13px;
box-shadow: 0px 6px 10px 0px rgba(0, 0, 0, 0.08), 0px 1px 18px 0px rgba(0, 0, 0, 0.06),
0px 3px 5px 0px rgba(0, 0, 0, 0.1);
}
}

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Typography } from '@navi/web-ui/lib/primitives';
import { formatAmount } from '@cp/src/utils/commonUtils';
import HourGlassIcon from '@cp/src/assets/icons/HourGlassIcon';
import HourGlassIcon from '@cp/assets/icons/HourglassIconV2';
import cx from 'classnames';
import dayjs from 'dayjs';
import { EmiFeeActions, IEmiBreakup, PenaltyWaivedLabelMap } from './interfaces';

View File

@@ -1,26 +1,38 @@
import React from 'react';
import React, { MutableRefObject } from 'react';
import GridContainer from '@navi/web-ui/lib/layouts/Grid/GridContainer/GridContainer';
import GridRow from '@navi/web-ui/lib/layouts/Grid/GridRow/GridRow';
import { Chip, Typography } from '@navi/web-ui/lib/primitives';
import { Checkbox, Tag, Typography } from '@navi/web-ui/lib/primitives';
import styles from './AmountdueCard.module.scss';
import { formatAmount } from 'src/utils/commonUtils';
import cx from 'classnames';
import EnachCard from './dc-97/EnachCard';
import {
HumanReminderType,
IHumanReminderDues,
MandateStatus,
RepaymentFailureDetails,
UpcomingDueDetails
UpcomingDueDetails,
WAIVER_REQUEST_TYPE
} from 'src/reducers/commonSlice';
import { COLOR_CODING, ColorCoding, DAYS_PAST_DUE } from './dc-97/dc97Constant';
import { calculateDateDifferenceInDays, DateFormat, getFormatDate } from '../../utils/DateHelper';
import { calculateDateDifferenceInDays } from '../../utils/DateHelper';
import useUpdateEffect from '@cp/hooks/useUpdateEffect';
import {
Popper,
PopperContent,
PopperContextType,
PopperTrigger
} from '@cp/components/Popper/Popper';
import { Tooltip, TooltipContent, TooltipTrigger } from '@cp/components/TooltipV2/TooltipV2';
import InfoIconOutlined from '@cp/assets/images/icons/InfoIconOutlined';
import HourglassIconV2 from '@cp/assets/icons/HourglassIconV2';
interface AmountDueCardProps {
totalAmount: number;
emiDueDate: string;
emiAmount: number;
emiDaysRemaining: number;
emiPenaltyCharge: string;
emiPenaltyCharge: string | number;
emiIncreasePenaltyChargeDate: string;
emiIncreasePenalChargeAmount: number;
emiAmountWithIncrementalPenaltyCharge: number;
@@ -28,6 +40,14 @@ interface AmountDueCardProps {
repaymentFailureDetails: RepaymentFailureDetails;
reminderType: HumanReminderType;
upcomingDueDetails?: UpcomingDueDetails;
totalUnpaidDueAmount: number;
totalEmiAmount: number;
penaltyApplied: number;
nextIncrementAmount: number;
paidAmount: number;
heldPenaltyCharge: number;
holdEligibleDues: IHumanReminderDues;
nextDayDues: IHumanReminderDues;
}
const MANDATE_NOT_SETUP = 'Mandate not set up';
@@ -65,19 +85,41 @@ const AmountDueCard = (props: AmountDueCardProps) => {
repaymentFailureDetails,
reminderType,
upcomingDueDetails,
emiAmountWithIncrementalPenaltyCharge
emiAmountWithIncrementalPenaltyCharge,
totalUnpaidDueAmount,
totalEmiAmount,
penaltyApplied,
nextIncrementAmount,
paidAmount,
heldPenaltyCharge,
holdEligibleDues,
nextDayDues
} = props;
const upcomingDueDateDiff = calculateDateDifferenceInDays(
new Date(),
new Date(upcomingDueDetails?.emiDueDate)
);
const upcomingDueDays = upcomingDueDateDiff > 1 ? DAYS_PAST_DUE.DUE_DAYS : DAYS_PAST_DUE.DUE_DAY;
const [slotValue, setSlotValue] = React.useState('');
const [showHoldEligibility, setShowHoldEligibility] = React.useState(false);
const isMandateStatusSuccess = mandateStatus === MandateStatus.SUCCESS;
const hideEnachCard = isMandateStatusSuccess && !repaymentFailureDetails?.reason;
const enachCardText = repaymentFailureDetails?.reason
? repaymentFailureDetails?.reason
: MANDATE_NOT_SETUP;
const popperTriggerRef = React.useRef<MutableRefObject<PopperContextType>>(null);
useUpdateEffect(() => {
if (showHoldEligibility) {
setSlotValue(formatAmount(holdEligibleDues?.totalUnpaidDueAmount?.amount || 0));
popperTriggerRef.current?.context?.setOpen(true);
} else {
popperTriggerRef.current?.context?.setOpen(false);
setSlotValue(formatAmount(totalUnpaidDueAmount));
}
}, [showHoldEligibility]);
return (
<GridContainer
className={cx(styles.emiDueContainer, {
@@ -111,23 +153,19 @@ const AmountDueCard = (props: AmountDueCardProps) => {
)}
</span>
{emiDaysRemaining && reminderType === HumanReminderType.POST_DUE ? (
<span className={styles.topChipText}>since Due Date</span>
<span className={styles.topChipText}>since Due Date ({emiDueDate})</span>
) : null}
</div>
<GridRow className={styles.justify_btw}>
<Typography variant="h3" className={styles.headingText}>
Total Amount Due
Total Overdue
</Typography>
<Typography
variant="h3"
className={styles.headingValue}
color={getDpdColor(emiDaysRemaining, COLOR_CODING.TOTAL_AMOUNT_COLOR, reminderType)}
>
{reminderType === HumanReminderType.POST_DUE
? formatAmount(totalAmount)
: reminderType === HumanReminderType.PRE_DUE
? formatAmount(upcomingDueDetails?.upcomingPayableDueAmount.amount)
: '--'}
{totalUnpaidDueAmount ? formatAmount(totalUnpaidDueAmount) : '--'}
</Typography>
</GridRow>
</GridContainer>
@@ -141,26 +179,135 @@ const AmountDueCard = (props: AmountDueCardProps) => {
<>
<GridRow className={cx(styles.emiPenaltyRow, styles.justify_btw)}>
<Typography variant="p3" className={styles.emiPenaltyText}>
EMI Due Date
EMI Amount
</Typography>
<Typography variant="p3" className={cx(styles.fw700, styles.emiPenaltyValue)}>
{emiDueDate}
{formatAmount(totalEmiAmount)}
</Typography>
</GridRow>
<GridRow className={cx(styles.emiPenaltyCharge, styles.justify_btw)}>
<Typography variant="p3" className={styles.emiPenaltyText}>
EMI Penalty Charge
EMI Penalty
</Typography>
<Typography variant="p3" className={cx(styles.fw700, styles.emiPenaltyValue)}>
{emiPenaltyCharge}
<Typography
variant="p3"
className={cx(styles.fw700, styles.emiPenaltyValue)}
color={typeof emiPenaltyCharge !== 'number' ? 'var(--blue-base)' : ''}
>
{typeof emiPenaltyCharge === 'number'
? formatAmount(emiPenaltyCharge)
: emiPenaltyCharge}
</Typography>
</GridRow>
<GridRow className={cx(styles.emiPenaltyRow, styles.justify_btw)}>
{(holdEligibleDues || nextDayDues) && (
<GridRow className={cx(styles.emiPenaltyCharge, styles.justify_btw)}>
<Typography
variant="p3"
className={cx(styles.emiPenaltyText, 'flex gap-[10px] items-center')}
>
Penalty Held
{nextDayDues ? (
<div className={cx('flex', 'gap-[8px]', 'items-center')}>
<Tag
color="blue"
startAdornment={<HourglassIconV2 />}
label={`Till 11:59 PM today`}
size="sm"
variant="transparent"
/>
<Tooltip placement="top" hiddenPadding={0} hideStrategy="referenceHidden">
<TooltipTrigger tooltipTriggerClassName="tooltipTriggerWrapper">
<InfoIconOutlined fillColor="var(--blue-base)" />
</TooltipTrigger>
<TooltipContent className={styles.tooltipWrapper}>
<div className="flex justify-between gap-[20px]">
<Typography
color="var(--text-primary)"
className="text-[13px]"
variant="p4"
>
Total Overdue (Tomorrow)
</Typography>
<Typography
color="var(--text-primary)"
className="text-[13px]"
variant="p4"
>
{formatAmount(nextDayDues?.totalUnpaidDueAmount?.amount || 0)}
</Typography>
</div>
<div className="flex justify-between gap-[20px]">
<Typography
color="var(--text-primary)"
className="text-[13px]"
variant="p4"
>
EMI Penalty (Tomorrow)
</Typography>
<Typography
color="var(--text-primary)"
className="text-[13px]"
variant="p4"
>
{formatAmount(nextDayDues?.penaltyApplied?.amount || 0)}
</Typography>
</div>
</TooltipContent>
</Tooltip>
</div>
) : (
<></>
// @TODO : to be added later
/* <Checkbox
checked={showHoldEligibility}
onChange={() => {
setShowHoldEligibility(prev => !prev);
}}
title="Show Hold Eligibility"
checkboxTitleClass={cx('text-[var(--blue-base)] font-medium font-[14px]')}
/>*/
)}
</Typography>
<Typography variant="p3" className={cx(styles.fw700, styles.emiPenaltyValue)}>
<Popper
placement="right-end"
openOnClick={false}
mainAxisOffset={17}
crossAxisOffset={5.5}
disableCloseOnOutsideClick
transform={false}
>
<PopperTrigger openOnClick={false} ref={popperTriggerRef}>
{showHoldEligibility
? `${
holdEligibleDues?.heldPenaltyCharge?.amount > 0 ? '-' : ''
} ${formatAmount(holdEligibleDues?.heldPenaltyCharge?.amount)}`
: `${heldPenaltyCharge > 0 ? '-' : ''} ${formatAmount(heldPenaltyCharge)}`}
</PopperTrigger>
<PopperContent
className={cx('penaltyPopperWrapper', 'swing')}
arrowColor="var(--green-dark)"
noHeader
>
{holdEligibleDues?.waiverRequestType === WAIVER_REQUEST_TYPE.WAIVER
? `Eligible for 100% waiver to close EMI`
: 'Eligible for 50% of EMI Penalty'}
</PopperContent>
</Popper>
</Typography>
</GridRow>
)}
<GridRow className={cx(styles.emiPenaltyCharge, styles.justify_btw)}>
<Typography variant="p3" className={styles.emiPenaltyText}>
EMI Amount
Paid Amount
</Typography>
<Typography variant="p3" className={cx(styles.fw700, styles.emiPenaltyValue)}>
{formatAmount(emiAmount)}
<Typography
variant="p3"
className={cx(styles.fw700, styles.emiPenaltyValue)}
color="var(--green-base)"
>
- {formatAmount(paidAmount)}
</Typography>
</GridRow>
<GridRow
@@ -171,29 +318,18 @@ const AmountDueCard = (props: AmountDueCardProps) => {
</GridRow>
<GridRow className={cx(styles.emiPenaltyRow, styles.justify_btw)}>
<GridRow className={styles.justify_btw} style={{ margin: '0px', padding: '0px' }}>
<Typography variant="p3" className={styles.emiPenaltyText}>
Upcoming EMI penalty charge
<Typography
variant="p3"
className={cx(styles.emiPenaltyText, 'flex items-center gap-[10px]')}
>
Upcoming Overdue
<Tag
color="blue"
label={emiIncreasePenaltyChargeDate ? `On ${emiIncreasePenaltyChargeDate}` : ``}
size="sm"
variant="transparent"
/>
</Typography>
<Chip
wrapperClasses={styles.emiPenaltyChip}
label={emiIncreasePenaltyChargeDate}
></Chip>
</GridRow>
<GridRow style={{ margin: '0px', padding: '0px' }}>
<Typography variant="p3" className={styles.emiPenaltyValue}>
{formatAmount(emiIncreasePenalChargeAmount)}
</Typography>
</GridRow>
</GridRow>
<GridRow className={cx(styles.emiPenaltyRow, styles.justify_btw)}>
<GridRow className={styles.justify_btw} style={{ margin: '0px', padding: '0px' }}>
<Typography variant="p3" className={styles.emiPenaltyText}>
Upcoming Total Amount Due
</Typography>
<Chip
wrapperClasses={styles.emiPenaltyChip}
label={emiIncreasePenaltyChargeDate}
></Chip>
</GridRow>
<GridRow style={{ margin: '0px', padding: '0px' }}>
<Typography variant="p3" className={styles.emiPenaltyValue}>
@@ -201,25 +337,73 @@ const AmountDueCard = (props: AmountDueCardProps) => {
</Typography>
</GridRow>
</GridRow>
<GridRow className={cx(styles.emiPenaltyRow, styles.justify_btw)}>
<Typography variant="p3" className={styles.emiPenaltyText}>
Upcoming EMI Penalty
</Typography>
<Typography variant="p3" className={styles.emiPenaltyValue}>
{formatAmount(nextIncrementAmount)}
</Typography>
</GridRow>
</>
) : reminderType === HumanReminderType.PRE_DUE ? (
<>
<GridRow className={cx(styles.emiPenaltyRow, styles.justify_btw)}>
<Typography variant="p3" className={styles.emiPenaltyText}>
Upcoming EMI Due Date
EMI Amount
</Typography>
<Typography variant="p3" className={styles.emiPenaltyValue}>
{upcomingDueDetails?.emiDueDate
? getFormatDate(new Date(upcomingDueDetails.emiDueDate), DateFormat.DD_MMM_YYYY)
: '--'}
{formatAmount(totalEmiAmount)}
</Typography>
</GridRow>
<GridRow className={cx(styles.emiPenaltyRow, styles.justify_btw)}>
<Typography variant="p3" className={styles.emiPenaltyText}>
Upcoming EMI Amount
EMI Penalty
</Typography>
<Typography variant="p3" className={styles.emiPenaltyValue}>
{formatAmount(upcomingDueDetails?.upcomingDueAmount.amount)}
{formatAmount(penaltyApplied)}
</Typography>
</GridRow>
<GridRow className={cx(styles.emiPenaltyRow, styles.justify_btw)}>
<Typography variant="p3" className={styles.emiPenaltyText}>
Paid Amount
</Typography>
<Typography
variant="p3"
className={cx(styles.emiPenaltyValue, 'font-medium')}
color="var(--green-base)"
>
- {formatAmount(paidAmount)}
</Typography>
</GridRow>
<GridRow
style={{ border: '1px dashed #CACED5' }}
className={styles.emitPenaltyRowBorder}
>
{' '}
</GridRow>
<GridRow className={cx(styles.emiPenaltyRow, styles.justify_btw)}>
<Typography variant="p3" className={cx(styles.emiPenaltyText, 'font-medium')}>
Upcoming Overdue
{emiIncreasePenaltyChargeDate && (
<Tag
color="blue"
label={`On ${emiIncreasePenaltyChargeDate}`}
size="sm"
variant="transparent"
/>
)}
</Typography>
<Typography variant="p3" className={styles.emiPenaltyValue}>
{formatAmount(emiAmountWithIncrementalPenaltyCharge)}
</Typography>
</GridRow>
<GridRow className={cx(styles.emiPenaltyRow, styles.justify_btw)}>
<Typography variant="p3" className={styles.emiPenaltyText}>
Upcoming EMI Penalty
</Typography>
<Typography variant="p3" className={styles.emiPenaltyValue}>
{formatAmount(nextIncrementAmount)}
</Typography>
</GridRow>
</>

View File

@@ -159,3 +159,17 @@
.fw700 {
font-weight: 700 !important;
}
.tooltipWrapper {
padding: 4px 4px 4px 8px;
box-sizing: border-box;
width: fit-content;
z-index: var(--z-index-tooltip);
font-weight: 400;
font-size: 12px;
line-height: 14px;
word-wrap: break-word;
color: var(--text-primary);
border-radius: 4px;
background: var(--grayscale-warm-4);
}

View File

@@ -23,7 +23,7 @@ interface HrCustomerDetailsProps {
disConnectHandler: () => void;
}
const emiPenaltyChargeOnHold = 'on hold';
const emiPenaltyChargeOnHold = 'On hold';
const HrCustomerDetails = (props: HrCustomerDetailsProps) => {
const { resetCallData, disConnectHandler } = props;
@@ -80,9 +80,10 @@ const HrCustomerDetails = (props: HrCustomerDetailsProps) => {
const genderAndAge = `${customerDetails?.gender || '--'}, ${customerDetails?.age || '--'}`;
const lastUpdatedDue = loanDetails?.unpaidDues?.length ? loanDetails?.unpaidDues[0] : null;
const emiPenaltyChargeStatus =
lastUpdatedDue?.penaltyCharges?.amount === 0 && lastUpdatedDue?.heldPenaltyCharge?.amount > 0
lastUpdatedDue?.unpaidPenaltyCharges?.amount === 0 &&
lastUpdatedDue?.heldPenaltyCharge?.amount > 0
? emiPenaltyChargeOnHold
: formatAmount(lastUpdatedDue?.penaltyCharges?.amount);
: lastUpdatedDue?.penaltyApplied?.amount;
const showFeedbackOptions =
loanDetails?.loanAccountNumber && customerDetails?.customerReferenceId;
@@ -143,7 +144,7 @@ const HrCustomerDetails = (props: HrCustomerDetailsProps) => {
}
emiAmount={lastUpdatedDue?.emiAmount?.amount || 0}
emiDaysRemaining={loanDetails?.currentDpd || 0}
emiPenaltyCharge={emiPenaltyChargeStatus || '--'}
emiPenaltyCharge={emiPenaltyChargeStatus || 0}
emiIncreasePenaltyChargeDate={
lastUpdatedDue?.nextIncrementDate
? getFormatDate(new Date(lastUpdatedDue?.nextIncrementDate), DateFormat.DD_MMM_YYYY)
@@ -157,6 +158,14 @@ const HrCustomerDetails = (props: HrCustomerDetailsProps) => {
repaymentFailureDetails={loanDetails?.repaymentFailureDetails}
upcomingDueDetails={loanDetails?.upcomingDueDetails}
reminderType={reminderType}
totalUnpaidDueAmount={lastUpdatedDue?.totalUnpaidDueAmount?.amount || 0}
totalEmiAmount={lastUpdatedDue?.totalEmiAmount?.amount || 0}
penaltyApplied={lastUpdatedDue?.penaltyApplied?.amount || 0}
nextIncrementAmount={lastUpdatedDue?.nextIncrementAmount?.amount || 0}
paidAmount={lastUpdatedDue?.paidAmount?.amount || 0}
heldPenaltyCharge={lastUpdatedDue?.heldPenaltyCharge?.amount || 0}
holdEligibleDues={loanDetails?.holdEligibilityDues?.[0]}
nextDayDues={loanDetails?.nextDayDues?.[0]}
/>
</div>
<SendPaymentLinkCard

View File

@@ -136,6 +136,57 @@ export interface UpcomingDueDetails {
};
}
export enum WAIVER_REQUEST_TYPE {
HOLD = 'HOLD',
WAIVER = 'WAIVER'
}
export interface IHumanReminderDues {
emiDueDate: string;
waiverRequestType: WAIVER_REQUEST_TYPE;
nextIncrementDate: string;
emiAmount: {
currency: string;
amount: number;
};
heldPenaltyCharge: {
currency: string;
amount: number;
};
penaltyCharges: {
currency: string;
amount: number;
};
nextIncrementAmount: {
currency: string;
amount: number;
};
emiAmountWithIncrementalPenaltyCharge: {
currency: string;
amount: number;
};
totalUnpaidDueAmount: {
currency: string;
amount: number;
};
totalEmiAmount: {
currency: string;
amount: number;
};
unpaidPenaltyCharges: {
currency: string;
amount: number;
};
paidAmount: {
currency: string;
amount: number;
};
penaltyApplied: {
currency: string;
amount: number;
};
}
export interface HumanReminderCustomerDetails {
humanReminderResponse: {
customerDetails: {
@@ -165,30 +216,9 @@ export interface HumanReminderCustomerDetails {
amount: number;
};
currentDpd: number;
unpaidDues: {
emiDueDate: string;
nextIncrementDate: string;
emiAmount: {
currency: string;
amount: number;
};
heldPenaltyCharge: {
currency: string;
amount: number;
};
penaltyCharges: {
currency: string;
amount: number;
};
nextIncrementAmount: {
currency: string;
amount: number;
};
emiAmountWithIncrementalPenaltyCharge: {
currency: string;
amount: number;
};
}[];
unpaidDues: IHumanReminderDues[];
holdEligibilityDues: IHumanReminderDues[];
nextDayDues: IHumanReminderDues[];
mandateStatus: MandateStatus;
repaymentFailureDetails: RepaymentFailureDetails;
upcomingDueDetails: UpcomingDueDetails;