From 84d10757952d0c8fd09f58c3d029dd1fd5de7ec1 Mon Sep 17 00:00:00 2001 From: Eugene Kim <67894159+eugene028@users.noreply.github.com> Date: Mon, 12 Aug 2024 01:23:27 +0900 Subject: [PATCH] =?UTF-8?q?[Deploy]=20:=20wow-onboarding=202.0.0=20?= =?UTF-8?q?=EB=B0=B0=ED=8F=AC=20(#98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: cookie test * fix: 개발 환경 https 설정 제거 * chore: mkcert 패키지 제거 * chore: PR 템플릿 생성 * [Chore] 패키지 매니저를 pnpm으로 변경해요. (#52) * chore: 패키지 매니저 pnpm으로 변경 * chore: yaml파일 삭제 * fix : eslint,prettier 제대로 되게 수정 * [Chore] client 서비스에 wow-design 시스템을 적용해요. (#56) * feature: wowds로 마이그레이션 * fix: 디자인 시스템 마이그레이션 * feature: wow design system으로 마이그레이션 * fix: wowds 기본 CSS 설치 * feat : 디스코드 튜토리얼 UI 1차 반영 * feat : 가이드까지 UI 완성 * feat : width 에도 반영 * fix : spaceKet 로 타입 수정 * feat : spacing 토큰 변경 * feat : ㄹ리뷰 반영 * feat : 디스코드 api 연결 * feat : Image 컴포넌트 타입 수정 * fix: space 토큰 수정 * [Feature] github 로그인 페이지를 2차 MVP 페이지에 맞게 수정해요. (#62) * feature: github 로그인 페이지 생성 * fix: 패키지 매니저 구성 변경 * fix: 패키지 구성 변경 * refactor : 리팩토링 및 변수명 변경 * fix: 하드코딩된 토큰 환경변수에 저장 * Create CODEOWNERS * [Feature] 대시보드 2차 MVP DTO에 맞게 뷰를 수정해요. (#57) * chore: 패키지 매니저 pnpm으로 변경 * chore: yaml파일 삭제 * feature: 새롭게 바뀐 DTO 반영 * chore: 컴포넌트 단순화 분리 작업 * feature: Mypage status 생성 * feature: wowds로 마이그레이션 * fix: 디자인 시스템 마이그레이션 * feature: wow design system으로 마이그레이션 * fix: 이것저것 반영 * feature: 대시보드 2차 MVP 틀 구현 * fix: 메인화면 네임 수정 * #51: #51: WIP on feature/#51 * feature: helpBox 생성 * fix: 서버 번경 사항 챙기기 * feat: 정회원 버튼 생성 * feat: react-hook-form 기본 세팅 * feat: signup 페이지 완성 * fix: 백엔드 DTO 변경에 따른 반영 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 - 랜더링 최적화 * fix: 패키지 변경사항 반영 * [Feature] 기본 회원 정보를 받을 수 있는 Signup 페이지를 2차 MVP에 맞게 수정해요. (#60) * chore: 패키지 매니저 pnpm으로 변경 * chore: yaml파일 삭제 * feature: 새롭게 바뀐 DTO 반영 * chore: 컴포넌트 단순화 분리 작업 * feature: Mypage status 생성 * feature: wowds로 마이그레이션 * fix: 디자인 시스템 마이그레이션 * feature: wow design system으로 마이그레이션 * fix: 이것저것 반영 * feature: 대시보드 2차 MVP 틀 구현 * fix: 메인화면 네임 수정 * #51: #51: WIP on feature/#51 * feature: helpBox 생성 * fix: 서버 번경 사항 챙기기 * feat: 정회원 버튼 생성 * feat : wow ui 설치 * feat: react-hook-form 기본 세팅 * fix: 백엔드 api 명세 변경에 따른 프론트 수정 사항 반영 * fix: progressBar wow-ui로 변경 * fix: helpBox 안맞는 부분 수정 * fix: accesstoken 지우기 * feat: signup 페이지 완성 * fix: 코드리뷰 반영 * fix : pnpm install * refactor : query 관련 훅으로 리팩토링, Space 컴포넌트 수정 * fix: getValues 로 수정 * refactor: react-hook-form 의 pattern 사용해서 유효성 검증 * feat : 라우팅 반영 * style : width 100% 수정 * [Feature] 정회원 지원하기 액션시트를 생성하고, API를 연결해요. (#63) * chore: 패키지 매니저 pnpm으로 변경 * chore: yaml파일 삭제 * feature: 새롭게 바뀐 DTO 반영 * chore: 컴포넌트 단순화 분리 작업 * feature: Mypage status 생성 * feature: wowds로 마이그레이션 * fix: 디자인 시스템 마이그레이션 * feature: wow design system으로 마이그레이션 * fix: 이것저것 반영 * feature: 대시보드 2차 MVP 틀 구현 * fix: 메인화면 네임 수정 * #51: #51: WIP on feature/#51 * feature: helpBox 생성 * fix: 서버 번경 사항 챙기기 * feat: 정회원 버튼 생성 * feat: BottomSheet context 생성 * feat : wow ui 설치 * feat: react-hook-form 기본 세팅 * fix: 백엔드 api 명세 변경에 따른 프론트 수정 사항 반영 * fix: progressBar wow-ui로 변경 * fix: helpBox 안맞는 부분 수정 * fix: accesstoken 지우기 * chore: 패키지 업데이트 * feat: BottomSheet 기본 틀 잡기 * feat: 바텀시트 기본 틀 다잡아두기 * feature: API 연결 * fix: pc화면에서 어색해보이지 않도록 가운데 정렬 * fix: 준회원일 경우에만 가입 BottomSheet 보이게끔 * fix: merge 삑난거 수정하기 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: bottomSheet overlay fixed로 변경하기 * fix: 코드리뷰 반영 * [Feature] Bevy 가입 인증 절차를 생성해요. (#70) * feat: 기본 Bevy 뷰 생성 * fix: useMutation으로 API 분리 * fix: 사용하지 않는 파일 삭제 * [Feature] 홍익대학교 Gmail을 통해 재학생 인증 기능을 만들어요. (#67) * feat: 인증하기 초기 화면 디자인 변경 * fix : 필요없는 파일 삭제 * fix: API 객체로 변경 * fix: 이메일 인증 화면 변경하기 * feat: 재학생 인증 실패/성공 화면 만들기 * fix: 백엔드 API 반영 전 상태로 되돌리기 * fix: 코드리뷰 작성 * fix: preventReload 적용 * fix: 버튼 삑나간거 고치기 * fix: media query 중단점 수정 * fix: wowds ui 업데이트 * fix: code를 서버에게 보내요. * feat: 회비 납부 플로우 추가 * feat: 토스페이먼츠 결제하기 라우팅 * feat: 토스페이먼츠 클라이언트키 임시등록 * feat: 총 결제금액 표시 * feat: 결제 성공 시 마이페이지로 리다이렉트 * chore: 결제 위젯 연동에 필요한 패키지 설치 * fix: PENDING 상태일 때만 결제창 띄움 * fix: 총 결제 금액 임시 하드코딩 * feat: coupon API 추가 * design: 결제창 레이아웃 변경 * feat: 결제 성공 및 실패 화면, 라우팅 * chore: wowds-ui 설치 * feat: wowds로 마이그레이션 * design: wowds UI 적용 * fix: Box 테두리 색상 임시 변경 * feat: 결제정보 전달 API * feat: 유저정보 API 임시설정 * feat: 쿠폰 타입 변경 * feat: 토스페이먼츠 최신 API 임시 구현 사항 * fix: API post -> get * chore: payments 라이브러리 업데이트 * feat: 토스페이먼츠 위젯 라이브러리 업데이트에 의한 기능구현 변경 * feat: useProduct hook으로 결제 관리 * fix: 결제 실패 시 쿠폰 적용 페이지로 라우팅 * chore: react-secure-storage 설치 * feat: ENV 추가 * feat: 결제 정보 암호화, 로컬스토리지 저장 * fix: 할인금액이 있을 때만 노출 * feat: 결제 실패 시 로컬스토리지 초기화 * fix: 스토리지 리턴타입 단언 * fix: 토스페이먼츠 타입 any 허용 * refactor: 회비 납부 페이지 컴포넌트 분리 * feat: 임시 주문과 결제 승인 API 구분하기 * fix: 토스페이먼츠 테스트를 위한 로직 수정 * feat: 주문완료 API 추가 * design: 회비 납부 UI 수정 * feat: 쿠폰 정보 추가 * refactor: 라우팅 없이 결제 위젯 연결 * fix: 결제 실패 시 라우팅 변경 * fix: 스토리지 관련 로직 삭제 * fix: 스토리지 관련 로직 삭제 * refactor: useProduct 훅, 관련 로직 리렌더링 최소화 리팩토링 * fix: 스토리지 clear 로직 삭제 * fix: 테스트용 API 제거 * chore: 주석 제거 * chore: console.log 삭제 * chore: wowds-ui 버전업 * refactor: 쿠폰 드롭다운 * feat: 무료 주문 생성 API * feat: 주문 생성 API mutation hook으로 변경, 총 가격에 따른 API 조건부 반환 * feat: 주문 완료 API mutation hook으로 변경 * fix : 빌드 에러 수정 , ci 작성 * fix : ci 수정 * fix :svg 속성, 필요없는 컴포넌트 삭제 * fix : 안쓰는 api 삭제 * [Fix]: 디스코드 연동 마이너 이슈 수정 (#75) * fix: 디스코드 합류 체크 관련 API 호출 개선 및 문구 변경 * fix: 메서드 잘못된거 하나 슬쩍 고치기 * fix: API 문서 수정 * [Fix]: Signup 페이지 마이너 UI 이슈 수정 (#74) * fix: signup 마이너 UI 이슈 수정 * fix: 안쓰는 스타일 객체 일단 삭제 * feat: 푸터 텍스트 로고 추가 * feat: 푸터 UI * fix: 기존 홈 온보딩 이미지 삭제 * feat : qa반영 * fix : 불필요한 스타일 삭제, 텍필에 100% 추가 * [Refactor] : 학교 이메일 인증 페이지 QA 개선 반영 (#80) * fix: email 인증 error코드 중복 제거 * refac: 스팸메일함 안내문구 추가 * chore: 채널톡 위젯 삭제 * [Refactor] : Signup 페이지 QA 개선 반영 (#79) * fix: 하단 absolute 처리 * fix: bottom간격 해결 * fix: signup QA * chore: wow-ui 버전 업데이트 * [Feature]: Sentry 세팅 (#81) * chore: sentry 패키지 기본 설치 * feat: Sentry ErrorBoundary 추가 * fix: sentry 관련 기본적인 세팅 완료 * fix: json 문법 수정 * fix: Chatbot 삭제 * fix: 브라우저 설정 환경에 따른 sentry 세팅 * fix: 필요없는 dev 세팅 환경 지우기 * fix: 논리 테스트 (#82) * [Chore]: Sentry 논리 되돌리기 (#83) * fix: 논리 테스트 * fix: sentry 논리판단 되돌리기 * [Chore] : 빌드로그에서 vercel 환경변수 볼 수 있도록 하기 (#84) * fix: 논리 테스트 * fix: sentry 논리판단 되돌리기 * chore: console 테스트 * fix: 로딩 스피너 추가 및 기존 패키지 제거 (#89) * [Refactor]: 마이너 UI 이슈 수정 (#90) * fix: textfield 가로길이 안맞는 부분 수정 * fix: scroll 반 쯤 내려가 있는 문제 해결 * [Refactor] : 결제 페이지에 준회원이 아닌 경우 접근하지 못하도록 해요. (#88) * fix: payment 가드 생성 * fix: 현재 모집기간 닫혀있을때 결제화면 접근 못함 * refac: 토스페이먼츠 접근 화면 가드 꼼꼼하게 다듬기 * fix: data undefined 처리 * fix: payment 성공화면 access화면 생성 * [Refactor]: 학교 이메일 인증 정책을 변경해요 (#91) * fix: email 인증 error코드 중복 제거 * refac: 스팸메일함 안내문구 추가 * chore: 채널톡 위젯 삭제 * fix: 학회원 모집 마감 처리 Box 생성 * fix: 이메일 인증 in_progress 단계 추가 * fix: 이미 사용하고 있는 타입으로 변경 * [Fix] 토스페이먼츠 QA 개선 반영 (#93) * [Fix]: 서버 로그인 로직 변경에 따른 AccessToken, RefeshToken 쿠키 세팅 제거 및 landingStatus 제거 (#87) * fix: 논리 테스트 * fix: sentry 논리판단 되돌리기 * chore: console 테스트 * fix: cookie base-url 상위 도메인으로 변경 * fix: landingStatus 로직 제거 * fix: 메인화면 지원하기 버튼 dashboard로 라우트 * fix:landingStatus 삭제 및 쿠키로직 수정 * fix: landingStatus 관련된 모든 로직 제거 * fix: 쿠키 판단 로직 재건 * fix: 필요없는 guard 모두 삭제 * fix: 리다이렉트 정리 * fix: 로그인 유지 시간 sessionStorage에서 확인 * fix: 쿠키 관련 도메인 로직 모두 삭제 * fix: Cookie 관련 모든 로직 삭제 * fix: 빌드에러 터지는거 해결 * fix: 서버에서 refresh갱신 실패할때 로그아웃 처리 * fix: 403 에러 왔을때 세션 만료 * fix: 모집 기간 마감 예외처리 * fix: 파일 확장명 변경 * [Fix] 토스페이먼츠 결제성공 페이지 가드 임시삭제 (#94) * fix: PaymentsSuccess 가드 임시 삭제 * fix: 전체 금액이 0 미만일 때 0으로 처리 * fix: 사용하지 않는 import 삭제 * fix: 디스코드 관련 qa 반영 * feat : 인증을 완료한 경우에는 대시보드로 라우팅 하는 가드 설정 * [Fix]: 0807 QA 반영 (#95) * fix: navigate 정상화 * fix: 모집 차수 깨져 보이는 현상 개선 * fix: 모집 기간 아닐 때 에러 화면 제거 * fix: signup화면 제출 문구 수정 * refac: 이메일 도메인 직접 입력할 수 있도록 변경 * feat: 로그아웃 로직 붙임 * fix: wowds-ui 버전 업데이트 * fix: username 닉네임 잘못된 부분 수정 * fix: 대기중 문구만 뜨는 것 고치기 * fix: console log 삭제 * fix: 합류 확인 여부 리팩토링 * fix: 로그인 코드 변경 * fix:joinServer 안내문구 * fix:빌드실패 고치기 * fix:서버 status 변경사항 반영 * fix: build 에러 해결 * fix: paymentStatus enum 변경 * [Fix] 토스페이먼츠 쿠폰 관련 QA 사항 반영 (#97) * feat: 총 금액이 0원 이하일 때와 아닐 때의 로직 분리 * fix: 로직 수정 및 에러 토스트 메시지로 변환 * fix: 톤매너 정립 --------- Co-authored-by: Eugene Kim --------- Co-authored-by: 강나연 Co-authored-by: 강나연 <103591752+kongnayeon@users.noreply.github.com> Co-authored-by: SeieunYoo Co-authored-by: SeieunYoo <101736358+SeieunYoo@users.noreply.github.com> Co-authored-by: hamo-o Co-authored-by: 이현영 <89445100+hamo-o@users.noreply.github.com> --- package.json | 9 +- pnpm-lock.yaml | 311 +++++++++++++++++- src/App.tsx | 12 +- src/apis/auth/authApi.ts | 9 + src/apis/discord/discordApi.ts | 2 +- src/apis/index.ts | 11 +- src/apis/member/memberType.ts | 3 +- src/components/ApiErrorBoundary.tsx | 3 +- src/components/auth/guard/AuthAccessGuard.tsx | 24 +- .../auth/guard/MypageAccessGuard.tsx | 14 - .../guard/OnboardingClosedAccessGuard.tsx | 14 - .../guard/OnboardingNotOpenedAccessGuard.tsx | 14 - .../auth/guard/PaymentAccessGuard.tsx | 58 ++++ .../auth/guard/PaymentSuccessAccessGuard.tsx | 49 +++ .../auth/guard/SignupAccessGuard.tsx | 11 - .../guard/StudentVerificationAccessGuard.tsx | 11 - .../auth/guard/VerificationGuard.tsx | 63 ++++ src/components/auth/guard/index.ts | 6 - .../JoinRegularMemberBottomSheet.tsx | 5 +- src/components/chatbot/ChannelService.ts | 64 ---- src/components/chatbot/Chatbot.tsx | 17 - src/components/common/LoadingSpinner.tsx | 31 ++ src/components/discordConnect/DiscordName.tsx | 8 +- .../discordConnect/DiscordNickName.tsx | 8 +- src/components/discordConnect/JoinServer.tsx | 29 +- src/components/layout/Header.tsx | 19 +- src/components/layout/Layout.tsx | 10 +- src/components/myPage/ApproveBox.tsx | 27 +- .../myPage/AssociateRequirementCheck.tsx | 87 +++-- src/components/myPage/BasicUserInfo.tsx | 14 +- src/components/myPage/JoinRegularMember.tsx | 19 +- src/components/myPage/JoinStatus.tsx | 6 +- src/components/payments/PaymentsWidget.tsx | 2 +- .../{auth => signup}/DepartmentSelect.tsx | 46 +-- src/components/signup/EmailInputField.tsx | 139 ++++++++ src/constants/environment.ts | 4 +- src/constants/landingStatus.ts | 11 - src/hooks/auth/useAuthToken.ts | 18 - src/hooks/auth/useStudentVerification.ts | 2 +- src/hooks/mutation/index.ts | 1 + src/hooks/mutation/useCreateUserBasicInfo.ts | 2 - src/hooks/mutation/useLogout.ts | 23 ++ src/hooks/mutation/usePostDiscordName.ts | 4 +- src/hooks/mutation/usePostDiscordNickname.ts | 4 +- src/hooks/mutation/usePostFreeOrder.ts | 22 ++ src/hooks/mutation/usePostOrder.ts | 6 +- src/hooks/mutation/usePostPrevOrder.ts | 14 +- src/hooks/mutation/useSendStudentEmail.ts | 3 - src/hooks/query/useGetDiscordJoined.ts | 10 +- src/hooks/zustand/useLandingStatus.ts | 31 -- src/hooks/zustand/useProduct.ts | 3 +- src/main.tsx | 43 ++- src/pages/Auth.tsx | 16 - src/pages/Dashboard.tsx | 8 +- src/pages/DiscordConnect.tsx | 2 +- src/pages/OnboardingClosed.tsx | 95 ------ src/pages/OnboardingNotOpened.tsx | 77 ----- src/pages/PaymentsCheckout.tsx | 24 ++ src/pages/PaymentsSuccess.tsx | 11 +- src/pages/SignUp.tsx | 153 +++------ src/pages/StudentVerification.tsx | 65 ++-- src/pages/index.ts | 2 - .../redirect/AuthServerRedirectNavigate.tsx | 27 +- .../StudentVerificationServerRedirect.tsx | 5 +- src/routes/index.tsx | 111 ++++--- src/routes/routePath.ts | 11 +- src/types/status.ts | 4 +- src/types/user.ts | 8 +- src/utils/auth.ts | 90 +---- src/utils/mypage/recruitmentNameFormat.ts | 14 +- src/utils/sentry.ts | 46 +++ src/utils/storage/key.ts | 9 - vite.config.ts | 19 +- 73 files changed, 1242 insertions(+), 911 deletions(-) create mode 100644 src/apis/auth/authApi.ts delete mode 100644 src/components/auth/guard/MypageAccessGuard.tsx delete mode 100644 src/components/auth/guard/OnboardingClosedAccessGuard.tsx delete mode 100644 src/components/auth/guard/OnboardingNotOpenedAccessGuard.tsx create mode 100644 src/components/auth/guard/PaymentAccessGuard.tsx create mode 100644 src/components/auth/guard/PaymentSuccessAccessGuard.tsx delete mode 100644 src/components/auth/guard/SignupAccessGuard.tsx delete mode 100644 src/components/auth/guard/StudentVerificationAccessGuard.tsx create mode 100644 src/components/auth/guard/VerificationGuard.tsx delete mode 100644 src/components/auth/guard/index.ts delete mode 100644 src/components/chatbot/ChannelService.ts delete mode 100644 src/components/chatbot/Chatbot.tsx create mode 100644 src/components/common/LoadingSpinner.tsx rename src/components/{auth => signup}/DepartmentSelect.tsx (54%) create mode 100644 src/components/signup/EmailInputField.tsx delete mode 100644 src/constants/landingStatus.ts delete mode 100644 src/hooks/auth/useAuthToken.ts create mode 100644 src/hooks/mutation/useLogout.ts create mode 100644 src/hooks/mutation/usePostFreeOrder.ts delete mode 100644 src/hooks/zustand/useLandingStatus.ts delete mode 100644 src/pages/OnboardingClosed.tsx delete mode 100644 src/pages/OnboardingNotOpened.tsx create mode 100644 src/utils/sentry.ts delete mode 100644 src/utils/storage/key.ts diff --git a/package.json b/package.json index 0fda0a7..c5f4747 100644 --- a/package.json +++ b/package.json @@ -26,14 +26,15 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.50.1", "react-router-dom": "^6.22.1", - "react-spinners": "^0.13.8", "react-toastify": "^10.0.4", - "zustand": "^4.5.0", + "wowds-icons": "^0.1.0", "wowds-tokens": "^0.0.9", - "wowds-ui": "^0.1.7", - "wowds-icons": "^0.1.0" + "zustand": "^4.5.0", + "wowds-ui": "^0.1.9" }, "devDependencies": { + "@sentry/react": "^8.22.0", + "@sentry/vite-plugin": "^2.21.1", "@storybook/addon-essentials": "^7.6.14", "@storybook/addon-interactions": "^7.6.14", "@storybook/addon-links": "^7.6.14", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4687c3b..dc189e9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,9 +44,6 @@ dependencies: react-router-dom: specifier: ^6.22.1 version: 6.22.1(react-dom@18.2.0)(react@18.2.0) - react-spinners: - specifier: ^0.13.8 - version: 0.13.8(react-dom@18.2.0)(react@18.2.0) react-toastify: specifier: ^10.0.4 version: 10.0.4(react-dom@18.2.0)(react@18.2.0) @@ -57,13 +54,19 @@ dependencies: specifier: ^0.0.9 version: 0.0.9 wowds-ui: - specifier: ^0.1.7 - version: 0.1.7(next@14.2.4)(react@18.2.0) + specifier: ^0.1.9 + version: 0.1.9(next@14.2.4)(react-dom@18.2.0)(react@18.2.0) zustand: specifier: ^4.5.0 version: 4.5.1(@types/react@18.2.58)(react@18.2.0) devDependencies: + '@sentry/react': + specifier: ^8.22.0 + version: 8.22.0(react@18.2.0) + '@sentry/vite-plugin': + specifier: ^2.21.1 + version: 2.21.1 '@storybook/addon-essentials': specifier: ^7.6.14 version: 7.6.17(@types/react-dom@18.2.19)(@types/react@18.2.58)(react-dom@18.2.0)(react@18.2.0) @@ -3010,6 +3013,210 @@ packages: dev: true optional: true + /@sentry-internal/browser-utils@8.22.0: + resolution: {integrity: sha512-R0u8KPaSivueIwUOhmYxcisKaJq3gx+I0xOcWoluDB3OI1Ds/QOSP/vmTsMg/mjwG/nUJ8RRM8pj0s8vlqCrjg==} + engines: {node: '>=14.18'} + dependencies: + '@sentry/core': 8.22.0 + '@sentry/types': 8.22.0 + '@sentry/utils': 8.22.0 + dev: true + + /@sentry-internal/feedback@8.22.0: + resolution: {integrity: sha512-Sy2+v0xBmVnZ5LQ48603CvLy5vVQvAZ+hc9xQSAHexts07NkvApMU1qv26YNwxlAWfDha1wXiW6ryd4YDzaoVA==} + engines: {node: '>=14.18'} + dependencies: + '@sentry/core': 8.22.0 + '@sentry/types': 8.22.0 + '@sentry/utils': 8.22.0 + dev: true + + /@sentry-internal/replay-canvas@8.22.0: + resolution: {integrity: sha512-/gV8qN3JqWw0LXTMuCGB8RDI8Bx1VESNRBdh/7Cmc5+hxYBfcketuix3S8mHWcE/JO+Ed9g1Abzys6GphTB9LA==} + engines: {node: '>=14.18'} + dependencies: + '@sentry-internal/replay': 8.22.0 + '@sentry/core': 8.22.0 + '@sentry/types': 8.22.0 + '@sentry/utils': 8.22.0 + dev: true + + /@sentry-internal/replay@8.22.0: + resolution: {integrity: sha512-sF8RyMPJP1fSIyyBDAbtybvKCu0dy8ZAfMwLP7ZqEnWrhZqktVuqM7/++EAFMlD5YaWJXm1IDuOXjgSQjUtSIQ==} + engines: {node: '>=14.18'} + dependencies: + '@sentry-internal/browser-utils': 8.22.0 + '@sentry/core': 8.22.0 + '@sentry/types': 8.22.0 + '@sentry/utils': 8.22.0 + dev: true + + /@sentry/babel-plugin-component-annotate@2.21.1: + resolution: {integrity: sha512-u1L8gZ4He0WdyiIsohYkA/YOY1b6Oa5yIMRtfZZ9U5TiWYLgOfMWyb88X0GotZeghSbgxrse/yI4WeHnhAUQDQ==} + engines: {node: '>= 14'} + dev: true + + /@sentry/browser@8.22.0: + resolution: {integrity: sha512-t3b+/9WWcP9SQTWwrHrB57B33ENgmUjyFlW2+JSlCXkSJBSmAoquPZ/GPjOuPaSr3HIA0mu9uEr4A41d5diASQ==} + engines: {node: '>=14.18'} + dependencies: + '@sentry-internal/browser-utils': 8.22.0 + '@sentry-internal/feedback': 8.22.0 + '@sentry-internal/replay': 8.22.0 + '@sentry-internal/replay-canvas': 8.22.0 + '@sentry/core': 8.22.0 + '@sentry/types': 8.22.0 + '@sentry/utils': 8.22.0 + dev: true + + /@sentry/bundler-plugin-core@2.21.1: + resolution: {integrity: sha512-F8FdL/bS8cy1SY1Gw0Mfo3ROTqlrq9Lvt5QGvhXi22dpVcDkWmoTWE2k+sMEnXOa8SdThMc/gyC8lMwHGd3kFQ==} + engines: {node: '>= 14'} + dependencies: + '@babel/core': 7.23.9 + '@sentry/babel-plugin-component-annotate': 2.21.1 + '@sentry/cli': 2.33.1 + dotenv: 16.4.5 + find-up: 5.0.0 + glob: 9.3.5 + magic-string: 0.30.8 + unplugin: 1.0.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@sentry/cli-darwin@2.33.1: + resolution: {integrity: sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==} + engines: {node: '>=10'} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@sentry/cli-linux-arm64@2.33.1: + resolution: {integrity: sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux, freebsd] + requiresBuild: true + dev: true + optional: true + + /@sentry/cli-linux-arm@2.33.1: + resolution: {integrity: sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux, freebsd] + requiresBuild: true + dev: true + optional: true + + /@sentry/cli-linux-i686@2.33.1: + resolution: {integrity: sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==} + engines: {node: '>=10'} + cpu: [x86, ia32] + os: [linux, freebsd] + requiresBuild: true + dev: true + optional: true + + /@sentry/cli-linux-x64@2.33.1: + resolution: {integrity: sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux, freebsd] + requiresBuild: true + dev: true + optional: true + + /@sentry/cli-win32-i686@2.33.1: + resolution: {integrity: sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==} + engines: {node: '>=10'} + cpu: [x86, ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@sentry/cli-win32-x64@2.33.1: + resolution: {integrity: sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@sentry/cli@2.33.1: + resolution: {integrity: sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==} + engines: {node: '>= 10'} + hasBin: true + requiresBuild: true + dependencies: + https-proxy-agent: 5.0.1 + node-fetch: 2.7.0 + progress: 2.0.3 + proxy-from-env: 1.1.0 + which: 2.0.2 + optionalDependencies: + '@sentry/cli-darwin': 2.33.1 + '@sentry/cli-linux-arm': 2.33.1 + '@sentry/cli-linux-arm64': 2.33.1 + '@sentry/cli-linux-i686': 2.33.1 + '@sentry/cli-linux-x64': 2.33.1 + '@sentry/cli-win32-i686': 2.33.1 + '@sentry/cli-win32-x64': 2.33.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + + /@sentry/core@8.22.0: + resolution: {integrity: sha512-fYPnxp7UkY2tckaOtivIySxnJvlbekuxs+Qi6rkUv9JpF+TYKpt7OPNUAbgVIhS0xazAEN6iKTfmnmpUbFRLmQ==} + engines: {node: '>=14.18'} + dependencies: + '@sentry/types': 8.22.0 + '@sentry/utils': 8.22.0 + dev: true + + /@sentry/react@8.22.0(react@18.2.0): + resolution: {integrity: sha512-LcO8SPfjYsx3Zvg1mQwjreVvtriVxde+6njIJyXU9TArB0e8bFexvd4MGXdBExgW9aY449hNaStgKRWMNHeVHQ==} + engines: {node: '>=14.18'} + peerDependencies: + react: ^16.14.0 || 17.x || 18.x || 19.x + dependencies: + '@sentry/browser': 8.22.0 + '@sentry/core': 8.22.0 + '@sentry/types': 8.22.0 + '@sentry/utils': 8.22.0 + hoist-non-react-statics: 3.3.2 + react: 18.2.0 + dev: true + + /@sentry/types@8.22.0: + resolution: {integrity: sha512-1MLK3xO+uF2oJaa+M98aLIrQsEHzV7xnVWPfE3MhejYLNQebj4rQnQKTut/xZNIF9W0Q+bRcakLarC3ce2a74g==} + engines: {node: '>=14.18'} + dev: true + + /@sentry/utils@8.22.0: + resolution: {integrity: sha512-0ITG2+3EtyMtyc/nQG8aB9z9eIQ4L43nM/KuNgYSnM1vPl/zegbaLT0Ek/xkQB1OLIOLkEPQ6x9GWe+248/n3g==} + engines: {node: '>=14.18'} + dependencies: + '@sentry/types': 8.22.0 + dev: true + + /@sentry/vite-plugin@2.21.1: + resolution: {integrity: sha512-i2PqeLafGBcSROnmr9mS0dL2/JBJji/4rJZ2U2A+tqtAhDAAaCUNalbn6xLp/hawLExt/wRuBj1J7j46sGDOaA==} + engines: {node: '>= 14'} + dependencies: + '@sentry/bundler-plugin-core': 2.21.1 + unplugin: 1.0.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: true + /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true @@ -4655,6 +4862,15 @@ packages: engines: {node: '>= 6.0.0'} dev: true + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} @@ -6764,6 +6980,16 @@ packages: path-is-absolute: 1.0.1 dev: true + /glob@9.3.5: + resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + fs.realpath: 1.0.0 + minimatch: 8.0.4 + minipass: 4.2.8 + path-scurry: 1.10.1 + dev: true + /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -6882,7 +7108,6 @@ packages: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} dependencies: react-is: 16.13.1 - dev: false /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -6914,6 +7139,16 @@ packages: - supports-color dev: true + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -7574,6 +7809,21 @@ packages: dependencies: js-tokens: 4.0.0 + /lottie-react@2.4.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + lottie-web: 5.12.2 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /lottie-web@5.12.2: + resolution: {integrity: sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==} + dev: false + /loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} dependencies: @@ -7609,6 +7859,13 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /magic-string@0.30.8: + resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + /make-dir@2.1.0: resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} engines: {node: '>=6'} @@ -7740,6 +7997,13 @@ packages: brace-expansion: 2.0.1 dev: true + /minimatch@8.0.4: + resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimatch@9.0.3: resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} @@ -7765,6 +8029,11 @@ packages: yallist: 4.0.0 dev: true + /minipass@4.2.8: + resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} + engines: {node: '>=8'} + dev: true + /minipass@5.0.0: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} @@ -8627,16 +8896,6 @@ packages: react: 18.2.0 dev: false - /react-spinners@0.13.8(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-3e+k56lUkPj0vb5NDXPVFAOkPC//XyhKPJjvcGjyMNPWsBKpplfeyialP74G7H7+It7KzhtET+MvGqbKgAqpZA==} - peerDependencies: - react: ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 - dependencies: - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - dev: false - /react-style-singleton@2.2.1(@types/react@18.2.58)(react@18.2.0): resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} @@ -9720,6 +9979,15 @@ packages: engines: {node: '>= 0.8'} dev: true + /unplugin@1.0.1: + resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==} + dependencies: + acorn: 8.12.0 + chokidar: 3.6.0 + webpack-sources: 3.2.3 + webpack-virtual-modules: 0.5.0 + dev: true + /unplugin@1.7.1: resolution: {integrity: sha512-JqzORDAPxxs8ErLV4x+LL7bk5pk3YlcWqpSNsIkAZj972KzFZLClc/ekppahKkOczGkwIG6ElFgdOgOlK4tXZw==} dependencies: @@ -9918,6 +10186,10 @@ packages: engines: {node: '>=10.13.0'} dev: true + /webpack-virtual-modules@0.5.0: + resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} + dev: true + /webpack-virtual-modules@0.6.1: resolution: {integrity: sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==} dev: true @@ -10001,15 +10273,18 @@ packages: resolution: {integrity: sha512-fMGyb92sZ1iSf0TGSabQVym/MWsYyfetgBBNbZ0K6eGfESKtZF8AM1aDYRODmwyPkPSnt0SmOtRWMDxnPsnCqg==} dev: false - /wowds-ui@0.1.7(next@14.2.4)(react@18.2.0): - resolution: {integrity: sha512-ls2SnsTVfZpF2IOVu1N0FSo+XdGtlxtp+YOTwdd/l2lLX+Mh99/HKLsH6Q36p+yRF9zu0iiHv5dIlX790jvkOg==} + /wowds-ui@0.1.9(next@14.2.4)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-MDH0HqUCoRlHF1jtl+S6h+vusy5Lli+SVdu2SLhTaxlWJ6JQIqubesvNa16vaq/hRpn4WByX6x+aHrtM57cz3A==} peerDependencies: next: ^14.1.1 react: ^18.2.0 dependencies: + lottie-react: 2.4.0(react-dom@18.2.0)(react@18.2.0) next: 14.2.4(@babel/core@7.23.9)(react-dom@18.2.0)(react@18.2.0)(sass@1.71.1) react: 18.2.0 wowds-icons: 0.1.1 + transitivePeerDependencies: + - react-dom dev: false /wrap-ansi@7.0.0: diff --git a/src/App.tsx b/src/App.tsx index be0eca6..b952095 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -12,9 +12,8 @@ import styled from '@emotion/styled'; import { css } from '@emotion/react'; import GlobalSize from '@/constants/globalSize'; import { useNavigate } from 'react-router-dom'; -import { getAuthRedirectPath } from '@/utils/auth'; import 'react-toastify/dist/ReactToastify.css'; -import useLandingStatus from '@/hooks/zustand/useLandingStatus'; +import RoutePath from './routes/routePath'; const IMG_SRC = [ '/onboarding/1.png', @@ -29,7 +28,6 @@ const IMG_SRC = [ function App() { const navigate = useNavigate(); - const { landingStatus } = useLandingStatus(); return ( @@ -162,12 +160,8 @@ function App() { - navigate(getAuthRedirectPath(landingStatus))}> - {landingStatus === 'ONBOARDING_CLOSED' - ? '지금은 지원 기간이 아니에요' - : '가입하기'} + navigate(RoutePath.Dashboard)}> + 가입하기 diff --git a/src/apis/auth/authApi.ts b/src/apis/auth/authApi.ts new file mode 100644 index 0000000..150379e --- /dev/null +++ b/src/apis/auth/authApi.ts @@ -0,0 +1,9 @@ +import apiClient from '..'; + +const authApi = { + LOGOUT: async () => { + const response = await apiClient.get(`/auth/logout`); + return response.data; + } +}; +export default authApi; diff --git a/src/apis/discord/discordApi.ts b/src/apis/discord/discordApi.ts index 5a795d6..40810f3 100644 --- a/src/apis/discord/discordApi.ts +++ b/src/apis/discord/discordApi.ts @@ -25,7 +25,7 @@ const discordApi = { }); return response.data; }, - GET_DISCORD_JOIN: async (name: string) => { + GET_DISCORD_JOIN: async (name: string): Promise<{ isJoined: boolean }> => { const response = await apiClient.get('/onboarding/check-discord-join', { params: { username: name diff --git a/src/apis/index.ts b/src/apis/index.ts index a09ed77..ff10199 100644 --- a/src/apis/index.ts +++ b/src/apis/index.ts @@ -1,5 +1,4 @@ import { BASE_URL, DEV_AUTH_TOKEN } from '@/constants/environment'; -import useAuthToken from '@/hooks/auth/useAuthToken'; import axios from 'axios'; const apiClient = axios.create({ @@ -8,8 +7,12 @@ const apiClient = axios.create({ withCredentials: true }); -apiClient.defaults.headers.common['Authorization'] = DEV_AUTH_TOKEN - ? `${DEV_AUTH_TOKEN}` - : `Bearer ${useAuthToken().accessToken}`; +export function setAuthHeader() { + if (DEV_AUTH_TOKEN) { + apiClient.defaults.headers.common['Authorization'] = DEV_AUTH_TOKEN; + } +} + +setAuthHeader(); export default apiClient; diff --git a/src/apis/member/memberType.ts b/src/apis/member/memberType.ts index 13f24eb..abd5ae0 100644 --- a/src/apis/member/memberType.ts +++ b/src/apis/member/memberType.ts @@ -1,6 +1,5 @@ -import { Status } from '@/types/status'; import { User } from '@/types/user'; - +import { Status } from '@/types/status'; export interface MemberInfoResponse { member: User; currentRecruitmentRound: CurrentRecruitmentType; diff --git a/src/components/ApiErrorBoundary.tsx b/src/components/ApiErrorBoundary.tsx index 29bb051..d0efcd9 100644 --- a/src/components/ApiErrorBoundary.tsx +++ b/src/components/ApiErrorBoundary.tsx @@ -31,7 +31,8 @@ export default function ApiErrorBoundary({ children }: PropsWithChildren) { case 401: case 403: toast.error(message); - redirect(RoutePath.Index); + sessionStorage.setItem('isLogin', 'false'); + redirect(RoutePath.Home); break; default: toast.error(message); diff --git a/src/components/auth/guard/AuthAccessGuard.tsx b/src/components/auth/guard/AuthAccessGuard.tsx index a147080..9ea265b 100644 --- a/src/components/auth/guard/AuthAccessGuard.tsx +++ b/src/components/auth/guard/AuthAccessGuard.tsx @@ -1,13 +1,25 @@ -import useLandingStatus from '@/hooks/zustand/useLandingStatus'; -import { useEffect } from 'react'; -import { Outlet } from 'react-router-dom'; +import RoutePath from '@/routes/routePath'; +import { isAuthenticated } from '@/utils/auth'; +import { toast } from 'react-toastify'; +import { useNavigate, Outlet } from 'react-router-dom'; +import { useEffect, useState } from 'react'; export default function AuthAccessGuard() { - const { clearLandingStatus } = useLandingStatus(); + const navigate = useNavigate(); + const [redirect, setRedirect] = useState(false); useEffect(() => { - clearLandingStatus(); + if (!isAuthenticated()) { + toast.error('로그인이 필요한 서비스예요.'); + setRedirect(true); + } }, []); - return ; + useEffect(() => { + if (redirect) { + navigate(RoutePath.Home); + } + }, [redirect, navigate]); + + return isAuthenticated() ? : null; } diff --git a/src/components/auth/guard/MypageAccessGuard.tsx b/src/components/auth/guard/MypageAccessGuard.tsx deleted file mode 100644 index c0ff901..0000000 --- a/src/components/auth/guard/MypageAccessGuard.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import LandingStatus from '@/constants/landingStatus'; -import useLandingStatus from '@/hooks/zustand/useLandingStatus'; -import { getAuthRedirectPath } from '@/utils/auth'; -import { Navigate, Outlet } from 'react-router-dom'; - -export default function MypageAccessGuard() { - const { landingStatus } = useLandingStatus(); - - if (landingStatus !== LandingStatus.Dashboard) { - return ; - } - - return ; -} diff --git a/src/components/auth/guard/OnboardingClosedAccessGuard.tsx b/src/components/auth/guard/OnboardingClosedAccessGuard.tsx deleted file mode 100644 index a4f8916..0000000 --- a/src/components/auth/guard/OnboardingClosedAccessGuard.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import LandingStatus from '@/constants/landingStatus'; -import useLandingStatus from '@/hooks/zustand/useLandingStatus'; -import { getAuthRedirectPath } from '@/utils/auth'; -import { Navigate, Outlet } from 'react-router-dom'; - -export default function OnboardingClosedAccessGuard() { - const { landingStatus } = useLandingStatus(); - - if (landingStatus !== LandingStatus.OnboardingClosed) { - return ; - } - - return ; -} diff --git a/src/components/auth/guard/OnboardingNotOpenedAccessGuard.tsx b/src/components/auth/guard/OnboardingNotOpenedAccessGuard.tsx deleted file mode 100644 index 09a6899..0000000 --- a/src/components/auth/guard/OnboardingNotOpenedAccessGuard.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import LandingStatus from '@/constants/landingStatus'; -import useLandingStatus from '@/hooks/zustand/useLandingStatus'; -import { getAuthRedirectPath } from '@/utils/auth'; -import { Navigate, Outlet } from 'react-router-dom'; - -export default function OnboardingNotOpenedAccessGuard() { - const { landingStatus } = useLandingStatus(); - - if (landingStatus !== LandingStatus.OnboardingNotOpened) { - return ; - } - - return ; -} diff --git a/src/components/auth/guard/PaymentAccessGuard.tsx b/src/components/auth/guard/PaymentAccessGuard.tsx new file mode 100644 index 0000000..0337722 --- /dev/null +++ b/src/components/auth/guard/PaymentAccessGuard.tsx @@ -0,0 +1,58 @@ +import { useQuery } from '@tanstack/react-query'; +import memberApi from '@/apis/member/memberApi'; +import { useState, useEffect } from 'react'; +import { Outlet, useNavigate } from 'react-router-dom'; +import RoutePath from '@/routes/routePath'; +import { toast } from 'react-toastify'; +import LoadingSpinner from '@/components/common/LoadingSpinner'; + +const PaymentAccessGuard = () => { + const [redirect, setRedirect] = useState(false); + const navigate = useNavigate(); + const { data, isLoading } = useQuery({ + queryKey: ['member'], + queryFn: memberApi.GET_DASHBOARD + }); + + useEffect(() => { + if (!data) return; + + if (data.member.role !== 'ASSOCIATE') { + toast.error('준회원 조건을 충족해주세요.'); + setRedirect(true); + } + + if (!data.currentMembership) { + toast.error('정회원 지원 이후 학회비를 결제할 수 있어요.'); + setRedirect(true); + } + + if (!data.currentRecruitmentRound) { + toast.error('지금은 정회원 모집 기간이 아니에요.'); + setRedirect(true); + } + }, []); + + useEffect(() => { + if (redirect) { + navigate(RoutePath.Dashboard); + } + }, [redirect, navigate]); + + if (isLoading) { + return ; + } + + if (!data) return; + + if ( + data.member.role !== 'ASSOCIATE' || + !data.currentRecruitmentRound || + !data.currentMembership + ) { + navigate(RoutePath.Dashboard); + return null; + } else return ; +}; + +export default PaymentAccessGuard; diff --git a/src/components/auth/guard/PaymentSuccessAccessGuard.tsx b/src/components/auth/guard/PaymentSuccessAccessGuard.tsx new file mode 100644 index 0000000..d651bdc --- /dev/null +++ b/src/components/auth/guard/PaymentSuccessAccessGuard.tsx @@ -0,0 +1,49 @@ +import { useQuery } from '@tanstack/react-query'; +import memberApi from '@/apis/member/memberApi'; +import { useState, useEffect } from 'react'; +import { Outlet, useNavigate } from 'react-router-dom'; +import RoutePath from '@/routes/routePath'; +import { toast } from 'react-toastify'; +import LoadingSpinner from '@/components/common/LoadingSpinner'; + +const PaymentSuccessAccessGuard = () => { + const [redirect, setRedirect] = useState(false); + const navigate = useNavigate(); + const { data, isLoading } = useQuery({ + queryKey: ['member'], + queryFn: memberApi.GET_DASHBOARD + }); + + useEffect(() => { + if (!data) return; + + if (data.member.role !== 'REGULAR') { + toast.error('토스페이먼츠 결제를 완료해주세요.'); + setRedirect(true); + } + + if (!data.currentRecruitmentRound) { + toast.error('지금은 정회원 모집 기간이 아니에요.'); + setRedirect(true); + } + }, []); + + useEffect(() => { + if (redirect) { + navigate(RoutePath.Dashboard); + } + }, [redirect, navigate]); + + if (isLoading) { + return ; + } + + if (!data) return; + + if (data.member.role !== 'REGULAR' || !data.currentRecruitmentRound) { + navigate(RoutePath.Dashboard); + return null; + } else return ; +}; + +export default PaymentSuccessAccessGuard; diff --git a/src/components/auth/guard/SignupAccessGuard.tsx b/src/components/auth/guard/SignupAccessGuard.tsx deleted file mode 100644 index 94c42ac..0000000 --- a/src/components/auth/guard/SignupAccessGuard.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Outlet } from 'react-router-dom'; - -//deprecated: 추후 삭제 필요한 파일임 -export default function SignupAccessGuard() { - //TODO: 추후 보안 정책에 따라 수정 필요 - // if (landingStatus !== LandingStatus.Signup) { - // return ; - // } - - return ; -} diff --git a/src/components/auth/guard/StudentVerificationAccessGuard.tsx b/src/components/auth/guard/StudentVerificationAccessGuard.tsx deleted file mode 100644 index 7ec9007..0000000 --- a/src/components/auth/guard/StudentVerificationAccessGuard.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Outlet } from 'react-router-dom'; - -export default function StudentVerificationAccessGuard() { - // const { landingStatus } = useLandingStatus(); - - // if (landingStatus !== LandingStatus.StudentAuthentication) { - // return ; - // } - - return ; -} diff --git a/src/components/auth/guard/VerificationGuard.tsx b/src/components/auth/guard/VerificationGuard.tsx new file mode 100644 index 0000000..223dc83 --- /dev/null +++ b/src/components/auth/guard/VerificationGuard.tsx @@ -0,0 +1,63 @@ +import RoutePath from '@/routes/routePath'; +import { toast } from 'react-toastify'; +import { useNavigate } from 'react-router-dom'; +import { PropsWithChildren, useEffect } from 'react'; +import memberApi from '@/apis/member/memberApi'; +import { useQuery } from '@tanstack/react-query'; + +type GuardType = 'StudentVerification' | 'Discord' | 'SignUp' | 'Bevy'; + +interface VerificationGuardProps extends PropsWithChildren { + guardType: GuardType; +} +/** 기본 정보, 디스코드 정보, 이메일 정보가 인증되어 있는지에 대한 가드 */ + +export default function VerificationGuard({ + guardType, + children +}: VerificationGuardProps) { + const navigate = useNavigate(); + const { data } = useQuery({ + queryKey: ['member'], + queryFn: memberApi.GET_DASHBOARD + }); + + useEffect(() => { + if (!data) return; + + if ( + guardType === 'SignUp' && + data.member.associateRequirement.infoStatus === 'SATISFIED' + ) { + toast.error('기본 정보를 이미 입력했습니다.'); + navigate(RoutePath.Dashboard); + return; + } + if ( + guardType === 'Discord' && + data.member.associateRequirement.discordStatus === 'SATISFIED' + ) { + toast.error('디스코드 연동을 이미 완료했습니다.'); + navigate(RoutePath.Dashboard); + return; + } + if ( + guardType === 'StudentVerification' && + data.member.associateRequirement.univStatus === 'SATISFIED' + ) { + toast.error('재학생 인증을 이미 완료했습니다.'); + navigate(RoutePath.Dashboard); + return; + } + if ( + guardType === 'Bevy' && + data.member.associateRequirement.bevyStatus === 'SATISFIED' + ) { + toast.error('bevy 가입을 이미 완료했습니다.'); + navigate(RoutePath.Dashboard); + return; + } + }, [data, guardType, navigate]); + + return children; +} diff --git a/src/components/auth/guard/index.ts b/src/components/auth/guard/index.ts deleted file mode 100644 index 2d1665d..0000000 --- a/src/components/auth/guard/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { default as AuthAccessGuard } from './AuthAccessGuard'; -export { default as MypageAccessGuard } from './MypageAccessGuard'; -export { default as SignupAccessGuard } from './SignupAccessGuard'; -export { default as StudentVerificationAccessGuard } from './StudentVerificationAccessGuard'; -export { default as OnboardingNotOpenedAccessGuard } from './OnboardingNotOpenedAccessGuard'; -export { default as OnboardingClosedAccessGuard } from './OnboardingClosedAccessGuard'; diff --git a/src/components/bottomsheet/JoinRegularMemberBottomSheet.tsx b/src/components/bottomsheet/JoinRegularMemberBottomSheet.tsx index ad1ea79..b8b4ca6 100644 --- a/src/components/bottomsheet/JoinRegularMemberBottomSheet.tsx +++ b/src/components/bottomsheet/JoinRegularMemberBottomSheet.tsx @@ -19,7 +19,10 @@ const JoinRegularMemberBottomSheet = ({ currentRecruitment: CurrentRecruitmentType; }) => { const { joinRegularMember } = useJoinRegularMember(); - const bottomSheetTitle = convertRecruitmentName(currentRecruitment.name); + const bottomSheetTitle = convertRecruitmentName( + currentRecruitment.name, + currentRecruitment.roundTypeValue + ); const recruitmentPeriod = convertRecruitmentPeriod(currentRecruitment.period); return ( diff --git a/src/components/chatbot/ChannelService.ts b/src/components/chatbot/ChannelService.ts deleted file mode 100644 index 70e5326..0000000 --- a/src/components/chatbot/ChannelService.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -declare global { - interface Window { - ChannelIO: (arg0: string, arg1?: unknown, arg2?: unknown) => void; - ChannelIOInitialized: boolean; - } -} - -class ChannelService { - constructor() { - this.loadScript(); - } - - loadScript() { - const w = window; - if (w.ChannelIOInitialized) { - return; - } - const channelIO = function () { - // eslint-disable-next-line prefer-rest-params - channelIO.c(arguments); - }; - - channelIO.q = [] as any[]; - channelIO.c = function (args: any) { - channelIO.q.push(args); - }; - w.ChannelIO = channelIO; - function initializeChannelIO() { - if (w.ChannelIOInitialized) { - return; - } - w.ChannelIOInitialized = true; - const script = document.createElement("script"); - script.type = "text/javascript"; - script.async = true; - script.src = "https://cdn.channel.io/plugin/ch-plugin-web.js"; - const firstScript = document.getElementsByTagName("script")[0]; - if (firstScript?.parentNode) { - firstScript.parentNode.insertBefore(script, firstScript); - } - } - if (document.readyState === "complete") { - initializeChannelIO(); - } else { - w.addEventListener("DOMContentLoaded", initializeChannelIO); - w.addEventListener("load", initializeChannelIO); - } - } - boot(settings: any, callback: any) { - window.ChannelIO("boot", settings, callback); - } - onBadgeChanged(callback: (number: number) => void) { - window.ChannelIO("onBadgeChanged", callback); - } - addTags(tags: string[]) { - window.ChannelIO("addTags", tags); - } - shutdown() { - window.ChannelIO("shutdown"); - } -} - -export default ChannelService; diff --git a/src/components/chatbot/Chatbot.tsx b/src/components/chatbot/Chatbot.tsx deleted file mode 100644 index 422ef9e..0000000 --- a/src/components/chatbot/Chatbot.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { useEffect } from 'react'; - -import { CHANNELIO_PLUGIN_KEY } from '@constants/environment'; - -import ChannelService from '@/components/chatbot/ChannelService'; - -export default function Chatbot() { - useEffect(() => { - const channelTalk = new ChannelService(); - - channelTalk.boot({ pluginKey: CHANNELIO_PLUGIN_KEY }, () => {}); - - return () => channelTalk.shutdown(); - }, []); - - return