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:
Aman Chaturvedi
2023-03-17 13:10:19 +05:30
committed by GitHub Enterprise
parent afb6e6a3ac
commit c4749f37d8
10 changed files with 113 additions and 88 deletions

View File

@@ -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],

View File

@@ -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}))
});
};

View File

@@ -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)

View File

@@ -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;

View File

@@ -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}
})
},
},
});

View File

@@ -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}
})
},
},
});

View File

@@ -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}
})
},
},
});

View File

@@ -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(
() => [
{

View File

@@ -85,6 +85,9 @@ const FeedbackListContainer: React.FC<IFeedbackListContainer> = ({ loanAccountNu
}
useEffect(() => {
if(!loanAccountNumber) {
return;
}
if (isOnline || !feedbackList) {
dispatch(getCaseUnifiedData([loanAccountNumber], [UnifiedCaseDetailsTypes.FEEDBACKS]))
}

View File

@@ -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 = () => {