From a7b475d1908ebfaedf4c8ac9581e208e70de1db2 Mon Sep 17 00:00:00 2001 From: Aman Singh Date: Wed, 5 Jul 2023 20:46:16 +0530 Subject: [PATCH] TP-31863 |performance level dynamic| Aman Singh (#466) * TP-31863 | initial commit | Aman Singh * TP-0000 | Level icon with level number within it and color as prop | Herik * TP-31863 | second commit | Aman Singh * TP-0000 | Level icon implemented in the list with colors | Herik * TP-31863 | third commit | Aman Singh * TP-31863 | forth commit | Aman Singh * TP-31863 | integration done | Aman Singh * TP-31863 | design review done | Aman Singh * TP-31863 | design review done -1 | Aman Singh * TP-31863 | EM review done| Aman Singh * TP-31863 | EM review done -1| Aman Singh * TP-31863 | EM review done| Aman Singh * TP-0000 | maxLevel after UAT | Herik * TP-31863 |removed tooltip sachin suggestion| Aman Singh Co-authored-by: Herik Modi --- __mocks__/levels/agents/ranking.json | 124 ++++++++++++------ src/assets/icons/LevelIcon.tsx | 43 ++++++ src/assets/icons/PerformanceArrow.tsx | 24 ++++ src/assets/icons/types.ts | 3 + .../AgentProgressMeter.module.scss | 75 +++++++++++ .../AgentprogressMeter/AgentProgressMeter.tsx | 114 ++++++++++++++++ src/components/AgentprogressMeter/constant.ts | 78 +++++++++++ .../leaderboard/CashEarnedChartHC.tsx | 31 +++-- .../leaderboard/CumulativeCashCollected.tsx | 2 +- .../leaderboard/Leaderboard.module.scss | 4 + src/components/leaderboard/Leaderboard.tsx | 29 ++-- .../leaderboard/PerformanceChart.tsx | 23 +++- src/pages/Dashboard/Dashboard.tsx | 21 ++- src/pages/Dashboard/index.module.scss | 15 ++- 14 files changed, 516 insertions(+), 70 deletions(-) create mode 100644 src/assets/icons/LevelIcon.tsx create mode 100644 src/assets/icons/PerformanceArrow.tsx create mode 100644 src/components/AgentprogressMeter/AgentProgressMeter.module.scss create mode 100644 src/components/AgentprogressMeter/AgentProgressMeter.tsx create mode 100644 src/components/AgentprogressMeter/constant.ts diff --git a/__mocks__/levels/agents/ranking.json b/__mocks__/levels/agents/ranking.json index 77182cbb..9a4df1dc 100644 --- a/__mocks__/levels/agents/ranking.json +++ b/__mocks__/levels/agents/ranking.json @@ -1,91 +1,139 @@ { - "agentReferenceId": "4b6cbe75-59f9-4375-89fd-080b26d21b03", - "agentLevelRanking": 5, - "maxLevel": 7, - "cashCollectedInLast30Days": 1117146.44, - "firstAllocationDate": "2022-05-03T00:00:00", - "cashRequiredToReachNextLevel": 70274.98, + "agentReferenceId": "6fb98fe3-db72-41b6-9fe3-58969e19d986", + "agentLevelRanking": 9, + "maxLevel": 9, + "cashCollectedInLast30Days": 4720122.37, + "firstAllocationDate": "2022-07-25T00:00:00", + "cashRequiredToReachNextLevel": 199513.06, "levelConstructList": [ { "level": 1, - "levelLowerLimit": 25676.6, - "levelUpperLimit": 554464.91 + "levelLowerLimit": 10263.0, + "levelUpperLimit": 600844.86 }, { "level": 2, - "levelLowerLimit": 555717.36, - "levelUpperLimit": 876699.78 + "levelLowerLimit": 601023.92, + "levelUpperLimit": 868522.89 }, { "level": 3, - "levelLowerLimit": 882595.22, - "levelUpperLimit": 993750.74 + "levelLowerLimit": 868647.89, + "levelUpperLimit": 975410.37 }, { "level": 4, - "levelLowerLimit": 994443.69, - "levelUpperLimit": 1094499.45 + "levelLowerLimit": 975488.35, + "levelUpperLimit": 1081223.36 }, { "level": 5, - "levelLowerLimit": 1098591.56, - "levelUpperLimit": 1187158.21 + "levelLowerLimit": 1086032.59, + "levelUpperLimit": 1161649.97 }, { "level": 6, - "levelLowerLimit": 1187421.42, - "levelUpperLimit": 1301905.05 + "levelLowerLimit": 1164180.72, + "levelUpperLimit": 1295784.61 }, { "level": 7, - "levelLowerLimit": 1302165.74, - "levelUpperLimit": 1923532.05 + "levelLowerLimit": 1298859.54, + "levelUpperLimit": 1940339.37 + }, + { + "level": 8, + "levelLowerLimit": 1940344.54, + "levelUpperLimit": 2631379.37 + }, + { + "level": 9, + "levelLowerLimit": 2631382.54, + "levelUpperLimit": 4720122.37 } ], "currentMonthCashCollected": [ { "label": "EMIs", - "value": 893868.68, - "valuePercent": 89.95521132199717 + "value": 383003.99, + "valuePercent": 95.3908184628774 }, { "label": "Fees", - "value": 41930.079999999994, - "valuePercent": 4.219668158804094 + "value": 17800.0, + "valuePercent": 4.433260783103638 }, { "label": "Foreclosures", - "value": 30392.04, - "valuePercent": 3.0585279939628163 + "value": 0.0, + "valuePercent": 0.0 }, { "label": "Others", - "value": 27491.129999999997, - "valuePercent": 2.7665925252359167 + "value": 706.87, + "valuePercent": 0.17605275560407127 } ], "prevMonthCashCollected": [ { "label": "EMIs", - "value": 810255.89, - "valuePercent": 72.28522338317956 + "value": 0.0, + "valuePercent": "NaN" }, { "label": "Fees", - "value": 56414.66, - "valuePercent": 5.032911640032785 + "value": 0.0, + "valuePercent": "NaN" }, { "label": "Foreclosures", - "value": 184438.37, - "valuePercent": 16.454269497355362 + "value": 0.0, + "valuePercent": "NaN" }, { "label": "Others", - "value": 69806.05, - "valuePercent": 6.227595479432307 + "value": 0.0, + "valuePercent": "NaN" } ], - "totalCurrentMonthCashCollected": 993681.9300000002, - "totalPrevMonthCashCollected": 1120914.97 + "totalCurrentMonthCashCollected": 401510.33, + "totalPrevMonthCashCollected": 0.0, + "todaysCashCollected": 24344.0, + "noOfDaysCashCollected": 30, + "dateWhenRankingVisible": "2022-08-23", + "monthlyCashCollectedBreakupDropdownOptions": [ + { + "value": "JULY", + "label": "July" + }, + { + "value": "JUNE", + "label": "June" + } + ], + "monthlyCashCollected": { + "monthlyCashCollectedBreakup": [ + { + "label": "EMIs", + "value": 383003.99, + "valuePercent": 95.3908184628774 + }, + { + "label": "Fees", + "value": 17800.0, + "valuePercent": 4.433260783103638 + }, + { + "label": "Foreclosures", + "value": 0.0, + "valuePercent": 0.0 + }, + { + "label": "Others", + "value": 706.87, + "valuePercent": 0.17605275560407127 + } + ], + "totalMonthlyCashCollected": 401510.33 + } } \ No newline at end of file diff --git a/src/assets/icons/LevelIcon.tsx b/src/assets/icons/LevelIcon.tsx new file mode 100644 index 00000000..0cb5b6c5 --- /dev/null +++ b/src/assets/icons/LevelIcon.tsx @@ -0,0 +1,43 @@ +interface LevelIconProps { + level: number; + color?: string; + fontColor?: string; + fontClassName?: string; +} + +export const LevelIcon = ({ level = 1, color = '#F3D260', fontColor = '#000', fontClassName }: LevelIconProps) => { + return ( +
+ + {level} + + + + +
+ ); +}; diff --git a/src/assets/icons/PerformanceArrow.tsx b/src/assets/icons/PerformanceArrow.tsx new file mode 100644 index 00000000..98dbf56a --- /dev/null +++ b/src/assets/icons/PerformanceArrow.tsx @@ -0,0 +1,24 @@ +import React from 'react'; + +import { IconProps } from './types'; + +const PerformanceArrow: React.FC = props => { + const { className, style, title } = props; + return ( + // TODO: Use tooltip component instead of title. + + + + + ); +}; + +export default PerformanceArrow; diff --git a/src/assets/icons/types.ts b/src/assets/icons/types.ts index 2a74f7fc..cf66a311 100644 --- a/src/assets/icons/types.ts +++ b/src/assets/icons/types.ts @@ -5,4 +5,7 @@ export interface IconProps { onClick?: () => void; size?: number; opacity?: string; + className?: string; + style?: React.CSSProperties; + title?: string; } diff --git a/src/components/AgentprogressMeter/AgentProgressMeter.module.scss b/src/components/AgentprogressMeter/AgentProgressMeter.module.scss new file mode 100644 index 00000000..59078cbc --- /dev/null +++ b/src/components/AgentprogressMeter/AgentProgressMeter.module.scss @@ -0,0 +1,75 @@ +.parent { + width: 5px; + flex-shrink: 0; + border-radius: 1px 1px 0px 0px; + background: linear-gradient( + 180deg, + #65e64c 0%, + #8ef682 12.5%, + #1ddae4 27.08%, + #d2e555 38.77%, + #f2f57b 46.35%, + #fff04f 59.9%, + #fec786 69.27%, + #f8ada9 84.38%, + #f96c6c 100% + ); + display: flex; + flex-direction: column-reverse; + position: relative; + + > div:last-child { + .levelLine { + display: none; + } + + .maxLimitText { + display: none; + } + } + + .level { + width: 5px; + position: relative; + + .levelIcon { + position: absolute; + left: -40px; + top: 50%; + transform: translateY(-50%); + } + + .maxLimitText { + position: absolute; + top: -9px; + right: -73px; + font-size: 12px; + color: #97a1ac; + width: 60px; + } + } + + .performanceArrow { + position: absolute; + left: -11px; + transform: translateY(50%); + } + + .levelLine { + position: absolute; + background: #97a1ac; + width: 7px; + height: 1px; + border-radius: 2px; + left: -1px; + top: -1px; + } + + .active { + opacity: 1; + } + + .inActive { + opacity: 0.5; + } +} diff --git a/src/components/AgentprogressMeter/AgentProgressMeter.tsx b/src/components/AgentprogressMeter/AgentProgressMeter.tsx new file mode 100644 index 00000000..d036dfc2 --- /dev/null +++ b/src/components/AgentprogressMeter/AgentProgressMeter.tsx @@ -0,0 +1,114 @@ +import { Typography } from '@navi/web-ui/lib/primitives'; +import cx from 'classnames'; +import { LevelIcon } from 'src/assets/icons/LevelIcon'; +import PerformanceArrow from 'src/assets/icons/PerformanceArrow'; +import { formatAmount, shortNumberNotation } from 'src/utils/commonUtils'; +import styles from './AgentProgressMeter.module.scss'; +import { LEVEL_HEIGHT, MAX_LEVEL_GUARD_PERCENTAGE, MIN_LEVEL_GUARD_PERCENTAGE, PARENT_HEIGHT, levelColorsList, levelConstructList, levelConstructListBEType, levelConstructListType } from './constant'; + + +// const normaliseValues = (levelConstructList: Array, currentLevel: number) => { +// if (!currentLevel) return 1; +// if (currentLevel > MAX_NUMBER_OF_LEVELS) return MAX_NUMBER_OF_LEVELS; +// if (currentLevel < 1) return 1; +// return false; +// }; + +const getPercentageValue = ( + levelConstruct: levelConstructListType, + currentCashCollected: number, + maxLevel: number +) => { + if (!levelConstruct || !currentCashCollected) return 0; + const percentage = Math.round( + (Math.abs(currentCashCollected - levelConstruct.levelLowerLimit) / + (levelConstruct.levelUpperLimit - levelConstruct.levelLowerLimit)) * + 100 + ) + if (maxLevel === levelConstruct.level && percentage > MAX_LEVEL_GUARD_PERCENTAGE) return MAX_LEVEL_GUARD_PERCENTAGE; + if (1 === levelConstruct.level && percentage < MIN_LEVEL_GUARD_PERCENTAGE) return MIN_LEVEL_GUARD_PERCENTAGE; + + if (percentage > 100) return 100; + if (percentage < 0) return 0; + if (isNaN(percentage)) return 0; + + return percentage; +}; + +const generateDivForLevels = ( + levelConstructList: Array, + currentLevel: number, + cashCollected: number, + maxLevel: number, + fontStyle?: string, + iconStyle?: string, + parentStyle?: string, +) => { + // if (hasNullIssues(levelConstructList, currentLevel)) return null; + const div = []; + for (let i = 0; i < maxLevel; i++) { + div.push( +
+
+ +
+
+ + + {`₹${shortNumberNotation(levelConstructList[i].levelUpperLimit)}`} + + + {i === currentLevel - 1 ? ( + + ) : null} +
+ ); + } + return div; +}; + +interface AgentProgressMeterProps { + currentLevel: number; + cashCollected: number; + levelConstructList: Array; + fontStyle?: string; + iconStyle?: string; + parentStyle?: string; + maxLevel: number; +} + +const AgentProgressMeter: React.FC = (props) => { + const { currentLevel, levelConstructList, cashCollected, fontStyle, iconStyle, parentStyle, maxLevel } = props; + const PARENT_HEIGHT = `${maxLevel * parseInt(LEVEL_HEIGHT)}px`; + + const levelInfusedWithColors = levelConstructList?.map((levelConstruct, index) => { + const level = levelConstruct.level; + const levelLowerLimit = levelConstruct.levelLowerLimit; + const levelUpperLimit = levelConstruct.levelUpperLimit; + const color = levelColorsList[index]; + return { + level, + levelLowerLimit, + levelUpperLimit, + color + }; + } + ); + const renderDiv = generateDivForLevels(levelInfusedWithColors, currentLevel, cashCollected, maxLevel, fontStyle, iconStyle, parentStyle); + return ( +
+ {renderDiv} +
+ ); +}; + +export default AgentProgressMeter; diff --git a/src/components/AgentprogressMeter/constant.ts b/src/components/AgentprogressMeter/constant.ts new file mode 100644 index 00000000..e6353eef --- /dev/null +++ b/src/components/AgentprogressMeter/constant.ts @@ -0,0 +1,78 @@ +export const levelColorsList = [ + '#F97474', + '#FBB9A6', + '#FEBA65', + '#F3D260', + '#FFEA06', + '#E6EB00', + '#47E1DC', + '#5AE9B1', + '#70EB5A' +]; + +export const LEVEL_HEIGHT = '40px'; +export const MAX_LEVEL_GUARD_PERCENTAGE = 75; +export const MIN_LEVEL_GUARD_PERCENTAGE = 25; +export const MIN_LEVEL = 1; + +export const levelConstructList = [ + { + level: 1, + levelLowerLimit: 25676.6, + levelUpperLimit: 554464.91, + }, + { + level: 2, + levelLowerLimit: 555717.36, + levelUpperLimit: 876699.78, + }, + { + level: 3, + levelLowerLimit: 882595.22, + levelUpperLimit: 993750.74, + }, + { + level: 4, + levelLowerLimit: 994443.69, + levelUpperLimit: 1094499.45, + }, + { + level: 5, + levelLowerLimit: 1098591.56, + levelUpperLimit: 1187158.21, + }, + { + level: 6, + levelLowerLimit: 1187421.42, + levelUpperLimit: 1301905.05, + }, + { + level: 7, + levelLowerLimit: 1302165.74, + levelUpperLimit: 1923532.05, + }, + { + level: 8, + levelLowerLimit: 1923532.74, + levelUpperLimit: 3223532.05, + }, + { + level: 9, + levelLowerLimit: 3223532.74, + levelUpperLimit: 5223532.05, + } +]; + +export interface levelConstructListType { + level: number; + levelLowerLimit: number; + levelUpperLimit: number; + color: string; +} + + +export interface levelConstructListBEType { + level: number; + levelLowerLimit: number; + levelUpperLimit: number; +} diff --git a/src/components/leaderboard/CashEarnedChartHC.tsx b/src/components/leaderboard/CashEarnedChartHC.tsx index 1f62a74c..47f3d8c2 100644 --- a/src/components/leaderboard/CashEarnedChartHC.tsx +++ b/src/components/leaderboard/CashEarnedChartHC.tsx @@ -239,25 +239,30 @@ const CashEarnedChartHC: React.FC = props => { size="h6" /> )} +
+ {!showDropdown ? ( + + {view === 'curr' ? ( + + Last {getDayofMonth()} day(s) cash collected + + ) : ( + Cash collected last month + )} + + {' '} + {getFirstDate()} - {getLastDate(view)} + + + ) : null} +
{showDropdown ? ( <> Cash Collection Breakup - ) : ( - - {view === 'curr' ? ( - Last {getDayofMonth()} days cash collected - ) : ( - Cash collected last month - )} - - {' '} - {getFirstDate()} - {getLastDate(view)} - - - )} + ) : null}
diff --git a/src/components/leaderboard/CumulativeCashCollected.tsx b/src/components/leaderboard/CumulativeCashCollected.tsx index 797f0e96..c4a5aa9e 100644 --- a/src/components/leaderboard/CumulativeCashCollected.tsx +++ b/src/components/leaderboard/CumulativeCashCollected.tsx @@ -90,7 +90,7 @@ const CumulativeCashCollected: React.FC = props => { const { data, width = 350, - height = 133, + height = 150, legendWrapperStyle, graphWrapperContainerClass = '', isWeekData = false diff --git a/src/components/leaderboard/Leaderboard.module.scss b/src/components/leaderboard/Leaderboard.module.scss index 37bb1bb5..607145fc 100644 --- a/src/components/leaderboard/Leaderboard.module.scss +++ b/src/components/leaderboard/Leaderboard.module.scss @@ -558,7 +558,11 @@ display: flex; flex-direction: row-reverse; padding-right: 5px; + justify-content: space-between; + align-items: center; + padding-left: 24px; } + .dropdown { width: 130px; } diff --git a/src/components/leaderboard/Leaderboard.tsx b/src/components/leaderboard/Leaderboard.tsx index 07cc5d37..dca3ede1 100644 --- a/src/components/leaderboard/Leaderboard.tsx +++ b/src/components/leaderboard/Leaderboard.tsx @@ -25,6 +25,9 @@ import { Pie, PieChart, ResponsiveContainer, Sector, Tooltip } from 'recharts'; import { PERFORMANCE_CHART_TYPE } from './leaderboardConstant'; import { addClickstreamEvent } from '../../service/clickStreamEventService'; import { CLICKSTREAM_EVENT_NAMES } from '../../service/clickStream.constant'; +import AgentProgressMeter from '../AgentprogressMeter/AgentProgressMeter'; +import { LevelIcon } from 'src/assets/icons/LevelIcon'; +import { levelColorsList } from '../AgentprogressMeter/constant'; export const LEVEL_ICONS = [ , @@ -121,7 +124,11 @@ const Leaderboard = () => { {leaderboard?.agentLevelRanking ? ( - {LEVEL_ICONS[leaderboard?.agentLevelRanking - 1]} + + {/* {LEVEL_ICONS[leaderboard?.agentLevelRanking - 1]} */} ) : ( - @@ -172,14 +179,18 @@ const Leaderboard = () => { - + + {/* {LEVEL_ICONS[6]} @@ -201,15 +212,15 @@ const Leaderboard = () => { {LEVEL_ICONS[0]} - - + */} + {/* - + */} diff --git a/src/components/leaderboard/PerformanceChart.tsx b/src/components/leaderboard/PerformanceChart.tsx index 9873a4c5..1d6d25b1 100644 --- a/src/components/leaderboard/PerformanceChart.tsx +++ b/src/components/leaderboard/PerformanceChart.tsx @@ -16,6 +16,10 @@ import { LEVEL_ICONS } from './Leaderboard'; import styles from './Leaderboard.module.scss'; import cx from 'classnames'; import { tickFormatterHandler } from 'src/utils/Chart.utils'; +import { LevelIcon } from 'src/assets/icons/LevelIcon'; +import { levelColorsList } from '../AgentprogressMeter/constant'; +import { useSelector } from 'react-redux'; +import { RootState } from 'src/store'; export enum formatYAxisTypes { COMPACT_FORMATTED_AMOUNT @@ -38,17 +42,25 @@ const PerformanceChart: React.FC = props => { const { data, width = 350, - height = 133, + height = 150, legendWrapperStyle, graphWrapperContainerClass = '', isWeekData = false } = props; + const maxPerformance = useSelector((state: RootState) => state.leaderboard.maxLevel); + const newData = data?.data?.map(item => ({ ...item, level: Number(item?.level?.replace('L', '')) })); + const yAxisLevels = []; + + for (let i = 1; i <= maxPerformance; i++) { + yAxisLevels.push(i); + } + if (!newData) { return
Data Not Available
; } @@ -87,7 +99,7 @@ const PerformanceChart: React.FC = props => { /> } /> > = ({ active, pa }} >

- Perf Level {LEVEL_ICONS[(payload[0].value as number) - 1]} + Perf Level{' '} + + {/* {LEVEL_ICONS[(payload[0].value as number) - 1]} */}

{`${dateFormat(new Date(label), 'DD MMM')}`}

diff --git a/src/pages/Dashboard/Dashboard.tsx b/src/pages/Dashboard/Dashboard.tsx index 72b804cc..4f81f837 100644 --- a/src/pages/Dashboard/Dashboard.tsx +++ b/src/pages/Dashboard/Dashboard.tsx @@ -32,6 +32,9 @@ import { PERFORMANCE_CHART_TYPE } from 'src/components/leaderboard/leaderboardCo import { FeedbackTypesCodeMap } from '../Cases/constants/CasesConstants'; import { addClickstreamEvent } from '../../service/clickStreamEventService'; import { CLICKSTREAM_EVENT_NAMES } from '../../service/clickStream.constant'; +import AgentProgressMeter from 'src/components/AgentprogressMeter/AgentProgressMeter'; +import { LevelIcon } from 'src/assets/icons/LevelIcon'; +import { levelColorsList } from 'src/components/AgentprogressMeter/constant'; const LEVEL_ICONS = [ , @@ -417,7 +420,11 @@ const DashBoard = () => { {leaderboard?.agentLevelRanking ? ( - {LEVEL_ICONS[leaderboard?.agentLevelRanking - 1]} + + {/* {LEVEL_ICONS[leaderboard?.agentLevelRanking - 1]} */} ) : ( -- @@ -428,7 +435,15 @@ const DashBoard = () => { {isAgentRangeMeterPresent ? ( - + + {/* { leaderboardAmountTextClass={styles.leaderboardAmountTextClass} leaderboardPointerStyle={leaderboardPointerStyle} /> - + */} ) : null} diff --git a/src/pages/Dashboard/index.module.scss b/src/pages/Dashboard/index.module.scss index e9156da7..c377484c 100644 --- a/src/pages/Dashboard/index.module.scss +++ b/src/pages/Dashboard/index.module.scss @@ -180,14 +180,23 @@ .leaderboardContainer { position: absolute; - top: 25px; + top: 50px; display: flex; height: 100%; width: fit-content; - transform: scale(1.8) rotate(90deg); + transform: scale(1.6) rotate(90deg); align-items: center; padding: 0px; - + .agentLevelIcon{ + transform: rotate(-90deg); + scale: 0.8; + } + .agentLevelText{ + transform: rotate(-90deg) translate(4px, 0px); + scale: 0.6; + position: absolute; + left: -10px; + } .leaderboardIconContainer { padding: 0px; }