diff --git a/frontend/src/apis/user.ts b/frontend/src/apis/user.ts index f29479b76..b265b2ba2 100644 --- a/frontend/src/apis/user.ts +++ b/frontend/src/apis/user.ts @@ -35,17 +35,17 @@ export const deleteToken = async () => { }; export const postReissueAccessToken = async () => { - return await fetch(`${BASE_URL}${ENDPOINT.USER_ACCESS_TOKEN_REISSUE}`, { - method: 'POST', + return await fetcher.post({ + url: `${BASE_URL}${ENDPOINT.USER_ACCESS_TOKEN_REISSUE}`, credentials: 'include', - headers: { 'Content-Type': 'application/json' }, + // 쿠키전달이기때문에 body가 비어있는 post }); }; export const postSignUp = async ({ name, email, password }: { name: string; email: string; password: string }) => { - return await fetch(`${BASE_URL}${ENDPOINT.REGISTER}`, { - method: 'POST', - body: JSON.stringify({ name, email, password }), + return await fetcher.post({ + url: `${BASE_URL}${ENDPOINT.REGISTER}`, + body: { name, email, password }, credentials: 'include', }); }; diff --git a/frontend/src/components/EditChecklist/ChecklistContent/EditChecklistContent.tsx b/frontend/src/components/EditChecklist/ChecklistContent/EditChecklistContent.tsx index bb3398ea8..e6df86f1f 100644 --- a/frontend/src/components/EditChecklist/ChecklistContent/EditChecklistContent.tsx +++ b/frontend/src/components/EditChecklist/ChecklistContent/EditChecklistContent.tsx @@ -9,10 +9,12 @@ import RoomInfoTemplate from '@/components/NewChecklist/NewRoomInfoForm/RoomInfo import OptionTemplate from '@/components/NewChecklist/Option/OptionTemplate'; const EditChecklistContent = () => { - const { currentTabId } = useTabContext(); + const { currentTabId, useDragForTab } = useTabContext(); + + const ref = useDragForTab(); return ( - + {/*방 기본정보 템플릿 */} {currentTabId === -1 && } {/* 옵션 선택 템플릿 */} diff --git a/frontend/src/components/EditChecklist/ChecklistContent/EditChecklistQuestionTemplate.tsx b/frontend/src/components/EditChecklist/ChecklistContent/EditChecklistQuestionTemplate.tsx index 15b691735..2e147161f 100644 --- a/frontend/src/components/EditChecklist/ChecklistContent/EditChecklistQuestionTemplate.tsx +++ b/frontend/src/components/EditChecklist/ChecklistContent/EditChecklistQuestionTemplate.tsx @@ -4,6 +4,7 @@ import Divider from '@/components/_common/Divider/Divider'; import Layout from '@/components/_common/layout/Layout'; import { useTabContext } from '@/components/_common/Tabs/TabContext'; import ChecklistQuestionItem from '@/components/NewChecklist/ChecklistQuestion/ChecklistQuestion'; +import MoveNextButton from '@/components/NewChecklist/MoveNextButton'; import useChecklistStore from '@/store/useChecklistStore'; import { flexColumn } from '@/styles/common'; import theme from '@/styles/theme'; @@ -37,6 +38,8 @@ const EditChecklistQuestionTemplate = () => { ); })} + + ); }; diff --git a/frontend/src/components/NewChecklist/ChecklistContent.tsx b/frontend/src/components/NewChecklist/ChecklistContent.tsx index db96a1b2f..c82b5202d 100644 --- a/frontend/src/components/NewChecklist/ChecklistContent.tsx +++ b/frontend/src/components/NewChecklist/ChecklistContent.tsx @@ -9,7 +9,8 @@ import RoomInfoTemplate from '@/components/NewChecklist/NewRoomInfoForm/RoomInfo import OptionTemplate from '@/components/NewChecklist/Option/OptionTemplate'; const ChecklistContent = () => { - const { currentTabId } = useTabContext(); + const { currentTabId, useDragForTab } = useTabContext(); + useDragForTab(); return ( diff --git a/frontend/src/components/NewChecklist/ChecklistTab/NewChecklistTab.tsx b/frontend/src/components/NewChecklist/ChecklistTab/NewChecklistTab.tsx index 1526b1067..06caa21fb 100644 --- a/frontend/src/components/NewChecklist/ChecklistTab/NewChecklistTab.tsx +++ b/frontend/src/components/NewChecklist/ChecklistTab/NewChecklistTab.tsx @@ -1,11 +1,8 @@ import { useMemo } from 'react'; import ChecklistTabSuspense from '@/components/_common/errorBoundary/ChecklistTabSuspense'; -import { useTabContext } from '@/components/_common/Tabs/TabContext'; import Tabs from '@/components/_common/Tabs/Tabs'; -import { DefaultChecklistTabsNames } from '@/constants/tabs'; import useInitialChecklist from '@/hooks/useInitialChecklist'; -import useMouseDrag from '@/hooks/useMouseDrag'; import useTabs from '@/hooks/useTabs'; import useChecklistStore from '@/store/useChecklistStore'; import isSameCategory from '@/utils/isSameCategory'; @@ -14,20 +11,6 @@ const NewChecklistTab = () => { const { data: checklist, isSuccess, isLoading } = useInitialChecklist(); const checklistStore = useChecklistStore(state => state.checklistCategoryQnA); const { getTabsForChecklist } = useTabs(); - const { setCurrentTabId } = useTabContext(); - - useMouseDrag((S, E) => { - const DRAG_THRESHOLD = 100; - const TAB_COUNT = DefaultChecklistTabsNames.length; - const remainOp = (a: number, b: number) => (((a % b) + b + 1) % b) - 1; // 나머지연산자. -1부터 시작하므로 +1 -1 - setCurrentTabId(tabId => { - const isLeftDrag = E.x - S.x > DRAG_THRESHOLD; - const isRightDrag = S.x - E.x > DRAG_THRESHOLD; - if (isLeftDrag) return remainOp(tabId - 1, TAB_COUNT); - if (isRightDrag) return remainOp(tabId + 1, TAB_COUNT); - return tabId; - }); - }); const categoryTabs = useMemo(() => { if (isSuccess && isSameCategory(checklist, checklistStore)) { diff --git a/frontend/src/components/NewChecklist/NewRoomInfoForm/DepositAndRent.tsx b/frontend/src/components/NewChecklist/NewRoomInfoForm/DepositAndRent.tsx index e8c35b057..f5f92c6b2 100644 --- a/frontend/src/components/NewChecklist/NewRoomInfoForm/DepositAndRent.tsx +++ b/frontend/src/components/NewChecklist/NewRoomInfoForm/DepositAndRent.tsx @@ -13,6 +13,7 @@ const DepositAndRent = () => { { /> { { { { onSelectSetter={handleClickDropdown} /> { { onSuccess: () => setIsComplete(true), onError: error => setPostErrorMessage(error.message), }); - const handleClickNext = () => { - onNext(email); - }; + const handleClickNext = () => onNext(email); const canMove = isEmailValid && isComplete; @@ -74,7 +72,7 @@ const SendVerificationEmailStep = ({ onNext }: Props) => { style={{ width: '25rem' }} />
- + 전송
diff --git a/frontend/src/components/_common/Tabs/TabContext.tsx b/frontend/src/components/_common/Tabs/TabContext.tsx index 7e2a82b2c..3e99ebf02 100644 --- a/frontend/src/components/_common/Tabs/TabContext.tsx +++ b/frontend/src/components/_common/Tabs/TabContext.tsx @@ -1,28 +1,46 @@ -import { createContext, ReactNode, useContext, useState } from 'react'; +import { createContext, ReactNode, RefObject, useContext, useRef, useState } from 'react'; import { ERROR_MESSAGE } from '@/constants/messages/errorMessage'; +import { DefaultChecklistTabsNames, DRAG_THRESHOLD_PIXEL } from '@/constants/tabs'; +import useMouseDrag from '@/hooks/useMouseDrag'; interface ContextProps { currentTabId: number; setCurrentTabId: React.Dispatch>; + useDragForTab: () => RefObject; } -const defaultContext: ContextProps = { - currentTabId: 0, - setCurrentTabId: () => {}, -}; - -const TabContext = createContext(defaultContext); +const TabContext = createContext(null); interface Props { children: ReactNode; defaultTab: number; } +const remainOp = (a: number, b: number) => (((a % b) + b + 1) % b) - 1; // 나머지연산자. -1부터 시작하므로 +1 -1 + export const TabProvider = ({ children, defaultTab = 0 }: Props) => { const [currentTabId, setCurrentTabId] = useState(defaultTab); - return {children}; + // 드래그로 탭이동을 위한 훅을 리턴에 제공 + const useDragForTab = (dragThreshold: number = DRAG_THRESHOLD_PIXEL) => { + const ref = useRef(null); + useMouseDrag(ref, (S, E) => { + const TAB_COUNT = DefaultChecklistTabsNames.length; + + setCurrentTabId(tabId => { + const isLeftDrag = E.x - S.x > dragThreshold; + const isRightDrag = S.x - E.x > dragThreshold; + if (isLeftDrag) return remainOp(tabId - 1, TAB_COUNT); + if (isRightDrag) return remainOp(tabId + 1, TAB_COUNT); + return tabId; + }); + }); + + return ref; + }; + + return {children}; }; export const useTabContext = () => { diff --git a/frontend/src/constants/tabs.ts b/frontend/src/constants/tabs.ts index 9a4a7eb62..d4eb34a8d 100644 --- a/frontend/src/constants/tabs.ts +++ b/frontend/src/constants/tabs.ts @@ -23,3 +23,5 @@ export const DefaultChecklistTabsNames: Tab[] = [ name: '보안', }, ]; + +export const DRAG_THRESHOLD_PIXEL = 100; diff --git a/frontend/src/hooks/useMouseDrag.ts b/frontend/src/hooks/useMouseDrag.ts index d193c2b1f..286eed77a 100644 --- a/frontend/src/hooks/useMouseDrag.ts +++ b/frontend/src/hooks/useMouseDrag.ts @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { MutableRefObject, useEffect, useState } from 'react'; interface MousePosition { x: number; @@ -6,16 +6,14 @@ interface MousePosition { } type Handler = (start: MousePosition, end: MousePosition) => void; -const useMouseDrag = (handler: Handler) => { +const useMouseDrag = (ref: MutableRefObject, handler: Handler) => { const [startPosition, setStartPosition] = useState(null); useEffect(() => { - const pointerdownListener = (e: MouseEvent) => { - setStartPosition({ x: e.clientX, y: e.clientY }); - }; - const touchStartListener = (e: TouchEvent) => { + const pointerdownListener = (e: MouseEvent) => setStartPosition({ x: e.clientX, y: e.clientY }); + + const touchStartListener = (e: TouchEvent) => setStartPosition({ x: e.changedTouches[0].clientX, y: e.changedTouches[0].clientX }); - }; const pointerupListener = (e: MouseEvent) => { const endPosition = { x: e.clientX, y: e.clientY }; @@ -30,18 +28,20 @@ const useMouseDrag = (handler: Handler) => { setStartPosition(null); }; - window.addEventListener('mousedown', pointerdownListener); - window.addEventListener('touchstart', touchStartListener); - window.addEventListener('mouseup', pointerupListener); - window.addEventListener('touchend', touchEndListener); + const el = ref.current; + + el?.addEventListener('mousedown', pointerdownListener); + el?.addEventListener('touchstart', touchStartListener); + el?.addEventListener('mouseup', pointerupListener); + el?.addEventListener('touchend', touchEndListener); return () => { - window.removeEventListener('mousedown', pointerdownListener); - window.removeEventListener('mouseup', pointerupListener); - window.removeEventListener('touchstart', touchStartListener); - window.removeEventListener('touchend', touchEndListener); + el?.removeEventListener('mousedown', pointerdownListener); + el?.removeEventListener('mouseup', pointerupListener); + el?.removeEventListener('touchstart', touchStartListener); + el?.removeEventListener('touchend', touchEndListener); }; - }, [startPosition, handler]); + }, [startPosition, ref, handler]); }; export default useMouseDrag;