diff --git a/index.html b/index.html index 14fa5017..dd8569fd 100644 --- a/index.html +++ b/index.html @@ -52,9 +52,9 @@ } - + - + diff --git a/src/assets/styles/genericStyles.scss b/src/assets/styles/genericStyles.scss index 3cc298d4..02a2267f 100644 --- a/src/assets/styles/genericStyles.scss +++ b/src/assets/styles/genericStyles.scss @@ -122,3 +122,10 @@ font-style: normal; letter-spacing: -0.0125em; } + +.teamLeadContainer { + .ag-header-cell, + .ag-header-group-cell { + padding-right: 0px !important; + } +} diff --git a/src/components/TopNavBar/TopNavBar.tsx b/src/components/TopNavBar/TopNavBar.tsx index a0187acf..37993616 100644 --- a/src/components/TopNavBar/TopNavBar.tsx +++ b/src/components/TopNavBar/TopNavBar.tsx @@ -26,18 +26,30 @@ const TopNavBar = ({ isDc97User, isAgentDashboard }: ITopNavbarProps) => { const navigate = useNavigate(); const currentPath = useLocation().pathname; const isCasesListingPage = useLocation().pathname === APP_ROUTES.CASES.path; - const { isPlayerVisible, isPerformanceDashboardVisible } = useSelector((state: RootState) => ({ - isPlayerVisible: state.common.globalPlayer?.visible, - isPerformanceDashboardVisible: state.common.isPerformanceDashboardVisible - })); + const hideForTLCase = useLocation().pathname === APP_ROUTES.TEAM_LEAD_DASHBOARD.path; + const { isPlayerVisible, isPerformanceDashboardVisible, isTeamLead } = useSelector( + (state: RootState) => ({ + isPlayerVisible: state.common.globalPlayer?.visible, + isPerformanceDashboardVisible: state.common.isPerformanceDashboardVisible, + isTeamLead: state.common.isTeamLead + }) + ); const navigateToCases = useCallback(() => { + let url: string; addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.LH_CaseDetails_BackButtonClick); - const url = (document.getElementById(APP_ROUTES.CASES.path) as HTMLAnchorElement).href.split( + if (isTeamLead) { + url = ( + document.getElementById(APP_ROUTES.TEAM_LEAD_DASHBOARD.path) as HTMLAnchorElement + ).href.split(APP_ROUTES.TEAM_LEAD_DASHBOARD.path)[1]; + return navigate(APP_ROUTES.TEAM_LEAD_DASHBOARD.path + `${url}`); + } + + url = (document.getElementById(APP_ROUTES.CASES.path) as HTMLAnchorElement).href.split( APP_ROUTES.CASES.path )[1]; navigate(APP_ROUTES.CASES.path + `?${url}`); - }, []); + }, [isTeamLead]); const toggleNotifications = (show: boolean) => { setShowNotifications(show); @@ -50,8 +62,8 @@ const TopNavBar = ({ isDc97User, isAgentDashboard }: ITopNavbarProps) => { setShowCaseHistory(show); }; - const hideBackButton = isCasesListingPage || isDc97User || isAgentDashboard; - const showTopNavItems = !isDc97User && !isPerformanceDashboardVisible; + const hideBackButton = isCasesListingPage || isDc97User || isAgentDashboard || hideForTLCase; + const showTopNavItems = !isDc97User && !isPerformanceDashboardVisible && !isTeamLead; return (
diff --git a/src/components/sidebar/SideBarItems.tsx b/src/components/sidebar/SideBarItems.tsx index 273abff7..1cf692d3 100644 --- a/src/components/sidebar/SideBarItems.tsx +++ b/src/components/sidebar/SideBarItems.tsx @@ -20,5 +20,6 @@ const SideBarItems = [ export const HideSideBar = []; export const DASHBOARD_URL = location.origin + '/calling-agent/dashboard'; +export const ADMIN_CASES_URL = location.origin + '/admin'; export default SideBarItems; diff --git a/src/components/sidebar/SideNavBar.tsx b/src/components/sidebar/SideNavBar.tsx index 2bf8de6a..c81392f9 100644 --- a/src/components/sidebar/SideNavBar.tsx +++ b/src/components/sidebar/SideNavBar.tsx @@ -8,7 +8,7 @@ import styles from './SideNavBar.module.scss'; import NaviNewLogoIcon from '@navi/web-ui/lib/icons/NaviLogoIcon/NaviNewLogoIcon'; // import CircularProgress from '../ProgressBars/circularProgress/CircularProgress'; // import HorizontalProgress from '../ProgressBars/horizontalProgress/HorizontalProgress'; -import SideBarItems, { DASHBOARD_URL, HideSideBar } from './SideBarItems'; +import SideBarItems, { ADMIN_CASES_URL, DASHBOARD_URL, HideSideBar } from './SideBarItems'; import SidebarLinks, { clearParamsMap } from './SidebarLinks'; import AgentIcon from '../../assets/images/icons/AgentIcon'; import { useDispatch, useSelector } from 'react-redux'; @@ -31,6 +31,7 @@ import { toast } from '@navi/web-ui/lib/primitives/Toast/core/toast'; import { CLICKSTREAM_EVENT_NAMES } from '../../service/clickStream.constant'; import { addClickstreamEvent } from '../../service/clickStreamEventService'; import PDInactiveIcon from 'src/assets/icons/PDInactiveIcon'; +import { AllCasesActiveIcon, AllCasesInactiveIcon } from 'src/assets/images/icons/AllCasesIcon'; import IdCard from 'src/assets/images/icons/IdCard'; import { LOCAL_STORAGE_KEYS } from '../../constants/StorageKeys'; import useLocalStorageObserver from '../../hooks/useLocalStorageObserver'; @@ -40,9 +41,10 @@ interface ISideNavbarProps { } function SideNavBar({ isDc97User }: ISideNavbarProps) { const { pathname, search } = useLocation(); - const { user, isPerformanceDashboardVisible } = useSelector((state: RootState) => ({ + const { user, isPerformanceDashboardVisible, isTeamLead } = useSelector((state: RootState) => ({ user: state.common.userData, - isPerformanceDashboardVisible: state?.common?.isPerformanceDashboardVisible + isPerformanceDashboardVisible: state?.common?.isPerformanceDashboardVisible, + isTeamLead: state?.common?.isTeamLead })); const newDashboard = user?.revampedDashboardViewAllowed; @@ -136,12 +138,12 @@ function SideNavBar({ isDc97User }: ISideNavbarProps) { ); const showTooltipCircularProgress = - completedCasesPercent && !isDc97User && !isPerformanceDashboardVisible; + completedCasesPercent && !isDc97User && !isPerformanceDashboardVisible && !isTeamLead; - const showSideBarItems = !isDc97User && !isPerformanceDashboardVisible; + const showSideBarItems = !isDc97User && !isPerformanceDashboardVisible && !isTeamLead; const showAmeyoCollapsibleToolbar = - !disableAmeyoToolbarFlag && !isPerformanceDashboardVisible && !isDc97User; + !disableAmeyoToolbarFlag && !isPerformanceDashboardVisible && !isDc97User && !isTeamLead; return ( <> @@ -152,7 +154,9 @@ function SideNavBar({ isDc97User }: ISideNavbarProps) { onMouseLeave={() => setShowLogout(false)} >
- + + + {/*
@@ -242,6 +246,19 @@ function SideNavBar({ isDc97User }: ISideNavbarProps) { ) : ( <> )} + {isTeamLead ? ( + } + inActiveIcon={} + name={'Cases'} + route={APP_ROUTES.TEAM_LEAD_DASHBOARD.path} + linkClickHandler={linkClickHandler} + currentPathname={pathname} + currentSearch={search} + clickStreamEvent={CLICKSTREAM_EVENT_NAMES.LH_TEAM_LEAD_Dashboard_SidePanelIconClick} + /> + ) : null} {isPerformanceDashboardVisible ? ( <> store?.common?.isPerformanceDashboardVisible ); const isDc97User = roles?.includes(Roles.ROLE_HUMAN_REMINDER_AGENT); + const isTeamLead = useSelector((store: RootState) => store?.common?.isTeamLead); const todaysDate = new Date(getServerTime()); const currMonth = fullMonthNames[todaysDate?.getMonth() || 0]; useEffect(() => { @@ -80,9 +81,11 @@ function DefaultLayout() { if (isPerformanceDashboardVisible) return; if (referenceId) { dispatch(getLeaderboardDetails(referenceId, currMonth)); - dispatch(getPercentCompleted()); + if (!isTeamLead) { + dispatch(getPercentCompleted()); + } } - }, [referenceId, isPerformanceDashboardVisible]); + }, [referenceId, isPerformanceDashboardVisible, isTeamLead]); useEffect(() => { if (roles?.length && roles?.includes(Roles.ROLE_HUMAN_REMINDER_AGENT)) { @@ -130,7 +133,7 @@ function DefaultLayout() { ) : null} }> - {!isDc97Page && !isDashBoard ? : null} + {!isDc97Page && !isDashBoard && !isTeamLead ? : null}
{agencyCode && {routes}}
diff --git a/src/layout/Routes.tsx b/src/layout/Routes.tsx index b4102865..e29631ad 100644 --- a/src/layout/Routes.tsx +++ b/src/layout/Routes.tsx @@ -3,6 +3,7 @@ import HrDashBoard from 'src/pages/Dashboard/HrDashBoard'; import DashBoard from 'src/pages/Dashboard/Dashboard'; import CaseDetail from '../pages/CaseDetails/components/CaseDetail'; import PerformanceDashboard from 'src/pages/PerformanceDashboard/PerformanceDashboard'; +import { TeamLeadDashboard } from 'src/pages/TeamLeadDashboard'; import IDCardApprovals from 'src/pages/IDCardApprovals/components/IDCardApprovals'; const Cases = React.lazy(() => import('../pages/Cases/components/Cases')); @@ -35,6 +36,10 @@ const APP_ROUTES = { element: , exact: true }, + TEAM_LEAD_DASHBOARD: { + path: '/team-lead-dashboard', + element: , + }, ID_CARD_APPROVALS: { path: '/id-card-approvals', element: , diff --git a/src/pages/CaseDetails/feedbackForm/index.tsx b/src/pages/CaseDetails/feedbackForm/index.tsx index f2ef6c0a..4f462563 100644 --- a/src/pages/CaseDetails/feedbackForm/index.tsx +++ b/src/pages/CaseDetails/feedbackForm/index.tsx @@ -64,16 +64,16 @@ const FeedbackFrom = (props: FeedbackFromProps) => { const { register, handleSubmit, reset, setValue } = useForm(); const [activeTab, setActiveTab] = React.useState(FeedbackTabsEnum.DEFAULT); - const { questions, telephones, user, skipTracingData, spadeData, ameyoCallDetails } = useSelector( - (state: RootState) => ({ + const { questions, telephones, user, skipTracingData, spadeData, ameyoCallDetails, isTeamLead } = + useSelector((state: RootState) => ({ questions: state.feedBack.questionTypes, telephones: state.caseDetail.pageData?.[createKey(loanId, customerId)]?.telephones, user: state.common.userData, skipTracingData: state.caseDetail.pageData?.[createKey(loanId, customerId)]?.skipTracingData, spadeData: state.caseDetail.pageData?.[createKey(loanId, customerId)]?.spadeData, - ameyoCallDetails: state.common.ameyoCallDetails - }) - ); + ameyoCallDetails: state.common.ameyoCallDetails, + isTeamLead: state.common?.isTeamLead + })); const navigate = useNavigate(); // @TODO : move to useReducer const [feedback, dispatchFeedback] = useReducer(feedbackFromReducer, { @@ -537,7 +537,7 @@ const FeedbackFrom = (props: FeedbackFromProps) => {
- {!isDisableNextPreviousCaseAction ? : null} + {!isDisableNextPreviousCaseAction && !isTeamLead ? : null} {!disableSubmitButton ? ( +
+ } + placeholder="Search by lan, press enter to search" + /> + +
+ setShowFilterDrawer(false)} + headerText="FILTER BY" + showHeaderDivider={true} + usePadding={false} + style={{ width: 'auto', overflow: 'hidden' }} + > +
+
+
+ +
+
+
+ } + containerClassName={styles.inputContainer} + style={{ width: '80%' }} + /> +
+
{renderOptions(activeFilters)}
+
+
+ +
+ + +
+
+
+ + ); +}; + +export default TeamLeadFilters; diff --git a/src/pages/TeamLeadDashboard/TeamLeadRenderFilters.tsx b/src/pages/TeamLeadDashboard/TeamLeadRenderFilters.tsx new file mode 100644 index 00000000..e62ead15 --- /dev/null +++ b/src/pages/TeamLeadDashboard/TeamLeadRenderFilters.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import styles from './TeamLead.module.scss'; +import { FiltersKeys, ISelectedFilters } from './interface'; +import cx from 'classnames'; + +interface ITeamLeadRenderFiltersProps { + handleFilterSelection: (e: React.MouseEvent) => void; + selectedFilters: ISelectedFilters; + activeFilters: string; +} + +export const TeamLeadRenderFilters: React.FC = props => { + const { handleFilterSelection, selectedFilters, activeFilters } = props; + return ( + <> + {FiltersKeys.map(filter => { + const { key, label } = filter; + const selectionCount = Object.keys( + selectedFilters?.[key as keyof typeof selectedFilters] ?? {} + ).length; + return ( +
+
+ {label + ' '} +
+ {selectionCount > 0 && {selectionCount}} +
+ ); + })} + + ); +}; diff --git a/src/pages/TeamLeadDashboard/index.tsx b/src/pages/TeamLeadDashboard/index.tsx new file mode 100644 index 00000000..65f96031 --- /dev/null +++ b/src/pages/TeamLeadDashboard/index.tsx @@ -0,0 +1,185 @@ +import { ColDefsType } from '@navi/web-ui/lib/components/AgTable/types'; +import Pagination from '@navi/web-ui/lib/components/Pagination/Pagination'; +import { DropDownPosition } from '@navi/web-ui/lib/components/Pagination/constant'; +import React, { useEffect, useRef } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useLocation, useNavigate } from 'react-router-dom'; +import Loader from 'src/components/Loader/Loader'; +import { GridEvent, RowClickEvent } from 'src/components/interfaces'; +import { RootState } from 'src/store'; +import { createQueryParams, readQueryParams } from 'src/utils/QueryParamsHelper'; +import { TEAM_LEAD_COLUMN_DEFS } from './TableContent'; +import styles from './TeamLead.module.scss'; +import TeamLeadFilters from './TeamLeadFilters'; +import { TABLE_NAME, defaultQueryParam, filtersQueryParams, queryParam } from './interface'; +import { getTeamLeadDashboard, getTeamLeadDashboardFilters } from './teamLeadActions'; +import { formatNumber, navigateToCaseDetails } from 'src/utils/commonUtils'; +import APP_ROUTES from 'src/layout/Routes'; +const AgTable = React.lazy( + () => import(/* webpackChunkName: ['table'] */ '@navi/web-ui/lib/components/AgTable/AgTable') +); +import cx from 'classnames'; + +export const getQueryString = () => { + const queryParams = readQueryParams(); + return queryParams[TABLE_NAME] as queryParam; +}; + +export const TeamLeadDashboard = () => { + const dispatch = useDispatch(); + const navigate = useNavigate(); + const location = useLocation(); + const tableRef = useRef(null); + const { currentPageData, page, loading } = useSelector((state: RootState) => ({ + user: state.common.userData, + currentPageData: state.teamLeadDashboard.teamLeadData, + page: state.teamLeadDashboard.page, + loading: state.teamLeadDashboard.loading + })); + const user = useSelector((state: RootState) => state.common.userData); + + const handleFirstApiCall = () => { + const queryString = getQueryString(); + if (!user) return; + let initialPayload: queryParam = { + ...defaultQueryParam, + agencyCode: user?.agencyCode + }; + if (!queryString) { + const queryParams = createQueryParams({ + [TABLE_NAME]: initialPayload + }); + navigate(queryParams); + } else { + initialPayload = { + ...initialPayload, + ...queryString + }; + } + const filtersPayload: filtersQueryParams = { + agencyCode: user?.agencyCode + }; + dispatch(getTeamLeadDashboard(initialPayload)); + dispatch(getTeamLeadDashboardFilters(filtersPayload)); + }; + + useEffect(() => { + const queryString = getQueryString(); + if (!queryString) return; + dispatch(getTeamLeadDashboard(queryString)); + }, [location]); + + const getCurrentPageNumber = (): number => { + const queryString = getQueryString(); + return Number(queryString?.pageNo) + 1 || 1; + }; + const getPageSize = (): number => { + const queryString = getQueryString(); + return Number(queryString?.pageSize) || 50; + }; + const handlePageChange = (pageNumber: number) => { + const queryString = getQueryString(); + const payload = { + ...queryString, + pageNo: (pageNumber - 1).toString() + }; + const queryParams = createQueryParams({ + [TABLE_NAME]: payload + }); + navigate(queryParams); + }; + + const handlePageSizeChange = (pageSize: number) => { + const queryString = getQueryString(); + const payload: queryParam = { + ...queryString, + pageSize: pageSize.toString(), + pageNo: '0' + }; + const queryParams = createQueryParams({ + [TABLE_NAME]: payload + }); + navigate(queryParams); + }; + + const handleServerSorting = (params: ColDefsType) => { + const queryString = getQueryString(); + const { serverSort, field } = params; + const defaultSortColumnDirectionHandler = serverSort ? serverSort : 'asc'; + const defaultSortColumnNameHandler = serverSort ? field : 'name'; + tableRef.current.api.setColumnDefs(TEAM_LEAD_COLUMN_DEFS); + // TEAM_LEAD_COLUMN_DEFS.forEach((colDef: ColDefsType) => { + // if (colDef.field === field) { + // colDef.serverSort = defaultSortColumnDirectionHandler; + // } else { + // colDef.serverSort = ''; + // } + // }); + const payload: queryParam = { + ...queryString, + sortBy: defaultSortColumnNameHandler, + sortDirection: defaultSortColumnDirectionHandler, + pageNo: '0' + }; + const queryParams = createQueryParams({ + [TABLE_NAME]: payload + }); + + navigate(queryParams); + }; + + const onCasesGridReady = (event: GridEvent) => { + handleFirstApiCall(); + const { api: gridApi } = event; + gridApi.sizeColumnsToFit(); + gridApi.getColumnDefs(); + }; + + const columnDefs = TEAM_LEAD_COLUMN_DEFS; + + const onCasesRowClicked = (event: RowClickEvent) => { + const { data } = event; + navigateToCaseDetails( + data?.customerId, + data?.accountNumber, + navigate, + APP_ROUTES.CASE_DETAIL.path + ); + }; + return ( +
+
+
+ {formatNumber(page?.totalElements ?? 0)} Allocations +
+ +
+ + } + onGridReady={onCasesGridReady} + onRowClicked={onCasesRowClicked} + /> + +
+ ); +}; diff --git a/src/pages/TeamLeadDashboard/interface.ts b/src/pages/TeamLeadDashboard/interface.ts new file mode 100644 index 00000000..5f0bccba --- /dev/null +++ b/src/pages/TeamLeadDashboard/interface.ts @@ -0,0 +1,170 @@ +export interface ITeamLeadAPIResponse { + collectionCaseId: number; + customerId: string; + customerName: string; + phoneNumber: string; + accountNumber: string; + feedbackType: string; + feedbackDate: string; + pinCode: string; + city: string; + state: string; + outStandingAmount: number; + currentDPD: number; + dpdBucket: string; + agencyName: string; + agentName: string; + agentPhoneNumber: string; + agentType: string; + lastMonthEmiStatus: string; + lastPaidDate: string; + lastPaidEmiAmount: number; +} + +export interface IPage { + pageNo: number; + totalPages: number; + pageSize: number; + totalElements: number; + currentPageToken?: string; + nextPageToken: string; +} + +export interface queryParam { + pageSize?: string; + pageNo?: string; + sortBy?: string; + sortDirection?: string; + agencyCode?: string; + agentType?: string; + agentReferenceId?: string; + riskIndicator?: string; + interactionStatus?: string; + pinCodes?: string; + accountNumbers?: string; + dpdBuckets?: string; + names?: string; + queryType?: string; + query?: string; + lastUsed?: string; + isIncludePageLookup?: string; +} + +export interface filtersQueryParams { + agencyCode?: string; +} + +export const defaultQueryParam: queryParam = { + pageSize: '50', + pageNo: '0', + sortBy: 'name', + sortDirection: 'DESC', + isIncludePageLookup: 'true' +}; + +export const TABLE_NAME = 'teamLead'; + +export interface ITeamLeadAPIReducer { + teamLeadData: ITeamLeadAPIResponse[]; + page: IPage; + loading: boolean; + error: string; + filters: { + agentType: Array; + interactionStatus: Array; + paymentStatus: Array; + agentReferenceId: { + [key: string]: string; + }; + }; +} + +export enum AgentTypes { + FIELD = 'Field', + CALLING = 'Calling', + HUMAN_REMINDER = 'Human Reminder', + SKIP_TRACING = 'Skip Tracing' +} + +export enum InteractionStatus { + PAID = 'Paid', + PROMISE_TO_PAY = 'Promise to Pay', + REVISIT = 'Revisit', + PROMISE_FULFILLED = 'Promise Fulfilled', + BROKEN_PROMISE = 'Broken Promise', + NOT_CONTACTABLE = 'Not Contactable', + REQUESTED_CALLBACK = 'Requested Callback', + DISPUTE = 'Dispute', + CUSTOMER_EXPIRED = 'Customer Expired', + RINGING_NO_RESPONSE = 'Ringing No Response', + ADDRESS_NOT_FOUND = 'Address Not Found', + CUSTOMER_SHIFTED_FROM_ADDRESS = 'Customer Shifted from Address', + REFUSED_TO_PAY = 'Refused to Pay', + DOOR_LOCKED = 'Door Locked', + CALL_DISCONNECTED_RPC = 'Call Disconnected RPC', + CALL_DISCONNECTED_NON_RPC = 'Call Disconnected Non RPC', + MESSAGE_LEFT = 'Message Left', + OTHERS = 'Others', + SWITCHED_OFF = 'Switched Off', + INVALID_NUMBER = 'Invalid Number', + BUSY = 'Busy', + PARTIALLY_PAID = 'Partially Paid', + ENTRY_RESTRICTED = 'Entry Restricted', + CUSTOMER_NEVER_LIVED_IN_ADDRESS = 'Customer Never Lived in Address', + OUT_OF_NETWORK = 'Out of Network', + CUSTOMER_NOT_IN_ADDRESS_AT_PRESENT = 'Customer Not in Address at Present', + TPC_WRONG_NUMBER = 'TPC Wrong Number', + TPC_UNKNOWN = 'TPC Unknown', + NUMBER_PROVIDED = 'Number Provided', + ADDRESS_PROVIDED = 'Address Provided', + REQUESTED_LOAN_DETAILS = 'Requested Loan Details', + WILLING_TO_PAY = 'Willing to Pay', + SETTLEMENT = 'Settlement' +} + +export enum PaymentStatus { + ALL = 'All', + PAID = 'Paid', + UNPAID = 'Unpaid', + PARTIALLY_PAID = 'Partially Paid' +} + +export const FiltersKeys = [ + { + key: 'agentType', + label: 'Agent Type' + }, + { + key: 'interactionStatus', + label: 'Interaction Status' + }, + { + key: 'paymentStatus', + label: 'Payment Status' + }, + { + key: 'agentReferenceId', + label: 'Agent Name' + } +]; + +export const enumMapping = { + agentType: AgentTypes, + interactionStatus: InteractionStatus, + paymentStatus: PaymentStatus +}; + +export interface ISelectedFilters { + agentType?: { + [key: string]: boolean; + }; + interactionStatus?: { + [key: string]: boolean; + }; + paymentStatus?: { + [key: string]: boolean; + }; + agentReferenceId?: { + [key: string]: boolean; + }; +} diff --git a/src/pages/TeamLeadDashboard/teamLeadActions.ts b/src/pages/TeamLeadDashboard/teamLeadActions.ts new file mode 100644 index 00000000..1477f028 --- /dev/null +++ b/src/pages/TeamLeadDashboard/teamLeadActions.ts @@ -0,0 +1,32 @@ +import axiosInstance, { ApiKeys, getApiUrl, logError } from 'src/utils/ApiHelper'; +import { filtersQueryParams, queryParam } from './interface'; +import { Dispatch } from '@reduxjs/toolkit'; +import { setFilters, setTeamLeadApiCalling, setTeamLeadData } from 'src/reducers/TeamLeadSlice'; + +export const getTeamLeadDashboard = (queryParams: queryParam) => (dispatch: Dispatch) => { + dispatch(setTeamLeadApiCalling()); + const url = getApiUrl(ApiKeys.GET_TEAM_LEAD_CASES); + axiosInstance + .get(url, { params: queryParams }) + .then(response => { + dispatch(setTeamLeadData(response.data)); + dispatch(setTeamLeadApiCalling()); + }) + .catch(error => { + dispatch(setTeamLeadApiCalling()); + logError('Error inside getTeamLeadDashboardAPI', error); + }); +}; + +export const getTeamLeadDashboardFilters = + (queryParams: filtersQueryParams) => (dispatch: Dispatch) => { + const url = getApiUrl(ApiKeys.GET_TEAM_LEAD_FILTERS); + axiosInstance + .get(url, { params: queryParams }) + .then(response => { + dispatch(setFilters(response)); + }) + .catch(error => { + logError('Error inside getTeamLeadDashboardFilters', error); + }); + }; diff --git a/src/reducers/TeamLeadSlice.ts b/src/reducers/TeamLeadSlice.ts new file mode 100644 index 00000000..366bc7ec --- /dev/null +++ b/src/reducers/TeamLeadSlice.ts @@ -0,0 +1,38 @@ +import { createSlice } from '@reduxjs/toolkit'; +import { IPage, ITeamLeadAPIReducer } from 'src/pages/TeamLeadDashboard/interface'; + +const initialState = { + teamLeadData: [], + page: {} as IPage, + loading: false, + error: '', + filters: { + agentType: [], + interactionStatus: [], + paymentStatus: [], + agentReferenceId: {} + } as ITeamLeadAPIReducer['filters'] +} as ITeamLeadAPIReducer; + +const teamLeadSlice = createSlice({ + name: 'teamLeadDashboard', + initialState, + reducers: { + setTeamLeadData(state, action) { + const { data, pages } = action.payload; + state.teamLeadData = data; + state.page = pages; + }, + setTeamLeadApiCalling(state) { + state.loading = !state.loading; + }, + setFilters(state, action) { + const { data } = action.payload; + state.filters = data; + } + } +}); + +export const { setTeamLeadData, setTeamLeadApiCalling, setFilters } = teamLeadSlice.actions; + +export default teamLeadSlice.reducer; diff --git a/src/reducers/commonSlice.ts b/src/reducers/commonSlice.ts index 1d5a624e..d0287d63 100644 --- a/src/reducers/commonSlice.ts +++ b/src/reducers/commonSlice.ts @@ -192,6 +192,7 @@ export interface CommonState { humanReminderAgentDetails: HumanReminderAgentDetails; humanReminderCustomerDetails: HumanReminderCustomerDetails; isPerformanceDashboardVisible: boolean; + isTeamLead: boolean; humanReminderCustomerDetailsLoading: boolean; } @@ -238,6 +239,7 @@ export const commonSlice = createSlice({ action.payload.roles?.includes(Roles.ROLE_NAVI_FIELD_EXTERNAL_TEAM_LEAD) || action.payload.roles?.includes(Roles.ROLE_NAVI_FIELD_TEAM_LEAD); state.isPerformanceDashboardVisible = agencyPerformanceDashboardVisible; + state.isTeamLead = action.payload.roles?.includes(Roles.ROLE_TEAM_LEAD); } state.userData = { ...state.userData, ...action.payload }; }, diff --git a/src/service/clickStream.constant.ts b/src/service/clickStream.constant.ts index 1b1a7666..d3b366ba 100644 --- a/src/service/clickStream.constant.ts +++ b/src/service/clickStream.constant.ts @@ -390,6 +390,10 @@ export const CLICKSTREAM_EVENT_NAMES = Object.freeze({ LH_Dashboard_QuickFilterPerformanceLevel: { name: 'LH_Dashboard_QuickFilterPerformanceLevel', description: 'Click on Quick filter view of Performance level' + }, + LH_TEAM_LEAD_Dashboard_SidePanelIconClick: { + name: 'LH_TEAM_LEAD_Dashboard_SidePanelIconClick', + description: 'Click on TEAM_LEAD Dashboard option on Side Panel' } }); @@ -634,12 +638,6 @@ export enum HRC_EVENTS { DASHBOARD_DETAILS_SHOWN = 'HRC_DASHBOARD_DETAILS_SHOWN' } -export enum PERFORMANCE_DASHBOARD_EVENTS { - LH_PERF_DASHBOARD_LOAD = 'LH_PERF_DASHBOARD_LOAD', - LH_PERF_DASHBOARD_FILTER_CLICKED = 'LH_PERF_DASHBOARD_FILTER_CLICKED', - LH_PERF_DASHBOARD_FILTER_OPTION_SELECTED = 'LH_PERF_DASHBOARD_FILTER_OPTION_SELECTED', - LH_PERF_DASHBOARD_CLEAR_FILTER_CLICKED = 'LH_PERF_DASHBOARD_CLEAR_FILTER_CLICKED' -} export const HRC_CLICKSTREAM: Record = { [HRC_EVENTS.ACCEPT_CALL_MADE]: { diff --git a/src/store/index.ts b/src/store/index.ts index bfa71709..bec5875b 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -13,6 +13,7 @@ import performanceDashboardSlice from 'src/pages/PerformanceDashboard/reducers/p import storage from 'redux-persist/lib/storage'; import { persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from 'redux-persist'; +import TeamLeadSlice from 'src/reducers/TeamLeadSlice'; import IDCardApprovalsSlice from 'src/pages/IDCardApprovals/reducers/IDCardApprovalsSlice'; export const reducer = combineReducers({ @@ -26,6 +27,7 @@ export const reducer = combineReducers({ humanReminder: humanReminderSlice, performanceDashboard: performanceDashboardSlice, caseHistoryDetail: CaseHistoryDetailSlice, + teamLeadDashboard: TeamLeadSlice, idCardApprovals: IDCardApprovalsSlice }); diff --git a/src/utils/ApiHelper.ts b/src/utils/ApiHelper.ts index 4decb41f..5ba70c5b 100644 --- a/src/utils/ApiHelper.ts +++ b/src/utils/ApiHelper.ts @@ -101,8 +101,10 @@ export enum ApiKeys { AGENCY_INPUT, PD_FILTERS, PREVIOUS_LAN_INTERACTIONS, - VERIFY_CAPTCHA, CASE_BROWSING_HISTORY, + GET_TEAM_LEAD_CASES, + GET_TEAM_LEAD_FILTERS, + VERIFY_CAPTCHA, GET_APPROVAL_REQUESTS, APPROVE_ID_CARD } @@ -182,6 +184,8 @@ API_URLS[ApiKeys.PD_FILTERS] = '/longhorn/metrics/filters'; API_URLS[ApiKeys.PREVIOUS_LAN_INTERACTIONS] = '/v2/interactions/previous'; API_URLS[ApiKeys.VERIFY_CAPTCHA] = '/recaptcha/verify'; API_URLS[ApiKeys.CASE_BROWSING_HISTORY] = '/history/case-visit-history'; +API_URLS[ApiKeys.GET_TEAM_LEAD_CASES] = '/case-allocations/all-cases'; +API_URLS[ApiKeys.GET_TEAM_LEAD_FILTERS] = '/case-allocations/case-filter'; API_URLS[ApiKeys.GET_APPROVAL_REQUESTS] = '/approval-requests/pending'; API_URLS[ApiKeys.APPROVE_ID_CARD] = '/approval-requests/approval-status'; @@ -344,7 +348,9 @@ axiosInstance.interceptors.request.use( const excludedRedirectionEndPointsList = [ APP_ROUTES.PERFORMANCE_DASHBOARD.path, - APP_ROUTES.ID_CARD_APPROVALS.path + APP_ROUTES.ID_CARD_APPROVALS.path, + APP_ROUTES.TEAM_LEAD_DASHBOARD.path, + '/cases/details/lan' ]; const checkIsValidRedirection = () => {