refactor: Enhance survey hook and integrate spinner functionality
- Refactored useSurvey hook to utilize useAxios for API calls. - Added spinner visibility management in EdgeProvider to improve loading feedback. - Cleaned up imports and organized code structure for better readability.
This commit is contained in:
parent
0e7de68f29
commit
2c5ddad29b
93
src/hooks/useAxios.ts
Normal file
93
src/hooks/useAxios.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
import { useSpinnerStore } from '@/store/spinnerStore'
|
||||||
|
|
||||||
|
export const useAxios = () => {
|
||||||
|
const { setIsShow } = useSpinnerStore()
|
||||||
|
|
||||||
|
const axiosInstance = (url: string | null | undefined) => {
|
||||||
|
const baseURL = url || process.env.NEXT_PUBLIC_API_URL
|
||||||
|
const instance = axios.create({
|
||||||
|
baseURL,
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
instance.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
// console.log('🚀 ~ config:', config)
|
||||||
|
setIsShow(true)
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
return Promise.reject(error)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
instance.interceptors.response.use(
|
||||||
|
(response) => {
|
||||||
|
response.data = transferResponse(response)
|
||||||
|
setIsShow(false)
|
||||||
|
return response
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
// 에러 처리 로직
|
||||||
|
return Promise.reject(error)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
|
||||||
|
// response데이터가 array, object에 따라 분기하여 키 변환
|
||||||
|
const transferResponse = (response: any) => {
|
||||||
|
if (!response.data) return response.data
|
||||||
|
|
||||||
|
// 배열인 경우 각 객체의 키를 변환
|
||||||
|
if (Array.isArray(response.data)) {
|
||||||
|
return response.data.map((item: any) => transformObjectKeys(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 단일 객체인 경우
|
||||||
|
return transformObjectKeys(response.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// camel case object 반환
|
||||||
|
const transformObjectKeys = (obj: any): any => {
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
return obj.map(transformObjectKeys)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj !== null && typeof obj === 'object') {
|
||||||
|
return Object.keys(obj).reduce((acc: any, key: string) => {
|
||||||
|
let transformedKey = key
|
||||||
|
|
||||||
|
// Handle uppercase snake_case (e.g., USER_NAME -> userName)
|
||||||
|
// Handle lowercase snake_case (e.g., user_name -> userName)
|
||||||
|
if (/^[A-Z_]+$/.test(key) || /^[a-z_]+$/.test(key)) {
|
||||||
|
transformedKey = snakeToCamel(key)
|
||||||
|
}
|
||||||
|
// Handle single uppercase word (e.g., ROLE -> role)
|
||||||
|
else if (/^[A-Z]+$/.test(key)) {
|
||||||
|
transformedKey = key.toLowerCase()
|
||||||
|
}
|
||||||
|
// Preserve existing camelCase
|
||||||
|
|
||||||
|
acc[transformedKey] = transformObjectKeys(obj[key])
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
const snakeToCamel = (str: string): string => {
|
||||||
|
return str.toLowerCase().replace(/([-_][a-z])/g, (group) => group.toUpperCase().replace('-', '').replace('_', ''))
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
axiosInstance,
|
||||||
|
transferResponse,
|
||||||
|
transformObjectKeys,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +1,10 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
|
||||||
import type { SurveyBasicInfo, SurveyDetailInfo, SurveyDetailRequest, SurveyDetailCoverRequest, SurveyRegistRequest } from '@/types/Survey'
|
import type { SurveyBasicInfo, SurveyDetailInfo, SurveyDetailRequest, SurveyDetailCoverRequest, SurveyRegistRequest } from '@/types/Survey'
|
||||||
import { axiosInstance } from '@/libs/axios'
|
|
||||||
import { useSurveyFilterStore } from '@/store/surveyFilterStore'
|
|
||||||
import { queryStringFormatter } from '@/utils/common-utils'
|
|
||||||
import { useSessionStore } from '@/store/session'
|
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { AxiosResponse } from 'axios'
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||||
|
import { useSurveyFilterStore } from '@/store/surveyFilterStore'
|
||||||
|
import { useSessionStore } from '@/store/session'
|
||||||
|
import { useAxios } from './useAxios'
|
||||||
|
import { queryStringFormatter } from '@/utils/common-utils'
|
||||||
|
|
||||||
export const requiredFields = [
|
export const requiredFields = [
|
||||||
{
|
{
|
||||||
@ -75,6 +74,7 @@ export function useServey(id?: number): {
|
|||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const { keyword, searchOption, isMySurvey, sort, offset } = useSurveyFilterStore()
|
const { keyword, searchOption, isMySurvey, sort, offset } = useSurveyFilterStore()
|
||||||
const { session } = useSessionStore()
|
const { session } = useSessionStore()
|
||||||
|
const { axiosInstance } = useAxios()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: surveyListData,
|
data: surveyListData,
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { useSpinnerStore } from '@/store/spinnerStore'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
export const axiosInstance = (url: string | null | undefined) => {
|
export const axiosInstance = (url: string | null | undefined) => {
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import { usePopupController } from '@/store/popupController'
|
|||||||
import { useSideNavState } from '@/store/sideNavState'
|
import { useSideNavState } from '@/store/sideNavState'
|
||||||
import { useSessionStore } from '@/store/session'
|
import { useSessionStore } from '@/store/session'
|
||||||
import { tracking } from '@/libs/tracking'
|
import { tracking } from '@/libs/tracking'
|
||||||
|
import Spinner from '@/components/ui/common/Spinner'
|
||||||
|
import { useSpinnerStore } from '@/store/spinnerStore'
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
@ -28,6 +30,7 @@ export default function EdgeProvider({ children, sessionData }: EdgeProviderProp
|
|||||||
const { reset } = useSideNavState()
|
const { reset } = useSideNavState()
|
||||||
const { setAlertMsg, setAlertBtn, setAlert, setAlert2, setAlert2BtnYes, setAlert2BtnNo } = usePopupController()
|
const { setAlertMsg, setAlertBtn, setAlert, setAlert2, setAlert2BtnYes, setAlert2BtnNo } = usePopupController()
|
||||||
const { session, setSession } = useSessionStore()
|
const { session, setSession } = useSessionStore()
|
||||||
|
const { isShow, setIsShow } = useSpinnerStore()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 사용자 이벤트 트래킹 처리
|
* 사용자 이벤트 트래킹 처리
|
||||||
@ -110,5 +113,10 @@ export default function EdgeProvider({ children, sessionData }: EdgeProviderProp
|
|||||||
handlePageEvent(pathname)
|
handlePageEvent(pathname)
|
||||||
}, [pathname])
|
}, [pathname])
|
||||||
|
|
||||||
return <>{children}</>
|
return (
|
||||||
|
<>
|
||||||
|
{children}
|
||||||
|
{isShow && <Spinner />}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/store/spinnerStore.ts
Normal file
21
src/store/spinnerStore.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { create } from 'zustand'
|
||||||
|
|
||||||
|
type SpinnerState = {
|
||||||
|
isShow: boolean
|
||||||
|
setIsShow: (isShow: boolean) => void
|
||||||
|
resetCount: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
type InitialState = {
|
||||||
|
isShow: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: InitialState = {
|
||||||
|
isShow: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSpinnerStore = create<SpinnerState>((set) => ({
|
||||||
|
...initialState,
|
||||||
|
setIsShow: (isShow: boolean) => set({ isShow }),
|
||||||
|
resetCount: () => set(initialState),
|
||||||
|
}))
|
||||||
Loading…
x
Reference in New Issue
Block a user