첫 커밋
This commit is contained in:
4
src/shared/lib/convert-currency-string-to-number.ts
Normal file
4
src/shared/lib/convert-currency-string-to-number.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const convertCurrencyStringToNumber = (currencyString: string): number => {
|
||||
const cleanedString = currencyString.replace(/[^\d]/g, '');
|
||||
return parseInt(cleanedString, 10);
|
||||
};
|
||||
1
src/shared/lib/delay.ts
Normal file
1
src/shared/lib/delay.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
11
src/shared/lib/error.ts
Normal file
11
src/shared/lib/error.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import axios from 'axios';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
import { IS_MOCK_PHASE } from '@/shared/constants/environment';
|
||||
|
||||
// CBDCAxiosError가 아니라면 상위 Error Boundary로 위임
|
||||
export const checkIsAxiosError = (error: Error): error is CBDCAxiosError => axios.isAxiosError(error);
|
||||
|
||||
export const checkIsKickOutError = (error: CBDCAxiosError) => {
|
||||
const status = error.response?.status.toString();
|
||||
return !IS_MOCK_PHASE && (status === '401' || status === '403');
|
||||
};
|
||||
16
src/shared/lib/format-korean-number.ts
Normal file
16
src/shared/lib/format-korean-number.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export const formatKoreanNumber = (num: number): string => {
|
||||
const units = ['', '만', '억', '조', '경', '해'];
|
||||
let result = '';
|
||||
let unitIndex = 0;
|
||||
|
||||
while (num > 0) {
|
||||
const part = num % 10000;
|
||||
if (part != 0) {
|
||||
result = `${part.toLocaleString()}${units[unitIndex]}${result}`;
|
||||
}
|
||||
num = Math.floor(num / 10000);
|
||||
unitIndex++;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
12
src/shared/lib/hooks/index.tsx
Normal file
12
src/shared/lib/hooks/index.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
export * from './use-navigate';
|
||||
export * from './use-app-version';
|
||||
export * from './use-change-bg-color';
|
||||
export * from './use-device-uid';
|
||||
export * from './use-fix-scroll-view-safari';
|
||||
export * from './use-has-bio-hardware';
|
||||
export * from './use-navigate';
|
||||
export * from './use-location-permission';
|
||||
export * from './use-window-focus-change';
|
||||
export * from './use-router-listener';
|
||||
export * from './use-scroll-to-top';
|
||||
export * from './use-app-page-speed';
|
||||
15
src/shared/lib/hooks/use-app-page-speed.ts
Normal file
15
src/shared/lib/hooks/use-app-page-speed.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { useEffectOnce } from 'react-use';
|
||||
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
import { StorageKeys } from '@/shared/constants/local-storage';
|
||||
import { setAfterPageRendered } from '@/shared/lib';
|
||||
|
||||
export const useAppPagingSpeed = () => {
|
||||
return useLocalStorageState(StorageKeys.AppPagingSpeed, { defaultValue: '250' });
|
||||
};
|
||||
|
||||
export const useEffectOnceAfterPageRendered = (callback: () => void) => {
|
||||
useEffectOnce(() => {
|
||||
setAfterPageRendered(callback);
|
||||
});
|
||||
};
|
||||
17
src/shared/lib/hooks/use-app-version.tsx
Normal file
17
src/shared/lib/hooks/use-app-version.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import { useMemo } from 'react';
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
import { config } from '@/shared/configs';
|
||||
import { StorageKeys } from '@/shared/constants/local-storage';
|
||||
|
||||
export const DEFAULT_APP_VERSION = '1.0';
|
||||
export const useAppVersion = () => {
|
||||
const [appVersion] = useLocalStorageState(StorageKeys.AppVersion, { defaultValue: DEFAULT_APP_VERSION });
|
||||
return appVersion;
|
||||
};
|
||||
|
||||
export const webVersion = config.WEB_VERSION.replace(/\b(\d+)(?:\.0\.0)?\b/g, '$1');
|
||||
export const useFullVersion = () => {
|
||||
const appVersion = useAppVersion();
|
||||
const fullVersion = useMemo(() => `${appVersion}.${webVersion}`, [appVersion]);
|
||||
return { fullVersion };
|
||||
};
|
||||
10
src/shared/lib/hooks/use-block-back.ts
Normal file
10
src/shared/lib/hooks/use-block-back.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { useBlocker } from '@use-blocker';
|
||||
|
||||
export const useBlockBack = (blockPaths: string[]) => {
|
||||
useBlocker(({ nextLocation }) => {
|
||||
if (blockPaths.includes(nextLocation.pathname)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
2
src/shared/lib/hooks/use-blocker.ts
Normal file
2
src/shared/lib/hooks/use-blocker.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import { useBlocker as _useBlocker } from 'react-router';
|
||||
export const useBlocker = _useBlocker;
|
||||
44
src/shared/lib/hooks/use-change-bg-color.ts
Normal file
44
src/shared/lib/hooks/use-change-bg-color.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useLayoutEffect } from 'react';
|
||||
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
import { DEFAULT_BACKGROUND_COLOR } from '@/shared/constants/colors';
|
||||
import { StorageKeys } from '@/shared/constants/local-storage';
|
||||
import { NativeFunction } from '@/shared/constants/native-function';
|
||||
import { useRouterListener } from './use-router-listener';
|
||||
|
||||
export const useChangeBgColor = (color: string) => {
|
||||
const [, setAppColor] = useAppColor();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAppColor(color);
|
||||
window.webViewBridge.send(NativeFunction.SetAppColor, color);
|
||||
document.body.style.backgroundColor = color;
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const useResetBgColor = () => {
|
||||
const [, setAppColor] = useAppColor();
|
||||
const defaultColor = DEFAULT_BACKGROUND_COLOR;
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setAppColor(defaultColor);
|
||||
window.webViewBridge.send(NativeFunction.SetAppColor, defaultColor);
|
||||
document.body.style.backgroundColor = defaultColor;
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const useResetBgColorOnLeave = () => {
|
||||
const [, setAppColor] = useAppColor();
|
||||
const defaultColor = DEFAULT_BACKGROUND_COLOR;
|
||||
|
||||
useRouterListener(() => {
|
||||
setAppColor(defaultColor);
|
||||
document.body.style.backgroundColor = defaultColor;
|
||||
window.webViewBridge.send(NativeFunction.SetAppColor, defaultColor);
|
||||
});
|
||||
};
|
||||
|
||||
export const useAppColor = () => {
|
||||
return useLocalStorageState(StorageKeys.AppColor, { defaultValue: DEFAULT_BACKGROUND_COLOR });
|
||||
};
|
||||
31
src/shared/lib/hooks/use-device-uid.ts
Normal file
31
src/shared/lib/hooks/use-device-uid.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
/* eslint-disable @cspell/spellchecker */
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
// import { useUpdateUserInfo } from '@/entities/user/lib/use-update-user-info';
|
||||
import { StorageKeys } from '@/shared/constants/local-storage';
|
||||
import { useStore } from '@/shared/model/store';
|
||||
|
||||
export const useDeviceUid = () => {
|
||||
let defaultUid = '';
|
||||
if (!window.ReactNativeWebView) {
|
||||
defaultUid = '1234567890';
|
||||
}
|
||||
const userInfo = useStore((state: any) => state.userSlice.userInfo);
|
||||
const [deviceUid] = useLocalStorageState(StorageKeys.DeviceUniqueId, { defaultValue: defaultUid });
|
||||
//const { updateUserInfo } = useUpdateUserInfo();
|
||||
|
||||
useEffect(() => {
|
||||
if (deviceUid.length < 1) {
|
||||
return;
|
||||
}
|
||||
if (userInfo?.appEsntlNo && userInfo?.appEsntlNo?.length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// updateUserInfo((prev: any) => ({ ...prev, appEsntlNo: deviceUid }));
|
||||
}, [deviceUid]);
|
||||
|
||||
return deviceUid;
|
||||
};
|
||||
12
src/shared/lib/hooks/use-fix-scroll-view-safari.ts
Normal file
12
src/shared/lib/hooks/use-fix-scroll-view-safari.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const useFixScrollViewSafari = () => {
|
||||
useEffect(() => {
|
||||
const timeout = setTimeout(() => {
|
||||
window.scrollTo(0, 1);
|
||||
}, 100);
|
||||
return () => {
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
}, []);
|
||||
};
|
||||
45
src/shared/lib/hooks/use-fixed-button-position.ts
Normal file
45
src/shared/lib/hooks/use-fixed-button-position.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { CSSProperties, useEffect, useState } from 'react';
|
||||
|
||||
export const useFixedButtonPosition = () => {
|
||||
const [buttonStyle, setButtonStyle] = useState<CSSProperties | undefined>();
|
||||
|
||||
const updateButtonPosition = () => {
|
||||
const viewport = window.visualViewport;
|
||||
const viewportHeight = viewport?.height;
|
||||
const viewportOffsetTop = viewport?.offsetTop ?? 0;
|
||||
|
||||
if (viewportHeight && viewportHeight < window.innerHeight) {
|
||||
setButtonStyle({ bottom: `${window.innerHeight - viewportHeight - viewportOffsetTop + 15}px` });
|
||||
} else {
|
||||
setButtonStyle(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
updateButtonPosition();
|
||||
};
|
||||
|
||||
visualViewport?.addEventListener('resize', handleResize);
|
||||
window.addEventListener('resize', handleResize); // fallback for window resize
|
||||
|
||||
return () => {
|
||||
visualViewport?.removeEventListener('resize', handleResize);
|
||||
window.removeEventListener('resize', handleResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
updateButtonPosition();
|
||||
};
|
||||
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('scroll', handleScroll);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return buttonStyle;
|
||||
};
|
||||
14
src/shared/lib/hooks/use-hardware-back-press-listener.ts
Normal file
14
src/shared/lib/hooks/use-hardware-back-press-listener.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useEffect } from 'react';
|
||||
import { NativeMessage } from '@/shared/constants/native-message';
|
||||
import { bridge } from '@/bridge';
|
||||
|
||||
export const useHardwareBackPressListener = (callback: () => void) => {
|
||||
useEffect(() => {
|
||||
// Subscribe to events from react native.
|
||||
return bridge.addEventListener(NativeMessage.HardwareBackPress, (message: any) => {
|
||||
callback?.();
|
||||
});
|
||||
}, []);
|
||||
};
|
||||
7
src/shared/lib/hooks/use-has-bio-hardware.ts
Normal file
7
src/shared/lib/hooks/use-has-bio-hardware.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import useLocalStorageState from 'use-local-storage-state';
|
||||
import { StorageKeys } from '@/shared/constants/local-storage';
|
||||
|
||||
export const useHasBioHardware = () => {
|
||||
const [hasBioHardware] = useLocalStorageState(StorageKeys.HasBioHardware, { defaultValue: false });
|
||||
return hasBioHardware;
|
||||
};
|
||||
46
src/shared/lib/hooks/use-location-permission.ts
Normal file
46
src/shared/lib/hooks/use-location-permission.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/* eslint-disable @cspell/spellchecker */
|
||||
import { useEffect } from 'react';
|
||||
import { PERMISSION_RESULTS, PermissionResultValues, WebViewBridgeResponse } from '@/shared/@types/webview-bridge';
|
||||
|
||||
import { NativeFunction } from '@/shared/constants/native-function';
|
||||
|
||||
interface CheckLocationPermissionResponse extends WebViewBridgeResponse {
|
||||
data: PermissionResultValues;
|
||||
}
|
||||
|
||||
export const useRequestLocationPermission = () => {
|
||||
useEffect(() => {
|
||||
window.webViewBridge.send(NativeFunction.LocationPermission, {
|
||||
success: async () => {
|
||||
// console.log('res', res);
|
||||
},
|
||||
});
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const useCheckLocationPermission = () => {
|
||||
useEffect(() => {
|
||||
window.webViewBridge.send(NativeFunction.CheckLocationPermission, {
|
||||
success: async (res: CheckLocationPermissionResponse) => {
|
||||
// console.log('res', res.data);
|
||||
switch (res.data) {
|
||||
case PERMISSION_RESULTS.UNAVAILABLE:
|
||||
console.log('This feature is not available (on this device / in this context)');
|
||||
break;
|
||||
case PERMISSION_RESULTS.DENIED:
|
||||
console.log('The permission has not been requested / is denied but requestable');
|
||||
break;
|
||||
case PERMISSION_RESULTS.LIMITED:
|
||||
console.log('The permission is limited: some actions are possible');
|
||||
break;
|
||||
case PERMISSION_RESULTS.GRANTED:
|
||||
console.log('The permission is granted');
|
||||
break;
|
||||
case PERMISSION_RESULTS.BLOCKED:
|
||||
console.log('The permission is denied and not requestable anymore');
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
}, []);
|
||||
};
|
||||
37
src/shared/lib/hooks/use-navigate.ts
Normal file
37
src/shared/lib/hooks/use-navigate.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { PathType } from '@/shared/constants/paths';
|
||||
import {
|
||||
NavigateOptions,
|
||||
To,
|
||||
useNavigate as _useNavigate
|
||||
} from 'react-router';
|
||||
|
||||
export type NavigateTo = PathType | -1 | 0;
|
||||
|
||||
export const goBackWebview = (goBack: () => void) => {
|
||||
if (!window.ReactNativeWebView) {
|
||||
if (window.history.state?.idx > 0) {
|
||||
goBack();
|
||||
return;
|
||||
} else {
|
||||
window.close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
export const useNavigate = () => {
|
||||
const _navigate = _useNavigate();
|
||||
|
||||
const navigate = (to: NavigateTo, options?: NavigateOptions): void => {
|
||||
const path = typeof to === 'number' ? to : to.toString();
|
||||
_navigate(path as To, options);
|
||||
};
|
||||
|
||||
const reload = async () => {
|
||||
navigate(0);
|
||||
};
|
||||
|
||||
const navigateBack = () => goBackWebview(() => _navigate(-1));
|
||||
|
||||
return { navigate, navigateBack, reload };
|
||||
};
|
||||
13
src/shared/lib/hooks/use-request-notification.ts
Normal file
13
src/shared/lib/hooks/use-request-notification.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { NativeFunction } from '@/shared/constants/native-function';
|
||||
|
||||
export const useRequestNotification = () => {
|
||||
useEffect(() => {
|
||||
window.webViewBridge.send(NativeFunction.RequestNotification, {
|
||||
success: async () => {
|
||||
// console.log('res', res);
|
||||
},
|
||||
});
|
||||
}, []);
|
||||
};
|
||||
20
src/shared/lib/hooks/use-router-listener.ts
Normal file
20
src/shared/lib/hooks/use-router-listener.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { RouterState } from '@remix-run/router';
|
||||
import { useEffect } from 'react';
|
||||
import { NavigationType } from 'react-router';
|
||||
|
||||
import { router } from '@/shared/configs/sentry';
|
||||
|
||||
type IRouterListener = (state: RouterState) => void;
|
||||
|
||||
export const useRouterListener = (callback: IRouterListener, actionType?: NavigationType) => {
|
||||
useEffect(() => {
|
||||
const unsubscribe = router.subscribe((state: any) => {
|
||||
if (actionType && state.historyAction !== actionType) return;
|
||||
if (!actionType || state.historyAction === actionType) {
|
||||
callback?.(state);
|
||||
}
|
||||
});
|
||||
|
||||
return unsubscribe;
|
||||
}, [callback, actionType]);
|
||||
};
|
||||
37
src/shared/lib/hooks/use-script.ts
Normal file
37
src/shared/lib/hooks/use-script.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export function useScript(src: string) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
let script = document.querySelector(`script[src="${src}"]`);
|
||||
|
||||
const handleLoad = () => setLoading(false);
|
||||
const handleError = (err: any) => {
|
||||
setError(err);
|
||||
setLoading(false);
|
||||
};
|
||||
if(!script){
|
||||
script = document.createElement('script');
|
||||
(script as any).src = src;
|
||||
(script as any).type = 'text/javascript';
|
||||
(script as any).charset = 'utf-8';
|
||||
|
||||
script.addEventListener('load', handleLoad);
|
||||
script.addEventListener('error', handleError);
|
||||
console.log(script);
|
||||
// document.getElementsByTagName('head')[0].appendChild(script);
|
||||
}
|
||||
else{
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
return () => {
|
||||
script.removeEventListener('load', handleLoad);
|
||||
script.removeEventListener('error', handleError);
|
||||
}
|
||||
}, [src]);
|
||||
|
||||
return [loading, error];
|
||||
}
|
||||
7
src/shared/lib/hooks/use-scroll-to-top.ts
Normal file
7
src/shared/lib/hooks/use-scroll-to-top.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const useScrollToTop = () => {
|
||||
useEffect(() => {
|
||||
document.body.scrollTop = 0;
|
||||
}, []);
|
||||
};
|
||||
50
src/shared/lib/hooks/use-select-bottom-sheet.tsx
Normal file
50
src/shared/lib/hooks/use-select-bottom-sheet.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import { overlay } from 'overlay-kit';
|
||||
import { BottomSheet } from '@/shared/ui/bottom-sheets/bottom-sheet';
|
||||
import {
|
||||
SelectTemplate,
|
||||
ElementType,
|
||||
RadioChangeProps,
|
||||
SelectTemplateProps,
|
||||
} from '@/shared/ui/selects/select-template';
|
||||
import { JSX } from 'react/jsx-runtime';
|
||||
|
||||
export interface SelectBottomSheetProps<T> extends SelectTemplateProps<T> {
|
||||
title?: string | JSX.Element;
|
||||
description?: string | JSX.Element;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
export const useSelectBottomSheet = <T,>() => {
|
||||
const openSelectBottomSheet = (selectBottomSheet: SelectBottomSheetProps<T>) => {
|
||||
const {
|
||||
values = [],
|
||||
labels = [],
|
||||
valueKey = undefined,
|
||||
selectedLabel = '',
|
||||
selectedValue = '',
|
||||
title = '',
|
||||
description = '',
|
||||
} = selectBottomSheet;
|
||||
|
||||
const handleRadioChange = ({ event, label, value }: RadioChangeProps<ElementType<typeof values>>) => {
|
||||
selectBottomSheet?.onRadioChange?.({ event, label, value });
|
||||
};
|
||||
|
||||
overlay.open(({ isOpen, close, unmount }) => {
|
||||
return (
|
||||
<BottomSheet title={title} description={description} afterLeave={unmount} open={isOpen} onClose={close}>
|
||||
<SelectTemplate
|
||||
values={values}
|
||||
valueKey={valueKey}
|
||||
labels={labels}
|
||||
selectedLabel={selectedLabel}
|
||||
selectedValue={selectedValue}
|
||||
onRadioChange={handleRadioChange}
|
||||
/>
|
||||
</BottomSheet>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return { openSelectBottomSheet, closeBottomSheet: overlay.closeAll };
|
||||
};
|
||||
28
src/shared/lib/hooks/use-window-focus-change.ts
Normal file
28
src/shared/lib/hooks/use-window-focus-change.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import { useEffect } from 'react';
|
||||
|
||||
interface WindowFocusProps {
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
args?: any[];
|
||||
}
|
||||
|
||||
export const useWindowFocusChange = ({ onFocus, onBlur, ...args }: WindowFocusProps) => {
|
||||
const dependencies: any[] = [];
|
||||
if (Array.isArray(args)) {
|
||||
dependencies.push(...args);
|
||||
}
|
||||
const handleEvent = () => {
|
||||
if (document.hidden) {
|
||||
// the page is hidden
|
||||
onBlur?.();
|
||||
} else {
|
||||
// the page is visible
|
||||
onFocus?.();
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
window.document.addEventListener('visibilitychange', handleEvent);
|
||||
return () => window.document.removeEventListener('visibilitychange', handleEvent);
|
||||
}, [onFocus, onBlur, ...dependencies]);
|
||||
};
|
||||
5
src/shared/lib/index.ts
Normal file
5
src/shared/lib/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export * from './error';
|
||||
export * from './toast';
|
||||
export * from './web-view-bridge';
|
||||
export * from './format-korean-number';
|
||||
export * from './set-after-page-rendered';
|
||||
17
src/shared/lib/resultify.ts
Normal file
17
src/shared/lib/resultify.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
|
||||
export const resultify = async <T = any>(promiseObj: AxiosPromise<T>): Promise<T> => {
|
||||
try {
|
||||
const result: any = await promiseObj;
|
||||
return result?.data !== undefined && result?.data !== null ? result.data : result;
|
||||
} catch (error: any) {
|
||||
const axiosError = error as CBDCAxiosError;
|
||||
console.error(
|
||||
`${
|
||||
axiosError.response?.status ? `[${axiosError.response.status}], ` : ''
|
||||
}${JSON.stringify(axiosError.response?.data)}`,
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
9
src/shared/lib/set-after-page-rendered.ts
Normal file
9
src/shared/lib/set-after-page-rendered.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { StorageKeys } from '@/shared/constants/local-storage';
|
||||
import { getLocalStorage } from './web-view-bridge';
|
||||
|
||||
export const setAfterPageRendered = (callback: () => void) => {
|
||||
setTimeout(callback, PAGING_SPEED);
|
||||
};
|
||||
export const PAGING_SPEED = getLocalStorage(StorageKeys.AppPagingSpeed)
|
||||
? Number(getLocalStorage(StorageKeys.AppPagingSpeed))
|
||||
: 250;
|
||||
6
src/shared/lib/to-camel-case.ts
Normal file
6
src/shared/lib/to-camel-case.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export const toCamelCase = (str: string) => {
|
||||
return str
|
||||
.split('-')
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
||||
.join('');
|
||||
};
|
||||
11
src/shared/lib/toast.tsx
Normal file
11
src/shared/lib/toast.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
/* eslint-disable @cspell/spellchecker */
|
||||
import { toast } from 'react-toastify';
|
||||
export const snackBar = (text: string) => {
|
||||
toast.dismiss({ containerId: 'snackbar' });
|
||||
toast(text, { containerId: 'snackbar' });
|
||||
};
|
||||
|
||||
export const notiBar = (text: string) => {
|
||||
toast.dismiss({ containerId: 'notibar' });
|
||||
toast(text);
|
||||
};
|
||||
79
src/shared/lib/web-view-bridge.ts
Normal file
79
src/shared/lib/web-view-bridge.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
export const setLocalStorage = (key: string, value: any) => {
|
||||
if (!key) return false;
|
||||
if (value) {
|
||||
if (typeof value === 'object') {
|
||||
window?.localStorage?.setItem(key, JSON.stringify(value));
|
||||
} else {
|
||||
window?.localStorage?.setItem(key, value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export const getLocalStorage = (key: string) => {
|
||||
if (!key) return;
|
||||
const ret = window?.localStorage?.getItem(key);
|
||||
|
||||
try {
|
||||
return ret && JSON.parse(ret);
|
||||
} catch (error) {
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
export const parseValueToDate = (
|
||||
date: string | number | Date | string[] | number[] | null | undefined,
|
||||
type?: string,
|
||||
fixType?: string,
|
||||
): string => {
|
||||
if (!date) return '';
|
||||
let parse = '';
|
||||
switch (typeof date) {
|
||||
case 'string':
|
||||
return date;
|
||||
case 'number':
|
||||
case 'object':
|
||||
let dDate = null;
|
||||
if (date instanceof Date || typeof date === 'number') {
|
||||
dDate = new Date(date);
|
||||
} else if (date instanceof Array) {
|
||||
if (date.length === 6)
|
||||
dDate = new Date(
|
||||
Number(date[0]),
|
||||
Number(date[1]) - 1,
|
||||
Number(date[2]),
|
||||
Number(date[3]),
|
||||
Number(date[4]),
|
||||
Number(date[5]),
|
||||
);
|
||||
else if (date.length === 5)
|
||||
dDate = dDate = new Date(
|
||||
Number(date[0]),
|
||||
Number(date[1]) - 1,
|
||||
Number(date[2]),
|
||||
Number(date[3]),
|
||||
Number(date[4]),
|
||||
);
|
||||
else if (date.length === 4)
|
||||
dDate = dDate = new Date(Number(date[0]), Number(date[1]) - 1, Number(date[2]), Number(date[3]));
|
||||
else if (date.length === 3) dDate = dDate = new Date(Number(date[0]), Number(date[1]) - 1, Number(date[2]));
|
||||
else if (date.length === 2) dDate = dDate = new Date(Number(date[0]), Number(date[1]) - 1);
|
||||
else if (date.length === 1) dDate = new Date(Number(date[0]));
|
||||
}
|
||||
|
||||
if (dDate) {
|
||||
if (type !== 'time') {
|
||||
parse = dDate.getFullYear() + (fixType ? fixType : '-');
|
||||
parse += String(dDate.getMonth() + 1).padStart(2, '0') + (fixType ? fixType : '-');
|
||||
parse += String(dDate.getDate()).padStart(2, '0');
|
||||
}
|
||||
if (type !== 'date') {
|
||||
if (type !== 'time') parse += ' ';
|
||||
parse += String(dDate.getHours()).padStart(2, '0') + ':';
|
||||
parse += String(dDate.getMinutes()).padStart(2, '0') + ':';
|
||||
parse += String(dDate.getSeconds()).padStart(2, '0');
|
||||
}
|
||||
}
|
||||
return parse;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user