TP-21355 | Generic case batch api changes | Aman C (#155)
* TP-21355 batch case details API * TP-21355 | Aman C | batch case details API * TP-21355 | Aman C | batch api fix * TP-21355 | Generic batch API
This commit is contained in:
committed by
GitHub Enterprise
parent
afb6e6a3ac
commit
c4749f37d8
@@ -10,7 +10,7 @@ import Widget from './src/components/form';
|
||||
import { registerNavigateAndDispatch } from './src/components/utlis/apiHelper';
|
||||
import { getLoanIdToValueFromLocal } from './src/components/utlis/registerPaymentUtils';
|
||||
import { setGlobalUserData } from './src/constants/Global';
|
||||
import { useAppDispatch } from './src/hooks';
|
||||
import { useAppDispatch, useAppSelector } from './src/hooks';
|
||||
import useFirestoreUpdates from './src/hooks/useFirestoreUpdates';
|
||||
import { setLoanIdToValue } from './src/reducer/paymentSlice';
|
||||
import { setDeviceId } from './src/reducer/userSlice';
|
||||
@@ -29,6 +29,8 @@ import TodoList from './src/screens/todoList/TodoList';
|
||||
import { RootState } from './src/store/store';
|
||||
import { CaseAllocationType } from "./src/screens/allCases/interface";
|
||||
import { getTemplateRoute } from "./src/components/utlis/navigationUtlis";
|
||||
import { resetNewVisitedCases } from './src/reducer/allCasesSlice';
|
||||
import { getCaseUnifiedData, UnifiedCaseDetailsTypes } from './src/action/caseApiActions';
|
||||
|
||||
const ANIMATION_DURATION = 300;
|
||||
|
||||
@@ -45,6 +47,25 @@ const ProtectedRouter = () => {
|
||||
const user = useSelector(
|
||||
(state: RootState) => state.user,
|
||||
);
|
||||
const { newVisitedCases, caseDetails } = useAppSelector(state => state.allCases);
|
||||
|
||||
useEffect(() => {
|
||||
if(newVisitedCases?.length) {
|
||||
const loanAccountNumbers: string[] = [];
|
||||
newVisitedCases.forEach(caseId => {
|
||||
const { loanAccountNumber } = caseDetails[caseId];
|
||||
if(!loanAccountNumber) {
|
||||
return;
|
||||
}
|
||||
loanAccountNumbers.push(loanAccountNumber);
|
||||
});
|
||||
if(loanAccountNumbers.length) {
|
||||
const { EMI_SCHEDULE, REPAYMENTS, ADDRESS_AND_GEOLOCATIONS, FEEDBACKS } = UnifiedCaseDetailsTypes;
|
||||
dispatch(getCaseUnifiedData(loanAccountNumbers, [EMI_SCHEDULE, REPAYMENTS, ADDRESS_AND_GEOLOCATIONS, FEEDBACKS]))
|
||||
}
|
||||
dispatch(resetNewVisitedCases());
|
||||
}
|
||||
}, [newVisitedCases])
|
||||
|
||||
const avTemplate = useSelector(
|
||||
(state: RootState) => state.case.templateData[CaseAllocationType.ADDRESS_VERIFICATION_CASE],
|
||||
|
||||
@@ -45,13 +45,13 @@ const setUnifiedDataLoading =
|
||||
(queryParams: Record<UnifiedCaseDetailsTypes, boolean>, loanAccountNumbers: string[]) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
if (queryParams[UnifiedCaseDetailsTypes.EMI_SCHEDULE]) {
|
||||
dispatch(setEmiScheduleLoading(true));
|
||||
dispatch(setEmiScheduleLoading({loanAccountNumbers, isLoading : true}));
|
||||
}
|
||||
if (queryParams[UnifiedCaseDetailsTypes.FEEDBACKS]) {
|
||||
dispatch(setFeedbackHistoryLoading(true));
|
||||
dispatch(setFeedbackHistoryLoading({loanAccountNumbers, isLoading : true}));
|
||||
}
|
||||
if (queryParams[UnifiedCaseDetailsTypes.REPAYMENTS]) {
|
||||
dispatch(setRepaymentsLoading(true));
|
||||
dispatch(setRepaymentsLoading({loanAccountNumbers, isLoading : true}));
|
||||
}
|
||||
if (queryParams[UnifiedCaseDetailsTypes.ADDRESS_AND_GEOLOCATIONS]) {
|
||||
dispatch(setAddressLoading({loanAccountNumbers, isLoading : true}));
|
||||
@@ -116,9 +116,9 @@ export const getCaseUnifiedData =
|
||||
Promise.allSettled(promisesList).then(res => {
|
||||
dispatch(setUnifiedData(queryParams, loanAccountNumbers, res));
|
||||
}).finally(() => {
|
||||
dispatch(setEmiScheduleLoading(false));
|
||||
dispatch(setFeedbackHistoryLoading(false));
|
||||
dispatch(setRepaymentsLoading(false));
|
||||
dispatch(setEmiScheduleLoading({isLoading:false, loanAccountNumbers}));
|
||||
dispatch(setFeedbackHistoryLoading({isLoading:false, loanAccountNumbers}));
|
||||
dispatch(setRepaymentsLoading({isLoading:false, loanAccountNumbers}));
|
||||
dispatch(setAddressLoading({isLoading:false, loanAccountNumbers}))
|
||||
});
|
||||
};
|
||||
|
||||
@@ -21,18 +21,12 @@ import {logError} from '../components/utlis/errorUtils';
|
||||
import {setFilters} from "../reducer/filtersSlice";
|
||||
import { toast } from "../../RN-UI-LIB/src/components/toast";
|
||||
import { ToastMessages } from '../screens/allCases/contants';
|
||||
import { getCaseUnifiedData, UnifiedCaseDetailsTypes } from './caseApiActions';
|
||||
|
||||
export const postPinnedList =
|
||||
(pinnedCases: IPinnedCasesPayload[], updatedCaseList: ICaseItem[], type: string, newlyPinnedCasesLANs?: string[]) =>
|
||||
(pinnedCases: IPinnedCasesPayload[], updatedCaseList: ICaseItem[], type: string) =>
|
||||
(dispatch: AppDispatch) => {
|
||||
dispatch(setVisitPlansUpdating(true));
|
||||
|
||||
if(newlyPinnedCasesLANs?.length) {
|
||||
const { EMI_SCHEDULE, REPAYMENTS, ADDRESS_AND_GEOLOCATIONS, FEEDBACKS } = UnifiedCaseDetailsTypes;
|
||||
getCaseUnifiedData(newlyPinnedCasesLANs, [EMI_SCHEDULE, REPAYMENTS, ADDRESS_AND_GEOLOCATIONS, FEEDBACKS]);
|
||||
}
|
||||
|
||||
const url = getApiUrl(ApiKeys.PINNED_CASES);
|
||||
axiosInstance
|
||||
.post(url, pinnedCases)
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
navigateToScreen,
|
||||
} from '../components/utlis/navigationUtlis';
|
||||
import { CaseUpdates } from '../hooks/useFirestoreUpdates';
|
||||
import { COMPLETED_STATUSES } from '../screens/allCases/contants';
|
||||
|
||||
import {
|
||||
CaseStatuses,
|
||||
@@ -28,7 +29,6 @@ export type ICasesMap = { [key: string]: ICaseItem };
|
||||
|
||||
interface IAllCasesSlice {
|
||||
casesList: ICaseItem[];
|
||||
pinnedList: ICaseItem[];
|
||||
casesListMap: ICasesMap;
|
||||
intermediateTodoList: ICaseItem[];
|
||||
intermediateTodoListMap: ICasesMap;
|
||||
@@ -44,11 +44,14 @@ interface IAllCasesSlice {
|
||||
searchQuery: string;
|
||||
isOnboarded: boolean;
|
||||
visitPlansUpdating: boolean;
|
||||
pendingList:ICaseItem[];
|
||||
completedList:ICaseItem[];
|
||||
pinnedList:ICaseItem[];
|
||||
newVisitedCases: string[];
|
||||
}
|
||||
|
||||
const initialState: IAllCasesSlice = {
|
||||
casesList: [],
|
||||
pinnedList: [],
|
||||
casesListMap: {},
|
||||
intermediateTodoList: [],
|
||||
intermediateTodoListMap: {},
|
||||
@@ -64,6 +67,27 @@ const initialState: IAllCasesSlice = {
|
||||
searchQuery: '',
|
||||
isOnboarded: false,
|
||||
visitPlansUpdating: false,
|
||||
pendingList: [],
|
||||
completedList: [],
|
||||
pinnedList: [],
|
||||
newVisitedCases: []
|
||||
};
|
||||
|
||||
const getCaseListComponents = (casesList: ICaseItem[], caseDetails: Record<string, CaseDetail>) => {
|
||||
const pendingList: ICaseItem[] = [];
|
||||
const completedList: ICaseItem[] = [];
|
||||
const pinnedList: ICaseItem[] = [];
|
||||
casesList.forEach(item => {
|
||||
const { caseReferenceId, pinRank } = item;
|
||||
const { caseStatus } = caseDetails[caseReferenceId];
|
||||
const isCaseCompleted = COMPLETED_STATUSES.includes(caseStatus);
|
||||
isCaseCompleted
|
||||
? completedList.push(item)
|
||||
: pinRank
|
||||
? pinnedList.push(item)
|
||||
: pendingList.push(item);
|
||||
});
|
||||
return { pendingList, completedList, pinnedList };
|
||||
};
|
||||
|
||||
const getPinnedListDetails = (casesList: ICaseItem[]) => {
|
||||
@@ -207,7 +231,8 @@ const allCasesSlice = createSlice({
|
||||
if (state.loading) {
|
||||
state.loading = false;
|
||||
}
|
||||
let newVisitedCases = 0;
|
||||
let newVisitCaseCount: number = 0;
|
||||
let newVisitCases: string[] = [];
|
||||
let removedVisitedCases = 0;
|
||||
caseUpdates.forEach(({ updateType, updatedCaseDetail }) => {
|
||||
const { caseType, caseReferenceId, id, pinRank } =
|
||||
@@ -221,7 +246,10 @@ const allCasesSlice = createSlice({
|
||||
);
|
||||
if (index !== -1) {
|
||||
if (pinRank && !state.casesList[index].pinRank) {
|
||||
newVisitedCases++;
|
||||
newVisitCaseCount++;
|
||||
if(caseType === CaseAllocationType.COLLECTION_CASE) {
|
||||
newVisitCases.push(caseId);
|
||||
}
|
||||
}
|
||||
if(!pinRank && state.casesList[index].pinRank) {
|
||||
removedVisitedCases++;
|
||||
@@ -253,6 +281,9 @@ const allCasesSlice = createSlice({
|
||||
if (state.caseDetails[caseId]) {
|
||||
return;
|
||||
}
|
||||
if(pinRank && caseType === CaseAllocationType.COLLECTION_CASE) {
|
||||
newVisitCases.push(caseId);
|
||||
}
|
||||
const caseListItem = {
|
||||
caseReferenceId: caseId,
|
||||
pinRank: pinRank || null,
|
||||
@@ -298,11 +329,17 @@ const allCasesSlice = createSlice({
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (newVisitedCases) {
|
||||
const { pendingList, completedList, pinnedList } = getCaseListComponents(state.casesList, state.caseDetails);
|
||||
state.pendingList = pendingList;
|
||||
state.completedList = completedList;
|
||||
state.pinnedList = pinnedList;
|
||||
state.newVisitedCases = newVisitCases;
|
||||
|
||||
if (newVisitCaseCount) {
|
||||
toast({
|
||||
type: 'info',
|
||||
text1: `${newVisitedCases} case${
|
||||
newVisitedCases > 1 ? 's' : ''
|
||||
text1: `${newVisitCaseCount} case${
|
||||
newVisitCaseCount > 1 ? 's' : ''
|
||||
} added to the visit plan`,
|
||||
});
|
||||
return;
|
||||
@@ -438,7 +475,6 @@ const allCasesSlice = createSlice({
|
||||
},
|
||||
resetCasesData: state => {
|
||||
state.casesList = [];
|
||||
state.pinnedList = [];
|
||||
state.casesListMap = {};
|
||||
state.intermediateTodoList = [];
|
||||
state.intermediateTodoListMap = {};
|
||||
@@ -453,10 +489,17 @@ const allCasesSlice = createSlice({
|
||||
state.caseDetails = {};
|
||||
state.searchQuery = '';
|
||||
state.isOnboarded = state.isOnboarded;
|
||||
state.newVisitedCases = [];
|
||||
state.pendingList = [];
|
||||
state.pinnedList = [];
|
||||
state.completedList = [];
|
||||
},
|
||||
setVisitPlansUpdating: (state, action) => {
|
||||
state.visitPlansUpdating = action.payload;
|
||||
},
|
||||
resetNewVisitedCases: (state) => {
|
||||
state.newVisitedCases = [];
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -476,7 +519,8 @@ export const {
|
||||
toggleNewlyAddedCase,
|
||||
resetCasesData,
|
||||
updateCaseDetailBeforeApiCall,
|
||||
setVisitPlansUpdating
|
||||
setVisitPlansUpdating,
|
||||
resetNewVisitedCases,
|
||||
} = allCasesSlice.actions;
|
||||
|
||||
export default allCasesSlice.reducer;
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
|
||||
interface IEmiScheduleState {
|
||||
//TODO: update interface of EMISchedule instead of any
|
||||
data: Record<string, any>;
|
||||
isLoading: boolean;
|
||||
timestamp: string;
|
||||
//TODO: update interface of EmiSchedule instead of any
|
||||
[loanAccountNumber: string] : {data : any, isLoading: boolean, timestamp: string };
|
||||
}
|
||||
|
||||
const initialState: IEmiScheduleState = {
|
||||
data: {},
|
||||
isLoading: false,
|
||||
timestamp: ''
|
||||
};
|
||||
const initialState: IEmiScheduleState = {};
|
||||
|
||||
const EmiScheduleSlice = createSlice({
|
||||
name: 'emiSchedule',
|
||||
@@ -19,12 +14,13 @@ const EmiScheduleSlice = createSlice({
|
||||
reducers: {
|
||||
setEmiSchedule: (state, action) => {
|
||||
const { loanAccountNumber, emiSchedule } = action.payload;
|
||||
state.timestamp = new Date().toISOString();
|
||||
state.data[loanAccountNumber] = emiSchedule;
|
||||
state.isLoading = false;
|
||||
state[loanAccountNumber] = {data: emiSchedule, timestamp: new Date().toISOString(),isLoading: false }
|
||||
},
|
||||
setEmiScheduleLoading: (state, action: PayloadAction<boolean>) => {
|
||||
state.isLoading = action.payload;
|
||||
setEmiScheduleLoading: (state, action: PayloadAction<{ loanAccountNumbers: string[], isLoading: boolean }>) => {
|
||||
const payloadData = action.payload
|
||||
payloadData.loanAccountNumbers.forEach((loanAccNumber)=>{
|
||||
state[loanAccNumber] = {...(state?.[loanAccNumber] || []), isLoading: payloadData.isLoading}
|
||||
})
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,16 +2,10 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
interface IFeedbackHistoryState {
|
||||
//TODO: update interface of FeedbackHistory instead of any
|
||||
data: Record<string, any>;
|
||||
isLoading: boolean;
|
||||
timestamp: string;
|
||||
[loanAccountNumber: string] : {data : any, isLoading: boolean, timestamp: string };
|
||||
}
|
||||
|
||||
const initialState: IFeedbackHistoryState = {
|
||||
data: {},
|
||||
isLoading: false,
|
||||
timestamp: ''
|
||||
};
|
||||
const initialState: IFeedbackHistoryState = {};
|
||||
|
||||
const FeedbackHistorySlice = createSlice({
|
||||
name: 'feedbackHistory',
|
||||
@@ -19,12 +13,13 @@ const FeedbackHistorySlice = createSlice({
|
||||
reducers: {
|
||||
setFeedbackHistory: (state, action) => {
|
||||
const { loanAccountNumber, feedbacks } = action.payload;
|
||||
state.timestamp = new Date().toISOString();
|
||||
state.data[loanAccountNumber] = feedbacks;
|
||||
state.isLoading = false;
|
||||
state[loanAccountNumber] = {data: feedbacks, timestamp: new Date().toISOString(),isLoading: false }
|
||||
},
|
||||
setFeedbackHistoryLoading: (state, action: PayloadAction<boolean>) => {
|
||||
state.isLoading = action.payload;
|
||||
setFeedbackHistoryLoading: (state, action: PayloadAction<{ loanAccountNumbers: string[], isLoading: boolean }>) => {
|
||||
const payloadData = action.payload
|
||||
payloadData.loanAccountNumbers.forEach((loanAccNumber)=>{
|
||||
state[loanAccNumber] = {...(state?.[loanAccNumber] || []), isLoading: payloadData.isLoading}
|
||||
})
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,16 +2,10 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
interface IRepaymentsState {
|
||||
//TODO: update interface of Repayments instead of any
|
||||
data: Record<string, any>;
|
||||
isLoading: boolean;
|
||||
timestamp: string;
|
||||
[loanAccountNumber: string] : {data : any, isLoading: boolean, timestamp: string };
|
||||
}
|
||||
|
||||
const initialState: IRepaymentsState = {
|
||||
data: {},
|
||||
isLoading: false,
|
||||
timestamp: ''
|
||||
};
|
||||
const initialState: IRepaymentsState = {};
|
||||
|
||||
const RepaymentsSlice = createSlice({
|
||||
name: 'repayments',
|
||||
@@ -19,12 +13,13 @@ const RepaymentsSlice = createSlice({
|
||||
reducers: {
|
||||
setRepayments: (state, action) => {
|
||||
const { loanAccountNumber, repayments } = action.payload;
|
||||
state.timestamp = new Date().toISOString();
|
||||
state.data[loanAccountNumber] = repayments;
|
||||
state.isLoading = false;
|
||||
state[loanAccountNumber] = {data: repayments, timestamp: new Date().toISOString(),isLoading: false }
|
||||
},
|
||||
setRepaymentsLoading: (state, action: PayloadAction<boolean>) => {
|
||||
state.isLoading = action.payload;
|
||||
setRepaymentsLoading: (state, action: PayloadAction<{ loanAccountNumbers: string[], isLoading: boolean }>) => {
|
||||
const payloadData = action.payload
|
||||
payloadData.loanAccountNumbers.forEach((loanAccNumber)=>{
|
||||
state[loanAccNumber] = {...(state?.[loanAccNumber] || []), isLoading: payloadData.isLoading}
|
||||
})
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { useAppDispatch, useAppSelector } from '../../hooks';
|
||||
import CasesList from './CasesList';
|
||||
import { ICaseItem } from './interface';
|
||||
import { RootState } from '../../store/store';
|
||||
import { initCrashlytics } from '../../components/utlis/firebaseUtils';
|
||||
import Layout from '../layout/Layout';
|
||||
@@ -12,14 +11,13 @@ import CasesIcon from '../../../RN-UI-LIB/src/Icons/CasesIcon';
|
||||
import Profile from '../Profile';
|
||||
import ProfileIcon from '../../../RN-UI-LIB/src/Icons/ProfileIcon';
|
||||
import VisitPlanIcon from '../../../RN-UI-LIB/src/Icons/VisitPlanIcon';
|
||||
import { COMPLETED_STATUSES, ListHeaderItems } from './contants';
|
||||
import CasesActionButtons from './CasesActionButtons';
|
||||
import FullScreenLoader from '../../../RN-UI-LIB/src/components/FullScreenLoader';
|
||||
import { getCurrentScreen } from '../../components/utlis/navigationUtlis';
|
||||
import { resetSelectedTodoList, resetTodoList, setLoading, setVisitPlansUpdating } from '../../reducer/allCasesSlice';
|
||||
|
||||
const AllCasesMain = () => {
|
||||
const { casesList, caseDetails, loading } = useAppSelector(state => state.allCases);
|
||||
const { pendingList, completedList, pinnedList, loading } = useAppSelector(state => state.allCases);
|
||||
const userState = useAppSelector((state: RootState) => state.user);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
@@ -27,23 +25,6 @@ const AllCasesMain = () => {
|
||||
(state: RootState) => state.allCases,
|
||||
);
|
||||
|
||||
const { pendingList, completedList, pinnedList } = useMemo(() => {
|
||||
const pendingList: ICaseItem[] = [];
|
||||
const completedList: ICaseItem[] = [];
|
||||
const pinnedList: ICaseItem[] = [];
|
||||
casesList.forEach(item => {
|
||||
const { caseReferenceId, pinRank } = item;
|
||||
const { caseStatus } = caseDetails[caseReferenceId];
|
||||
const isCaseCompleted = COMPLETED_STATUSES.includes(caseStatus);
|
||||
isCaseCompleted
|
||||
? completedList.push(item)
|
||||
: pinRank
|
||||
? pinnedList.push(item)
|
||||
: pendingList.push(item);
|
||||
});
|
||||
return { pendingList, completedList, pinnedList };
|
||||
}, [casesList, caseDetails, selectedTodoListCount]);
|
||||
|
||||
const HOME_SCREENS: ITabScreen[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
|
||||
@@ -85,6 +85,9 @@ const FeedbackListContainer: React.FC<IFeedbackListContainer> = ({ loanAccountNu
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if(!loanAccountNumber) {
|
||||
return;
|
||||
}
|
||||
if (isOnline || !feedbackList) {
|
||||
dispatch(getCaseUnifiedData([loanAccountNumber], [UnifiedCaseDetailsTypes.FEEDBACKS]))
|
||||
}
|
||||
|
||||
@@ -63,7 +63,6 @@ const TodoList = () => {
|
||||
}
|
||||
const updatedPinnedList: ICaseItem[] = [];
|
||||
const pinnedCasesPayload: IPinnedCasesPayload[] = [];
|
||||
const newlyPinnedCasesLANs: string[] = [];
|
||||
const updatedCaseList = casesList.map(caseItem => {
|
||||
const { caseReferenceId } = caseItem;
|
||||
const pinnedItem =
|
||||
@@ -83,9 +82,6 @@ const TodoList = () => {
|
||||
updatedPinnedList.push(pinnedItem);
|
||||
pinnedCasePayload.pinRank = pinnedItem.pinRank;
|
||||
pinnedCasesPayload.push(pinnedCasePayload);
|
||||
if(caseType === CaseAllocationType.COLLECTION_CASE && loanAccountNumber) {
|
||||
newlyPinnedCasesLANs.push(loanAccountNumber);
|
||||
}
|
||||
}
|
||||
return pinnedItem ? pinnedItem : caseItem;
|
||||
});
|
||||
@@ -97,7 +93,7 @@ const TodoList = () => {
|
||||
return caseA.pinRank - caseB.pinRank
|
||||
},
|
||||
);
|
||||
dispatch(postPinnedList(sortedPinnedCasesPayload, updatedCaseList, 'ADDED', newlyPinnedCasesLANs));
|
||||
dispatch(postPinnedList(sortedPinnedCasesPayload, updatedCaseList, 'ADDED'));
|
||||
};
|
||||
|
||||
const handleCancelTodoList = () => {
|
||||
|
||||
Reference in New Issue
Block a user