From f28f748584300a26009d957125c94edcc1a40af8 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 14:22:51 +0900 Subject: [PATCH 01/19] =?UTF-8?q?feat:=20header=20user=20button=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=AA=A8=EB=8B=AC=20?= =?UTF-8?q?=EC=97=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/user/src/components/layout/header/user/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/user/src/components/layout/header/user/index.tsx b/packages/user/src/components/layout/header/user/index.tsx index 569ff6bb..f47ecfde 100644 --- a/packages/user/src/components/layout/header/user/index.tsx +++ b/packages/user/src/components/layout/header/user/index.tsx @@ -1,4 +1,6 @@ import UserIcon from 'src/assets/icons/user.svg?react'; +import TriggerButtonWrapper from 'src/components/common/TriggerButtonWrapper.tsx'; +import LoginModal from 'src/components/shared/modal/login/index.tsx'; import useAuth from 'src/hooks/useAuth.tsx'; import SpeechBubble from './SpeechBubble.tsx'; @@ -13,9 +15,7 @@ export default function User() { ) : ( <> - + } /> )} From 83151005388af1c4ac601f702d92e972fe50d20c Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 14:35:55 +0900 Subject: [PATCH 02/19] =?UTF-8?q?feat:=20=EC=9C=A0=ED=98=95=20=EA=B2=80?= =?UTF-8?q?=EC=82=AC=20=EB=AA=A8=EB=8B=AC=20=EB=82=B4=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EB=AA=A8=EB=8B=AC=20=EC=97=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/src/components/shared/modal/teamSelectModal/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/user/src/components/shared/modal/teamSelectModal/index.tsx b/packages/user/src/components/shared/modal/teamSelectModal/index.tsx index 61890da1..62788682 100644 --- a/packages/user/src/components/shared/modal/teamSelectModal/index.tsx +++ b/packages/user/src/components/shared/modal/teamSelectModal/index.tsx @@ -1,5 +1,6 @@ import { Suspense } from 'react'; import Modal, { ModalProps } from 'src/components/common/Modal.tsx'; +import LoginModal from 'src/components/shared/modal/login/index.tsx'; import PendingStep from 'src/components/shared/modal/PendingStep.tsx'; import useAuth from 'src/hooks/useAuth.tsx'; import TeamSelectModalContent from './ModalContent.tsx'; @@ -9,7 +10,7 @@ interface TeamSelectModalProps extends Omit {} export default function TeamSelectModal({ openTrigger, ...props }: TeamSelectModalProps) { const { user } = useAuth(); - // if (!user) return ; + if (!user) return ; return ( From 9cdac1f49d8a540c15e181d754273f9cbdd3c926 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 15:15:44 +0900 Subject: [PATCH 03/19] style: prettier --- .../event/racing/controls/ControlButton.tsx | 34 +++++++++---------- .../components/layout/header/user/index.tsx | 8 ++++- .../user/src/hooks/socket/useRacingSocket.ts | 13 ++++--- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/packages/user/src/components/event/racing/controls/ControlButton.tsx b/packages/user/src/components/event/racing/controls/ControlButton.tsx index 44f1b94f..c450383b 100644 --- a/packages/user/src/components/event/racing/controls/ControlButton.tsx +++ b/packages/user/src/components/event/racing/controls/ControlButton.tsx @@ -25,25 +25,23 @@ export interface ChargeButtonData { percentage: number; } -const ControlButton = memo( - ({ onCharge, onFullyCharged, type, data }: ControlButtonProps) => { - const { rank, percentage } = data; - const { progress, clickCount, handleClick } = useGaugeProgress({ - percentage, - onCharge, - onFullyCharged, - }); +const ControlButton = memo(({ onCharge, onFullyCharged, type, data }: ControlButtonProps) => { + const { rank, percentage } = data; + const { progress, clickCount, handleClick } = useGaugeProgress({ + percentage, + onCharge, + onFullyCharged, + }); - return ( - - - - - - - ); - }, -); + return ( + + + + + + + ); +}); export default ControlButton; diff --git a/packages/user/src/components/layout/header/user/index.tsx b/packages/user/src/components/layout/header/user/index.tsx index f47ecfde..a82c61d0 100644 --- a/packages/user/src/components/layout/header/user/index.tsx +++ b/packages/user/src/components/layout/header/user/index.tsx @@ -15,7 +15,13 @@ export default function User() { ) : ( <> - } /> + + + + } + /> )} diff --git a/packages/user/src/hooks/socket/useRacingSocket.ts b/packages/user/src/hooks/socket/useRacingSocket.ts index a25da756..584b3d54 100644 --- a/packages/user/src/hooks/socket/useRacingSocket.ts +++ b/packages/user/src/hooks/socket/useRacingSocket.ts @@ -58,11 +58,14 @@ export default function useRacingSocket() { const handleCarFullyCharged = (category: Category) => { const chargeData = { [categoryToSocketCategory[category]]: 1 }; - const completeChargeData = Object.keys(categoryToSocketCategory).reduce((acc, key) => { - const socketCategory = categoryToSocketCategory[key as Category]; - acc[socketCategory] = chargeData[socketCategory] ?? 0; - return acc; - }, {} as Record); + const completeChargeData = Object.keys(categoryToSocketCategory).reduce( + (acc, key) => { + const socketCategory = categoryToSocketCategory[key as Category]; + acc[socketCategory] = chargeData[socketCategory] ?? 0; + return acc; + }, + {} as Record, + ); socketClient.sendMessages({ destination: RACING_SOCKET_ENDPOINTS.PUBLISH, From 57752c31af9299f4ee0f159de3e5c6e5364b1909 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 15:18:00 +0900 Subject: [PATCH 04/19] =?UTF-8?q?chore:=20CORS=20error=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0=20=EC=9C=84=ED=95=B4=20=EC=84=9C=EB=B2=84=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=97=B4=EC=96=B4=EB=91=94=20port:5173=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/user/vite.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/user/vite.config.ts b/packages/user/vite.config.ts index b188d139..002e7343 100644 --- a/packages/user/vite.config.ts +++ b/packages/user/vite.config.ts @@ -10,7 +10,7 @@ interface VitestConfigExport extends UserConfig { export default defineConfig({ plugins: [react(), svgr(), visualizer()], - server: { port: 3000 }, + // server: { port: 3000 }, cacheDir: './.yarn/.vite', test: { globals: true, From 63b25bc812a7cdfc5d07afe154cfa6e9621d555f Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 17:24:30 +0900 Subject: [PATCH 05/19] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=95=98=EC=9D=84=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20Login=20modal=20=EC=9D=84=20=EB=9D=84=EC=9B=8C?= =?UTF-8?q?=EC=A4=98=EC=95=BC=20=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=EC=9D=84=20=EA=B3=B5=ED=86=B5=20withAuth=20HOC=EC=9D=84=20?= =?UTF-8?q?=ED=86=B5=ED=95=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../event/chatting/inputArea/input/index.tsx | 12 ++--- .../event/racing/dashboard/card/index.tsx | 21 +++++---- .../layout/fcfsController/index.tsx | 46 ++++++++----------- .../components/layout/header/user/index.tsx | 32 +++++-------- .../shared/modal/teamSelectModal/index.tsx | 3 -- .../src/components/shared/withAuthHOC.tsx | 32 +++++++++++++ 6 files changed, 82 insertions(+), 64 deletions(-) create mode 100644 packages/user/src/components/shared/withAuthHOC.tsx diff --git a/packages/user/src/components/event/chatting/inputArea/input/index.tsx b/packages/user/src/components/event/chatting/inputArea/input/index.tsx index f5ddc833..3cbd9b6e 100644 --- a/packages/user/src/components/event/chatting/inputArea/input/index.tsx +++ b/packages/user/src/components/event/chatting/inputArea/input/index.tsx @@ -1,6 +1,6 @@ import { useRef } from 'react'; import OutlinedButton from 'src/components/common/OutlinedButton.tsx'; -import LoginModal from 'src/components/shared/modal/login/index.tsx'; +import withAuth from 'src/components/shared/withAuthHOC.tsx'; import useAuth from 'src/hooks/useAuth.tsx'; import { useToast } from 'src/hooks/useToast.ts'; import Input from './Input.tsx'; @@ -31,14 +31,14 @@ export default function ChatInput({ onSend }: ChatInputProps) { } } + const ProtectedWrapper = withAuth(() => 보내기); + return (
- {isAuthenticated ? ( - 보내기 - ) : ( - 로그인하고 채팅 보내기} /> - )} + 로그인하고 채팅 보내기} + /> ); } diff --git a/packages/user/src/components/event/racing/dashboard/card/index.tsx b/packages/user/src/components/event/racing/dashboard/card/index.tsx index 878069ba..03c4128a 100644 --- a/packages/user/src/components/event/racing/dashboard/card/index.tsx +++ b/packages/user/src/components/event/racing/dashboard/card/index.tsx @@ -3,6 +3,7 @@ import { useState } from 'react'; import TriggerButtonWrapper from 'src/components/common/TriggerButtonWrapper.tsx'; import TeamSelectModal from 'src/components/shared/modal/teamSelectModal/index.tsx'; import ShareCountTeamCard from 'src/components/shared/ShareCountTeamCard.tsx'; +import withAuth from 'src/components/shared/withAuthHOC.tsx'; import useAuth from 'src/hooks/useAuth.tsx'; import UnassignedCard from './UnassignedCard.tsx'; @@ -10,20 +11,24 @@ export default function RacingCard() { const { user } = useAuth(); const [type, setType] = useState(user?.type); + const ProtectedTeamSelectModal = withAuth(() => ( + + + + } + onClose={() => setType(user?.type)} // onClose를 사용해 타입을 설정 + /> + )); + return (
{type ? ( ) : ( - - - - } - onClose={() => setType(user?.type)} - /> + } /> )}
); diff --git a/packages/user/src/components/layout/fcfsController/index.tsx b/packages/user/src/components/layout/fcfsController/index.tsx index 5b73c4fd..9de258c7 100644 --- a/packages/user/src/components/layout/fcfsController/index.tsx +++ b/packages/user/src/components/layout/fcfsController/index.tsx @@ -1,7 +1,6 @@ import { lazy, Suspense, useEffect, useState } from 'react'; import TriggerButtonWrapper from 'src/components/common/TriggerButtonWrapper.tsx'; -import LoginModal from 'src/components/shared/modal/login/index.tsx'; -import useAuth from 'src/hooks/useAuth.tsx'; +import withAuth from 'src/components/shared/withAuthHOC.tsx'; import TriggerButtonLike from './TriggerButtonLike.tsx'; const FCFSModal = lazy(() => import('src/components/shared/modal/fcfs/index.tsx')); @@ -9,8 +8,19 @@ const FCFSModal = lazy(() => import('src/components/shared/modal/fcfs/index.tsx' const EVENT_OPEN_HOUR = 15; const EVENT_OPEN_MINUTE = 15; +const ProtectedFCFSButton = withAuth(() => ( + + + 선착순 퀴즈

OPEN

+
+ + } + /> +)); + export default function FCFSFloatingButtonController() { - const { isAuthenticated } = useAuth(); const shouldLoadComponent = useEventActivation(EVENT_OPEN_HOUR, EVENT_OPEN_MINUTE); // 설정한 시각 이전에는 버튼 노출하지 않음 @@ -18,34 +28,16 @@ export default function FCFSFloatingButtonController() { return null; } - // 로그인하지 않은 유저에게는 로그인 모달 트리거 버튼 노출 - if (!isAuthenticated) { - return ( - - -

로그인

하고 퀴즈 풀기 -
- - } - /> - ); - } - - // 로그인한 유저에게는 선착순 퀴즈 모달 트리거 버튼 노출 return ( - - - 선착순 퀴즈

