Files
address-verification-app/src/components/utlis/apiHelper.ts
Himanshu Kansal 11f5f70c0e TP-20465 | Feedback Detail Screen (#156)
* TP-20465 | Feedback Detail Screen

* TP-20465 | Fix integration bugs

* TP-20465 | Added scroll Animation

* TP-20465 | Minor Fix

* TP-20465 | API integration + feedbackAction
2023-03-17 13:26:18 +05:30

215 lines
7.4 KiB
TypeScript

import axios from 'axios';
import { Dispatch } from '@reduxjs/toolkit';
import { setAuthData } from '../../reducer/userSlice';
import { toast } from '../../../RN-UI-LIB/src/components/toast';
import { navigateToScreen } from './navigationUtlis';
import { GLOBAL } from '../../constants/Global';
import { _map } from '../../../RN-UI-LIB/src/utlis/common';
import { BASE_AV_APP_URL } from '../../constants/config';
import { logError } from './errorUtils';
import { ClickstreamAPIToMonitor, CLICKSTREAM_EVENT_NAMES } from '../../common/Constants';
import { addClickstreamEvent } from '../../services/clickstreamEventService';
import { resetCasesData } from '../../reducer/allCasesSlice';
export enum ApiKeys {
GENERATE_OTP,
VERIFY_OTP,
ALL_CASES,
CASE_DETAIL,
PINNED_CASES,
LOGOUT,
FEEDBACK,
FILTERS,
JANUS,
GENERATE_PAYMENT_LINK,
ADDRESSES_GEOLOCATION,
NEW_ADDRESS,
GET_SIGNED_URL,
CASE_UNIFIED_DETAILS,
PAST_FEEDBACK,
}
export const API_URLS: Record<ApiKeys, string> = {} as Record<ApiKeys, string>;
API_URLS[ApiKeys.GENERATE_OTP] = '/auth/otp/generate';
API_URLS[ApiKeys.VERIFY_OTP] = '/auth/otp/verify';
API_URLS[ApiKeys.ALL_CASES] = '/cases/all-cases';
API_URLS[ApiKeys.CASE_DETAIL] = '/cases/get-cases';
API_URLS[ApiKeys.PINNED_CASES] = '/cases/pin';
API_URLS[ApiKeys.LOGOUT] = '/auth/logout';
API_URLS[ApiKeys.FEEDBACK] = '/cases/feedback';
API_URLS[ApiKeys.FILTERS] = '/cases/filters';
API_URLS[ApiKeys.JANUS] = '/events/json';
API_URLS[ApiKeys.GENERATE_PAYMENT_LINK] = '/send-payment-link';
API_URLS[ApiKeys.ADDRESSES_GEOLOCATION] = '/addresses-geolocations';
API_URLS[ApiKeys.NEW_ADDRESS] = '/addresses';
API_URLS[ApiKeys.GET_SIGNED_URL] = '/cases/get-signed-urls';
API_URLS[ApiKeys.CASE_UNIFIED_DETAILS] = '/collection-cases/unified-details/{loanAccountNumber}';
API_URLS[ApiKeys.PAST_FEEDBACK] = '/field-app/feedbacks';
export const API_STATUS_CODE = {
OK: 200,
CREATED: 201,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
FORBIDDEN: 403,
NOT_FOUND: 404,
INTERNAL_SERVER_ERROR: 500
};
const API_TIMEOUT_INTERVAL = 1e4;
let dispatch: Dispatch<any>;
export const getErrorMessage = (err: any) => {
if (err?.response?.data?.title) {
return err?.response?.data?.title;
}
const errorContent = err?.response?.data?.message
? JSON.parse(err?.response?.data?.message)
: '';
return errorContent?.detail || errorContent?.message || errorContent || err;
};
export function getApiUrl(
apiKey: ApiKeys,
params?: Record<string, string | number>,
queryParams?: Record<string, string | number | boolean>,
) {
let apiUrl = API_URLS[apiKey];
// replace all {placeholders} with their values in params
if (params) {
Object.keys(params).forEach(paramKey => {
apiUrl = apiUrl.split(`{${paramKey}}`).join(`${params[paramKey]}`);
// apiUrl = apiUrl.replaceAll(`{${paramKey}}`, `${params[paramKey]}`);
});
}
if (queryParams) {
apiUrl +=
'?' +
_map(queryParams, key => `${key}=${queryParams[key]}`).join('&');
}
return `${apiUrl}`;
}
// status code to be retried on
const errorsToRetry = [500, 503];
const axiosInstance = axios.create({timeout: API_TIMEOUT_INTERVAL});
axiosInstance.interceptors.request.use(request => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.retry = request?.retry < 4 ? request.retry : 3;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.headers['X-Auth-Source'] = 'mjolnir';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.retry = request?.retry < 4 ? request.retry : 3;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.headers['request-start-time'] = Date.now();
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.headers['X-Session-Token'] = GLOBAL.SESSION_TOKEN || '';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
request.headers['deviceId'] = GLOBAL.DEVICE_ID || '';
return request;
});
axiosInstance.interceptors.response.use(
response => {
if (response.config.headers) {
const start = response.config.headers['request-start-time'];
const end = Date.now();
const milliseconds = end - Number(start);
response.headers['request-duration'] = String(milliseconds);
if(response?.config?.url) {
const url = response?.config?.url;
if(ClickstreamAPIToMonitor[url]) {
const eventName = ClickstreamAPIToMonitor[url] + '_SUCCESS'
if(CLICKSTREAM_EVENT_NAMES[eventName]) {
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES[eventName], {timeTaken: milliseconds})
}
}
}
}
return response;
},
error => {
logError(error as Error, 'From API Helper');
const {config, response} = error;
if(config.headers.donotHandleError) {
return;
}
if (config?.headers) {
const start = response.config.headers['request-start-time'];
const end = Date.now();
const milliseconds = end - Number(start);
if(config?.url) {
const url = response?.config?.url;
if(ClickstreamAPIToMonitor[url]) {
const eventName = ClickstreamAPIToMonitor[url] + '_FAILED'
if(CLICKSTREAM_EVENT_NAMES[eventName]) {
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES[eventName], {timeTaken: milliseconds, response})
}
}
}
}
if (
!config ||
config.retry <= 1 ||
!errorsToRetry.includes(error.response.status)
) {
const errorString = getErrorMessage(error);
if (!config.headers.donotHandleError) {
toast({
type: 'error',
text1:
typeof errorString === 'string'
? errorString
: 'Oops! something went wrong',
});
}
if ([API_STATUS_CODE.UNAUTHORIZED, API_STATUS_CODE.FORBIDDEN].includes(response.status)) {
// Reset user info
dispatch &&
dispatch(
setAuthData({
sessionDetails: null,
isLoggedIn: false,
user: null,
}),
);
dispatch && dispatch(resetCasesData());
navigateToScreen('Login');
}
return Promise.reject(error);
}
config.retry -= 1;
const delayRetryRequest = new Promise<void>(resolve => {
setTimeout(() => {
resolve();
}, 0);
});
return delayRetryRequest.then(() => axiosInstance(config));
},
);
axiosInstance.defaults.headers.common['Content-Type'] = 'application/json';
axiosInstance.defaults.baseURL = BASE_AV_APP_URL;
// TODO:: Ideally should happen through middlewares.
export const registerNavigateAndDispatch = (
dispatchParam: Dispatch<any>
) => ((dispatch = dispatchParam));
export default axiosInstance;