diff --git a/client/cypress/e2e/createEvent.cy.ts b/client/cypress/e2e/createEvent.cy.ts index 5de7f4592..edd4ddc6d 100644 --- a/client/cypress/e2e/createEvent.cy.ts +++ b/client/cypress/e2e/createEvent.cy.ts @@ -1,4 +1,6 @@ +import {ROUTER_URLS} from '@constants/routerUrls'; import CONSTANTS from '../constants/constants'; + beforeEach(() => { cy.blockSentry(); cy.blockKakao(); @@ -8,18 +10,17 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl it('랜딩페이지에서 "행사 생성하기" 버튼을 눌러 행사 이름 입력 페이지로 이동해야 한다.', () => { cy.visit('/'); cy.get('header').find('button').click(); - cy.url().should('include', '/event/create/name'); + cy.url().should('include', ROUTER_URLS.createEvent); }); context('행사 이름 입력 페이지', () => { beforeEach(() => { - cy.visit('/event/create/name'); + cy.visit(ROUTER_URLS.createEvent); }); it('행사 이름 입력 페이지에서 input이 포커싱 되어 있고, "다음" 버튼이 비활성화 되어 있어야 한다.', () => { cy.get('input').focused(); cy.get('button').contains('다음').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/name'); }); it('행사 이름이 1자 이상 입력된 경우 "다음" 버튼이 활성화 되고, 값이 없는 경우 "다음" 버튼이 비활성화 되어야 한다.', () => { @@ -28,13 +29,14 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.get('input').clear(); cy.get('input').should('have.value', ''); cy.get('button').contains('다음').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/name'); }); it('행사 이름을 입력한 후 "다음" 버튼을 누르면 행사 비밀번호 설정 화면으로 이동해야 한다.', () => { cy.get('input').type(CONSTANTS.eventName); cy.get('button').contains('다음').click(); - cy.url().should('include', '/event/create/password'); + + // 다음 버튼을 클릭하면 /create/event 경로가 아니라 /create/event/?로 가네요.. 그래서 일단 제거함. + cy.contains('비밀번호').should('exist'); }); }); @@ -46,7 +48,6 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl it('행사 비밀번호 입력 페이지에서 input이 포커싱 되어 있고, "행동 개시!" 버튼이 비활성화 되어 있어야 한다.', () => { cy.get('input').focused(); cy.get('button').contains('행동 개시!').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/password'); }); it('행사 비밀번호에 숫자가 아닌 입력을 할 경우 값이 입력되지 않아야 한다.', () => { @@ -65,7 +66,6 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.get('input').clear(); cy.get('input').should('have.value', ''); cy.get('button').contains('행동 개시!').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/password'); }); it('행사 비밀번호을 입력한 후 "행동 개시!" 버튼을 누르면 행사 생성 완료 화면으로 이동해야 한다.', () => { @@ -73,8 +73,6 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.interceptAPI({type: 'getEventName', statusCode: 200}); cy.get('input').type(CONSTANTS.eventPassword); cy.get('button').contains('행동 개시!').click(); - - cy.url().should('include', '/event/create/complete'); }); }); }); diff --git a/client/cypress/support/commands.ts b/client/cypress/support/commands.ts index 70c8524ea..6ef75b4dc 100644 --- a/client/cypress/support/commands.ts +++ b/client/cypress/support/commands.ts @@ -1,3 +1,4 @@ +import {ROUTER_URLS} from '@constants/routerUrls'; import CONSTANTS from '../constants/constants'; type APIType = 'sentry' | 'postEvent' | 'getEventName'; @@ -46,10 +47,9 @@ Cypress.Commands.add('interceptAPI', ({type, delay = 0, statusCode = 200}: Inter }); Cypress.Commands.add('createEventName', (eventName: string) => { - cy.visit('/event/create/name'); + cy.visit(ROUTER_URLS.createEvent); cy.get('input').type(eventName); cy.get('button').contains('다음').click(); - cy.url().should('include', '/event/create/password'); }); declare global { diff --git a/client/src/components/Design/components/TopNav/Back.tsx b/client/src/components/Design/components/TopNav/Back.tsx index 73065ebce..5bbd83618 100644 --- a/client/src/components/Design/components/TopNav/Back.tsx +++ b/client/src/components/Design/components/TopNav/Back.tsx @@ -1,14 +1,17 @@ /** @jsxImportSource @emotion/react */ -import React from 'react'; import {useNavigate} from 'react-router-dom'; import TextButton from '@HDcomponents/TextButton/TextButton'; -function Back() { +type BackProps = { + onClick?: () => void; +}; + +function Back({onClick}: BackProps) { const navigate = useNavigate(); return ( - navigate(-1)} textSize="bodyBold" textColor="gray"> + (onClick ? onClick() : navigate(-1))} textSize="bodyBold" textColor="gray"> 뒤로가기 ); diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index 8cd486d9b..de3cc5946 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -1,9 +1,7 @@ export const ROUTER_URLS = { main: '/', - eventCreateName: '/event/create/name', - eventCreatePassword: '/event/create/password', - eventCreateComplete: '/event/create/complete', - event: '/event', // TODO: (@weadie) baseurl을 어떻게 관리할 것인가? + createEvent: '/event/create', + event: '/event', eventLogin: '/event/:eventId/login', eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', diff --git a/client/src/hooks/queries/event/useRequestPostEvent.ts b/client/src/hooks/queries/event/useRequestPostEvent.ts index ec4c6f2b0..d59f6b913 100644 --- a/client/src/hooks/queries/event/useRequestPostEvent.ts +++ b/client/src/hooks/queries/event/useRequestPostEvent.ts @@ -3,12 +3,13 @@ import {useMutation} from '@tanstack/react-query'; import {RequestPostEvent, requestPostEvent} from '@apis/request/event'; const useRequestPostEvent = () => { - const {mutate, ...rest} = useMutation({ + const {mutate, mutateAsync, ...rest} = useMutation({ mutationFn: ({eventName, password}: RequestPostEvent) => requestPostEvent({eventName, password}), }); + // 실행 순서를 await으로 보장하기 위해 mutateAsync 사용 return { - postEvent: mutate, + postEvent: mutateAsync, isPostEventPending: rest.isPending, ...rest, }; diff --git a/client/src/hooks/useCreateEventData.tsx b/client/src/hooks/useCreateEventData.tsx new file mode 100644 index 000000000..fed21d8ae --- /dev/null +++ b/client/src/hooks/useCreateEventData.tsx @@ -0,0 +1,17 @@ +import {useState} from 'react'; + +import useSetEventNameStep from './useSetEventNameStep'; + +// 행사 생성 페이지에서 여러 스텝에 걸쳐 사용되는 상태를 선언해 내려주는 용도의 훅입니다. +const useCreateEventData = () => { + const eventNameProps = useSetEventNameStep(); + const [eventToken, setEventToken] = useState(''); + + return { + eventNameProps, + eventToken, + setEventToken, + }; +}; + +export default useCreateEventData; diff --git a/client/src/hooks/useFunnel.tsx b/client/src/hooks/useFunnel.tsx new file mode 100644 index 000000000..196bb37b4 --- /dev/null +++ b/client/src/hooks/useFunnel.tsx @@ -0,0 +1,58 @@ +import {useState} from 'react'; + +type UseFunnel = { + defaultStep: string; + stepList: string[]; +}; + +type StepProps = { + children: React.ReactNode; + name: string; +}; + +type FunnelProps = { + children: React.ReactElement[]; +}; + +const useFunnel = ({defaultStep, stepList}: UseFunnel) => { + const [step, setStep] = useState(defaultStep); + + const moveToNextStep = () => { + const curStepIndex = stepList.indexOf(step); + + if (curStepIndex === stepList.length - 1) return; + + setStep(stepList[curStepIndex + 1]); + }; + + const moveToPrevStep = () => { + const curStepIndex = stepList.indexOf(step); + + if (curStepIndex === 0) return; + + setStep(stepList[curStepIndex - 1]); + }; + + const Step = (stepProps: StepProps) => { + return <>{stepProps.children}; + }; + + const Funnel = ({children}: FunnelProps) => { + const targetStep = children.find(curStep => curStep.props.name === step); + + if (!targetStep) + throw new Error(`현재 ${step} 단계에 보여줄 컴포넌트가 존재하지 않습니다. Step 컴포넌트를 호출해 사용해주세요.`); + + return <>{targetStep}; + }; + + return { + Step, + step, + Funnel, + moveToNextStep, + moveToPrevStep, + }; +}; + +export default useFunnel; diff --git a/client/src/hooks/useSetEventNamePage.ts b/client/src/hooks/useSetEventNameStep.ts similarity index 82% rename from client/src/hooks/useSetEventNamePage.ts rename to client/src/hooks/useSetEventNameStep.ts index f5b5bce12..cd2a35302 100644 --- a/client/src/hooks/useSetEventNamePage.ts +++ b/client/src/hooks/useSetEventNameStep.ts @@ -2,7 +2,9 @@ import {useState} from 'react'; import validateEventName from '@utils/validate/validateEventName'; -const useSetEventNamePage = () => { +export type UseSetEventNameStepReturnType = ReturnType; + +const useSetEventNameStep = () => { const [eventName, setEventName] = useState(''); const [errorMessage, setErrorMessage] = useState(null); const [canSubmit, setCanSubmit] = useState(false); @@ -29,4 +31,4 @@ const useSetEventNamePage = () => { }; }; -export default useSetEventNamePage; +export default useSetEventNameStep; diff --git a/client/src/hooks/useSetEventPasswordPage.ts b/client/src/hooks/useSetEventPasswordPage.ts deleted file mode 100644 index ba8549258..000000000 --- a/client/src/hooks/useSetEventPasswordPage.ts +++ /dev/null @@ -1,65 +0,0 @@ -import {useEffect, useState} from 'react'; -import {useLocation, useNavigate} from 'react-router-dom'; - -import validateEventPassword from '@utils/validate/validateEventPassword'; - -import {ROUTER_URLS} from '@constants/routerUrls'; -import RULE from '@constants/rule'; - -import useRequestPostEvent from './queries/event/useRequestPostEvent'; - -const useSetEventPasswordPage = () => { - const [eventName, setEventName] = useState(''); - const [password, setPassword] = useState(''); - const [errorMessage, setErrorMessage] = useState(''); - const [canSubmit, setCanSubmit] = useState(false); - const navigate = useNavigate(); - const location = useLocation(); - const {postEvent, isPostEventPending} = useRequestPostEvent(); - - useEffect(() => { - if (!location.state) { - navigate(ROUTER_URLS.main); - } else { - setEventName(location.state.eventName); - } - }, []); - - const submitPassword = async (event: React.FormEvent) => { - event.preventDefault(); - - onSuccess(); - }; - - const onSuccess = () => { - postEvent( - {eventName, password: String(password).padStart(4, '0')}, - { - onSuccess: data => { - navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId: data.eventId})}`, { - replace: true, - }); - }, - }, - ); - }; - - const handleChange = (event: React.ChangeEvent) => { - const newValue = event.target.value; - const validation = validateEventPassword(newValue); - - setCanSubmit(newValue.length === RULE.maxEventPasswordLength); - - if (validation.isValid) { - setPassword(newValue); - setErrorMessage(''); - } else { - event.target.value = password; - setErrorMessage(validation.errorMessage ?? ''); - } - }; - - return {submitPassword, errorMessage, password, handleChange, onSuccess, canSubmit, isPostEventPending}; -}; - -export default useSetEventPasswordPage; diff --git a/client/src/hooks/useSetEventPasswordStep.ts b/client/src/hooks/useSetEventPasswordStep.ts new file mode 100644 index 000000000..5705be855 --- /dev/null +++ b/client/src/hooks/useSetEventPasswordStep.ts @@ -0,0 +1,72 @@ +import {useState} from 'react'; +import {useNavigate} from 'react-router-dom'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; + +import RULE from '@constants/rule'; + +import useRequestPostEvent from './queries/event/useRequestPostEvent'; + +export type UseSetEventPasswordStepReturnType = ReturnType; + +const useSetEventPasswordStep = () => { + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + const {postEvent: requestPostEvent, isPostEventPending} = useRequestPostEvent(); + + const submitDataForPostEvent = async ({ + event, + eventName, + setEventToken, + }: { + event: React.FormEvent; + eventName: string; + setEventToken: (eventToken: string) => void; + }) => { + event.preventDefault(); + + await postEvent(eventName, setEventToken); + }; + + const getPasswordWithPad = () => { + return String(password).padStart(4, '0'); + }; + + const postEvent = async (eventName: string, updateEventToken: (eventToken: string) => void) => { + await requestPostEvent( + {eventName, password: getPasswordWithPad()}, + { + onSuccess: ({eventId}) => { + updateEventToken(eventId); + }, + }, + ); + }; + + const handleChange = (event: React.ChangeEvent) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + + if (validation.isValid) { + setPassword(newValue); + setErrorMessage(''); + } else { + event.target.value = password; + setErrorMessage(validation.errorMessage ?? ''); + } + }; + + return { + submitDataForPostEvent, + errorMessage, + handleChange, + canSubmit, + isPostEventPending, + password, + }; +}; + +export default useSetEventPasswordStep; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx similarity index 78% rename from client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx rename to client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx index 385d8c968..a2e19b5f7 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx @@ -8,12 +8,12 @@ import {FixedButton, MainLayout, Title, TopNav} from '@HDesign/index'; import {ROUTER_URLS} from '@constants/routerUrls'; -const CompleteCreateEventPage = () => { - const navigate = useNavigate(); - const location = useLocation(); +type CompleteCreateEventStepProps = { + eventToken: string; +}; - const params = new URLSearchParams(location.search); - const eventId = params.get('eventId'); +const CompleteCreateEventStep = ({eventToken}: CompleteCreateEventStepProps) => { + const navigate = useNavigate(); return ( @@ -32,9 +32,9 @@ const CompleteCreateEventPage = () => { - navigate(`${ROUTER_URLS.event}/${eventId}/admin`)}>관리 페이지로 이동 + navigate(`${ROUTER_URLS.event}/${eventToken}/admin`)}>관리 페이지로 이동 ); }; -export default CompleteCreateEventPage; +export default CompleteCreateEventStep; diff --git a/client/src/pages/CreateEventPage/CreateEventFunnel.tsx b/client/src/pages/CreateEventPage/CreateEventFunnel.tsx new file mode 100644 index 000000000..d9347a389 --- /dev/null +++ b/client/src/pages/CreateEventPage/CreateEventFunnel.tsx @@ -0,0 +1,56 @@ +import {useNavigate} from 'react-router-dom'; + +import useFunnel from '@hooks/useFunnel'; +import useCreateEventData from '@hooks/useCreateEventData'; + +import {Back, MainLayout, TopNav} from '@components/Design'; + +import SetEventNameStep from './SetEventNameStep'; +import SetEventPasswordStep from './SetEventPasswordStep'; +import CompleteCreateEventStep from './CompleteCreateEventStep'; + +type CreateEventStep = 'eventName' | 'eventPassword' | 'complete'; +const STEP_SEQUENCE: CreateEventStep[] = ['eventName', 'eventPassword', 'complete']; + +const CreateEventFunnel = () => { + const navigate = useNavigate(); + const {moveToNextStep, moveToPrevStep, Step, Funnel, step} = useFunnel({ + defaultStep: 'eventName', + stepList: STEP_SEQUENCE, + }); + + const {eventNameProps, eventToken, setEventToken} = useCreateEventData(); + + const handleBack = () => { + if (step === STEP_SEQUENCE[0]) { + navigate('/'); + } else { + moveToPrevStep(); + } + }; + + return ( + + {step !== STEP_SEQUENCE[STEP_SEQUENCE.length - 1] && } + + + + + + + + + + + + + + + ); +}; + +export default CreateEventFunnel; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx deleted file mode 100644 index 1f7d0acf6..000000000 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import {useNavigate} from 'react-router-dom'; -import {css} from '@emotion/react'; - -import Top from '@components/Design/components/Top/Top'; - -import useSetEventNamePage from '@hooks/useSetEventNamePage'; - -import {FixedButton, MainLayout, LabelInput, TopNav, Back} from '@HDesign/index'; - -import {ROUTER_URLS} from '@constants/routerUrls'; - -const SetEventNamePage = () => { - const navigate = useNavigate(); - const {eventName, errorMessage, canSubmit, handleEventNameChange} = useSetEventNamePage(); - - const submitEventName = (event: React.FormEvent) => { - event.preventDefault(); - - onSuccessSubmint(); - }; - - const onSuccessSubmint = () => { - navigate(ROUTER_URLS.eventCreatePassword, {state: {eventName}}); - }; - - const handleGoNextStep = (event: React.KeyboardEvent) => { - if (event.key === 'Enter') { - onSuccessSubmint(); - } - }; - - return ( - - - - -
- - - - - -
- - 다음 -
-
-
- ); -}; - -export default SetEventNamePage; diff --git a/client/src/pages/CreateEventPage/SetEventNameStep.tsx b/client/src/pages/CreateEventPage/SetEventNameStep.tsx new file mode 100644 index 000000000..5653038ff --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventNameStep.tsx @@ -0,0 +1,56 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; + +import {UseSetEventNameStepReturnType} from '@hooks/useSetEventNameStep'; + +import {FixedButton, Flex, LabelInput} from '@HDesign/index'; + +type SetEventNamePageProps = UseSetEventNameStepReturnType & { + moveToNextStep: () => void; +}; + +const SetEventNameStep = ({ + eventName, + moveToNextStep, + errorMessage, + handleEventNameChange, + canSubmit, +}: SetEventNamePageProps) => { + const onSubmit = (event: React.FormEvent) => { + event.preventDefault(); + + moveToNextStep(); + }; + + return ( +
+ + + + +
+ + 다음 +
+
+ ); +}; + +export default SetEventNameStep; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx deleted file mode 100644 index 4c0b70ad2..000000000 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import {css} from '@emotion/react'; - -import Top from '@components/Design/components/Top/Top'; - -import useSetEventPasswordPage from '@hooks/useSetEventPasswordPage'; - -import {FixedButton, MainLayout, LabelInput, TopNav, Back} from '@HDesign/index'; - -import RULE from '@constants/rule'; - -const SetEventPasswordPage = () => { - const {submitPassword, onSuccess, errorMessage, password, handleChange, canSubmit, isPostEventPending} = - useSetEventPasswordPage(); - - const handleGoNextStep = (event: React.KeyboardEvent) => { - if (event.key === 'Enter') { - onSuccess(); - } - }; - - return ( - - - - -
- - - - -
- - {/* 가상 키패드 적용 예정 */} - - 행동 개시! - - -
-
- ); -}; - -export default SetEventPasswordPage; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx b/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx new file mode 100644 index 000000000..c11c376f2 --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx @@ -0,0 +1,61 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; + +import useSetEventPasswordStep, {UseSetEventPasswordStepReturnType} from '@hooks/useSetEventPasswordStep'; + +import {FixedButton, LabelInput} from '@HDesign/index'; + +import RULE from '@constants/rule'; + +type SetEventPasswordPageProps = { + eventName: string; + moveToNextStep: () => void; + setEventToken: (eventToken: string) => void; +}; + +const SetEventPasswordStep = ({eventName, moveToNextStep, setEventToken}: SetEventPasswordPageProps) => { + const {submitDataForPostEvent, errorMessage, password, handleChange, isPostEventPending, canSubmit} = + useSetEventPasswordStep(); + + const submit = async (event: React.FormEvent) => { + await submitDataForPostEvent({event, eventName, setEventToken}); + + moveToNextStep(); + }; + + return ( +
+ + + + +
+ + {/* 가상 키패드 적용 예정 */} + + 행동 개시! + + +
+ ); +}; + +export default SetEventPasswordStep; diff --git a/client/src/pages/CreateEventPage/index.ts b/client/src/pages/CreateEventPage/index.ts index 6d3d6c808..8d5867dc6 100644 --- a/client/src/pages/CreateEventPage/index.ts +++ b/client/src/pages/CreateEventPage/index.ts @@ -1,3 +1,3 @@ -export {default as SetEventNamePage} from './SetEventNamePage'; -export {default as SetEventPasswordPage} from './SetEventPasswordPage'; -export {default as CompleteCreateEventPage} from './CompleteCreateEventPage'; +export {default as SetEventNameStep} from './SetEventNameStep'; +export {default as SetEventPasswordStep} from './SetEventPasswordStep'; +export {default as CompleteCreateEventStep} from './CompleteCreateEventStep'; diff --git a/client/src/pages/ErrorPage/ErrorPage.tsx b/client/src/pages/ErrorPage/ErrorPage.tsx index 84f61b2a3..92810e668 100644 --- a/client/src/pages/ErrorPage/ErrorPage.tsx +++ b/client/src/pages/ErrorPage/ErrorPage.tsx @@ -1,9 +1,13 @@ -import {MainLayout, Title} from '@HDesign/index'; +import Top from '@components/Design/components/Top/Top'; + +import {MainLayout} from '@HDesign/index'; const ErrorPage = () => { return ( - + <Top> + <Top.Line text="알 수 없는 오류입니다." emphasize={['알 수 없는 오류입니다.']} /> + </Top> </MainLayout> ); }; diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx index 5fd1ba3f8..2a45267cb 100644 --- a/client/src/pages/MainPage/Nav/Nav.tsx +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -18,7 +18,7 @@ const Nav = () => { <Text size="subTitle">행동대장</Text> </div> </Flex> - <Button size="medium" variants="tertiary" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + <Button size="medium" variants="tertiary" onClick={() => navigate(ROUTER_URLS.createEvent)}> 정산 시작하기 </Button> </header> diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx index 18f8e9208..5ae1dd8cb 100644 --- a/client/src/pages/MainPage/Section/MainSection.tsx +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -40,7 +40,7 @@ const MainSection = () => { <Text css={animateWithDelay(1)} style={{textAlign: 'center'}} size="title">{`행동대장을 통해 간편하게 정산하세요 `}</Text> - <Button css={animateWithDelay(2)} size="large" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + <Button css={animateWithDelay(2)} size="large" onClick={() => navigate(ROUTER_URLS.createEvent)}> 정산 시작하기 </Button> </div> diff --git a/client/src/router.tsx b/client/src/router.tsx index 0a1372829..566a07b7f 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -5,9 +5,9 @@ import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; +import CreateEventFunnel from '@pages/CreateEventPage/CreateEventFunnel'; import Account from '@pages/AccountPage/Account'; -import {CompleteCreateEventPage, SetEventNamePage, SetEventPasswordPage} from '@pages/CreateEventPage'; import {MainPage} from '@pages/MainPage'; import {EventPage} from '@pages/EventPage'; @@ -20,26 +20,15 @@ const router = createBrowserRouter([ path: '', element: <App />, children: [ - { - path: 'cookie', - element: <Account />, - }, { index: true, path: ROUTER_URLS.main, element: <MainPage />, }, { - path: ROUTER_URLS.eventCreateName, - element: <SetEventNamePage />, - }, - { - path: ROUTER_URLS.eventCreatePassword, - element: <SetEventPasswordPage />, - }, - { - path: ROUTER_URLS.eventCreateComplete, - element: <CompleteCreateEventPage />, + path: ROUTER_URLS.createEvent, + + element: <CreateEventFunnel />, }, { path: ROUTER_URLS.event, diff --git a/client/src/utils/validate/validateEventName.ts b/client/src/utils/validate/validateEventName.ts index 93f4ecef1..1c88fd4b3 100644 --- a/client/src/utils/validate/validateEventName.ts +++ b/client/src/utils/validate/validateEventName.ts @@ -7,6 +7,7 @@ const validateEventName = (name: string): ValidateResult => { if (name.length > RULE.maxEventNameLength) { return {isValid: false, errorMessage: ERROR_MESSAGE.eventName}; } + return {isValid: true, errorMessage: null}; };