OPEN

-
- + +

로그인

하고 퀴즈 풀기 + } /> -
+ ); } diff --git a/packages/user/src/components/layout/header/user/index.tsx b/packages/user/src/components/layout/header/user/index.tsx index a82c61d0..4b4780e6 100644 --- a/packages/user/src/components/layout/header/user/index.tsx +++ b/packages/user/src/components/layout/header/user/index.tsx @@ -1,29 +1,21 @@ import UserIcon from 'src/assets/icons/user.svg?react'; -import TriggerButtonWrapper from 'src/components/common/TriggerButtonWrapper.tsx'; -import LoginModal from 'src/components/shared/modal/login/index.tsx'; -import useAuth from 'src/hooks/useAuth.tsx'; +import withAuth from 'src/components/shared/withAuthHOC.tsx'; import SpeechBubble from './SpeechBubble.tsx'; -export default function User() { - const { user } = useAuth(); +const UserGreeting = withAuth(() =>

김보민님 반갑습니다

); - // TODO: 로그인, 로그아웃 +export default function User() { + // TODO: 로그아웃 return (
- {user ? ( -

김보민님 반갑습니다

- ) : ( - <> - - - - - } - /> - - )} + + + + + } + />
); } diff --git a/packages/user/src/components/shared/modal/teamSelectModal/index.tsx b/packages/user/src/components/shared/modal/teamSelectModal/index.tsx index 62788682..31fb8b39 100644 --- a/packages/user/src/components/shared/modal/teamSelectModal/index.tsx +++ b/packages/user/src/components/shared/modal/teamSelectModal/index.tsx @@ -1,6 +1,5 @@ import { Suspense } from 'react'; import Modal, { ModalProps } from 'src/components/common/Modal.tsx'; -import LoginModal from 'src/components/shared/modal/login/index.tsx'; import PendingStep from 'src/components/shared/modal/PendingStep.tsx'; import useAuth from 'src/hooks/useAuth.tsx'; import TeamSelectModalContent from './ModalContent.tsx'; @@ -10,8 +9,6 @@ interface TeamSelectModalProps extends Omit {} export default function TeamSelectModal({ openTrigger, ...props }: TeamSelectModalProps) { const { user } = useAuth(); - if (!user) return ; - return ( 유형 검사 리스트 불러오는 중 ...}> diff --git a/packages/user/src/components/shared/withAuthHOC.tsx b/packages/user/src/components/shared/withAuthHOC.tsx new file mode 100644 index 00000000..e879a7a4 --- /dev/null +++ b/packages/user/src/components/shared/withAuthHOC.tsx @@ -0,0 +1,32 @@ +import React, { PropsWithChildren, ReactElement, useCallback, useState } from 'react'; +import TriggerButtonWrapper from 'src/components/common/TriggerButtonWrapper.tsx'; +import LoginModal from 'src/components/shared/modal/login/index.tsx'; +import useAuth from 'src/hooks/useAuth.tsx'; + +interface WithAuthProps { + unauthenticatedDisplay: ReactElement; +} + +export default function withAuth(WrappedComponent: React.ComponentType) { + return function AuthWrapper({ + unauthenticatedDisplay, + ...props + }: T & PropsWithChildren) { + const { isAuthenticated } = useAuth(); + const [isUnauthenticatedDisplay, setIsUnauthenticatedDisplay] = useState(false); + + const handleLoginModalClose = useCallback(() => setIsUnauthenticatedDisplay(false), []); + + if (!isAuthenticated || isUnauthenticatedDisplay) { + if (!isUnauthenticatedDisplay) setIsUnauthenticatedDisplay(true); + return ( + {unauthenticatedDisplay}} + onClose={handleLoginModalClose} + /> + ); + } + + return ; + }; +} From 674370e06a47bbf47a8d9102880aa4260f7f544a Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 17:28:42 +0900 Subject: [PATCH 06/19] =?UTF-8?q?refactor:=20=EC=84=A0=EC=B0=A9=EC=88=9C?= =?UTF-8?q?=20=ED=80=B4=EC=A6=88=20=EB=AA=A8=EB=8B=AC=20=EB=82=B4=20?= =?UTF-8?q?=ED=80=B4=EC=A6=88=20=EC=A0=9C=EC=B6=9C=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?->=20=ED=80=B4=EC=A6=88=20=EC=8A=A4=ED=85=9D=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/shared/modal/fcfs/QuizStep.tsx | 34 +++++++++++++++++-- .../components/shared/modal/fcfs/index.tsx | 32 ++--------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/packages/user/src/components/shared/modal/fcfs/QuizStep.tsx b/packages/user/src/components/shared/modal/fcfs/QuizStep.tsx index 731969c4..d35ee439 100644 --- a/packages/user/src/components/shared/modal/fcfs/QuizStep.tsx +++ b/packages/user/src/components/shared/modal/fcfs/QuizStep.tsx @@ -1,16 +1,31 @@ +import { useEffect } from 'react'; import Chip from 'src/components/common/Chip.tsx'; import OptionButton from 'src/components/common/OptionButton.tsx'; import useGetFCFSQuiz from 'src/hooks/query/useGetFCFSQuiz.ts'; +import useSubmitFCFSQuiz, { SubmitFCFSQuizResponse } from 'src/hooks/query/useSubmitFCFSQuiz.ts'; +type ResultStepType = ReturnType; interface QuizStepProps { - onSelect: (answer: number) => void; + onStepChange: (step: ResultStepType | 'pending') => void; } -export default function QuizStep({ onSelect }: QuizStepProps) { +export default function QuizStep({ onStepChange }: QuizStepProps) { const { quiz: { question, choices }, } = useGetFCFSQuiz(); + const { isPending, mutate: submitAnswer } = useSubmitFCFSQuiz(); + + useEffect(() => { + if (isPending) onStepChange('pending'); + }, [isPending]); + + const handleSubmit = (answer: number) => + submitAnswer( + { answer }, + { onSuccess: (response) => onStepChange(getResultStepFromStatus(response)) }, + ); + return (
@@ -19,7 +34,7 @@ export default function QuizStep({ onSelect }: QuizStepProps) {
{choices.map(({ num, text }) => ( - onSelect(num)}> + handleSubmit(num)}> {text} ))} @@ -27,3 +42,16 @@ export default function QuizStep({ onSelect }: QuizStepProps) {
); } + +function getResultStepFromStatus({ status }: SubmitFCFSQuizResponse) { + switch (status) { + case 'END': + return 'end'; + case 'PARTICIPATED': + return 'already-done'; + case 'WRONG': + return 'wrong-answer'; + default: + return 'correct-answer'; + } +} diff --git a/packages/user/src/components/shared/modal/fcfs/index.tsx b/packages/user/src/components/shared/modal/fcfs/index.tsx index 894d2e4f..9dd88ad2 100644 --- a/packages/user/src/components/shared/modal/fcfs/index.tsx +++ b/packages/user/src/components/shared/modal/fcfs/index.tsx @@ -1,16 +1,13 @@ import { QueryErrorResetBoundary } from '@tanstack/react-query'; -import { Suspense, useEffect } from 'react'; +import { Suspense } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import Modal, { ModalProps } from 'src/components/common/Modal.tsx'; import PendingStep from 'src/components/shared/modal/PendingStep.tsx'; -import useSubmitFCFSQuiz, { SubmitFCFSQuizResponse } from 'src/hooks/query/useSubmitFCFSQuiz.ts'; import useFunnel from 'src/hooks/useFunnel.ts'; import ErrorStep from './ErrorStep.tsx'; import QuizStep from './QuizStep.tsx'; import ResultStep from './ResultStep.tsx'; -export type ResultStepType = ReturnType; - export default function FCFSModal(props: ModalProps) { const [Funnel, setStep] = useFunnel( [ @@ -26,18 +23,6 @@ export default function FCFSModal(props: ModalProps) { }, ); - const { isPending, mutate: submitAnswer } = useSubmitFCFSQuiz(); - - useEffect(() => { - if (isPending) setStep('pending'); - }, [isPending]); - - const handleSubmit = (answer: number) => - submitAnswer( - { answer }, - { onSuccess: (response) => setStep(getResultStepFromStatus(response)) }, - ); - return (
@@ -47,7 +32,7 @@ export default function FCFSModal(props: ModalProps) { {({ reset }) => ( 선착순 퀴즈 불러오는 중...}> - + )} @@ -75,16 +60,3 @@ export default function FCFSModal(props: ModalProps) { ); } - -function getResultStepFromStatus({ status }: SubmitFCFSQuizResponse) { - switch (status) { - case 'END': - return 'end'; - case 'PARTICIPATED': - return 'already-done'; - case 'WRONG': - return 'wrong-answer'; - default: - return 'correct-answer'; - } -} From 611284b45dc3b3c0732948d673545a5458d6c1a4 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 17:38:32 +0900 Subject: [PATCH 07/19] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=20=EB=82=B4=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?step=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20api=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shared/modal/login/LoginStep.tsx | 69 +++++++++++++++++++ .../components/shared/modal/login/index.tsx | 19 ++++- .../user/src/hooks/query/useSubmitLogin.ts | 33 +++++++++ packages/user/src/types/user.d.ts | 2 +- 4 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 packages/user/src/components/shared/modal/login/LoginStep.tsx create mode 100644 packages/user/src/hooks/query/useSubmitLogin.ts diff --git a/packages/user/src/components/shared/modal/login/LoginStep.tsx b/packages/user/src/components/shared/modal/login/LoginStep.tsx new file mode 100644 index 00000000..5b8f2ce4 --- /dev/null +++ b/packages/user/src/components/shared/modal/login/LoginStep.tsx @@ -0,0 +1,69 @@ +/* eslint-disable no-return-assign */ +import { FormEvent, useRef } from 'react'; +import Button from 'src/components/common/Button.tsx'; +import useSubmitLogin, { SubmitLoginRequest } from 'src/hooks/query/useSubmitLogin.ts'; +import inputStyles from 'src/styles/input.ts'; + +interface LoginStepProps { + onMoveSuccessStep: () => void; +} + +// TODO: KAKAO OAuth +export default function LoginStep({ onMoveSuccessStep }:LoginStepProps) { + const { mutate: login } = useSubmitLogin(); + + const inputRefs = useRef([]); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + const submitData = { userId: inputRefs.current[0].value, password: inputRefs.current[1].value }; + if (hasRequiredLoginFields(submitData)) { + login(submitData, { + onSuccess: onMoveSuccessStep, + }); + } + }; + + return ( +
+

+ 이벤트 참여를 위해 로그인을 진행해주세요 +

+
+ (inputRefs.current[0] = el!)} + className={loginInputStyles} + /> +
+
+ (inputRefs.current[1] = el!)} + className={loginInputStyles} + /> +
+ +
+ ); +} + +/** Helper Function */ +function hasRequiredLoginFields(inputs: Partial): inputs is SubmitLoginRequest { + return typeof inputs.userId === 'string' && typeof inputs.password === 'string'; +} + +const loginInputStyles = `${inputStyles} border border-foreground focus-visible:ring-primary rounded-2.5 h-[54px] w-[450px] bg-neutral-800 p-3 placeholder:text-neutral-300`; diff --git a/packages/user/src/components/shared/modal/login/index.tsx b/packages/user/src/components/shared/modal/login/index.tsx index b086e7d9..c71d071e 100644 --- a/packages/user/src/components/shared/modal/login/index.tsx +++ b/packages/user/src/components/shared/modal/login/index.tsx @@ -1,7 +1,22 @@ import Modal, { ModalProps } from 'src/components/common/Modal.tsx'; +import useFunnel from 'src/hooks/useFunnel.ts'; +import LoginStep from './LoginStep.tsx'; interface LoginModalProps extends Omit {} -export default function LoginModal({ openTrigger }: LoginModalProps) { - return 로그인 모달; +export default function LoginModal({ openTrigger, ...props }: LoginModalProps) { + const [Funnel, setStep] = useFunnel(['login', 'success', 'error'] as NonEmptyArray, { + initialStep: 'login', + }); + + return ( + + + + setStep('success')} /> + + 로그인 성공 + + + ); } diff --git a/packages/user/src/hooks/query/useSubmitLogin.ts b/packages/user/src/hooks/query/useSubmitLogin.ts new file mode 100644 index 00000000..6d2c89c7 --- /dev/null +++ b/packages/user/src/hooks/query/useSubmitLogin.ts @@ -0,0 +1,33 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/naming-convention */ +import { useMutation } from '@tanstack/react-query'; +import useTokenStorage from 'src/hooks/storage/useTokenStorage.ts'; +import useAuth from 'src/hooks/useAuth.tsx'; +import { useToast } from 'src/hooks/useToast.ts'; +import http from 'src/services/api/index.ts'; + +export type SubmitLoginRequest = { userId: string; password: string }; + +export interface SubmitLoginResponse { + accessToken: string; +} + +const LOGIN_ERROR_TOAST_DESCRIPTION = '문제가 발생했습니다. 다시 시도해주세요.'; + +export default function useSubmitLogin() { + const { setAuthData } = useAuth(); + const [_, setToken] = useTokenStorage(); + + const { toast } = useToast(); + + const mutation = useMutation({ + mutationFn: (data: SubmitLoginRequest) => http.post('/login', data), + onSuccess: ({ accessToken }, { userId: id }) => { + setAuthData({ userData: { id, name: '캐스퍼' } }); + setToken(accessToken); + }, + onError: () => toast({ description: LOGIN_ERROR_TOAST_DESCRIPTION }), + }); + + return mutation; +} diff --git a/packages/user/src/types/user.d.ts b/packages/user/src/types/user.d.ts index 21551de2..689927fe 100644 --- a/packages/user/src/types/user.d.ts +++ b/packages/user/src/types/user.d.ts @@ -1,7 +1,7 @@ import type { Category } from '@softeer/common/types'; export interface User { - id: number; + id: string; name: string; type?: Category; } From 4cf2b56764848c9c00308b62b07e719d7b93d9c7 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 17:38:53 +0900 Subject: [PATCH 08/19] =?UTF-8?q?design:=20info=20step=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=ED=81=AC=EA=B8=B0=20=EC=B6=95=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/user/src/components/shared/modal/InfoStep.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/user/src/components/shared/modal/InfoStep.tsx b/packages/user/src/components/shared/modal/InfoStep.tsx index 119b06ee..06796f63 100644 --- a/packages/user/src/components/shared/modal/InfoStep.tsx +++ b/packages/user/src/components/shared/modal/InfoStep.tsx @@ -2,8 +2,8 @@ import { PropsWithChildren } from 'react'; export default function InfoStep({ children }: PropsWithChildren) { return ( -
- modal +
+ modal
{children}
); From 05fd8c3d6499b62c8b9ac86b1a3f70436889e910 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 17:39:50 +0900 Subject: [PATCH 09/19] style: prettier --- .../layout/fcfsController/index.tsx | 20 +++++++++---------- .../shared/modal/login/LoginStep.tsx | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/user/src/components/layout/fcfsController/index.tsx b/packages/user/src/components/layout/fcfsController/index.tsx index 9de258c7..cf358d64 100644 --- a/packages/user/src/components/layout/fcfsController/index.tsx +++ b/packages/user/src/components/layout/fcfsController/index.tsx @@ -9,15 +9,15 @@ const EVENT_OPEN_HOUR = 15; const EVENT_OPEN_MINUTE = 15; const ProtectedFCFSButton = withAuth(() => ( - - - 선착순 퀴즈

OPEN

-
- - } - /> + + + 선착순 퀴즈

OPEN

+
+ + } + /> )); export default function FCFSFloatingButtonController() { @@ -37,7 +37,7 @@ export default function FCFSFloatingButtonController() { } /> - + ); } diff --git a/packages/user/src/components/shared/modal/login/LoginStep.tsx b/packages/user/src/components/shared/modal/login/LoginStep.tsx index 5b8f2ce4..b12788ab 100644 --- a/packages/user/src/components/shared/modal/login/LoginStep.tsx +++ b/packages/user/src/components/shared/modal/login/LoginStep.tsx @@ -9,7 +9,7 @@ interface LoginStepProps { } // TODO: KAKAO OAuth -export default function LoginStep({ onMoveSuccessStep }:LoginStepProps) { +export default function LoginStep({ onMoveSuccessStep }: LoginStepProps) { const { mutate: login } = useSubmitLogin(); const inputRefs = useRef([]); From 4ae7ee80dae023376395eaa4b812fd49cab1d025 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 17:44:37 +0900 Subject: [PATCH 10/19] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EC=95=98=EC=9D=84=20=EB=95=8C=20?= =?UTF-8?q?=EB=B3=B4=EC=9D=B4=EB=8A=94=20=ED=97=A4=EB=8D=94=20=EB=82=B4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=B2=84=ED=8A=BC=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=95=84=EC=9B=83=20=EA=B9=A8=EC=A7=80=EB=8A=94=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/layout/header/user/index.tsx | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/user/src/components/layout/header/user/index.tsx b/packages/user/src/components/layout/header/user/index.tsx index 4b4780e6..5d7dddb1 100644 --- a/packages/user/src/components/layout/header/user/index.tsx +++ b/packages/user/src/components/layout/header/user/index.tsx @@ -4,18 +4,16 @@ import SpeechBubble from './SpeechBubble.tsx'; const UserGreeting = withAuth(() =>

