From b9817f9104c5f79177ca9cd2a9a47500c3daf0e0 Mon Sep 17 00:00:00 2001 From: Aman Singh Date: Tue, 20 Feb 2024 19:08:44 +0530 Subject: [PATCH] TP-42467 | Tele sensei v3.1 (#815) * TP-42467 |release 18th jan| Aman Singh * TP-42467 |3.2 half done| Aman Singh * TP-42467 |EM UAT done| Aman Singh * TP-42467 |linting fix| Aman Singh * TP-42467 |linting fix| Aman Singh * TP-42467 |tele sensei done| Aman Singh * TP-42467 |tele sensei done| Aman Singh * TP-42467 |tele sensei done| Aman Singh * TP-42467 |tele sensei done| Aman Singh * TP-42467 |tele sensei done| Aman Singh * TP-42467 |final commit| Aman singh * TP-42467 |lint fix| Aman singh * TP-42467 |before UAT| Aman singh * TP-48182 | UAT Fixes * TP-48182 | UAT Fix * TP-48182 | Resolved PR comments * TP-48182 | Removed Mock Data * TP-48182 | PR comments * TP-57238|tele sensei v3.1 comments resolved| Aman Singh * TP-48182 | Border Radius Removed from header * TP-57238|tele sensei v3.1 comments resolved| Aman Singh * TP-57238|tele sensei v3.1 comments resolved| Aman Singh --------- Co-authored-by: yashmantri Co-authored-by: Varnit Goyal --- src/assets/styles/variables.scss | 1 + .../CellRendererShortNumber.tsx | 22 +- src/components/sidebar/SideNavBar.tsx | 11 +- src/pages/SenseiTele/action/index.ts | 20 +- .../components/agentInput/ColumnDefs.tsx | 2 +- .../components/agentInput/index.module.scss | 6 + .../agentPerformance/index.module.scss | 13 + .../components/agentPerformance/index.tsx | 5 + .../despositionSummary/index.module.scss | 13 +- .../components/despositionSummary/index.tsx | 4 + .../CallOverViewProgressBar.tsx | 27 + .../emiBucketWiseSummary/CallsOverView.tsx | 89 ++++ .../NoDataFoundComponent.tsx | 22 + .../emiBucketWiseSummary/NumberOfCases.tsx | 117 ++++ .../emiBucketWiseSummary/PtpOverview.tsx | 159 ++++++ .../emiBucketWiseSummary/columnDef.tsx | 186 +++++++ .../emiBucketWiseSummary/index.module.scss | 388 ++++++++++++++ .../components/emiBucketWiseSummary/index.tsx | 275 ++++++++++ .../components/filters/index.module.scss | 1 - src/pages/SenseiTele/constants/index.ts | 500 +++++++++++++++++- src/pages/SenseiTele/index.tsx | 73 ++- src/pages/SenseiTele/reducer/index.ts | 19 +- src/pages/SenseiTele/types/index.ts | 86 ++- src/pages/auth/constants/AuthConstants.ts | 3 +- src/utils/ApiHelper.ts | 5 +- 25 files changed, 2018 insertions(+), 29 deletions(-) create mode 100644 src/pages/SenseiTele/components/emiBucketWiseSummary/CallOverViewProgressBar.tsx create mode 100644 src/pages/SenseiTele/components/emiBucketWiseSummary/CallsOverView.tsx create mode 100644 src/pages/SenseiTele/components/emiBucketWiseSummary/NoDataFoundComponent.tsx create mode 100644 src/pages/SenseiTele/components/emiBucketWiseSummary/NumberOfCases.tsx create mode 100644 src/pages/SenseiTele/components/emiBucketWiseSummary/PtpOverview.tsx create mode 100644 src/pages/SenseiTele/components/emiBucketWiseSummary/columnDef.tsx create mode 100644 src/pages/SenseiTele/components/emiBucketWiseSummary/index.module.scss create mode 100644 src/pages/SenseiTele/components/emiBucketWiseSummary/index.tsx diff --git a/src/assets/styles/variables.scss b/src/assets/styles/variables.scss index 8e85f8a6..fb08e019 100644 --- a/src/assets/styles/variables.scss +++ b/src/assets/styles/variables.scss @@ -89,6 +89,7 @@ --light-blue-background: #e5f3ff; --navigation-blue-navigation-content-1: #fcfcfd; --navigation-blue-c2: #caced5; + --navi-color-blue-navigation: #001833; // black base order --black-base: #1a1a1a; diff --git a/src/components/TableCellRenderer/CellRendererShortNumber.tsx b/src/components/TableCellRenderer/CellRendererShortNumber.tsx index 0c6f6e87..be29b73f 100644 --- a/src/components/TableCellRenderer/CellRendererShortNumber.tsx +++ b/src/components/TableCellRenderer/CellRendererShortNumber.tsx @@ -9,6 +9,7 @@ interface ICellRendererShortNumber { hiddenPadding?: number; significantDigits?: number; isCurrency?: boolean; + ellipsisWrapperClass?: string; } const CellRendererShortNumber: React.FC = props => { @@ -17,7 +18,8 @@ const CellRendererShortNumber: React.FC = props => { lineClamp = 1, hiddenPadding = 10, significantDigits = 1, - isCurrency = false + isCurrency = false, + ellipsisWrapperClass } = props; if (!Number.isFinite(value)) { @@ -26,7 +28,9 @@ const CellRendererShortNumber: React.FC = props => { } if (!value && value !== 0) { - return ; + return ( + + ); } let shorthandNumber = value == 0 ? '0' : shortNumberNotation(value, significantDigits); @@ -37,7 +41,13 @@ const CellRendererShortNumber: React.FC = props => { if (isCurrency) { shorthandNumber = `₹${shorthandNumber}`; } - return ; + return ( + + ); } if (isCurrency) { @@ -48,7 +58,11 @@ const CellRendererShortNumber: React.FC = props => { return ( - + pathname.includes(path)); + const isTeleInhouseTeamLead = userData?.roles?.includes(Roles.ROLE_NAVI_TELE_INHOUSE_TEAM_LEAD); const disableAmeyoToolbarFlag = window?.config?.DISABLE_AMEYO_TOOLBAR === 'true' || isDc97User; @@ -422,7 +423,7 @@ function SideNavBar({ isDc97User, isHRCChatUser }: ISideNavbarProps) { /> ) : null} - {isInternalTeamLead ? ( + {isTeleInhouseTeamLead ? ( } inActiveIcon={} @@ -489,12 +490,12 @@ function SideNavBar({ isDc97User, isHRCChatUser }: ISideNavbarProps) { /> ) : null} - {isInternalTeamLead ? ( + {isTeleInhouseTeamLead ? ( } inActiveIcon={} - name={'Availablity Tracker'} + name={'Availability Tracker'} route={APP_ROUTES.AGENT_AVAILABILITY.path} linkClickHandler={linkClickHandler} currentPathname={pathname} @@ -530,13 +531,13 @@ function SideNavBar({ isDc97User, isHRCChatUser }: ISideNavbarProps) { /> ) : null} - {isInternalTeamLead ? ( + {isTeleInhouseTeamLead ? ( <> } inActiveIcon={} - name={'Tele Sensei'} + name={'Performance Dashboard'} route={APP_ROUTES.SENSEI_TELE.path} linkClickHandler={linkClickHandler} currentPathname={pathname} diff --git a/src/pages/SenseiTele/action/index.ts b/src/pages/SenseiTele/action/index.ts index 865fa34b..db8f778d 100644 --- a/src/pages/SenseiTele/action/index.ts +++ b/src/pages/SenseiTele/action/index.ts @@ -4,9 +4,11 @@ import { setAgentPerformance, setApiResponse, setDespositionSummary, + setEmiBucketWiseSummary, setLoading, setLoadingAgentPerformance, - setLoadingDespositionSummary + setLoadingDespositionSummary, + setLoadingEmiBucketWiseSummary } from '../reducer'; export const getAgentPerformanceData = () => (dispatch: Dispatch) => { @@ -62,3 +64,19 @@ export const getDespositionSummary = () => (dispatch: Dispatch) => { dispatch(setLoadingDespositionSummary(false)); }); }; + +export const getEMIBucketWiseSummary = () => (dispatch: Dispatch) => { + dispatch(setLoadingEmiBucketWiseSummary(true)); + const url = getApiUrl(ApiKeys.EMI_BUCKET_WISE_SUMMARY); + axiosInstance + .get(url) + .then(response => { + dispatch(setEmiBucketWiseSummary(response?.data?.data)); + }) + .catch(error => { + logError(error, 'emiBucketWiseSummary'); + }) + .finally(() => { + dispatch(setLoadingEmiBucketWiseSummary(false)); + }); +}; diff --git a/src/pages/SenseiTele/components/agentInput/ColumnDefs.tsx b/src/pages/SenseiTele/components/agentInput/ColumnDefs.tsx index 649af198..df1f530f 100644 --- a/src/pages/SenseiTele/components/agentInput/ColumnDefs.tsx +++ b/src/pages/SenseiTele/components/agentInput/ColumnDefs.tsx @@ -185,7 +185,7 @@ export const AgentPerformanceColumns = [ }, { field: 'avgAttemptPerUnpaidCase', - headerName: 'Average Calls / Unpaid Case', + headerName: 'Average Calls / Unpaid Cases', minWidth: 150, sortable: true, wrapHeaderText: true, diff --git a/src/pages/SenseiTele/components/agentInput/index.module.scss b/src/pages/SenseiTele/components/agentInput/index.module.scss index 34028bff..f711eaa6 100644 --- a/src/pages/SenseiTele/components/agentInput/index.module.scss +++ b/src/pages/SenseiTele/components/agentInput/index.module.scss @@ -44,6 +44,10 @@ line-height: 20px; /* 142.857% */ letter-spacing: -0.175px; + width: -webkit-fill-available !important; + width: -moz-available !important; + width: -webkit-fill-available !important; + width: fill-available !important; } .ag-header-group-cell-label { @@ -159,9 +163,11 @@ } .ag-floating-top { + overflow-y: hidden !important; font-weight: 900; color: var(--navi-color-gray-c1) !important; border-bottom: 0px !important; + .ag-row { background-color: var(--bg-primary) !important; } diff --git a/src/pages/SenseiTele/components/agentPerformance/index.module.scss b/src/pages/SenseiTele/components/agentPerformance/index.module.scss index 22802a0b..915888f6 100644 --- a/src/pages/SenseiTele/components/agentPerformance/index.module.scss +++ b/src/pages/SenseiTele/components/agentPerformance/index.module.scss @@ -62,6 +62,7 @@ line-height: 20px; /* 142.857% */ letter-spacing: -0.175px; + width: -webkit-fill-available !important; } .ag-header-group-cell-label { @@ -88,6 +89,7 @@ } .ag-header-row { + width: 100% !important; .ag-header-cell { padding-left: 16px; padding-right: 0px; @@ -183,11 +185,15 @@ .ag-floating-top { font-weight: 900; + overflow-y: hidden !important; color: var(--navi-color-gray-c1) !important; border-bottom: 0px !important; .ag-row { background-color: var(--bg-primary) !important; } + .ag-floating-top-container { + width: -webkit-fill-available !important; + } } .ag-sort-indicator-icon { @@ -200,5 +206,12 @@ .ag-header-cell-text { line-height: 18px; } + + .ag-header-container { + width: 100% !important; + } + .ag-center-cols-viewport { + overflow: hidden; + } } } diff --git a/src/pages/SenseiTele/components/agentPerformance/index.tsx b/src/pages/SenseiTele/components/agentPerformance/index.tsx index 149cffe7..215493fb 100644 --- a/src/pages/SenseiTele/components/agentPerformance/index.tsx +++ b/src/pages/SenseiTele/components/agentPerformance/index.tsx @@ -147,6 +147,10 @@ const Index: React.FC = props => { return [data]; }, [tableData]); + useEffect(() => { + ref?.current?.api?.sizeColumnsToFit(); + }, [tableData, loading]); + return (
@@ -185,6 +189,7 @@ const Index: React.FC = props => { animateRows pinnedTopRowData={pinnedRow} suppressRowClickSelection={true} + headerHeight={80} PaginationComponent={ div:nth-child(1) { + > div:nth-child(2) { background-color: var(--green-light); color: var(--green-base); pointer-events: none; @@ -32,9 +32,10 @@ line-height: 20px; /* 142.857% */ letter-spacing: -0.175px; + width: -webkit-fill-available !important; } - > div:nth-child(2) { + > div:nth-child(3) { background-color: var(--pale-yellow); color: var(--navi-color-yellow-dark); pointer-events: none; @@ -72,6 +73,7 @@ } .ag-header-row { + width: 100% !important; .ag-header-cell { padding-left: 16px; padding-right: 0px; @@ -161,6 +163,7 @@ } .ag-floating-top { + overflow-y: hidden !important; font-weight: 900; color: var(--navi-color-gray-c1) !important; border-bottom: 0px !important; @@ -185,5 +188,11 @@ .ag-horizontal-left-spacer { visibility: hidden; } + .ag-center-cols-viewport { + overflow: hidden; + } + .ag-header-container { + width: 100% !important; + } } } diff --git a/src/pages/SenseiTele/components/despositionSummary/index.tsx b/src/pages/SenseiTele/components/despositionSummary/index.tsx index bbc88028..a011ac28 100644 --- a/src/pages/SenseiTele/components/despositionSummary/index.tsx +++ b/src/pages/SenseiTele/components/despositionSummary/index.tsx @@ -64,6 +64,10 @@ const Index: React.FC = props => { setColumnData(newColumnData); }, []); + useEffect(() => { + ref?.current?.api?.sizeColumnsToFit(); + }, [tableData, loading]); + const handlePageChange = (e: number) => { const newParams = { ...params }; const pageNumber = e.toString(); diff --git a/src/pages/SenseiTele/components/emiBucketWiseSummary/CallOverViewProgressBar.tsx b/src/pages/SenseiTele/components/emiBucketWiseSummary/CallOverViewProgressBar.tsx new file mode 100644 index 00000000..b9080dd9 --- /dev/null +++ b/src/pages/SenseiTele/components/emiBucketWiseSummary/CallOverViewProgressBar.tsx @@ -0,0 +1,27 @@ +import HorizontalProgress from '@cp/src/components/ProgressBars/horizontalProgress/HorizontalProgress'; +import React from 'react'; +import styles from './index.module.scss'; +import cx from 'classnames'; +import { formatNumber } from '@cp/src/utils/commonUtils'; + +interface ICallOverViewProgressBar { + title: string; + percentage: number; +} + +const CallOverViewProgressBar: React.FC = props => { + const { title, percentage } = props; + return ( +
+ {title} + + {formatNumber(percentage, true)}% +
+ ); +}; + +export default CallOverViewProgressBar; diff --git a/src/pages/SenseiTele/components/emiBucketWiseSummary/CallsOverView.tsx b/src/pages/SenseiTele/components/emiBucketWiseSummary/CallsOverView.tsx new file mode 100644 index 00000000..38ccf84a --- /dev/null +++ b/src/pages/SenseiTele/components/emiBucketWiseSummary/CallsOverView.tsx @@ -0,0 +1,89 @@ +import Dropdown from '@cp/src/components/Dropdown'; +import HorizontalProgress from '@cp/src/components/ProgressBars/horizontalProgress/HorizontalProgress'; +import { SelectPickerOptionProps } from '@cp/src/types/CommonConstans'; +import { readQueryParams } from '@cp/src/utils/QueryParamsHelper'; +import { formatNumber } from '@cp/src/utils/commonUtils'; +import { Typography } from '@navi/web-ui/lib/primitives'; +import cx from 'classnames'; +import React from 'react'; +import { AGENT_PERFORMANCE_TABLE, DROPDOWN_OPTIONS } from '../../constants'; +import { ICallsOverView } from '../../types'; +import NoDataFoundComponent from './NoDataFoundComponent'; +import styles from './index.module.scss'; +import CallOverViewProgressBar from './CallOverViewProgressBar'; + +const CallsOverView: React.FC = props => { + const { data, updateAndNavigate, params } = props; + + if (!data) { + return ; + } + + const handleSelectionChange = (value: SelectPickerOptionProps) => { + if (!value) return; + const { [AGENT_PERFORMANCE_TABLE]: updatedParams } = readQueryParams(); + const newParams = { ...updatedParams }; + newParams.depositionSummaryCallOverViewFilter = value.value as string; + updateAndNavigate(newParams); + }; + + const { TOTAL_CALLS, VIA_AMEYO, VIA_LONGHORN, VIA_SELF } = data ?? {}; + + const longhornPercentage = + (Number( + VIA_LONGHORN?.[params.depositionSummaryCallOverViewFilter as keyof typeof VIA_LONGHORN] + ) / + Number( + TOTAL_CALLS?.[params.depositionSummaryCallOverViewFilter as keyof typeof TOTAL_CALLS] + )) * + 100; + + const ameyoPercentage = + (Number(VIA_AMEYO?.[params.depositionSummaryCallOverViewFilter as keyof typeof VIA_AMEYO]) / + Number( + TOTAL_CALLS?.[params.depositionSummaryCallOverViewFilter as keyof typeof TOTAL_CALLS] + )) * + 100; + + const selfPercentage = + (Number(VIA_SELF?.[params.depositionSummaryCallOverViewFilter as keyof typeof VIA_SELF]) / + Number( + TOTAL_CALLS?.[params.depositionSummaryCallOverViewFilter as keyof typeof TOTAL_CALLS] + )) * + 100; + + return ( +
+
+ + Calls Overview + + item.value === params.depositionSummaryCallOverViewFilter + )} + /> +
+
+
+
+ + + +
+
+
+
+ ); +}; + +export default CallsOverView; diff --git a/src/pages/SenseiTele/components/emiBucketWiseSummary/NoDataFoundComponent.tsx b/src/pages/SenseiTele/components/emiBucketWiseSummary/NoDataFoundComponent.tsx new file mode 100644 index 00000000..eeb62df2 --- /dev/null +++ b/src/pages/SenseiTele/components/emiBucketWiseSummary/NoDataFoundComponent.tsx @@ -0,0 +1,22 @@ +import NoDataFound from '@cp/src/assets/icons/NoDataFound'; +import { Typography } from '@navi/web-ui/lib/primitives'; +import styles from './index.module.scss'; +import React from 'react'; + +interface NoDataFoundComponentProps { + title: string; +} + +const NoDataFoundComponent: React.FC = props => { + const { title } = props; + return ( +
+
+ {title} +
+ +
+ ); +}; + +export default NoDataFoundComponent; diff --git a/src/pages/SenseiTele/components/emiBucketWiseSummary/NumberOfCases.tsx b/src/pages/SenseiTele/components/emiBucketWiseSummary/NumberOfCases.tsx new file mode 100644 index 00000000..5ede4e7c --- /dev/null +++ b/src/pages/SenseiTele/components/emiBucketWiseSummary/NumberOfCases.tsx @@ -0,0 +1,117 @@ +import Highcharts from 'highcharts'; +import HighchartsReact from 'highcharts-react-official'; +import React from 'react'; +import { formatNumber, pluralisation } from 'src/utils/commonUtils'; +import styles from './index.module.scss'; +import { Typography } from '@navi/web-ui/lib/primitives'; +import { summaryGroup, summaryGroupColorMapping } from '../../constants'; +import NoDataFoundComponent from './NoDataFoundComponent'; +import { CashEarnedChartHCProps, responseDataType } from '../../types'; + +const transformData = (responseData: responseDataType) => { + const data = []; + let key: keyof typeof responseData; + for (key in responseData) { + data.push({ + name: summaryGroup[key as keyof typeof summaryGroup], + y: responseData[key], + value: responseData[key], + color: summaryGroupColorMapping[key as keyof typeof summaryGroupColorMapping], + formattedValue: formatNumber(responseData[key] as number, false) + }); + } + return data; +}; + +const getSum = (data: any) => { + let sum = 0; + let key: keyof typeof data; + for (key in data) { + sum += Number.isInteger(data[key]) ? data[key] : 0; + } + return sum; +}; +const NumberOfCases: React.FC = props => { + const { dataTObeFed } = props; + + if (!dataTObeFed) { + return ; + } + + const sum = getSum(dataTObeFed); + + const options = { + chart: { + plotBackgroundColor: null, + plotBorderWidth: 0, + plotShadow: false, + style: { + fontFamily: 'Inter' + }, + renderTo: 'container', + height: 215, + width: 500 + }, + credits: { + enabled: false + }, + title: { + text: `
${formatNumber(sum)}
Total ${pluralisation('Case', sum, 's')}
`, + align: 'center', + verticalAlign: 'middle' + }, + tooltip: { + enabled: false + }, + accessibility: { + point: { + valueSuffix: '%' + } + }, + plotOptions: { + pie: { + size: 160, + animation: true, + dataLabels: { + enabled: true, + allowOverlap: true, + align: 'left', + format: `
{point.name}
{point.formattedValue} ({point.percentage:.1f}%)
`, + useHTML: true, + distance: 20, + filter: { + property: 'percentage', + operator: '>', + value: 0 + } + } + } + }, + series: [ + { + type: 'pie', + name: 'CashEarned', + innerSize: '70%', + data: transformData(dataTObeFed) + } + ] + }; + + return ( +
+
+ + Number of cases + +
+
+
+ +
+
+
+ ); +}; +export default NumberOfCases; diff --git a/src/pages/SenseiTele/components/emiBucketWiseSummary/PtpOverview.tsx b/src/pages/SenseiTele/components/emiBucketWiseSummary/PtpOverview.tsx new file mode 100644 index 00000000..6ab44c8f --- /dev/null +++ b/src/pages/SenseiTele/components/emiBucketWiseSummary/PtpOverview.tsx @@ -0,0 +1,159 @@ +import Highcharts from 'highcharts'; +import HighchartsReact from 'highcharts-react-official'; +import React from 'react'; +import styles from './index.module.scss'; +import cx from 'classnames'; +import Dropdown from '@cp/src/components/Dropdown'; +import { readQueryParams } from '@cp/src/utils/QueryParamsHelper'; +import { Typography } from '@navi/web-ui/lib/primitives'; +import { AGENT_PERFORMANCE_TABLE, DROPDOWN_OPTIONS } from '../../constants'; +import { IPTPOverView } from '../../types'; +import NoDataFoundComponent from './NoDataFoundComponent'; +import { formatNumber } from '@cp/src/utils/commonUtils'; + +const PTPOverView: React.FC = props => { + const { data, params, updateAndNavigate } = props; + + if (!data) { + return ; + } + const { PTP_GENERATED, PTP_CONVERTED, BROKEN_PTP, FUTURE_PTP } = data; + + const handleSelectionChange = (value: any) => { + if (!value) return; + const { [AGENT_PERFORMANCE_TABLE]: updatedParams } = readQueryParams(); + const newParams = { ...updatedParams }; + newParams.depositionSummaryPTPOverViewFilter = value.value as string; + updateAndNavigate(newParams); + }; + + const dataToBeFed = [ + { + name: 'PTP Converted', + y: Number( + PTP_CONVERTED[params.depositionSummaryPTPOverViewFilter as keyof typeof PTP_CONVERTED] + ), + value: Number( + PTP_CONVERTED[params.depositionSummaryPTPOverViewFilter as keyof typeof PTP_CONVERTED] + ), + color: '#5D87FF', + formattedValue: formatNumber( + Number( + PTP_CONVERTED[params.depositionSummaryPTPOverViewFilter as keyof typeof PTP_CONVERTED] + ), + true + ) + }, + { + name: 'Broken PTP', + y: Number(BROKEN_PTP[params.depositionSummaryPTPOverViewFilter as keyof typeof BROKEN_PTP]), + value: Number( + BROKEN_PTP[params.depositionSummaryPTPOverViewFilter as keyof typeof BROKEN_PTP] + ), + color: '#6FE8C8', + formattedValue: formatNumber( + Number(BROKEN_PTP[params.depositionSummaryPTPOverViewFilter as keyof typeof BROKEN_PTP]), + true + ) + }, + { + name: 'Future PTP', + y: Number(FUTURE_PTP[params.depositionSummaryPTPOverViewFilter as keyof typeof FUTURE_PTP]), + value: Number( + FUTURE_PTP[params.depositionSummaryPTPOverViewFilter as keyof typeof FUTURE_PTP] + ), + color: '#FA896B', + formattedValue: formatNumber( + Number(FUTURE_PTP[params.depositionSummaryPTPOverViewFilter as keyof typeof FUTURE_PTP]), + true + ) + } + ]; + const options = { + chart: { + plotBackgroundColor: null, + plotBorderWidth: 0, + plotShadow: false, + style: { + fontFamily: 'Inter' + }, + renderTo: 'container', + height: 225, + width: 500 + }, + credits: { + enabled: false + }, + title: { + text: `
+
${formatNumber( + Number( + PTP_GENERATED[params.depositionSummaryPTPOverViewFilter as keyof typeof PTP_GENERATED] + ) + )}
+
`, + align: 'center', + verticalAlign: 'middle' + }, + tooltip: { + enabled: false + }, + accessibility: { + point: { + valueSuffix: '%' + } + }, + plotOptions: { + pie: { + size: 160, + animation: true, + dataLabels: { + enabled: true, + allowOverlap: true, + align: 'left', + format: `
{point.name}
{point.formattedValue}
`, + useHTML: true, + distance: 10, + filter: { + property: 'percentage', + operator: '>', + value: 0 + } + } + } + }, + series: [ + { + type: 'pie', + name: 'CashEarned', + innerSize: '70%', + data: dataToBeFed + } + ] + }; + + return ( +
+
+ + PTPs Overview + + item.value === params.depositionSummaryPTPOverViewFilter + )} + /> +
+
+
+ +
+
+
+ ); +}; +export default PTPOverView; diff --git a/src/pages/SenseiTele/components/emiBucketWiseSummary/columnDef.tsx b/src/pages/SenseiTele/components/emiBucketWiseSummary/columnDef.tsx new file mode 100644 index 00000000..8d626ba8 --- /dev/null +++ b/src/pages/SenseiTele/components/emiBucketWiseSummary/columnDef.tsx @@ -0,0 +1,186 @@ +import { ICellRendererParams } from 'ag-grid-community'; +import styles from './index.module.scss'; +import TableCellRenderer from '@cp/src/components/TableCellRenderer'; +import CellRendererShortNumber from '@cp/src/components/TableCellRenderer/CellRendererShortNumber'; +import cx from 'classnames'; +import { shortNumberNotation } from '@cp/src/utils/commonUtils'; + +export const AgentPerformanceColumns = [ + { + headerName: '', + children: [ + { + field: 'name', + headerName: '', + minWidth: 280, + pinned: 'left', + cellClass: (params: ICellRendererParams) => { + return cx({ [styles.bold]: params?.data?.bold }, styles.border, { + [styles.blueBackground]: params?.data?.blue + }); + }, + suppressMovable: true, + cellRenderer: (params: ICellRendererParams) => { + const { name } = params.data || {}; + return ( + + ); + } + } + ] + }, + { + headerName: 'Bucket Range', + children: [ + { + field: '<4k', + headerName: 'Less than 4k', + width: 160, + autoHeaderHeight: true, + wrapHeaderText: true, + cellClass: (params: ICellRendererParams) => { + return cx({ [styles.blueBackground]: params?.data?.blue }); + }, + cellRenderer: (params: ICellRendererParams) => { + const data = params.data?.['<4k']; + const isCurrency = params.data?.isCurrency; + const isPercentage = params.data?.percentage; + const value = shortNumberNotation(data, 2) + '%'; + if (isPercentage) { + return ( + + ); + } + return ( + + ); + } + }, + { + field: '4k-7k', + wrapHeaderText: true, + headerName: '4k to 7k', + autoHeaderHeight: true, + width: 120, + cellClass: (params: ICellRendererParams) => { + return cx({ [styles.blueBackground]: params?.data?.blue }); + }, + cellRenderer: (params: ICellRendererParams) => { + const data = params.data?.['4k-7k']; + const isPercentage = params.data?.percentage; + const isCurrency = params.data?.isCurrency; + const value = shortNumberNotation(data, 2) + '%'; + if (isPercentage) { + return ( + + ); + } + return ( + + ); + } + }, + { + field: '7k-10k', + wrapHeaderText: true, + headerName: '7k to 10k', + autoHeaderHeight: true, + width: 120, + cellClass: (params: ICellRendererParams) => { + return cx({ [styles.blueBackground]: params?.data?.blue }); + }, + cellRenderer: (params: ICellRendererParams) => { + const data = params.data?.['7k-10k']; + const isPercentage = params.data?.percentage; + const isCurrency = params.data?.isCurrency; + const value = shortNumberNotation(data, 2) + '%'; + if (isPercentage) { + return ( + + ); + } + return ( + + ); + } + }, + { + field: '10k+', + wrapHeaderText: true, + headerName: 'More than 10k', + autoHeaderHeight: true, + cellClass: (params: ICellRendererParams) => { + return cx({ [styles.blueBackground]: params?.data?.blue }); + }, + width: 160, + cellRenderer: (params: ICellRendererParams) => { + const data = params.data?.['10k+']; + const isPercentage = params.data?.percentage; + const isCurrency = params.data?.isCurrency; + const value = shortNumberNotation(data, 2) + '%'; + if (isPercentage) { + return ( + + ); + } + return ( + + ); + } + } + ] + } +]; diff --git a/src/pages/SenseiTele/components/emiBucketWiseSummary/index.module.scss b/src/pages/SenseiTele/components/emiBucketWiseSummary/index.module.scss new file mode 100644 index 00000000..95f382e3 --- /dev/null +++ b/src/pages/SenseiTele/components/emiBucketWiseSummary/index.module.scss @@ -0,0 +1,388 @@ +.EmiBucketWiseSummary { + position: relative; + margin-top: 120px; + + .tableContainer { + .tableActions { + display: flex; + justify-content: space-between; + // padding-right: 32px; + margin-bottom: 12px; + } + } + + .border { + border-right: 1px solid var(--navi-color-gray-border) !important; + } + + .bold { + font-weight: 600; + } + + .blueBackground { + background-color: var(--bg-blue); + } + + .dataContainer { + display: flex; + gap: 24px; + + .tableContainer { + position: relative; + flex-basis: 66%; + box-shadow: 0px 8px 20px 0px rgba(221, 221, 221, 0.3); + .noDataFound { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + } + + .subPoint { + margin-left: 20px; + color: var(--navi-color-gray-c2); + font-size: 13px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.13px; + } + + .subPointInternal { + color: var(--navi-color-gray-c2); + font-size: 13px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.13px; + } + + .mb0 { + margin-bottom: 0px !important; + } + + .ptpOverview { + margin-bottom: 24px; + background: white; + padding-bottom: 32px; + border-radius: 16px; + box-shadow: 0px 8px 20px 0px rgba(221, 221, 221, 0.3); + height: 252px; + .headingAndFilter { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + border-radius: 8px 8px 0px 0px; + border: 0px solid var(--navi-color-gray-border); + background: #f1f2f4; + padding: 0px 16px; + margin-bottom: 12px; + height: 44px; + + .heading { + font-size: 20px; + font-weight: 600; + line-height: 28px; + letter-spacing: -0.25px; + color: var(--navi-color-gray-c1); + } + + .dropdownContainer { + width: 150px; + + .dropdownInnerContainer { + border-radius: 4px; + border: 1px solid var(--navi-color-gray-border); + background: var(--navi-color-gray-bg-primary); + padding: 4px 12.5px; + box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.06); + } + } + } + } + + .emptyView { + width: 500px; + height: 252px; + margin-bottom: 24px; + background: white; + padding: 16px 20px 16px 20px; + border-radius: 16px; + box-shadow: 0px 8px 20px 0px rgba(221, 221, 221, 0.3); + position: relative; + + &:last-child { + margin-bottom: 0px; + } + + .headingAndFilter { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + } + + .noDataFoundIcon { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + + .barChartLabel { + color: var(--navi-color-gray-c2); + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 18px; + letter-spacing: -0.12px; + } + + .barchartLabelNumber { + color: var(--navi-color-blue-navigation); + text-align: center; + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 12px; + /* 100% */ + letter-spacing: -0.12px; + text-align: left; + } + + .pieChartCenter { + color: var(--navi-color-gray-c3); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.175px; + } + + .pieChartSubtext { + color: var(--navi-color-gray-c3); + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: 20px; + letter-spacing: -0.175px; + opacity: 0.5; + } + + .progressColorBackground { + background-color: var(--grayscale-6); + height: 12px; + width: 305px; + } + + .progressColor { + background-color: var(--green-base); + transition: width 400ms ease-in-out; + } + + .percentage { + color: var(--navi-color-gray-c3); + } + + .numberOfCallsLineChartContainer { + display: flex; + gap: 8px; + align-items: center; + + .label { + flex-basis: 15%; + text-align: right; + } + + .text { + color: var(--navi-color-gray-c2); + text-align: right; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: 18px; + letter-spacing: -0.12px; + } + } + + .pieChartContainer { + display: flex; + justify-content: space-around; + flex-direction: column; + } + .callsOverviewHeight { + height: 200px; + } +} + +.fb32 { + flex-basis: 32%; +} + +:global { + .agentDepositionSummary { + .ag-header-viewport { + .ag-header-row-column-group { + > div:nth-child(1) { + background-color: var(--pale-yellow); + color: var(--navi-color-yellow-dark); + pointer-events: none; + text-align: center; + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; + /* 142.857% */ + letter-spacing: -0.175px; + } + + .ag-header-group-cell-label { + flex: none; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + } + + text-align: center; + font-size: 14px; + font-style: normal; + font-weight: 600; + line-height: 20px; + letter-spacing: -0.175px; + } + } + + .ag-pinned-left-cols-container { + .ag-cell { + padding-right: 5px !important; + } + } + + .ag-header-row { + .ag-header-cell { + padding-left: 16px; + padding-right: 0px; + } + } + + .ag-row { + .ag-cell { + padding-left: 16px; + padding-right: 0px; + } + } + + .ag-pinned-left-header { + .ag-header-cell { + padding-right: 10px; + } + + .ag-header-group-cell { + background-color: unset !important; + padding-left: 5px; + } + } + + .ag-center-cols-clipper { + min-height: unset !important; + } + + .ag-header-group-cell { + border-right: 1px solid var(--greyscale-light); + padding: 0 !important; + margin: 0 !important; + } + + .ag-header-group-cell-label { + display: flex; + align-items: center; + justify-content: center; + padding: 0; + } + + .ag-header-group-cell { + .ag-header-group-text { + font-size: 14px !important; + } + + :nth-child(1) { + display: inline-block; + align-items: center; + justify-content: center; + text-align: center; + width: 100%; + } + } + + .paginationWrapperClasses { + overflow: unset; + z-index: var(--z-index-pagination-wrapper); + bottom: 4px; + + > div:nth-child(1) { + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + } + } + + .customHeaderManagement { + width: 140px; + text-align: center; + + .ag-header-cell-comp-wrapper { + .ag-header-cell-label { + display: grid; + margin: auto; + } + } + + span { + text-overflow: inherit; + text-wrap: wrap; + width: 42px; // according to figma width + } + } + + .ag-react-container { + display: none; + } + + .ag-floating-top { + font-weight: 900; + overflow-y: hidden !important; + color: var(--navi-color-gray-c1) !important; + border-bottom: 0px !important; + + .ag-row { + background-color: var(--bg-primary) !important; + } + } + + .ag-sort-indicator-icon { + padding-right: 4px; + } + + .ag-row-last { + border-bottom: none !important; + } + + .ag-header-cell-text { + line-height: 18px; + } + + .ag-horizontal-left-spacer { + visibility: hidden; + } + } + + .pieChartContainerClass { + display: flex; + justify-content: center; + } +} diff --git a/src/pages/SenseiTele/components/emiBucketWiseSummary/index.tsx b/src/pages/SenseiTele/components/emiBucketWiseSummary/index.tsx new file mode 100644 index 00000000..6e0a6d65 --- /dev/null +++ b/src/pages/SenseiTele/components/emiBucketWiseSummary/index.tsx @@ -0,0 +1,275 @@ +import Download from '@cp/src/assets/images/icons/Download'; +import Loader from '@cp/src/components/Loader/Loader'; +import { RootState } from '@cp/src/store'; +import { DateFormat, dateFormat } from '@cp/src/utils/DateHelper'; +import { AgTable } from '@navi/web-ui/lib/components'; +import { Button, Typography } from '@navi/web-ui/lib/primitives'; +import { SortChangedEvent } from 'ag-grid-community'; +import { AgGridReact } from 'ag-grid-react'; +import cx from 'classnames'; +import React, { useEffect, useRef } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { IBuckerrWiseSummarySum, IEMIBucketWiseSummary, IFilters } from '../../types'; +import { AgentPerformanceColumns } from './columnDef'; +import styles from './index.module.scss'; +import { + SUMMARY_GROUP, + emiBucketWiseRowsEnum, + generateFinalSummaryGroup, + getRowObject, + IEmiBucketWiseDataObject +} from '../../constants'; +import NumberOfCases from './NumberOfCases'; +import CallsOverView from './CallsOverView'; +import PTPOverView from './PtpOverview'; +import NoDataFound from '@cp/src/assets/icons/NoDataFound'; +import { l } from 'msw/lib/core/GraphQLHandler-d4787f91'; + +const Index: React.FC = props => { + const { params, updateAndNavigate, url } = props; + const ref = useRef>(null); + const [columnData, setColumnData] = React.useState(AgentPerformanceColumns); + const [dataObject, setDataObject] = React.useState(); + const tableData = useSelector((state: RootState) => state.teleSensei.emiBucketWiseSummaryFilter); + const loading = useSelector((state: RootState) => state.teleSensei.loadingDespositionSummary); + const [data, setData] = React.useState>([]); + const dispatch = useDispatch(); + const handleSort = (e: SortChangedEvent) => { + if (e?.source === 'gridOptionsChanged') return; + const newParams = { ...params }; + const sortModel = e?.columnApi?.getColumnState(); + const sortedColumns = sortModel?.find(item => item.sort !== null); + if (!sortedColumns) { + delete newParams?.sortColumnDisposition; + delete newParams?.sortOrderDisposition; + newParams.pageNoDisposition = '1'; + updateAndNavigate(newParams); + ref?.current?.api.paginationGoToPage(0); + return; + } + const { colId, sort } = sortedColumns; + newParams.sortColumnDisposition = colId; + newParams.sortOrderDisposition = sort as string; + newParams.pageNoDisposition = '1'; + ref?.current?.api.paginationGoToPage(0); + updateAndNavigate(newParams); + }; + + useEffect(() => { + if (!params?.sortColumnDisposition) { + setColumnData(AgentPerformanceColumns); + } + const newColumnData = AgentPerformanceColumns.map(item => { + const children = item.children?.map(child => { + if (child.field === params?.sortColumnDisposition) { + return { + ...child, + sort: params?.sortOrderDisposition as any + }; + } + return child; + }); + return { + ...item, + children + }; + }); + setColumnData(newColumnData); + }, []); + + const handleDownloadReport = () => { + ref?.current?.api?.exportDataAsCsv({ + fileName: `EMI-Bucket-Wise-Summary-${dateFormat(new Date(), DateFormat.FILE_DATE_FORMAT)}` + }); + }; + + const generateData = () => { + const allBucketWiseSummary = tableData?.flatMap(item => item.bucketWiseSummary); + const allData: IEmiBucketWiseDataObject = getRowObject(); + const finalSummaryGroup = generateFinalSummaryGroup(); + if (!allBucketWiseSummary.length) { + setData([]); + setDataObject(null); + return; + } + let coverageUnpaidCases4k = 0; + let coverageUnpaidCases7k = 0; + let coverageUnpaidCases10k = 0; + let coverageUnpaidCases4k7k = 0; + + let avgUnpaidCases4k = 0; + let avgUnpaidCases7k = 0; + let avgUnpaidCases10k = 0; + let avgUnpaidCases4k7k = 0; + + for (const item of allBucketWiseSummary) { + const { bucketGroup } = item; + let key: keyof typeof finalSummaryGroup; + switch (bucketGroup) { + case '<4k': + for (key in item) { + finalSummaryGroup['<4k'][key as IBuckerrWiseSummarySum] += + item[key as keyof typeof item]; + } + coverageUnpaidCases4k += item.unpaidCases ?? 0 * item.unpaidCasesCoverage ?? 0; + avgUnpaidCases4k += item.averageUniqueDaysCalledPerUnpaidCases * item.unpaidCases ?? 0; + break; + case '4k-7k': + for (key in item) { + finalSummaryGroup['4k-7k'][key as IBuckerrWiseSummarySum] += + item[key as keyof typeof item]; + } + coverageUnpaidCases4k7k += item.unpaidCases ?? 0 * item.unpaidCasesCoverage ?? 0; + avgUnpaidCases4k7k += item.averageUniqueDaysCalledPerUnpaidCases * item.unpaidCases ?? 0; + break; + case '7k-10k': + for (key in item) { + finalSummaryGroup['7k-10k'][key as IBuckerrWiseSummarySum] += + item[key as keyof typeof item]; + } + coverageUnpaidCases7k += item.unpaidCases ?? 0 * item.unpaidCasesCoverage ?? 0; + avgUnpaidCases7k += item.averageUniqueDaysCalledPerUnpaidCases * item.unpaidCases ?? 0; + break; + case '10k+': + for (key in item) { + finalSummaryGroup['10k+'][key as IBuckerrWiseSummarySum] += + item[key as keyof typeof item]; + } + coverageUnpaidCases10k += item.unpaidCases ?? 0 * item.unpaidCasesCoverage ?? 0; + avgUnpaidCases10k += item.averageUniqueDaysCalledPerUnpaidCases * item.unpaidCases ?? 0; + break; + default: + break; + } + } + + for (const allDataKey in allData) { + for (const summaryGroupKey in SUMMARY_GROUP) { + const rightHandSideKey = allData[allDataKey as keyof typeof allData].key; + allData[allDataKey][SUMMARY_GROUP[summaryGroupKey]] = + finalSummaryGroup[SUMMARY_GROUP[summaryGroupKey]][rightHandSideKey]; + } + } + + // EMI CE % calculation + allData[emiBucketWiseRowsEnum.EMI_CE] = { + ...allData[emiBucketWiseRowsEnum.EMI_CE], + '<4k': (finalSummaryGroup['<4k'].emiCollected / finalSummaryGroup['<4k'].emiAllocated) * 100, + '4k-7k': + (finalSummaryGroup['4k-7k'].emiCollected / finalSummaryGroup['4k-7k'].emiAllocated) * 100, + '7k-10k': + (finalSummaryGroup['7k-10k'].emiCollected / finalSummaryGroup['7k-10k'].emiAllocated) * 100, + '10k+': + (finalSummaryGroup['10k+'].emiCollected / finalSummaryGroup['10k+'].emiAllocated) * 100 + }; + + //Calculation for coverage on unpaid cases + allData[emiBucketWiseRowsEnum.COVERAGE_UNPAID_CASES] = { + ...allData[emiBucketWiseRowsEnum.COVERAGE_UNPAID_CASES], + '<4k': + (finalSummaryGroup['<4k'].unpaidCasesCovered / finalSummaryGroup['<4k'].unpaidCases) * 100, + '4k-7k': + (finalSummaryGroup['4k-7k'].unpaidCasesCovered / finalSummaryGroup['4k-7k'].unpaidCases) * + 100, + '7k-10k': + (finalSummaryGroup['7k-10k'].unpaidCasesCovered / finalSummaryGroup['7k-10k'].unpaidCases) * + 100, + '10k+': + (finalSummaryGroup['10k+'].unpaidCasesCovered / finalSummaryGroup['10k+'].unpaidCases) * 100 + }; + + allData[emiBucketWiseRowsEnum.AVG_CALLS_UNPAID_CASES] = { + ...allData[emiBucketWiseRowsEnum.AVG_CALLS_UNPAID_CASES], + '<4k': finalSummaryGroup['<4k'].totalCalls / coverageUnpaidCases4k, + '4k-7k': finalSummaryGroup['4k-7k'].totalCalls / coverageUnpaidCases4k7k, + '7k-10k': finalSummaryGroup['7k-10k'].totalCalls / coverageUnpaidCases7k, + '10k+': finalSummaryGroup['10k+'].totalCalls / coverageUnpaidCases10k + }; + + allData[emiBucketWiseRowsEnum.AVG_UNIQUE_DAYS_CALLED_UNPAID_CASES] = { + ...allData[emiBucketWiseRowsEnum.AVG_UNIQUE_DAYS_CALLED_UNPAID_CASES], + '<4k': avgUnpaidCases4k / finalSummaryGroup['<4k'].unpaidCases, + '4k-7k': avgUnpaidCases4k7k / finalSummaryGroup['4k-7k'].unpaidCases, + '7k-10k': avgUnpaidCases7k / finalSummaryGroup['7k-10k'].unpaidCases, + '10k+': avgUnpaidCases10k / finalSummaryGroup['10k+'].unpaidCases + }; + + const totalCases = Object.values({ ...allData }); + setData(totalCases); + setDataObject(allData); + }; + + useEffect(() => { + generateData(); + }, [tableData]); + + useEffect(() => { + ref?.current?.api?.sizeColumnsToFit(); + }, [tableData, loading]); + + return ( +
+
+
+ + EMI Bucket wise Summary + + +
+
+
+ params.data?.rowHeight} + /> + {!data.length ? : null} +
+
+ i.key === 'totalCases')} + casesData={data.find(i => i.key === 'totalCases')} + /> + + +
+
+
+ +
+ ); +}; + +export default Index; diff --git a/src/pages/SenseiTele/components/filters/index.module.scss b/src/pages/SenseiTele/components/filters/index.module.scss index 50c8703a..d813bd51 100644 --- a/src/pages/SenseiTele/components/filters/index.module.scss +++ b/src/pages/SenseiTele/components/filters/index.module.scss @@ -4,7 +4,6 @@ justify-content: space-between; align-items: center; padding: 16px; - border-radius: 0px 0px 32px 32px; box-shadow: 0px 14px 38px 0px rgba(125, 125, 125, 0.08); position: sticky; top: 0; diff --git a/src/pages/SenseiTele/constants/index.ts b/src/pages/SenseiTele/constants/index.ts index 66eac80e..eb0c92de 100644 --- a/src/pages/SenseiTele/constants/index.ts +++ b/src/pages/SenseiTele/constants/index.ts @@ -1,3 +1,6 @@ +import { SelectPickerOptionProps } from '@cp/src/components/interfaces'; +import { IAllDataBucketWiseSummary } from '../types'; + export enum ViewType { TEAM_LEAD = 'TEAM_LEAD', SENIOR_TEAM_LEAD = 'SENIOR_TEAM_LEAD' @@ -12,5 +15,500 @@ export const TABLE_DEFAULT_VALUES = { page: '1', orderBy: 'name', order: 'asc', - goToStart: 0 + goToStart: 0, + depositionSummaryPTPOverViewFilter: '<4k', + depositionSummaryCallOverViewFilter: '<4k' +}; + +export enum summaryGroup { + '<4k' = 'Less than 4k', + '4k-7k' = '4k to 7k', + '10k+' = 'More than 10k', + '7k-10k' = '7k to 10k' +} + +export enum summaryGroupColorMapping { + '<4k' = '#FFAD1E', + '4k-7k' = '#FA896B', + '10k+' = '#5D87FF', + '7k-10k' = '#6FE8C8' +} + +export enum emiBucketWiseRowsEnum { + EMI_ALLOCATED = 'EMI_ALLOCATED', + EMI_CE = 'EMI_CE', + TOTAL_CASES = 'TOTAL_CASES', + UNPAID_CASES = 'UNPAID_CASES', + TOTAL_CALLS = 'TOTAL_CALLS', + VIA_LONGHORN = 'VIA_LONGHORN', + VIA_AMEYO = 'VIA_AMEYO', + VIA_SELF = 'VIA_SELF', + COVERAGE_UNPAID_CASES = 'COVERAGE_UNPAID_CASES', + AVG_CALLS_UNPAID_CASES = 'AVG_CALLS_UNPAID_CASES', + AVG_UNIQUE_DAYS_CALLED_UNPAID_CASES = 'AVG_UNIQUE_DAYS_CALLED_UNPAID_CASES', + PTP_GENERATED = 'PTP_GENERATED', + PTP_CONVERTED = 'PTP_CONVERTED', + BROKEN_PTP = 'BROKEN_PTP', + FUTURE_PTP = 'FUTURE_PTP' +} + +export enum emiBucketWiseRowsReadableNameEnum { + EMI_ALLOCATED = 'EMI ALLOCATED', + EMI_CE = 'EMI CE', + TOTAL_CASES = 'TOTAL CASES', + UNPAID_CASES = 'UNPAID CASES', + TOTAL_CALLS = 'TOTAL CALLS', + VIA_LONGHORN = 'VIA LONGHORN', + VIA_AMEYO = 'VIA AMEYO', + VIA_SELF = 'VIA SELF', + COVERAGE_UNPAID_CASES = 'COVERAGE UNPAID CASES', + AVG_CALLS_UNPAID_CASES = 'AVG CALLS UNPAID CASES', + AVG_UNIQUE_DAYS_CALLED_UNPAID_CASES = 'AVG UNIQUE DAYS CALLED UNPAID CASES', + PTP_GENERATED = 'PTP GENERATED', + PTP_CONVERTED = 'PTP CONVERTED', + BROKEN_PTP = 'BROKEN PTP', + FUTURE_PTP = 'FUTURE PTP' +} + +export const emiBucketWiseData = [ + { + name: emiBucketWiseRowsEnum.EMI_ALLOCATED, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'emiAllocated' + }, + { + name: emiBucketWiseRowsEnum.EMI_CE, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'emiCollectionEfficiency' + }, + { + name: emiBucketWiseRowsEnum.UNPAID_CASES, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'unpaidCases' + }, + { + name: emiBucketWiseRowsEnum.TOTAL_CALLS, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'totalCalls' + }, + { + name: emiBucketWiseRowsEnum.VIA_LONGHORN, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'slashCalls' + }, + { + name: emiBucketWiseRowsEnum.VIA_AMEYO, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'ameyoCalls' + }, + { + name: emiBucketWiseRowsEnum.VIA_SELF, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + selfCalls: 'selfCalls' + }, + { + name: emiBucketWiseRowsEnum.COVERAGE_UNPAID_CASES, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'unpaidCasesCoverage' + }, + { + name: emiBucketWiseRowsEnum.AVG_CALLS_UNPAID_CASES, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'averageCallsPerUnpaidCases' + }, + { + name: emiBucketWiseRowsEnum.AVG_UNIQUE_DAYS_CALLED_UNPAID_CASES, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'averageUniqueDaysCalledPerUnpaidCases' + }, + { + name: emiBucketWiseRowsEnum.PTP_GENERATED, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'generatedPtpCount' + }, + { + name: emiBucketWiseRowsEnum.PTP_CONVERTED, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'convertedPtpCount' + }, + { + name: emiBucketWiseRowsEnum.BROKEN_PTP, + lessThan4k: 0, + between4k7k: 0, + between7k10k: 0, + greaterThan10k: 0, + key: 'brokenPtpCount' + } +]; +export const emiBucketWiseRows = [ + 'EMI Allocated', + 'EMI CE %', + '% Unpaid cases', + 'Total Calls', + 'Via Longhorn', + 'Via Ameyo', + 'Via Self', + 'Coverage % Unpaid cases', + 'Avg calls/Unpaid cases', + 'Avg Unique Days Called/Unpaid cases', + '% PTP Generated', + '% PTP Converted', + '% Broken PTP' +]; +// create emiBucketWiseData object with keys as enum values +export type IEmiBucketWiseDataObject = typeof emiBucketWiseDataObject; + +export const emiBucketWiseDataObject = { + [emiBucketWiseRowsEnum.EMI_ALLOCATED]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'emiAllocated', + name: 'EMI Allocated' + }, + [emiBucketWiseRowsEnum.EMI_CE]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'emiCollectionEfficiency', + name: 'EMI CE %' + }, + [emiBucketWiseRowsEnum.TOTAL_CASES]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'totalCases', + name: 'Total Cases', + bold: true + }, + [emiBucketWiseRowsEnum.UNPAID_CASES]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'unpaidCases', + name: 'Unpaid Cases' + }, + [emiBucketWiseRowsEnum.TOTAL_CALLS]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'totalCalls', + name: 'Total Calls', + bold: true + }, + [emiBucketWiseRowsEnum.VIA_LONGHORN]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'slashCalls', + name: 'Via Longhorn', + subPoint: true, + blue: true + }, + [emiBucketWiseRowsEnum.VIA_AMEYO]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'ameyoCalls', + name: 'Via Ameyo', + subPoint: true, + blue: true + }, + [emiBucketWiseRowsEnum.VIA_SELF]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'selfCalls', + name: 'Via Self', + subPoint: true, + blue: true + }, + [emiBucketWiseRowsEnum.COVERAGE_UNPAID_CASES]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'unpaidCasesCoverage', + name: 'Coverage on Unpaid Cases %' + }, + [emiBucketWiseRowsEnum.AVG_CALLS_UNPAID_CASES]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'averageCallsPerUnpaidCases', + name: 'Avg Calls/Unpaid Cases' + }, + [emiBucketWiseRowsEnum.AVG_UNIQUE_DAYS_CALLED_UNPAID_CASES]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'averageUniqueDaysCalledPerUnpaidCases', + name: 'Avg Unique Days Called/Unpaid Cases' + }, + [emiBucketWiseRowsEnum.PTP_GENERATED]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'generatedPtpCount', + name: 'PTP Generated', + bold: true + }, + [emiBucketWiseRowsEnum.PTP_CONVERTED]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'convertedPtpCount', + name: 'PTP Converted', + subPoint: true + }, + [emiBucketWiseRowsEnum.BROKEN_PTP]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'brokenPtpCount', + name: 'Broken PTP', + subPoint: true + }, + [emiBucketWiseRowsEnum.FUTURE_PTP]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'futurePtpCount', + name: 'Future PTP', + subPoint: true + } +}; +export const getRowObject = () => { + return { + [emiBucketWiseRowsEnum.EMI_ALLOCATED]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'emiAllocated', + name: 'EMI Allocated', + isCurrency: true + }, + [emiBucketWiseRowsEnum.EMI_CE]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'emiCollectionEfficiency', + name: 'EMI CE %', + percentage: true + }, + [emiBucketWiseRowsEnum.TOTAL_CASES]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'totalCases', + name: 'Total Cases', + bold: true + }, + [emiBucketWiseRowsEnum.UNPAID_CASES]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'unpaidCases', + name: 'Unpaid Cases' + }, + [emiBucketWiseRowsEnum.TOTAL_CALLS]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'totalCalls', + name: 'Total Calls', + bold: true + }, + [emiBucketWiseRowsEnum.VIA_LONGHORN]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'slashCalls', + name: 'Via Longhorn', + subPoint: true, + blue: true, + rowHeight: 42 + }, + [emiBucketWiseRowsEnum.VIA_AMEYO]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'ameyoCalls', + name: 'Via Ameyo', + subPoint: true, + blue: true, + rowHeight: 42 + }, + [emiBucketWiseRowsEnum.VIA_SELF]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'selfCalls', + name: 'Via Self', + subPoint: true, + blue: true, + rowHeight: 42 + }, + [emiBucketWiseRowsEnum.COVERAGE_UNPAID_CASES]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'unpaidCasesCoverage', + name: 'Coverage on Unpaid Cases %', + blueBackground: true, + percentage: true + }, + [emiBucketWiseRowsEnum.AVG_CALLS_UNPAID_CASES]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'averageCallsPerUnpaidCases', + name: 'Avg Calls/Unpaid Cases' + }, + [emiBucketWiseRowsEnum.AVG_UNIQUE_DAYS_CALLED_UNPAID_CASES]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'averageUniqueDaysCalledPerUnpaidCases', + name: 'Avg Unique Days Called/Unpaid Cases' + }, + [emiBucketWiseRowsEnum.PTP_GENERATED]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'generatedPtpCount', + name: 'PTP Generated', + bold: true + }, + [emiBucketWiseRowsEnum.PTP_CONVERTED]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'convertedPtpCount', + name: 'PTP Converted', + subPoint: true, + blue: true, + rowHeight: 42 + }, + [emiBucketWiseRowsEnum.BROKEN_PTP]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'brokenPtpCount', + name: 'Broken PTP', + subPoint: true, + blue: true, + rowHeight: 42 + }, + [emiBucketWiseRowsEnum.FUTURE_PTP]: { + '<4k': 0, + '4k-7k': 0, + '7k-10k': 0, + '10k+': 0, + key: 'futurePtpCount', + name: 'Future PTP', + subPoint: true, + blue: true, + rowHeight: 42 + } + }; +}; + +export const DROPDOWN_OPTIONS = [ + { value: '<4k', label: 'Less than 4k' }, + { value: '4k-7k', label: '4k to 7k' }, + { value: '7k-10k', label: '7k to 10k' }, + { value: '10k+', label: 'More than 10k' } +] as SelectPickerOptionProps[]; + +export const SUMMARY_GROUP = ['<4k', '4k-7k', '10k+', '7k-10k']; + +export const generateFinalSummaryGroup = () => { + const finalSummaryGroup: IAllDataBucketWiseSummary = {}; + for (const key of SUMMARY_GROUP) { + finalSummaryGroup[key as string] = { + emiAllocated: 0, + emiCollectionEfficiency: 0, + totalCases: 0, + unpaidCases: 0, + totalCalls: 0, + slashCalls: 0, + ameyoCalls: 0, + selfCalls: 0, + unpaidCasesCoverage: 0, + averageCallsPerUnpaidCases: 0, + averageUniqueDaysCalledPerUnpaidCases: 0, + generatedPtpCount: 0, + convertedPtpCount: 0, + brokenPtpCount: 0, + futurePtpCount: 0, + emiCollected: 0, + unpaidCasesCovered: 0 + }; + } + return finalSummaryGroup; }; diff --git a/src/pages/SenseiTele/index.tsx b/src/pages/SenseiTele/index.tsx index 6c8756fe..6e4b364c 100644 --- a/src/pages/SenseiTele/index.tsx +++ b/src/pages/SenseiTele/index.tsx @@ -1,10 +1,21 @@ import React, { useEffect } from 'react'; import Filter from './components/filters'; import AgentPerformance from './components/agentPerformance'; -import { getAgentInputData, getAgentPerformanceData, getDespositionSummary } from './action'; +import { + getAgentInputData, + getAgentPerformanceData, + getDespositionSummary, + getEMIBucketWiseSummary +} from './action'; import { useDispatch, useSelector } from 'react-redux'; import { createQueryParams, readQueryParams } from '@cp/src/utils/QueryParamsHelper'; -import { IAgent, IAgentPerformance, IAgentPerformanceParams, IDepositionSummary } from './types'; +import { + IAgent, + IAgentPerformance, + IAgentPerformanceParams, + IDepositionSummary, + IEMIBucketWiseSummary +} from './types'; import { AGENT_PERFORMANCE_TABLE, TABLE_DEFAULT_VALUES, pollingInterval } from './constants'; import { useLocation, useNavigate } from 'react-router'; import AgentInput from './components/agentInput'; @@ -13,6 +24,7 @@ import store, { RootState } from '@cp/src/store'; import { setAgentPerformanceFiltered, setDespositionSummaryFilter, + setEmiBucketWiseSummaryFilter, setFilteredData } from './reducer'; import { poll } from '@cp/src/utils/polling'; @@ -25,16 +37,22 @@ import { Typography } from '@navi/web-ui/lib/primitives'; import AgentInputIcon from '@cp/src/assets/icons/AgentInputIcon'; import { addClickstreamEvent } from '@cp/src/service/clickStreamEventService'; import { CLICKSTREAM_EVENT_NAMES } from '@cp/src/service/clickStream.constant'; - +import EmiBucketSummary from './components/emiBucketWiseSummary'; const Index = () => { const dispatch = useDispatch(); - const { loading, loadingAgentPerformance, agentData, IAgentPerformance, despositionSummary } = - useSelector((state: RootState) => state.teleSensei); + const { + loading, + loadingAgentPerformance, + agentData, + IAgentPerformance, + despositionSummary, + emiBucketWiseSummary + } = useSelector((state: RootState) => state.teleSensei); const location = useLocation(); const { [AGENT_PERFORMANCE_TABLE]: params } = readQueryParams(); const navigate = useNavigate(); - const unsubscribeRef = React.useRef<() => void>(); + const updateAndNavigate = (updatedParams: IAgentPerformanceParams) => { addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.LH_TELE_SENSEI_FILTER_APPLY, { updatedParams }); const url = createQueryParams({ @@ -47,6 +65,7 @@ const Index = () => { dispatch(getAgentInputData()); dispatch(getAgentPerformanceData()); dispatch(getDespositionSummary()); + dispatch(getEMIBucketWiseSummary()); }, []); useEffect(() => { @@ -65,10 +84,18 @@ const Index = () => { queryParams['pageSizeInput'] = TABLE_DEFAULT_VALUES.rowsPerPage; } if (!queryParams?.pageNoDisposition) { - queryParams['pageNoDisposition'] = '1'; + queryParams['pageNoDisposition'] = TABLE_DEFAULT_VALUES.page; } if (!queryParams?.pageSizeDisposition) { - queryParams['pageSizeDisposition'] = '10'; + queryParams['pageSizeDisposition'] = TABLE_DEFAULT_VALUES.rowsPerPage; + } + if (!queryParams?.depositionSummaryCallOverViewFilter) { + queryParams['depositionSummaryCallOverViewFilter'] = + TABLE_DEFAULT_VALUES.depositionSummaryCallOverViewFilter; + } + if (!queryParams?.depositionSummaryPTPOverViewFilter) { + queryParams['depositionSummaryPTPOverViewFilter'] = + TABLE_DEFAULT_VALUES.depositionSummaryPTPOverViewFilter; } updateAndNavigate(queryParams); }, []); @@ -79,6 +106,7 @@ const Index = () => { let filteredAgentData: IAgent[] = []; let filteredAgentInput: IAgentPerformance[] = []; let filteredDespositionData: IDepositionSummary[] = []; + let filteredEmiBucketData: IEMIBucketWiseSummary[] = []; // filtering this out if both the filter selected if (params?.teamLeadId && params?.agentId) { const dataAfterTLFilter = agentData?.filter( @@ -107,6 +135,15 @@ const Index = () => { ); dispatch(setDespositionSummaryFilter(filteredDespositionData)); + const dataAfterTLFilterEmiBucket = emiBucketWiseSummary?.filter( + agentData => agentData?.tlReferenceId === params?.teamLeadId + ); + + filteredEmiBucketData = dataAfterTLFilterEmiBucket?.filter(agentData => + selectedAgents?.some((agentID: string) => agentData?.agentReferenceId === agentID) + ); + dispatch(setEmiBucketWiseSummaryFilter(filteredEmiBucketData)); + return; } if (params?.teamLeadId && !params?.agentId) { @@ -124,6 +161,11 @@ const Index = () => { agentData => agentData?.tlReferenceId === params?.teamLeadId ); dispatch(setDespositionSummaryFilter(filteredDespositionData)); + + filteredEmiBucketData = emiBucketWiseSummary?.filter( + agentData => agentData?.tlReferenceId === params?.teamLeadId + ); + dispatch(setEmiBucketWiseSummaryFilter(filteredEmiBucketData)); return; } if (!params?.teamLeadId && params?.agentId) { @@ -142,6 +184,11 @@ const Index = () => { selectedAgents?.some((agentID: string) => agentData?.agentReferenceId === agentID) ); dispatch(setDespositionSummaryFilter(filteredDespositionData)); + + filteredEmiBucketData = emiBucketWiseSummary?.filter(agentData => + selectedAgents?.some((agentID: string) => agentData?.agentReferenceId === agentID) + ); + dispatch(setEmiBucketWiseSummaryFilter(filteredEmiBucketData)); return; } if (!params?.teamLeadId && !params?.agentId) { @@ -153,9 +200,12 @@ const Index = () => { filteredDespositionData = despositionSummary; dispatch(setDespositionSummaryFilter(filteredDespositionData)); + + filteredEmiBucketData = emiBucketWiseSummary; + dispatch(setEmiBucketWiseSummaryFilter(filteredEmiBucketData)); return; } - }, [location, agentData, IAgentPerformance, despositionSummary]); + }, [location, agentData, IAgentPerformance, despositionSummary, emiBucketWiseSummary]); return (
@@ -175,6 +225,11 @@ const Index = () => { updateAndNavigate={updateAndNavigate} url={location.hash} /> +
diff --git a/src/pages/SenseiTele/reducer/index.ts b/src/pages/SenseiTele/reducer/index.ts index ef70843e..dc7b7fdf 100644 --- a/src/pages/SenseiTele/reducer/index.ts +++ b/src/pages/SenseiTele/reducer/index.ts @@ -17,7 +17,10 @@ const initialState: IAgentData = { lastRefreshedTimeStampInput: '', despositionSummary: [], loadingDespositionSummary: false, - despositionSummaryFilter: [] + despositionSummaryFilter: [], + emiBucketWiseSummary: [], + loadingEmiBucketWiseSummary: false, + emiBucketWiseSummaryFilter: [] }; const TeleSenseiSlice = createSlice({ @@ -58,6 +61,15 @@ const TeleSenseiSlice = createSlice({ setDespositionSummary(state, action) { const { data } = action.payload; state.despositionSummary = data; + }, + setEmiBucketWiseSummary(state, action) { + state.emiBucketWiseSummary = action.payload; + }, + setLoadingEmiBucketWiseSummary(state, action) { + state.loadingEmiBucketWiseSummary = action.payload; + }, + setEmiBucketWiseSummaryFilter(state, action) { + state.emiBucketWiseSummaryFilter = action.payload; } } }); @@ -71,7 +83,10 @@ export const { setAgentPerformanceFiltered, setDespositionSummaryFilter, setLoadingDespositionSummary, - setDespositionSummary + setDespositionSummary, + setEmiBucketWiseSummary, + setEmiBucketWiseSummaryFilter, + setLoadingEmiBucketWiseSummary } = TeleSenseiSlice.actions; export default TeleSenseiSlice.reducer; diff --git a/src/pages/SenseiTele/types/index.ts b/src/pages/SenseiTele/types/index.ts index 15bb1464..31e92dfb 100644 --- a/src/pages/SenseiTele/types/index.ts +++ b/src/pages/SenseiTele/types/index.ts @@ -1,4 +1,5 @@ -import { ViewType } from '../constants'; +import { A } from 'msw/lib/core/RequestHandler-bb5cbb8f'; +import { IEmiBucketWiseDataObject, ViewType } from '../constants'; export type IViewType = keyof typeof ViewType | null; @@ -18,6 +19,10 @@ export interface IAgentPerformanceParams { sortOrderDisposition?: string; pageNoDisposition?: string; pageSizeDisposition?: string; + depositionSummaryCallOverViewFilter?: string; + depositionSummaryPTPOverViewFilter?: string; + unpaidCasesCovered?: number; + unpaidCases?: number; } export interface IFilters { @@ -68,6 +73,9 @@ export interface IAgentData { despositionSummary: IDepositionSummary[]; loadingDespositionSummary: boolean; despositionSummaryFilter: IDepositionSummary[]; + emiBucketWiseSummary: IEMIBucketWiseSummary[]; + loadingEmiBucketWiseSummary: boolean; + emiBucketWiseSummaryFilter: IEMIBucketWiseSummary[]; } export enum FilterType { @@ -115,3 +123,79 @@ export interface IDepositionSummary { ptpTodayCount: number; ptpTodayEmi: number; } + +export interface IEMIBucketWiseSummary { + agentName: string; + agentReferenceId: string; + tlReferenceId: string; + dueCycle: string; + bucketWiseSummary: IBucketWiseSummary[]; +} + +interface IBucketWiseSummary { + bucketGroup: string; + emiAllocated: number; + emiCollectionEfficiency: number; + totalCases: number; + unpaidCases: number; + totalCalls: number; + slashCalls: number; + ameyoCalls: number; + selfCalls: number; + unpaidCasesCoverage: number; + averageCallsPerUnpaidCases: number; + averageUniqueDaysCalledPerUnpaidCases: number; + generatedPtpCount: number; + convertedPtpCount: number; + brokenPtpCount: number; + futurePtpCount: number; + emiCollected: number; +} + +export interface IAllDataBucketWiseSummary { + [key: string]: IBuckerrWiseSummarySum; +} + +export interface IBuckerrWiseSummarySum { + emiAllocated: number; + emiCollectionEfficiency: number; + totalCases: number; + unpaidCases: number; + totalCalls: number; + slashCalls: number; + ameyoCalls: number; + selfCalls: number; + unpaidCasesCoverage: number; + averageCallsPerUnpaidCases: number; + averageUniqueDaysCalledPerUnpaidCases: number; + generatedPtpCount: number; + convertedPtpCount: number; + brokenPtpCount: number; + futurePtpCount: number; + emiCollected: number; + unpaidCasesCovered: number; +} + +export interface ICallsOverView { + data: IEmiBucketWiseDataObject; + params: IAgentPerformanceParams; + updateAndNavigate: (params: IAgentPerformanceParams) => void; +} + +export interface CashEarnedChartHCProps { + dataTObeFed: Array; + casesData: Array; +} + +export type responseDataType = { + label: string; + value: string; + fill: string; + color: string; +}; + +export interface IPTPOverView { + data: IEmiBucketWiseDataObject; + params: IAgentPerformanceParams; + updateAndNavigate: (params: IAgentPerformanceParams) => void; +} diff --git a/src/pages/auth/constants/AuthConstants.ts b/src/pages/auth/constants/AuthConstants.ts index 668693b4..aa61da55 100644 --- a/src/pages/auth/constants/AuthConstants.ts +++ b/src/pages/auth/constants/AuthConstants.ts @@ -71,7 +71,8 @@ export enum Roles { NAVI_INHOUSE_FIELD_ZONAL_MANAGER = 'NAVI_INHOUSE_FIELD_ZONAL_MANAGER', ROLE_NAVI_FIELD_AGENCY_TEAM_LEAD = 'ROLE_NAVI_FIELD_AGENCY_TEAM_LEAD', ROLE_HUMAN_REMINDER_TEAM_LEAD = 'ROLE_HUMAN_REMINDER_TEAM_LEAD', - ROLE_HUMAN_REMINDER_CHAT_AGENT = 'ROLE_HUMAN_REMINDER_CHAT_AGENT' + ROLE_HUMAN_REMINDER_CHAT_AGENT = 'ROLE_HUMAN_REMINDER_CHAT_AGENT', + ROLE_NAVI_TELE_INHOUSE_TEAM_LEAD = 'ROLE_NAVI_TELE_INHOUSE_TEAM_LEAD' } export const permissionScreenConstants = { diff --git a/src/utils/ApiHelper.ts b/src/utils/ApiHelper.ts index d4d558df..2978ae89 100644 --- a/src/utils/ApiHelper.ts +++ b/src/utils/ApiHelper.ts @@ -167,7 +167,8 @@ export enum ApiKeys { GET_AGENCY_NAME_OPTIONS, GET_AGENCY_DETAILS_DATA, GET_AGENT_PERFORMANCE_DATA, - GET_AGENT_PERFORMANCE_TL_DATA + GET_AGENT_PERFORMANCE_TL_DATA, + EMI_BUCKET_WISE_SUMMARY } // TODO: try to get rid of `as` @@ -325,6 +326,8 @@ API_URLS[ApiKeys.GET_AGENT_PERFORMANCE_DATA] = '/longhorn/external-agency-performance-dashboard/field-governance/agent'; API_URLS[ApiKeys.GET_AGENT_PERFORMANCE_TL_DATA] = '/longhorn/external-agency-performance-dashboard/overall-performance/agent-performance'; +API_URLS[ApiKeys.EMI_BUCKET_WISE_SUMMARY] = + '/team-lead/dashboard/reportees-emi-bucket-wise-summary'; // TODO: try to get rid of `as` const MOCK_API_URLS: Record = {} as Record;