212 lines
7.2 KiB
TypeScript
212 lines
7.2 KiB
TypeScript
import firestore from '@react-native-firebase/firestore';
|
|
import { useAppDispatch, useAppSelector } from '@hooks';
|
|
import store, { type RootState } from '@store';
|
|
import { updateCaseDetailsFirestore } from '@reducers/allCasesSlice';
|
|
import { CLICKSTREAM_EVENT_NAMES, FirestoreUpdateTypes, SyncedSource } from '@common/Constants';
|
|
import axiosInstance, { ApiKeys, getApiUrl } from '@utils/apiHelper';
|
|
import { getSyncCaseIds } from '@utils/firebaseFallbackUtils';
|
|
import { logError } from '@utils/errorUtils';
|
|
import { addClickstreamEvent } from '@services/clickstreamEventService';
|
|
import { GenericObject } from '@common/GenericTypes';
|
|
import { setLastFirebaseResyncTimestamp } from '@reducers/metadataSlice';
|
|
import dayJs from 'dayjs';
|
|
import {
|
|
getEnableFirestoreResync,
|
|
getFirestoreResyncIntervalInMinutes,
|
|
} from '@common/AgentActivityConfigurableConstants';
|
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
|
|
const selectedAgentReferenceIDForMyCases = 'MY_CASES';
|
|
|
|
type CasesToFetchPayload = {
|
|
data: {
|
|
allocatedCaseIds: string[];
|
|
deallocatedCaseIds: string[];
|
|
updatedCaseIds: string[];
|
|
};
|
|
};
|
|
const useResyncFirebase = () => {
|
|
const dispatch = useAppDispatch();
|
|
|
|
const refId = store?.getState()?.user?.user?.referenceId || '';
|
|
const selectedAgent = store?.getState()?.user?.selectedAgent;
|
|
const selectedAgentRefId = store?.getState()?.user?.selectedAgent?.referenceId || '';
|
|
const refIdForLoggedInAndSelectedUser =
|
|
selectedAgentRefId === selectedAgentReferenceIDForMyCases ? refId : selectedAgentRefId;
|
|
|
|
const _getCaseDetailsFromApi = async (caseId: string) => {
|
|
const getCaseDetailsFromApiUrl = getApiUrl(ApiKeys.GET_CASE_DETAILS_FROM_API_V2, {
|
|
caseId: caseId,
|
|
});
|
|
|
|
return axiosInstance.get(getCaseDetailsFromApiUrl, {
|
|
params: {
|
|
allocatedAgentReferenceId: refIdForLoggedInAndSelectedUser,
|
|
},
|
|
});
|
|
};
|
|
|
|
const updateCaseInRedux = (
|
|
updateType: FirestoreUpdateTypes,
|
|
caseDetails: GenericObject,
|
|
selectedAgent: GenericObject
|
|
) => {
|
|
dispatch(
|
|
updateCaseDetailsFirestore({
|
|
caseUpdates: [
|
|
{
|
|
updateType: updateType,
|
|
updatedCaseDetail: caseDetails,
|
|
},
|
|
],
|
|
isInitialLoad: false,
|
|
isVisitPlanLocked: false,
|
|
selectedAgent,
|
|
})
|
|
);
|
|
};
|
|
|
|
return async (): Promise<void> => {
|
|
console.log('firebase resync called');
|
|
const now = dayJs().toString();
|
|
const FIRST_DATE = new Date(1970, 1, 1);
|
|
const lastFirebaseResyncTimestamp =
|
|
(await AsyncStorage.getItem('lastFirebaseResyncTimestamp')) || dayJs(FIRST_DATE).toString();
|
|
const minutesSinceLastResync = dayJs(now).diff(dayJs(lastFirebaseResyncTimestamp), 'minutes');
|
|
if (!getEnableFirestoreResync()) {
|
|
return;
|
|
}
|
|
if (minutesSinceLastResync < getFirestoreResyncIntervalInMinutes()) {
|
|
return;
|
|
}
|
|
|
|
void addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_FIREBASE_RESYNC_STARTED);
|
|
const getFirestoreInconsistencyUrl = getApiUrl(ApiKeys.FIRESTORE_INCONSISTENCY_INFO_V2);
|
|
const casesList = store?.getState()?.allCases?.casesList || [];
|
|
const casesPath = `allocations/${refIdForLoggedInAndSelectedUser}/cases`;
|
|
const localCases = getSyncCaseIds(casesList);
|
|
const casesToFetch: CasesToFetchPayload = await axiosInstance.post(
|
|
getFirestoreInconsistencyUrl,
|
|
{
|
|
agentId: refIdForLoggedInAndSelectedUser,
|
|
cases: localCases,
|
|
}
|
|
);
|
|
|
|
const allocatedCases = casesToFetch?.data?.allocatedCaseIds;
|
|
const unallocatedCases = casesToFetch?.data?.deallocatedCaseIds;
|
|
const updatedCases = casesToFetch?.data?.updatedCaseIds;
|
|
|
|
allocatedCases.forEach((caseId: string) => {
|
|
if (!caseId) {
|
|
return null;
|
|
}
|
|
firestore()
|
|
.collection(casesPath)
|
|
.doc(caseId.toString())
|
|
.get({ source: 'server' })
|
|
.then((res) => {
|
|
const firebaseCase = res?.data() || {};
|
|
if (!firebaseCase?.caseReferenceId) {
|
|
throw new Error('could not find case in firebase');
|
|
}
|
|
dispatch(
|
|
updateCaseDetailsFirestore({
|
|
caseUpdates: [
|
|
{
|
|
updateType: FirestoreUpdateTypes.ADDED,
|
|
updatedCaseDetail: firebaseCase,
|
|
},
|
|
],
|
|
isInitialLoad: false,
|
|
isVisitPlanLocked: false,
|
|
selectedAgent,
|
|
})
|
|
);
|
|
void addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_FIREBASE_RESYNC, {
|
|
added: caseId,
|
|
syncedSource: SyncedSource.FIREBASE,
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
logError(err as Error, 'Error fetching cases from firestore');
|
|
void _getCaseDetailsFromApi(caseId).then((res: { data: GenericObject }) => {
|
|
const caseDetails = res?.data;
|
|
updateCaseInRedux(FirestoreUpdateTypes.ADDED, caseDetails, selectedAgent);
|
|
void addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_FIREBASE_RESYNC, {
|
|
updated: caseId,
|
|
syncedSource: SyncedSource.API,
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
unallocatedCases.forEach((caseId: string) => {
|
|
if (!caseId) {
|
|
return null;
|
|
}
|
|
dispatch(
|
|
updateCaseDetailsFirestore({
|
|
caseUpdates: [
|
|
{
|
|
updateType: FirestoreUpdateTypes.REMOVED,
|
|
updatedCaseDetail: {
|
|
caseType: '',
|
|
caseReferenceId: caseId,
|
|
id: '',
|
|
pinRank: '',
|
|
caseViewCreatedAt: '',
|
|
},
|
|
},
|
|
],
|
|
isInitialLoad: false,
|
|
isVisitPlanLocked: false,
|
|
selectedAgent,
|
|
})
|
|
);
|
|
void addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_FIREBASE_RESYNC, { deleted: caseId });
|
|
});
|
|
|
|
updatedCases.forEach((caseId: string) => {
|
|
if (!caseId) {
|
|
return null;
|
|
}
|
|
firestore()
|
|
.collection(casesPath)
|
|
.doc(caseId.toString())
|
|
.get({ source: 'server' })
|
|
.then((res) => {
|
|
const firebaseCase = res?.data() || {};
|
|
|
|
if (!firebaseCase?.caseReferenceId) {
|
|
throw new Error('could not find case in firebase');
|
|
}
|
|
updateCaseInRedux(FirestoreUpdateTypes.MODIFIED, firebaseCase, selectedAgent);
|
|
void addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_FIREBASE_RESYNC, {
|
|
updated: caseId,
|
|
syncedSource: SyncedSource.FIREBASE,
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
void _getCaseDetailsFromApi(caseId).then((res: { data: GenericObject }) => {
|
|
const caseDetails = res?.data || {};
|
|
updateCaseInRedux(FirestoreUpdateTypes.MODIFIED, caseDetails, selectedAgent);
|
|
void addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_FIREBASE_RESYNC, {
|
|
updated: caseId,
|
|
syncedSource: SyncedSource.API,
|
|
});
|
|
});
|
|
logError(err as Error, 'Error fetching cases from firestore');
|
|
console.log('cases err:', err);
|
|
});
|
|
});
|
|
|
|
dispatch(setLastFirebaseResyncTimestamp(dayJs().toString()));
|
|
await AsyncStorage.setItem('lastFirebaseResyncTimestamp', dayJs().toString());
|
|
|
|
await Promise.resolve();
|
|
};
|
|
};
|
|
|
|
export default useResyncFirebase;
|