김보민님 반갑습니다

); +// TODO: 로그아웃 export default function User() { - // TODO: 로그아웃 return ( -
- - - - - } - /> -
+ + + +
+ } + /> ); } From 452e0648652b7601d62672d0a5498eaf69b0afaf Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 17:56:16 +0900 Subject: [PATCH 11/19] =?UTF-8?q?fix:=20socket=20subscribe=20=EA=B0=92?= =?UTF-8?q?=EC=9D=B4=20trigger=20=EB=90=A0=20=EB=95=8C=EB=A7=88=EB=8B=A4?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EA=B0=80=20=EB=A6=AC?= =?UTF-8?q?=EB=A0=8C=EB=8D=94=EB=A7=81=EB=90=98=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EA=B8=B0=EB=8C=80=ED=8F=89=20=ED=86=A0=ED=94=BD=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20-=20=ED=95=B4=EA=B2=B0(=EB=A6=AC=EB=A0=8C?= =?UTF-8?q?=EB=8D=94=EB=A7=81=20=EB=90=98=EB=A9=B4=20=EB=AA=A8=EB=8B=AC?= =?UTF-8?q?=EB=8F=84=20=EB=8B=AB=ED=9E=98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/event/chatting/index.tsx | 34 ++++++++------- .../event/chatting/inputArea/index.tsx | 9 ++-- .../user/src/hooks/socket/useChatSocket.ts | 42 +++++++++++-------- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/packages/user/src/components/event/chatting/index.tsx b/packages/user/src/components/event/chatting/index.tsx index 1a829fd5..521088e1 100644 --- a/packages/user/src/components/event/chatting/index.tsx +++ b/packages/user/src/components/event/chatting/index.tsx @@ -1,22 +1,26 @@ import { ChatList } from '@softeer/common/components'; +import { memo } from 'react'; +import ChatInput from 'src/components/event/chatting/inputArea/input/index.tsx'; import { UseChatSocketReturnType } from 'src/hooks/socket/useChatSocket.ts'; import Chat from './Chat.tsx'; import ChatInputArea from './inputArea/index.tsx'; /** 실시간 기대평 섹션 */ -export default function RealTimeChatting({ onSendMessage, messages }: UseChatSocketReturnType) { - return ( -
-
기대평을 남겨보세요!
- -
- - {messages.map((message) => ( - - ))} - -
-
- ); -} +const RealTimeChatting = memo(({ onSendMessage, messages }: UseChatSocketReturnType) => ( +
+
기대평을 남겨보세요!
+ + + +
+ + {messages.map((message) => ( + + ))} + +
+
+)); + +export default RealTimeChatting; diff --git a/packages/user/src/components/event/chatting/inputArea/index.tsx b/packages/user/src/components/event/chatting/inputArea/index.tsx index 95da6548..5c180164 100644 --- a/packages/user/src/components/event/chatting/inputArea/index.tsx +++ b/packages/user/src/components/event/chatting/inputArea/index.tsx @@ -1,16 +1,13 @@ -import ChatInput from './input/index.tsx'; +import { PropsWithChildren } from 'react'; -interface ChatInputAreaProps { - onSend: (message: string) => void; -} -export default function ChatInputArea({ onSend }: ChatInputAreaProps) { +export default function ChatInputArea({ children }: PropsWithChildren) { return (
{/* Todo: 비속어 작성 횟수 불러오기 */}

비속어 혹은 부적절한 기대평을 5회 이상 작성할 경우, 댓글 작성이 제한됩니다.

- + {children}
); } diff --git a/packages/user/src/hooks/socket/useChatSocket.ts b/packages/user/src/hooks/socket/useChatSocket.ts index f1a5c821..c05660ab 100644 --- a/packages/user/src/hooks/socket/useChatSocket.ts +++ b/packages/user/src/hooks/socket/useChatSocket.ts @@ -1,7 +1,7 @@ import { ChatProps } from '@softeer/common/components'; import { CHAT_SOCKET_ENDPOINTS } from '@softeer/common/constants'; import { SocketSubscribeCallbackType } from '@softeer/common/utils'; -import { useState } from 'react'; +import { useCallback, useState } from 'react'; import useAuth from 'src/hooks/useAuth.tsx'; import socketClient from 'src/services/socket.ts'; import type { User } from 'src/types/user.d.ts'; @@ -13,23 +13,29 @@ export default function useChatSocket() { const [chatMessages, setChatMessages] = useState([]); - const handleIncomingMessage: SocketSubscribeCallbackType = (data: unknown, messageId: string) => { - const parsedData = data as Omit; - const parsedMessage = { id: messageId, ...parsedData }; - setChatMessages((prevMessages) => [...prevMessages, parsedMessage] as ChatProps[]); - }; - - const handleSendMessage = (content: string) => { - console.assert(user !== null, '로그인 되지 않은 사용자가 메세지 전송을 시도했습니다.'); - - const { id: sender, type: team } = user as NonNullable; - const chatMessage = { sender, team, content }; - - socketClient.sendMessages({ - destination: CHAT_SOCKET_ENDPOINTS.PUBLISH, - body: chatMessage, - }); - }; + const handleIncomingMessage: SocketSubscribeCallbackType = useCallback( + (data: unknown, messageId: string) => { + const parsedData = data as Omit; + const parsedMessage = { id: messageId, ...parsedData }; + setChatMessages((prevMessages) => [...prevMessages, parsedMessage] as ChatProps[]); + }, + [], + ); + + const handleSendMessage = useCallback( + (content: string) => { + console.assert(user !== null, '로그인 되지 않은 사용자가 메세지 전송을 시도했습니다.'); + + const { id: sender, type: team } = user as NonNullable; + const chatMessage = { sender, team, content }; + + socketClient.sendMessages({ + destination: CHAT_SOCKET_ENDPOINTS.PUBLISH, + body: chatMessage, + }); + }, + [socketClient], + ); return { onReceiveMessage: handleIncomingMessage, From 81bd31a191b636e4e537ca54450ee2c63373d732 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 18:14:26 +0900 Subject: [PATCH 12/19] =?UTF-8?q?fix:=20socket=20subscribe=20=EA=B0=92?= =?UTF-8?q?=EC=9D=B4=20trigger=20=EB=90=A0=20=EB=95=8C=EB=A7=88=EB=8B=A4?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EA=B0=80=20=EB=A6=AC?= =?UTF-8?q?=EB=A0=8C=EB=8D=94=EB=A7=81=EB=90=98=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EB=A0=88=EC=9D=B4=EC=8B=B1=20=ED=86=A0=ED=94=BD=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20-=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/user/src/hooks/socket/useRacingSocket.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/user/src/hooks/socket/useRacingSocket.ts b/packages/user/src/hooks/socket/useRacingSocket.ts index 584b3d54..a596d5ec 100644 --- a/packages/user/src/hooks/socket/useRacingSocket.ts +++ b/packages/user/src/hooks/socket/useRacingSocket.ts @@ -48,14 +48,18 @@ export default function useRacingSocket() { setRanks(newRankStatus); storeRank(newRankStatus); } - }, [newRankStatus, ranks, storeRank]); + }, [newRankStatus, ranks]); const handleStatusChange: SocketSubscribeCallbackType = useCallback((data: unknown) => { const newVoteStatus = parseSocketVoteData(data as SocketData); - setVotes(newVoteStatus); - }, []); + const isVotesChanged = Object.keys(newVoteStatus).some( + (category) => newVoteStatus[category as Category] !== votes[category as Category], + ); + + if (isVotesChanged) setVotes(newVoteStatus); + }, [votes]); - const handleCarFullyCharged = (category: Category) => { + const handleCarFullyCharged = useCallback((category: Category) => { const chargeData = { [categoryToSocketCategory[category]]: 1 }; const completeChargeData = Object.keys(categoryToSocketCategory).reduce( @@ -71,7 +75,7 @@ export default function useRacingSocket() { destination: RACING_SOCKET_ENDPOINTS.PUBLISH, body: completeChargeData, }); - }; + }, []); return { votes, From 40594f5156f0f2351c4c0f2c1fff66c8df7a86f1 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 18:43:16 +0900 Subject: [PATCH 13/19] =?UTF-8?q?fix:=20=EB=A0=88=EC=9D=B4=EC=8B=B1=20?= =?UTF-8?q?=EC=84=B9=EC=85=98=EC=97=90=EC=84=9C=20login=20=ED=95=A0=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20login=20=EB=AA=A8=EB=8B=AC=EC=9D=B4=20?= =?UTF-8?q?=EA=B0=95=EC=A0=9C=20=EC=A2=85=EB=A3=8C=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20->=20withAuth=EB=A5=BC=20memo=EB=A1=9C=20?= =?UTF-8?q?=EA=B0=90=EC=8B=B8=EC=84=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../event/chatting/inputArea/input/index.tsx | 10 +++---- .../event/racing/dashboard/card/index.tsx | 27 +++++++++---------- .../shared/modal/teamSelectModal/index.tsx | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/packages/user/src/components/event/chatting/inputArea/input/index.tsx b/packages/user/src/components/event/chatting/inputArea/input/index.tsx index 3cbd9b6e..574fd56e 100644 --- a/packages/user/src/components/event/chatting/inputArea/input/index.tsx +++ b/packages/user/src/components/event/chatting/inputArea/input/index.tsx @@ -1,10 +1,12 @@ -import { useRef } from 'react'; +import { memo, useCallback, useRef } from 'react'; import OutlinedButton from 'src/components/common/OutlinedButton.tsx'; import withAuth from 'src/components/shared/withAuthHOC.tsx'; import useAuth from 'src/hooks/useAuth.tsx'; import { useToast } from 'src/hooks/useToast.ts'; import Input from './Input.tsx'; +const ProtectedWrapper = memo(withAuth(() => 보내기)); + const DISABLED_CHATTING_TOAST_DESCRIPTION = '로그인 후 채팅에 참여할 수 있습니다!'; interface ChatInputProps { onSend: (message: string) => void; @@ -15,7 +17,7 @@ export default function ChatInput({ onSend }: ChatInputProps) { const inputRef = useRef(null); - function handleSubmit(event: React.FormEvent) { + const handleSubmit = useCallback((event: React.FormEvent) => { event.preventDefault(); const disabledChatting = !isAuthenticated; @@ -29,9 +31,7 @@ export default function ChatInput({ onSend }: ChatInputProps) { onSend(inputRef.current.value); inputRef.current.value = ''; } - } - - const ProtectedWrapper = withAuth(() => 보내기); + }, [isAuthenticated]); return (
diff --git a/packages/user/src/components/event/racing/dashboard/card/index.tsx b/packages/user/src/components/event/racing/dashboard/card/index.tsx index 03c4128a..409e5d1c 100644 --- a/packages/user/src/components/event/racing/dashboard/card/index.tsx +++ b/packages/user/src/components/event/racing/dashboard/card/index.tsx @@ -1,34 +1,33 @@ import { Category } from '@softeer/common/types'; -import { useState } from 'react'; +import { memo, useState } from 'react'; import TriggerButtonWrapper from 'src/components/common/TriggerButtonWrapper.tsx'; -import TeamSelectModal from 'src/components/shared/modal/teamSelectModal/index.tsx'; +import TeamSelectModal, { type TeamSelectModalProps } from 'src/components/shared/modal/teamSelectModal/index.tsx'; import ShareCountTeamCard from 'src/components/shared/ShareCountTeamCard.tsx'; import withAuth from 'src/components/shared/withAuthHOC.tsx'; import useAuth from 'src/hooks/useAuth.tsx'; import UnassignedCard from './UnassignedCard.tsx'; +const ProtectedTeamSelectModal = memo(withAuth(TeamSelectModal)); + export default function RacingCard() { const { user } = useAuth(); const [type, setType] = useState(user?.type); - const ProtectedTeamSelectModal = withAuth(() => ( - - - - } - onClose={() => setType(user?.type)} // onClose를 사용해 타입을 설정 - /> - )); - return (
{type ? ( ) : ( - } /> + + + + } + onClose={() => setType(user?.type)} + unauthenticatedDisplay={} + /> )}
); diff --git a/packages/user/src/components/shared/modal/teamSelectModal/index.tsx b/packages/user/src/components/shared/modal/teamSelectModal/index.tsx index 31fb8b39..76162ae5 100644 --- a/packages/user/src/components/shared/modal/teamSelectModal/index.tsx +++ b/packages/user/src/components/shared/modal/teamSelectModal/index.tsx @@ -4,7 +4,7 @@ import PendingStep from 'src/components/shared/modal/PendingStep.tsx'; import useAuth from 'src/hooks/useAuth.tsx'; import TeamSelectModalContent from './ModalContent.tsx'; -interface TeamSelectModalProps extends Omit {} +export interface TeamSelectModalProps extends Omit {} export default function TeamSelectModal({ openTrigger, ...props }: TeamSelectModalProps) { const { user } = useAuth(); From 6f867051f94b9800bafd82d12e5d1a55a5bb85a7 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 18:44:37 +0900 Subject: [PATCH 14/19] =?UTF-8?q?fix:=20form=20tag=20=EC=A4=91=EC=B2=A9=20?= =?UTF-8?q?=EC=8B=9C=20=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20submit=20eve?= =?UTF-8?q?nt=20propagation=20=EB=A7=89=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/src/components/shared/modal/login/LoginStep.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/user/src/components/shared/modal/login/LoginStep.tsx b/packages/user/src/components/shared/modal/login/LoginStep.tsx index b12788ab..a977384f 100644 --- a/packages/user/src/components/shared/modal/login/LoginStep.tsx +++ b/packages/user/src/components/shared/modal/login/LoginStep.tsx @@ -4,6 +4,8 @@ import Button from 'src/components/common/Button.tsx'; import useSubmitLogin, { SubmitLoginRequest } from 'src/hooks/query/useSubmitLogin.ts'; import inputStyles from 'src/styles/input.ts'; +const SUBMIT_BUTTON_ID = 'submit-only-for-login'; + interface LoginStepProps { onMoveSuccessStep: () => void; } @@ -16,6 +18,7 @@ export default function LoginStep({ onMoveSuccessStep }: LoginStepProps) { const handleSubmit = (e: FormEvent) => { e.preventDefault(); + e.stopPropagation(); const submitData = { userId: inputRefs.current[0].value, password: inputRefs.current[1].value }; if (hasRequiredLoginFields(submitData)) { login(submitData, { @@ -26,6 +29,7 @@ export default function LoginStep({ onMoveSuccessStep }: LoginStepProps) { return ( @@ -54,7 +58,7 @@ export default function LoginStep({ onMoveSuccessStep }: LoginStepProps) { className={loginInputStyles} />
- From ff3947c37f809990356604e1409cb33d58e7cc09 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 18:45:15 +0900 Subject: [PATCH 15/19] =?UTF-8?q?fix:=20user=20id=20type=EC=9D=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=ED=95=98=EB=A9=B4=EC=84=9C=20=EB=82=B4?= =?UTF-8?q?=EA=B0=80=20=EB=B3=B4=EB=82=B8=20=EB=A9=94=EC=8B=9C=EC=A7=80?= =?UTF-8?q?=EC=9E=84=EC=9D=84=20=ED=99=95=EC=9D=B8=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B3=BC=EC=A0=95=EC=97=90=EC=84=9C=20type=EC=9D=B4=20?= =?UTF-8?q?=EB=A7=9E=EC=A7=80=20=EC=95=8A=EC=95=84=20=EB=B0=9C=EC=83=9D?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/user/src/components/event/chatting/Chat.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/user/src/components/event/chatting/Chat.tsx b/packages/user/src/components/event/chatting/Chat.tsx index 97cac372..da3a62ae 100644 --- a/packages/user/src/components/event/chatting/Chat.tsx +++ b/packages/user/src/components/event/chatting/Chat.tsx @@ -15,7 +15,7 @@ export default function Chat({ type, team, sender, content }: ChatProps) { case 'm': default: return ( - + {content} ); From 248f65fb95e92b053430c981910d5119cbb2478a Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 18:49:39 +0900 Subject: [PATCH 16/19] =?UTF-8?q?design:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=8A=A4=ED=85=9D=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/shared/modal/login/LoginStep.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/user/src/components/shared/modal/login/LoginStep.tsx b/packages/user/src/components/shared/modal/login/LoginStep.tsx index a977384f..a514a294 100644 --- a/packages/user/src/components/shared/modal/login/LoginStep.tsx +++ b/packages/user/src/components/shared/modal/login/LoginStep.tsx @@ -31,12 +31,12 @@ export default function LoginStep({ onMoveSuccessStep }: LoginStepProps) {

- 이벤트 참여를 위해 로그인을 진행해주세요 + 이벤트 참여를 위해
로그인을 진행해주세요

-
+
(inputRefs.current[0] = el!)} className={loginInputStyles} /> -
-
- From b3cdf26e000f83ec5cd1b08f319112c8f04f1248 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 18:50:23 +0900 Subject: [PATCH 17/19] =?UTF-8?q?rename:=20login=20step=20=EB=82=B4=20onSu?= =?UTF-8?q?ccess=20props?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/src/components/shared/modal/login/LoginStep.tsx | 8 +++----- packages/user/src/components/shared/modal/login/index.tsx | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/user/src/components/shared/modal/login/LoginStep.tsx b/packages/user/src/components/shared/modal/login/LoginStep.tsx index a514a294..104a1c15 100644 --- a/packages/user/src/components/shared/modal/login/LoginStep.tsx +++ b/packages/user/src/components/shared/modal/login/LoginStep.tsx @@ -7,11 +7,11 @@ import inputStyles from 'src/styles/input.ts'; const SUBMIT_BUTTON_ID = 'submit-only-for-login'; interface LoginStepProps { - onMoveSuccessStep: () => void; + onSuccess: () => void; } // TODO: KAKAO OAuth -export default function LoginStep({ onMoveSuccessStep }: LoginStepProps) { +export default function LoginStep({ onSuccess }: LoginStepProps) { const { mutate: login } = useSubmitLogin(); const inputRefs = useRef([]); @@ -21,9 +21,7 @@ export default function LoginStep({ onMoveSuccessStep }: LoginStepProps) { e.stopPropagation(); const submitData = { userId: inputRefs.current[0].value, password: inputRefs.current[1].value }; if (hasRequiredLoginFields(submitData)) { - login(submitData, { - onSuccess: onMoveSuccessStep, - }); + login(submitData, { onSuccess }); } }; diff --git a/packages/user/src/components/shared/modal/login/index.tsx b/packages/user/src/components/shared/modal/login/index.tsx index c71d071e..db3afc63 100644 --- a/packages/user/src/components/shared/modal/login/index.tsx +++ b/packages/user/src/components/shared/modal/login/index.tsx @@ -13,7 +13,7 @@ export default function LoginModal({ openTrigger, ...props }: LoginModalProps) { - setStep('success')} /> + setStep('success')} /> 로그인 성공 From b4e515b3390ad88fc7c1f70ae8d746adb53a21d8 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 18:59:38 +0900 Subject: [PATCH 18/19] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=AC=20=EB=82=B4=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=84=B1=EA=B3=B5=20step=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/shared/modal/login/SuccessStep.tsx | 14 ++++++++++++++ .../src/components/shared/modal/login/index.tsx | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 packages/user/src/components/shared/modal/login/SuccessStep.tsx diff --git a/packages/user/src/components/shared/modal/login/SuccessStep.tsx b/packages/user/src/components/shared/modal/login/SuccessStep.tsx new file mode 100644 index 00000000..515f492a --- /dev/null +++ b/packages/user/src/components/shared/modal/login/SuccessStep.tsx @@ -0,0 +1,14 @@ +import useAuth from 'src/hooks/useAuth.tsx'; + +export default function SuccessStep() { + const { user } = useAuth(); + const displayName = user?.name ?? '사용자'; + + return ( +
+ 로그인 성공 캐스퍼 캐릭터 +

로그인 완료

+

{displayName}님 환영합니다!

+
+ ); +} diff --git a/packages/user/src/components/shared/modal/login/index.tsx b/packages/user/src/components/shared/modal/login/index.tsx index db3afc63..6638bf84 100644 --- a/packages/user/src/components/shared/modal/login/index.tsx +++ b/packages/user/src/components/shared/modal/login/index.tsx @@ -1,6 +1,7 @@ import Modal, { ModalProps } from 'src/components/common/Modal.tsx'; import useFunnel from 'src/hooks/useFunnel.ts'; import LoginStep from './LoginStep.tsx'; +import SuccessStep from './SuccessStep.tsx'; interface LoginModalProps extends Omit {} @@ -15,7 +16,7 @@ export default function LoginModal({ openTrigger, ...props }: LoginModalProps) { setStep('success')} /> - 로그인 성공 +
); From e3c81e3d4be308a7d97d314b8085f4ce908e5e49 Mon Sep 17 00:00:00 2001 From: nimod7890 Date: Thu, 15 Aug 2024 19:00:05 +0900 Subject: [PATCH 19/19] =?UTF-8?q?fix:=20ResultStepType=20import=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/user/src/components/shared/modal/fcfs/QuizStep.tsx | 2 +- .../user/src/components/shared/modal/fcfs/ResultStep.tsx | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/user/src/components/shared/modal/fcfs/QuizStep.tsx b/packages/user/src/components/shared/modal/fcfs/QuizStep.tsx index d35ee439..70b26480 100644 --- a/packages/user/src/components/shared/modal/fcfs/QuizStep.tsx +++ b/packages/user/src/components/shared/modal/fcfs/QuizStep.tsx @@ -4,7 +4,7 @@ import OptionButton from 'src/components/common/OptionButton.tsx'; import useGetFCFSQuiz from 'src/hooks/query/useGetFCFSQuiz.ts'; import useSubmitFCFSQuiz, { SubmitFCFSQuizResponse } from 'src/hooks/query/useSubmitFCFSQuiz.ts'; -type ResultStepType = ReturnType; +export type ResultStepType = ReturnType; interface QuizStepProps { onStepChange: (step: ResultStepType | 'pending') => void; } diff --git a/packages/user/src/components/shared/modal/fcfs/ResultStep.tsx b/packages/user/src/components/shared/modal/fcfs/ResultStep.tsx index f707741f..db3a1772 100644 --- a/packages/user/src/components/shared/modal/fcfs/ResultStep.tsx +++ b/packages/user/src/components/shared/modal/fcfs/ResultStep.tsx @@ -1,5 +1,5 @@ import { ReactNode } from 'react'; -import type { ResultStepType } from 'src/components/shared/modal/fcfs/index.tsx'; +import type { ResultStepType } from './QuizStep.tsx'; interface ResultStepProps { step: ResultStepType; @@ -8,9 +8,10 @@ interface ResultStepProps { export default function ResultStep({ step }: ResultStepProps) { const imageUrl = IMAGE_URLS[step]; const { title, subTitle, details } = DESCRIPTIONS[step]; + return (
- modal + {`${step}

{title}

{subTitle}

{details}