diff --git a/src/pages/sinitto/call-back/detail/CallBackDetailPage.tsx b/src/pages/sinitto/call-back/detail/CallBackDetailPage.tsx index 9492eebc..2f8c70a1 100644 --- a/src/pages/sinitto/call-back/detail/CallBackDetailPage.tsx +++ b/src/pages/sinitto/call-back/detail/CallBackDetailPage.tsx @@ -1,11 +1,14 @@ -import { useState } from 'react'; -import { useParams, Outlet } from 'react-router-dom'; +import { useEffect } from 'react'; +import { useParams, Outlet, useNavigate } from 'react-router-dom'; +import { useGetAccepted } from './api/hooks'; +import { CallbackMenu } from './components'; import { GuideLineList } from './components/guide-line-list'; -import { PostAcceptMenu } from './components/menu/post-accept'; -import { PreAcceptMenu } from './components/menu/pre-accept'; +import { RouterPath } from '@/app/routes/path'; +import { useGetCallback } from '@/shared/api/hooks'; import { Notice } from '@/shared/components'; -import { Divider } from '@chakra-ui/react'; +import { handleCallbackError } from '@/shared/utils'; +import { Divider, Spinner } from '@chakra-ui/react'; import styled from '@emotion/styled'; export type CallBackDetailParams = { @@ -14,41 +17,55 @@ export type CallBackDetailParams = { export const CallBackDetailPage = () => { const { callBackId = '' } = useParams(); - const [accept, setAccept] = useState(false); + const navigate = useNavigate(); - console.log(callBackId); + const { + data: callbackData, + isLoading: isCallBackLoading, + isError: isCallBackError, + error: callBackError, + } = useGetCallback(callBackId); - const handleRequestAccept = () => { - // 도움 수락 - setAccept(true); - }; + useEffect(() => { + if (isCallBackError) { + const errorMessage = handleCallbackError(callBackError); + alert(errorMessage); + navigate(RouterPath.CALL_BACK_LIST); + } + }, [isCallBackError, callBackError, navigate]); - const handleComplete = () => { - // 도움 완료 - }; - - const handleCancle = () => { - // 도움 포기 - }; + const { + data: currentReq, + isLoading: iscurrentReqLoading, + isError: iscurrentReqError, + } = useGetAccepted(); + const accept = + iscurrentReqError || !currentReq + ? false + : currentReq.callbackId == Number(callBackId); return ( <> - - - - {accept ? ( - + {isCallBackLoading ? ( + ) : ( - + callbackData && ( + <> + + + + {iscurrentReqLoading ? ( + + ) : ( + + )} + + ) )} diff --git a/src/pages/sinitto/call-back/detail/api/accept-call-back.api.ts b/src/pages/sinitto/call-back/detail/api/accept-call-back.api.ts new file mode 100644 index 00000000..ed40d8c1 --- /dev/null +++ b/src/pages/sinitto/call-back/detail/api/accept-call-back.api.ts @@ -0,0 +1,9 @@ +import { fetchInstance } from '@/shared/api/instance'; + +const getacceptCallbackPath = (callbackId: number) => + `/api/callbacks/accept/${callbackId}`; + +export const acceptCallback = async (callbackId: number) => { + const response = await fetchInstance.put(getacceptCallbackPath(callbackId)); + return response.data; +}; diff --git a/src/pages/sinitto/call-back/detail/api/cancel-call-back.api.ts b/src/pages/sinitto/call-back/detail/api/cancel-call-back.api.ts new file mode 100644 index 00000000..c52e648e --- /dev/null +++ b/src/pages/sinitto/call-back/detail/api/cancel-call-back.api.ts @@ -0,0 +1,9 @@ +import { fetchInstance } from '@/shared/api/instance'; + +const getCancelCallbackPath = (callbackId: number) => + `/api/callbacks/cancel/${callbackId}`; + +export const CancelCallback = async (callbackId: number) => { + const response = await fetchInstance.put(getCancelCallbackPath(callbackId)); + return response.data; +}; diff --git a/src/pages/sinitto/call-back/detail/api/complete-call-back.api.ts b/src/pages/sinitto/call-back/detail/api/complete-call-back.api.ts new file mode 100644 index 00000000..69a4e192 --- /dev/null +++ b/src/pages/sinitto/call-back/detail/api/complete-call-back.api.ts @@ -0,0 +1,9 @@ +import { fetchInstance } from '@/shared/api/instance'; + +const getCompleteCallbackPath = (callbackId: number) => + `/api/callbacks/complete/${callbackId}`; + +export const CompleteCallback = async (callbackId: number) => { + const response = await fetchInstance.put(getCompleteCallbackPath(callbackId)); + return response.data; +}; diff --git a/src/pages/sinitto/call-back/detail/api/get-accepted.api.ts b/src/pages/sinitto/call-back/detail/api/get-accepted.api.ts new file mode 100644 index 00000000..5ceef520 --- /dev/null +++ b/src/pages/sinitto/call-back/detail/api/get-accepted.api.ts @@ -0,0 +1,9 @@ +import { fetchInstance } from '@/shared/api/instance'; +import type { CallbackResponse } from '@/shared/types'; + +const getAcceptedPath = () => `/api/callbacks/sinitto/accepted`; + +export const getAccepted = async () => { + const response = await fetchInstance.get(getAcceptedPath()); + return response.data; +}; diff --git a/src/pages/sinitto/call-back/detail/api/hooks/index.ts b/src/pages/sinitto/call-back/detail/api/hooks/index.ts new file mode 100644 index 00000000..a6ce3d05 --- /dev/null +++ b/src/pages/sinitto/call-back/detail/api/hooks/index.ts @@ -0,0 +1,4 @@ +export { useAcceptCallback } from './useAcceptCallback'; +export { useCancelCallback } from './useCancelCallback'; +export { useCompleteCallback } from './useCompleteCallback'; +export { useGetAccepted } from './useGetAccepted'; diff --git a/src/pages/sinitto/call-back/detail/api/hooks/useAcceptCallback.ts b/src/pages/sinitto/call-back/detail/api/hooks/useAcceptCallback.ts new file mode 100644 index 00000000..39b9919c --- /dev/null +++ b/src/pages/sinitto/call-back/detail/api/hooks/useAcceptCallback.ts @@ -0,0 +1,14 @@ +import { acceptCallback } from '../accept-call-back.api'; +import { useMutation } from '@tanstack/react-query'; + +export const useAcceptCallback = () => { + return useMutation({ + mutationFn: acceptCallback, + onSuccess: () => { + alert('콜백 요청이 수락되었습니다.'); + }, + onError: (error) => { + alert(`콜백 요청 수락 신청 중 오류가 발생했습니다: ${error.message}`); + }, + }); +}; diff --git a/src/pages/sinitto/call-back/detail/api/hooks/useCancelCallback.ts b/src/pages/sinitto/call-back/detail/api/hooks/useCancelCallback.ts new file mode 100644 index 00000000..f351f266 --- /dev/null +++ b/src/pages/sinitto/call-back/detail/api/hooks/useCancelCallback.ts @@ -0,0 +1,14 @@ +import { CancelCallback } from '../cancel-call-back.api'; +import { useMutation } from '@tanstack/react-query'; + +export const useCancelCallback = () => { + return useMutation({ + mutationFn: CancelCallback, + onSuccess: () => { + alert('진행중인 콜백 서비스가 취소되었습니다.'); + }, + onError: (error) => { + alert(`콜백 서비스 취소 중 오류가 발생했습니다: ${error.message}`); + }, + }); +}; diff --git a/src/pages/sinitto/call-back/detail/api/hooks/useCompleteCallback.ts b/src/pages/sinitto/call-back/detail/api/hooks/useCompleteCallback.ts new file mode 100644 index 00000000..7f0af2b8 --- /dev/null +++ b/src/pages/sinitto/call-back/detail/api/hooks/useCompleteCallback.ts @@ -0,0 +1,14 @@ +import { CompleteCallback } from '../complete-call-back.api'; +import { useMutation } from '@tanstack/react-query'; + +export const useCompleteCallback = () => { + return useMutation({ + mutationFn: CompleteCallback, + onSuccess: () => { + alert('진행중인 콜백 서비스가 완료되었습니다.'); + }, + onError: (error) => { + alert(`콜백 서비스 완료 중 오류가 발생했습니다: ${error.message}`); + }, + }); +}; diff --git a/src/pages/sinitto/call-back/detail/api/hooks/useGetAccepted.ts b/src/pages/sinitto/call-back/detail/api/hooks/useGetAccepted.ts new file mode 100644 index 00000000..e5cd7f35 --- /dev/null +++ b/src/pages/sinitto/call-back/detail/api/hooks/useGetAccepted.ts @@ -0,0 +1,10 @@ +import { getAccepted } from '../get-accepted.api'; +import { useQuery } from '@tanstack/react-query'; + +export const useGetAccepted = () => { + return useQuery({ + queryKey: ['acceptedCallback'], + queryFn: getAccepted, + staleTime: 0, + }); +}; diff --git a/src/pages/sinitto/call-back/detail/api/index.ts b/src/pages/sinitto/call-back/detail/api/index.ts new file mode 100644 index 00000000..e28364b2 --- /dev/null +++ b/src/pages/sinitto/call-back/detail/api/index.ts @@ -0,0 +1,4 @@ +export { acceptCallback } from './accept-call-back.api'; +export { CancelCallback } from './cancel-call-back.api'; +export { CompleteCallback } from './complete-call-back.api'; +export { getAccepted } from './get-accepted.api'; diff --git a/src/pages/sinitto/call-back/detail/components/guide-line-list/GuideLineList.tsx b/src/pages/sinitto/call-back/detail/components/guide-line-list/GuideLineList.tsx index 3b9bfea0..e8c31094 100644 --- a/src/pages/sinitto/call-back/detail/components/guide-line-list/GuideLineList.tsx +++ b/src/pages/sinitto/call-back/detail/components/guide-line-list/GuideLineList.tsx @@ -7,7 +7,7 @@ export const GuideLineList = () => { {GUIDE_LINE_CATEGORIES.map((data) => ( { const location = useLocation(); const handleClick = () => { - navigate(`${location.pathname}/${id}`); + if (id == null) { + alert('개발 예정입니다.'); + } else { + navigate(`${location.pathname}/${id}`); + } }; return ( diff --git a/src/pages/sinitto/call-back/detail/components/menu/CallbackMenu.tsx b/src/pages/sinitto/call-back/detail/components/menu/CallbackMenu.tsx new file mode 100644 index 00000000..6d91951d --- /dev/null +++ b/src/pages/sinitto/call-back/detail/components/menu/CallbackMenu.tsx @@ -0,0 +1,60 @@ +import { useNavigate } from 'react-router-dom'; + +import { + useAcceptCallback, + useCancelCallback, + useCompleteCallback, +} from '../../api/hooks'; +import { PostAcceptMenu } from '../../components/menu/post-accept'; +import { PreAcceptMenu } from '../../components/menu/pre-accept'; +import { Spinner } from '@chakra-ui/react'; + +type MenuProps = { + callBackId: number; + accept: boolean; +}; + +export const CallbackMenu = ({ callBackId, accept }: MenuProps) => { + const navigate = useNavigate(); + + const { + mutate: acceptCallback, + isPending: isAcceptLoading, + isSuccess: isAcceptSuccess, + } = useAcceptCallback(); + if (isAcceptSuccess) { + window.location.reload(); + } + + const { + mutate: completeCallback, + isPending: isCompleteLoading, + isSuccess: isCompleteSuccess, + } = useCompleteCallback(); + if (isCompleteSuccess) { + navigate('/call-back'); // TODO: 완료 이후 이동 페이지 지정 필요 + } + + const { + mutate: cancelCallback, + isPending: isCancelLoading, + isSuccess: isCancelSuccess, + } = useCancelCallback(); + if (isCancelSuccess) { + navigate('/call-back'); // TODO: 취소 이후 이동 페이지 지정 필요 + } + + const isLoading = isAcceptLoading || isCancelLoading || isCompleteLoading; + + return isLoading ? ( + + ) : accept ? ( + completeCallback(callBackId)} + handleCancle={() => cancelCallback(callBackId)} + phoneNumber='010-1234-5678' // TODO: api로 콜백 조회 시 response에 전화번호 추가 필요 + /> + ) : ( + acceptCallback(callBackId)} /> + ); +}; diff --git a/src/pages/sinitto/call-back/detail/components/menu/index.ts b/src/pages/sinitto/call-back/detail/components/menu/index.ts index d3f62dfd..84f6c869 100644 --- a/src/pages/sinitto/call-back/detail/components/menu/index.ts +++ b/src/pages/sinitto/call-back/detail/components/menu/index.ts @@ -1,2 +1 @@ -export * from './post-accept'; -export * from './pre-accept'; +export { CallbackMenu } from './CallbackMenu'; diff --git a/src/pages/sinitto/call-back/detail/data/guide-line/guid-line-categories.ts b/src/pages/sinitto/call-back/detail/data/guide-line/guid-line-categories.ts index 9a1bb3e8..2222a1d4 100644 --- a/src/pages/sinitto/call-back/detail/data/guide-line/guid-line-categories.ts +++ b/src/pages/sinitto/call-back/detail/data/guide-line/guid-line-categories.ts @@ -1,22 +1,22 @@ export const GUIDE_LINE_CATEGORIES = [ { title: '택시 호출하기', - id: 'taxi', + id: 'TAXI', backgroundColor: '#81b6ff', }, { - title: '드라마 방영시간 알려주기', - id: 'drama', + title: '음식 배달 주문하기', + id: 'DELIVERY', backgroundColor: '#b28bff', }, { title: '서류 제출 도와주기', - id: 'document', + id: null, backgroundColor: '#ffa7b5', }, { title: '대중교통 이동 도와주기', - id: 'document', + id: null, backgroundColor: '#ff4d68', }, ]; diff --git a/src/pages/sinitto/call-back/list/CallBackListPage.tsx b/src/pages/sinitto/call-back/list/CallBackListPage.tsx index 5f575055..d4977638 100644 --- a/src/pages/sinitto/call-back/list/CallBackListPage.tsx +++ b/src/pages/sinitto/call-back/list/CallBackListPage.tsx @@ -1,23 +1,59 @@ +import { useRef, useCallback } from 'react'; import { Outlet } from 'react-router-dom'; +import { useGetCallbacks } from './api/hooks'; import { RequestRow } from './components'; -import { CALLBACK_MOCK_DATA } from './data'; +import { Spinner } from '@chakra-ui/react'; import styled from '@emotion/styled'; export const CallBackListPage = () => { - // TODO: 콜백 요청 리스트 불러오기 + const { data, isLoading, isError, fetchNextPage, hasNextPage } = + useGetCallbacks(10); + const observerRef = useRef(null); + + const lastElementRef = useCallback( + (node: HTMLButtonElement | null) => { + if (isLoading) return ; + + if (observerRef.current) observerRef.current.disconnect(); + + observerRef.current = new IntersectionObserver((entries) => { + if (entries[0].isIntersecting && hasNextPage) { + fetchNextPage(); + } + }); + + if (node) observerRef.current.observe(node); + }, + [isLoading, fetchNextPage, hasNextPage] + ); return ( <> - {CALLBACK_MOCK_DATA.map((data) => ( - - ))} + {isLoading && } + {isError &&

데이터를 불러오는데 오류가 발생했습니다

} + {data && + (data.pages.length === 0 ? ( +

콜백 요청이 없습니다.

+ ) : ( + data?.pages.map((page, pageIndex) => + page.content.map((callback, index) => { + const isLastElement = + pageIndex === data.pages.length - 1 && + index === page.content.length - 1; + return ( + + ); + }) + ) + ))}
diff --git a/src/pages/sinitto/call-back/list/api/callback-list.api.ts b/src/pages/sinitto/call-back/list/api/callback-list.api.ts new file mode 100644 index 00000000..c904b9ac --- /dev/null +++ b/src/pages/sinitto/call-back/list/api/callback-list.api.ts @@ -0,0 +1,25 @@ +import { CallbacksResponse } from './types'; +import { fetchInstance } from '@/shared/api/instance'; + +const getCallbackListPath = '/api/callbacks'; + +export const CallbackListQueryKey = (page: number, size: number) => [ + getCallbackListPath, + page, + size, +]; + +export const getCallbackList = async ( + page: number, + size: number +): Promise => { + const response = await fetchInstance.get(getCallbackListPath, { + params: { + pageable: { + page, + size, + }, + }, + }); + return response.data; +}; diff --git a/src/pages/sinitto/call-back/list/api/get-call-backs.api.ts b/src/pages/sinitto/call-back/list/api/get-call-backs.api.ts new file mode 100644 index 00000000..3bd83f9b --- /dev/null +++ b/src/pages/sinitto/call-back/list/api/get-call-backs.api.ts @@ -0,0 +1,17 @@ +import type { CallbacksResponse } from './types'; +import { fetchInstance } from '@/shared/api/instance'; + +const getCallbacksPath = () => `/api/callbacks`; + +export const getCallbacks = async (page: number, size: number) => { + const response = await fetchInstance.get( + getCallbacksPath(), + { + params: { + page, + size, + }, + } + ); + return response.data; +}; diff --git a/src/pages/sinitto/call-back/list/api/hooks/index.ts b/src/pages/sinitto/call-back/list/api/hooks/index.ts new file mode 100644 index 00000000..06d07882 --- /dev/null +++ b/src/pages/sinitto/call-back/list/api/hooks/index.ts @@ -0,0 +1 @@ +export { useGetCallbacks } from './useGetCallbacks.ts'; diff --git a/src/pages/sinitto/call-back/list/api/hooks/useGetCallbacks.ts b/src/pages/sinitto/call-back/list/api/hooks/useGetCallbacks.ts new file mode 100644 index 00000000..8bcc96aa --- /dev/null +++ b/src/pages/sinitto/call-back/list/api/hooks/useGetCallbacks.ts @@ -0,0 +1,16 @@ +import { getCallbacks } from '../get-call-backs.api'; +import { useInfiniteQuery } from '@tanstack/react-query'; + +export const useGetCallbacks = (size: number) => { + return useInfiniteQuery({ + queryKey: ['callbacks', size], + queryFn: ({ pageParam = 0 }) => getCallbacks(pageParam, size), + getNextPageParam: (lastPage) => { + if (!lastPage.last) { + return lastPage.number + 1; + } + return undefined; + }, + initialPageParam: 0, + }); +}; diff --git a/src/pages/sinitto/call-back/list/api/index.ts b/src/pages/sinitto/call-back/list/api/index.ts new file mode 100644 index 00000000..a2626325 --- /dev/null +++ b/src/pages/sinitto/call-back/list/api/index.ts @@ -0,0 +1 @@ +export { getCallbacks } from './get-call-backs.api'; diff --git a/src/pages/sinitto/call-back/list/api/types/callbacks.response.ts b/src/pages/sinitto/call-back/list/api/types/callbacks.response.ts new file mode 100644 index 00000000..020b7af0 --- /dev/null +++ b/src/pages/sinitto/call-back/list/api/types/callbacks.response.ts @@ -0,0 +1,13 @@ +import { CallbackResponse } from '@/shared/types'; + +export type CallbacksResponse = { + totalElements: number; + totalPages: number; + first: boolean; + last: boolean; + size: number; + content: Array; + number: number; + numberOfElements: number; + empty: boolean; +}; diff --git a/src/pages/sinitto/call-back/list/api/types/index.ts b/src/pages/sinitto/call-back/list/api/types/index.ts new file mode 100644 index 00000000..77c2c660 --- /dev/null +++ b/src/pages/sinitto/call-back/list/api/types/index.ts @@ -0,0 +1 @@ +export type { CallbacksResponse } from './callbacks.response'; diff --git a/src/pages/sinitto/call-back/list/components/request-row/RequestRow.tsx b/src/pages/sinitto/call-back/list/components/request-row/RequestRow.tsx index f400a4f7..10b1c1aa 100644 --- a/src/pages/sinitto/call-back/list/components/request-row/RequestRow.tsx +++ b/src/pages/sinitto/call-back/list/components/request-row/RequestRow.tsx @@ -1,31 +1,54 @@ +import { forwardRef } from 'react'; import { useNavigate } from 'react-router-dom'; import ArrowImg from '../../assets/arrow.png'; +import { RouterPath } from '@/app/routes/path'; import styled from '@emotion/styled'; type Props = { name: string; - time: number; + time: string; id: string; }; -export const RequestRow = ({ name, time, id }: Props) => { - const navigate = useNavigate(); - - const handleClick = () => { - navigate(`/call-back/${id}`); - }; - - return ( - - - {name}님의 요청 - - - - - ); -}; +export const RequestRow = forwardRef( + ({ name, time, id }, ref) => { + const navigate = useNavigate(); + + const handleClick = () => { + navigate(`${RouterPath.CALL_BACK_LIST}/${id}`); + }; + + const getTimeAgo = (postTime: string) => { + const postDate = new Date(postTime); + const now = new Date(); + const differenceInMinutes = Math.floor( + (now.getTime() - postDate.getTime()) / 60000 + ); + + if (differenceInMinutes < 60) { + return differenceInMinutes > 0 + ? differenceInMinutes + '분 전' + : '방금 전'; + } else { + const differenceInHours = Math.floor(differenceInMinutes / 60); + return differenceInHours + '시간 전'; + } + }; + + return ( + + + {name}님의 요청 + + + + + ); + } +); + +RequestRow.displayName = 'RequestRow'; const Wrapper = styled.button` width: 100%; diff --git a/src/pages/sinitto/guide-line/SinittoGuideLinePage.tsx b/src/pages/sinitto/guide-line/SinittoGuideLinePage.tsx index 13603aad..5dfa173b 100644 --- a/src/pages/sinitto/guide-line/SinittoGuideLinePage.tsx +++ b/src/pages/sinitto/guide-line/SinittoGuideLinePage.tsx @@ -1,8 +1,14 @@ -import { useParams } from 'react-router-dom'; +import { useEffect } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; -import { CATEGORIES, GUIDE_LINE_MOCK_DATA } from './data'; -import { Category, MockData } from './types'; -import { Container } from '@chakra-ui/react'; +import { useGetGuideline } from './api/hooks'; +import { GuidelineResponse } from './api/types'; +import { CATEGORIES } from './data'; +import { Category } from './types'; +import { RouterPath } from '@/app/routes/path'; +import { useGetCallback } from '@/shared/api/hooks'; +import { handleCallbackError } from '@/shared/utils'; +import { Container, Spinner } from '@chakra-ui/react'; import styled from '@emotion/styled'; type GuideLineParams = { @@ -12,17 +18,59 @@ type GuideLineParams = { export const SinittoGuideLinePage = () => { const { callBackId = '', guideLineId = '' } = useParams(); - console.log(callBackId, guideLineId); - + const navigate = useNavigate(); const guideLineInfo = CATEGORIES.find((item: Category) => item.id === guideLineId)?.name || null; + const { + data: callBack, + isLoading: isCallBackLoading, + isError: isCallBackError, + error: callBackError, + } = useGetCallback(callBackId); + const seniorId = + !isCallBackLoading && callBack ? callBack.seniorId : undefined; + + const { + data: guideLine, + isLoading: isGuideLineLoading, + isError: isGuideLineError, + } = useGetGuideline(Number(seniorId), guideLineId); + + useEffect(() => { + if (isCallBackError) { + const errorMessage = handleCallbackError(callBackError); + alert(errorMessage); + navigate(RouterPath.CALL_BACK_LIST); + } + }, [isCallBackError, callBackError, navigate]); + return ( - {guideLineInfo} - {GUIDE_LINE_MOCK_DATA.map((data: MockData, index: number) => ( - - ))} + {isCallBackLoading || isGuideLineLoading ? ( + + ) : ( + <> + + <EmphasisSpan>{guideLineInfo}</EmphasisSpan> 가이드라인 + + {isGuideLineError && ( +

데이터를 불러오는 중에 오류가 발생했습니다.

+ )} + {guideLine && + (guideLine.length == 0 ? ( +

등록된 가이드라인이 없습니다.

+ ) : ( + guideLine.map((data: GuidelineResponse, index: number) => ( + + )) + ))} + + )}
); }; @@ -41,5 +89,8 @@ const Title = styled.h2` margin-bottom: 20px; font-size: var(--font-size-xxl); font-weight: 700; +`; + +const EmphasisSpan = styled.span` color: #c69090; `; diff --git a/src/pages/sinitto/guide-line/api/get-guideline.api.ts b/src/pages/sinitto/guide-line/api/get-guideline.api.ts new file mode 100644 index 00000000..4bc12141 --- /dev/null +++ b/src/pages/sinitto/guide-line/api/get-guideline.api.ts @@ -0,0 +1,12 @@ +import type { GuidelineResponse } from './types'; +import { fetchInstance } from '@/shared/api/instance'; + +const getGuidelinesPath = (seniorId: number, type: string) => + `/api/guardguidelines/${seniorId}/${type}`; + +export const getGuidelines = async (seniorId: number, type: string) => { + const response = await fetchInstance.get( + getGuidelinesPath(seniorId, type) + ); + return response.data; +}; diff --git a/src/pages/sinitto/guide-line/api/hooks/index.ts b/src/pages/sinitto/guide-line/api/hooks/index.ts new file mode 100644 index 00000000..ad81d6a8 --- /dev/null +++ b/src/pages/sinitto/guide-line/api/hooks/index.ts @@ -0,0 +1 @@ +export { useGetGuideline } from './useGetGuideline'; diff --git a/src/pages/sinitto/guide-line/api/hooks/useGetGuideline.ts b/src/pages/sinitto/guide-line/api/hooks/useGetGuideline.ts new file mode 100644 index 00000000..57ffd458 --- /dev/null +++ b/src/pages/sinitto/guide-line/api/hooks/useGetGuideline.ts @@ -0,0 +1,10 @@ +import { getGuidelines } from '../get-guideline.api'; +import { useQuery } from '@tanstack/react-query'; + +export const useGetGuideline = (seniorId: number, type: string) => { + return useQuery({ + queryKey: ['Guideline', seniorId, type], + queryFn: () => getGuidelines(seniorId, type), + enabled: !!seniorId && !!type, + }); +}; diff --git a/src/pages/sinitto/guide-line/api/index.ts b/src/pages/sinitto/guide-line/api/index.ts new file mode 100644 index 00000000..f68afdec --- /dev/null +++ b/src/pages/sinitto/guide-line/api/index.ts @@ -0,0 +1 @@ +export { getGuidelines } from './get-guideline.api'; diff --git a/src/pages/sinitto/guide-line/api/types/guideline.response.ts b/src/pages/sinitto/guide-line/api/types/guideline.response.ts new file mode 100644 index 00000000..d1c38418 --- /dev/null +++ b/src/pages/sinitto/guide-line/api/types/guideline.response.ts @@ -0,0 +1,5 @@ +export type GuidelineResponse = { + type: string; + title: string; + content: string; +}; diff --git a/src/pages/sinitto/guide-line/api/types/index.ts b/src/pages/sinitto/guide-line/api/types/index.ts new file mode 100644 index 00000000..766d25ea --- /dev/null +++ b/src/pages/sinitto/guide-line/api/types/index.ts @@ -0,0 +1 @@ +export type { GuidelineResponse } from './guideline.response'; diff --git a/src/pages/sinitto/guide-line/data/categories/categories.ts b/src/pages/sinitto/guide-line/data/categories/categories.ts index 9c7780a3..beddb30a 100644 --- a/src/pages/sinitto/guide-line/data/categories/categories.ts +++ b/src/pages/sinitto/guide-line/data/categories/categories.ts @@ -1,18 +1,10 @@ export const CATEGORIES = [ { name: '택시', - id: 'taxi', + id: 'TAXI', }, { - name: '드라마 방영시간', - id: 'drama', - }, - { - name: '서류 제출', - id: 'document', - }, - { - name: '대중교통 이동', - id: 'document', + name: '음식 배달 주문', + id: 'DELIVERY', }, ]; diff --git a/src/shared/api/get-call-back.api.ts b/src/shared/api/get-call-back.api.ts new file mode 100644 index 00000000..c2962ad5 --- /dev/null +++ b/src/shared/api/get-call-back.api.ts @@ -0,0 +1,11 @@ +import type { CallbackResponse } from '../types'; +import { fetchInstance } from '@/shared/api/instance'; + +const getCallbackPath = (callbackId: string) => `/api/callbacks/${callbackId}`; + +export const getCallback = async (callbackId: string) => { + const response = await fetchInstance.get( + getCallbackPath(callbackId) + ); + return response.data; +}; diff --git a/src/shared/api/hooks/index.ts b/src/shared/api/hooks/index.ts new file mode 100644 index 00000000..976d77a4 --- /dev/null +++ b/src/shared/api/hooks/index.ts @@ -0,0 +1 @@ +export { useGetCallback } from './useGetCallback'; diff --git a/src/shared/api/hooks/useGetCallback.ts b/src/shared/api/hooks/useGetCallback.ts new file mode 100644 index 00000000..03c373a8 --- /dev/null +++ b/src/shared/api/hooks/useGetCallback.ts @@ -0,0 +1,10 @@ +import { getCallback } from '../get-call-back.api'; +import { useQuery } from '@tanstack/react-query'; + +export const useGetCallback = (callbackId: string) => { + return useQuery({ + queryKey: ['callback', callbackId], + queryFn: () => getCallback(callbackId), + enabled: !!callbackId, + }); +}; diff --git a/src/shared/api/index.ts b/src/shared/api/index.ts new file mode 100644 index 00000000..5ac75c09 --- /dev/null +++ b/src/shared/api/index.ts @@ -0,0 +1 @@ +export { getCallback } from './get-call-back.api'; diff --git a/src/shared/types/callback.response.ts b/src/shared/types/callback.response.ts new file mode 100644 index 00000000..715b3568 --- /dev/null +++ b/src/shared/types/callback.response.ts @@ -0,0 +1,7 @@ +export type CallbackResponse = { + callbackId: number; + seniorName: string; + postTime: string; + status: string; + seniorId: number; +}; diff --git a/src/shared/types/index.ts b/src/shared/types/index.ts new file mode 100644 index 00000000..91cf9d0c --- /dev/null +++ b/src/shared/types/index.ts @@ -0,0 +1 @@ +export type { CallbackResponse } from './callback.response'; diff --git a/src/shared/utils/handle-callback-error.ts b/src/shared/utils/handle-callback-error.ts new file mode 100644 index 00000000..aecebd26 --- /dev/null +++ b/src/shared/utils/handle-callback-error.ts @@ -0,0 +1,13 @@ +import { AxiosError } from 'axios'; + +export const handleCallbackError = (error: unknown): string => { + if (error instanceof AxiosError) { + switch (error.response?.status) { + case 409: + return '이미 진행 중인 콜백 요청이 있습니다.'; + default: + return '데이터를 불러오는 중 오류가 발생했습니다.'; + } + } + return '데이터를 불러오는 중 오류가 발생했습니다.'; +}; diff --git a/src/shared/utils/index.ts b/src/shared/utils/index.ts new file mode 100644 index 00000000..d2cfe48f --- /dev/null +++ b/src/shared/utils/index.ts @@ -0,0 +1 @@ +export { handleCallbackError } from './handle-callback-error';