From 31dc427f5bcafae08aedf5670cdc2f0157647bc1 Mon Sep 17 00:00:00 2001 From: DaHyeonJu Date: Sun, 26 Nov 2023 23:46:52 +0900 Subject: [PATCH] =?UTF-8?q?[Deploy]=205=EC=B0=A8=20=EC=8A=A4=ED=94=84?= =?UTF-8?q?=EB=A6=B0=ED=8A=B8=20=EB=B0=B0=ED=8F=AC=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20(#164)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style : 전역 디자인 시스템 세팅 * style : 전역 디자인 시스템 세팅 * chore : 이슈 템플릿 수정 * refactor: build-test.yml 파일 수정 (#14) - node_modules 캐싱 기능 추가 - main, dev 브랜치 push, PR 시 빌드 테스트 돌아가도록 수정 Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * feature: deploy.yml 파일 추가 (#15) * feature: deploy.yml 파일 추가 - main 브랜치에 push할 때 S3로 파일 업로드 * fix: pre-push 코드 수정 * fix: deploy.yml 파일 수정 - build폴더가 아닌 dist 폴더로 수정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * [Style] 모바일 레이아웃 작업 (#19) * style : 모바일 레이아웃 작업 * chore : 이슈, pr 템플릿 docs 수정 * style: HeroImage, AlertText 공통 컴포넌트 제작 (#24) * style: HeroImage 추가 * style: AlertText * style: Input 공통 컴포넌트 (#26) * style: HeroImage 추가 * style: AlertText * style: Input * feature: Button 공통 컴포넌트 제작 (#20) * feature: 네이버, 카카오 아이콘 컴포넌트 추가 * feature: NormalButton 컴포넌트 추가 * feature: palette, typo 스타일 수정 * feature: Divider, Text 공통 컴포넌트 추가 * feature: IconButtons 추가 - 관심사, 네이버, 카카오, 특정 주제, 랜덤 매칭 버튼 * feature: Button 컴포넌트 사용법 + timeStamp 유틸 함수 추가 * feature: RandomMatchingJoin 버튼 추가 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * style : flexbox 컴포넌트 제작 (#32) * style : spacing 컴포넌트 생성 (#33) * [Feature] mock service worker settings (#29) * deploy: 초기 배포 (#23) * style : 전역 디자인 시스템 세팅 * style : 전역 디자인 시스템 세팅 * chore : 이슈 템플릿 수정 * refactor: build-test.yml 파일 수정 (#14) - node_modules 캐싱 기능 추가 - main, dev 브랜치 push, PR 시 빌드 테스트 돌아가도록 수정 Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * feature: deploy.yml 파일 추가 (#15) * feature: deploy.yml 파일 추가 - main 브랜치에 push할 때 S3로 파일 업로드 * fix: pre-push 코드 수정 * fix: deploy.yml 파일 수정 - build폴더가 아닌 dist 폴더로 수정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * [Style] 모바일 레이아웃 작업 (#19) * style : 모바일 레이아웃 작업 * chore : 이슈, pr 템플릿 docs 수정 --------- Co-authored-by: judahhh Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * chore : mock service worker 설치 및 세팅 * chore : mock service worder setting --------- Co-authored-by: Changuk Woo <43228743+wukdddang@users.noreply.github.com> Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * style: BottomSheet 컴포넌트 제작 (#34) * feature: Timer 컴포넌트 추가 + d3.js 라이브러리 설치 * feature: BottomSheet 컴포넌트 추가 * feature: RandomMatchingJoinButton props 수정 * feature: framer-motion 설치 + 애니메이션 효과 추가 * refactor: BottomSheet 폴더 변경 * refactor: isDarkMode 필수 타입으로 수정 * refactor: AlertText, HeroImage 폴더 구조 변경 * refactor: BottomSheet 컴포넌트 분리 * feature: Avatar 컴포넌트 제작 * refactor: RandomMatchingSheet 컴포넌트 이벤트 props 추가 * fix: package-lock.json 파일 오류 수정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * [Style/] navigation bar 컴포넌트 제작 (#37) * style : 네비게이션 바 디자인 * style : 네비게이션 바 디자인 및 라우팅 처리 * fix : 프로필 이미지를 Avatar 컴포넌트를 이용하도록 수정 * chore : 타입 에러 해결 * chore : 홈 페이지에 네비게이션 바 예시 제거 * style: CountNumber 공통 컴포넌트 제작 (#38) * style: CountNumber * feat: Input Wrapper 추가. * chore : CountNumber 폴더 구조 변경 * style: InputTimer 공통 컴포넌트 제작 (#41) * style: CountNumber * feat: Input Wrapper 추가. * style: InputTimer 제작 * style : 로딩 컴포넌트 제작 (#47) * style: WhiteSelectorButton, DarkSelectorButton 공통 컴포넌트 (#46) * style: whiteselectorButton * refactor: 불필요 주석 삭제 * style: darkselectorbutton * Update src/components/common/DarkSelectorButton/index.tsx * Update src/components/common/WhiteSelectorButton/index.tsx * fix: font-weight 오타 수정 --------- Co-authored-by: Changuk Woo <43228743+wukdddang@users.noreply.github.com> Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * style: ListRow 컴포넌트 제작 (#43) * refactor: Style prefix 붙이도록 수정 * refactor: Divider 컴포넌트 수정 + 웹 폰트 수정 - Divider 컴포넌트가 확장성 있도록 수정 - 웹 폰트 오타 수정 * feature: AdminListRow 컴포넌트 추가 - 관리자 페이지에 사용되는 ListRow 컴포넌트 * feature: ProfileListRow 컴포넌트 추가 - 프로필 페이지에 사용되는 ListRow --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * style: useToast 커스텀 훅 제작 (#48) * feature: useToast 커스텀 훅 추가 * refactor: RandomMatchingJoinButton으로 이름 변경 * feature: Layout 컴포넌트에 ToastContainer 설정 * refactor: NormalButton 컴포넌트 수정 - isDarkMode props 받도록 수정 * fix: RandomMatchingJoin.tsx 파일 오류 수정 * fix: 파일명 오류 수정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * [Style] Modal 컴포넌트 제작 (#52) * chore : zustand 설치 및 store 폴더 생성 * feat : 모달창 전역 상태 추가 * style : 모달창 컴포넌트 제작 * fix: package.json 쉼표 오류 * fix: package-lock.json 쉼표 오류 * fix : 모달창 type 받아 분기 처리 * fix : type 에러 수정 * chore : 주석 제거 * fix: isDarkMode 옵셔널로 수정 --------- Co-authored-by: Changuk Woo <43228743+wukdddang@users.noreply.github.com> Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * style: selector button 공통 컴포넌트 (#55) * refactor: white,dark selectorbutton erase * style: selectorbutton * style: selectorbutton re * style: Appbar, Card, GradationBackground, PageContainer 컴포넌트 추가 + Home 페이지 레이아웃 추가 (#57) * refactor: CountNumber, Input 위치 변경 * refactor: Avatar 컴포넌트 props 타입 수정 + tsdoc 추가 * feature: Tip 컴포넌트 추가 * feature: AppHeader 컴포넌트 추가 * refactor: IconButtonType 수정 + 클릭 효과 속성 추가 * feature: Profile 페이지 라우팅 추가 * refactor: AppHeader 높이값 받도록 수정 * style: typo, palette, Layout, global 파일 수정 * refactor: RandomMatchingSheet 동적으로 변하도록 수정 * refactor: NormalButton 폴더 변경 + 클릭 시 배경 변경 타입 추가 * refactor: tsdoc 추가 * feature: GradationBackground 컴포넌트 추가 * refactor: NavigationBar 라우팅 + position: sticky로 수정 * feature: PageContainer 컴포넌트 추가 * feature: AvatarGroup 컴포넌트 추가 * feature: Card 컴포넌트 추가 * feature: Home 페이지 레이아웃 추가 * refactor: tsdoc 추가 * fix: merge conflict 해결용 파일 추가 * fix: NormalButton 파일 에러 수정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * style: PageHeader 컴포넌트 제작 (#59) * feature: ExitIcon 컴포넌트 추가 * feature: BackChevron 컴포넌트 추가 * feature: PageHeader 컴포넌트 추가 * refactor: 사용하지 않는 코드 제거 * refactor: tsdoc 추가 * refactor: tsdoc 추가 + exitClick으로 props명 변경 * refactor: PageHeader border-bottom 수정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * [Style] chatting bubble 컴포넌트 제작 및 소켓 라이브러리 설치 (#65) * style : chatting bubble 컴포넌트 publishing * chore : 소켓 라이브러리 stomp 설치 및 세팅 * style: BusinessCardContainer 공통 컴포넌트 (재PR) (#62) * feat: businesscardcontainer * style: Text 컴포넌트 textColor 속성 추가 * test: API Test 코드 (#76) * feat: businesscardcontainer * style: Text 컴포넌트 textColor 속성 추가 * style: alerttext, countnumber 수정 * style: selectorbutton 수정 * style: customselectorbutton * refactor: 필수 prop 설정 * style: selectorbuttoncontainer * refactor: 함수컴포넌트 구조 변경 * refactor: react 삭제 * test: APITest 코드 * test: retest (#78) * fix: vite 설정 (cors) (#80) * test: retest * fix: vite 설정 (cors) * fix: cors 재설정 (#82) * test: retest * fix: vite 설정 (cors) * fix: cors2 * fix: vite 설정 변경 (#84) Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * fix: axios 파일 수정 (#86) Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * fix: REST API 주소 코드 수정 (#92) Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * refactor: AlertText, CountNumber 공통 컴포넌트 수정 (#68) * feat: businesscardcontainer * style: Text 컴포넌트 textColor 속성 추가 * style: alerttext, countnumber 수정 * refactor: pr 수정사항 반영 * refactor: styled emotion 코드 통일성 적용 * feature: HomePage 다크모드 기능 추가 + Card 컴포넌트 분리 + timerWorker 추가 (#94) * style: DARK_GRADIENT 색 추가 * feature: 다크모드/화이트모드 설정을 위한 ThemeStore 추가 * feature: ParticularTopicButton에 이동하는 props 추가 * feature: AppHeader 컴포넌트 다크모드 설정 기능 추가 * feature: PageContainer 컴포넌트 다크모드 props 추가 * refactor: Card 컴포넌트 코드 분리 * refactor: Tip 컴포넌트 주석 제거 + import문 수정 * feature: timerWorker 추가 + TimerStore 추가 - 백그라운드에서 동작하는 웹 워커로 타이머 동작 - 새로고침을 해도 계속 동작하지만 어플리케이션을 종료하면 동작 종료 - 현재 동기적으로 코드가 작동하고 있어서, indexedDB를 사용해서 비동기 동작을 지원하도록 수정할 계획 * feature: 다크모드 추가 - GradationBackground, NavigationBar, Home 페이지 * refactor: 사용하지 않는 코드 제거 * refactor: Card 컴포넌트 수정 -undefined값을 가지는 time props 수정 - navigationType 에러 수정 * refactor: AppHeader 컴포넌트 수정 - cursor: pointer 스타일 추가 * refactor: Styled prefix 사용하도록 PR 관련 코드 수정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * style: LoginPage 레이아웃 작성 (#96) * feat: businesscardcontainer * style: Text 컴포넌트 textColor 속성 추가 * style: alerttext, countnumber 수정 * style: selectorbutton 수정 * style: customselectorbutton * refactor: 필수 prop 설정 * style: selectorbuttoncontainer * refactor: 함수컴포넌트 구조 변경 * refactor: react 삭제 * style: LoginPage 레이아웃 작성 * refactor: 이미지 경로 변경 * refactor: pr 수정사항 반영 * refactor: LoginImage 경로 변경 * style: naver, kakao Button 텍스트 위치 수정 * refactor: frament 제거 * style: 배경색 skyblue 적용. 불필요 fragment 제거. * feature: NotFoundPage 제작 (#102) * refactor: font-family를 동적으로 변경하도록 수정 - 600 미만이면 'Pretendard-Regular' - 600 이상이면 'Pretendard' * feature: NotFound 페이지 제작 - NotFoundIcon 추가 * fix: GradationBackground 에 isDarkMode props 추가 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * refactor: SelectorButton 공통 컴포넌트 수정 (#70) * feat: businesscardcontainer * style: Text 컴포넌트 textColor 속성 추가 * style: alerttext, countnumber 수정 * style: selectorbutton 수정 * refactor: pr 수정사항 반영 * refactor: prop 명 변경 * refactor: 변수명 수정 * refactor: pr 재수정 * style: CustomSelectorButton 공통 컴포넌트 (#71) * feat: businesscardcontainer * style: Text 컴포넌트 textColor 속성 추가 * style: alerttext, countnumber 수정 * style: selectorbutton 수정 * style: customselectorbutton * refactor: 필수 prop 설정 * refactor: pr 수정사항 반영 * refactor: 속성명 수정 * style: SelectorButtonContainer 공통 컴포넌트 (#72) * feat: businesscardcontainer * style: Text 컴포넌트 textColor 속성 추가 * style: alerttext, countnumber 수정 * style: selectorbutton 수정 * style: customselectorbutton * refactor: 필수 prop 설정 * style: selectorbuttoncontainer * refactor: 함수컴포넌트 구조 변경 * refactor: react 삭제 * refactor: pr 수정사항 반영 * refactor: Input 컴포넌트 ref, onchange 추가 (#90) * refactor: Input 컴포넌트 ref, onchange 추가 * refactor: pr 수정사항 반영 * feature: 로그인 페이지 OAuth 연결 + 반응형 레이아웃 구성 (#107) * feature: LoginPendingPage 컴포넌트 추가 - App.tsx에 라우팅 추가 * refactor: 네이버, 카카오 버튼 props 수정 - moveToOAuthProvider props 받도록 수정 * refactor: HeroImage 크기 수정 * feature: LoginPending 페이지 추가 - zustand-persist로 현재 OAuth provider를 저장하도록 설정 - Status Code가 400이면 회원가입 페이지로 가도록 라우팅 * fix: 회원가입 리다이렉트 상태코드 404로 변경 * refactor: 로그인 페이지 반응형 구현 - Spacing 컴포넌트 css props 받도록 리팩토링 - max-width: 280px인 갤럭시 폴드를 중심으로 리팩토링 * refactor: 로그인 페이지 폰트 크기 반응형으로 수정 * feature: 로그인 리다이렉팅 시 authCode를 state에 담도록 수정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * hotfix: VITE_BASE_URL 환경변수 설정 (#113) * fix: VITE_BASE_URL 환경변수 설정 * fix: 띄어쓰기 오류 수정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * fix: OAuth 로그인 오류 처리 * [Feature] 사용자의 닉네임, 관심사 정보 등록 페이지 구현 (#119) * style : RegisterInput 공통 컴포넌트 제작 * feat : 유저 정보 등록 페이지 기능 구현 * fix : Oauth 로그인 후 authCode와 token을 받아와 넘겨주도록 수정 * chore : 사용되지 않는 import 문 삭제 * chore : msw 버전에 따른 import 수정 * chore : 사용되지 않은 변수 에러 해결 * chore : 주석 제거 * chore : 닉네임 중복 요청 react-query로 수정 * chore : 사용되지 않은 import 문 제거 * feature: ChatList 페이지 레이아웃 제작 + 반응형 디자인 (#97) * refactor: Home 레이아웃 수정 - PageContainer 스타일을 동적으로 받도록 수정 * refactor: PageContainer 컴포넌트 수정 - style props 받을 수 있도록 수정 - 다크모드 받을 수 있도록 수정 * refactor: 반응형 디자인 - AppHeader: max-width: 280px일 때 텍스트 폰트 줄이도록 수정 - Avatar: max-width: 280px일 때 아바타 크기 줄이도록 수정 * refactor: PageHeader 컴포넌트 수정 - max-width: 414px로 가지도록 수정 - cursor: pointer 가지도록 수정 * refactor: AvatarGroup 수정 - style props 받도록 수정 - AvatarGroup이 높이를 가지도록 수정 * refactor: Card 컴포넌트 수정 - PageContainer 수정에 따른 리팩토링 * feature: ChatList 페이지 구현 - chatRoomList 더미데이터 추가 - ChatRoomBubbles: chatRoomList를 받아서 ChatRoomBubble 렌더링 - ChatRoomBubble: 채팅방 생성 시점 기준 1일 이후를 D-Day로 설정한 타이머 추가 - max-width: 280px일 때 column이 하나로만 나오도록 반응형 디자인 * refactor: ChatRoomBubble 빌드 오류 수정 * fix: merge conflict 해결 * refactor: Card 컴포넌트의 Styled 태그 코드들 하단으로 이동 * hotfix: VITE_BASE_URL 환경변수 설정 (#113) * fix: VITE_BASE_URL 환경변수 설정 * fix: 띄어쓰기 오류 수정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * feature: 이전대화방 MSW 설정 + framer-motion 효과 추가 - /api/v1/histories로 이전 대화방 목록 요청하도록 세팅 (+useQuery) - 로컬에서도 MSW 동작할 수 있도록 설정 --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> * [Fix] 관심사 버튼 해제 시 전역 store에 반영되지 않는 문제 해결 (#121) * fix : axios 요청이 가지 않는 에러 해결 * chore : 주석 제거 * fix : 관심사 버튼 해제 시 전역 store에 반영되지 않는 문제 해결 * feature: 관리자 페이지 '승인 대기 목록', '사용자 신고 내역' 레이아웃작업, 컴포넌트 제작 (mergeX, draft 미적용) (#105) * style: AdminAppHeader 컴포넌트 추가 * style: AdminNavigationBar 컴포넌트 생성 * style: AdminNavigationBar 색 변경 * feat: AdminTabs 컴포넌트 추가 * refactor: 컴포넌트 변수명 변경 * refactor: 컴포넌트 변수명 변경 * feat: AdminApprovalList 컴포넌트 추가 * feat: outerwrapper 제거 * feat: AdminReportListRow 컴포넌트 예시 추가 * feat: AdminReportList 컴포넌트 예시 추가 * feat: AdminTabs 컴포넌트로 다른 컴포넌트들 연결 및 디자인 수정, 변수명 수정 * refactor: admin 컴포넌트 이전 * refactor: eslint 에러 수정 * refactor: import 경로 변경 --------- Co-authored-by: Changuk Woo <43228743+wukdddang@users.noreply.github.com> * feature: 관리자 페이지 레이아웃, 기능 구현 (mergeX, draft) (#116) * style: AdminAppHeader 컴포넌트 추가 * style: AdminNavigationBar 컴포넌트 생성 * style: AdminNavigationBar 색 변경 * feat: AdminTabs 컴포넌트 추가 * refactor: 컴포넌트 변수명 변경 * refactor: 컴포넌트 변수명 변경 * feat: AdminApprovalList 컴포넌트 추가 * feat: outerwrapper 제거 * feat: AdminReportListRow 컴포넌트 예시 추가 * feat: AdminReportList 컴포넌트 예시 추가 * feat: AdminTabs 컴포넌트로 다른 컴포넌트들 연결 및 디자인 수정, 변수명 수정 * refactor: admin 컴포넌트 이전 * refactor: eslint 에러 수정 * refactor: import 경로 변경 * feat: AdminApprovalInfo 컴포넌트 1 * style: 예시 이미지 추가 * feat: AdminApprovalInfo 컴포넌트 추가 1 * feat: input text fontweight 속성 추가 * style: Input 속성 추가 * style: AdminApprovalInfo 컴포넌트 디자인 2 * style: AdminReportInfo 컴포넌트 1 * refactor: props명 수정 * style: AdminReportInfo 컴포넌트 1 * style: AdminReportInfoListRow 컴포넌트 * feat: useModal 컴포넌트 적용, 기타 스타일 수정 * feat: AdminReportInfo 컴포넌트 userModal 적용 * refactor: 불필요 컴포넌트 삭제 * refactor: 이름 수정 * feat: AdminReportListRow 속성 추가 * feat: 관리자페이지 신고자 목록 클릭 시, 정보 출력 * feat: AdminReportList 특정 목록 클릭 시, 해당 AdminReportInfo 출력 * feat: AdminReportList mockdata 추가, 함수 연결 * refactor: 이름 예시 변경 * refactor: 변수명 수정 (adminapprovalinfo와 구분) * feat: AdminTabs 승인 탭 추가 * refactor: 변수명 수정(구별필요) * feat: 승인 페이지 이름 적용, 불필요 컴포넌트 제거 * refactor: mock data 적용. 변수명 수정. * feat: 승인페이지 mock data 적용. 목록 클릭 함수 추가. interface 추가. * feat: adminapprovallistrow onclick 함수 속성 추가 * style: ListRow의 ListContainer 가운데 정렬 * style: 중복 HomeNavigationBar 제거 * feat: AdminInfo 컴포넌트 AdminPageHeader컴포넌트 적용 * feat: AdminPageHeader 컴포넌트 추가 * style: Admin 컴포넌트 스타일 수정(폰트,cursor,가운데정렬등) * style: Input component padding 속성추가 * feat: adminlogin 컴포넌트 추가 * feat: adminapprovalinfo input 텍스트로 변경 (+스타일 적용) * style: 관리자 페이지 스타일 피그마 세부 적용 * chore : 개발 단계에서 토큰을 볼 수 있도록 수정 * chore : 잘못 import 된 import 문 제거 * chore : lint 에러 수정 * feature: 프로필 페이지 제작 (#109) * refactor: Modal 컴포넌트 관련 코드 리팩토링 - useModal: acceptText, cancelText 받도록 수정 - Modal: framer-motion으로 애니메이션 효과 추가 * refactor: tsdoc 추가 + CSS 스타일 수정 - tsdoc: NaverIcon, KakaoIcon - CSS 스타일 수정: AppHeader,Avatar, BackChevron * refactor: CSS 스타일 수정 - Divider: width, height props string으로 타입 수정 - InterestButton: width props string으로 수정 - NavigationBar: Text 컴포넌트 사용하도록 수정 * refactor: tsdoc 추가 + emotion 코드 위치 변경 - emotion 코드 위치 변경: ProfileListRow, PageContainer, PageHeader - tsdoc 추가: Text 컴포넌트 * refactor: Home 페이지 fragment 제거 * feature: ProfileDefault 페이지 제작 - useModal: 로그아웃, 계정 삭제 시 모달 사용 - useNavigate: 뒤로가기, 프로필 수정, 회사 정보 변경, 로그아웃, 계정 삭제에 라우팅 기능 추가 - 페이지 레이아웃 작업 - ProfileEdit: 기존 테스트 코드 제거 * refactor: BusinessCardContainer 공백 제거 * refactor: StyleList 관련 conflict 해결 * feature: 프로필 페이지 반응형 디자인 제작 - 갤럭시 Fold에서 적절하게 보이도록 미디어 쿼리 사용 * refactor: 사용하지 않는 파일 제거 + 반응형 디자인 - 모달 버튼의 폰트 크기 수정 * feature: 프로필 페이지 다크모드 코드 추가 * feature: Modal 컴포넌트 다크모드 추가 * feature: 404 페이지에서 홈으로 라우팅하게 수정 * fix: msw 2 버전으로 수정 * fix: authTokens이 없어서 생기는 오류 수정 * feature: 레이아웃 깨지는 부분 수정 * fix: useAuthTokens 주석 처리 * chore: msw 2.0.5 버전으로 수정 * Update handlers.ts --------- Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> Co-authored-by: from1to2 <124763142+from1to2@users.noreply.github.com> Co-authored-by: DaHyeonJu * [Feature] 실시간 채팅 기능 및 상대방 프로필 클릭 시 상대방 프로필 조회 기능 (#125) * chore : 충돌 수정 * chore : 충돌 수정 * chore : 충돌 수정 * fix : 에러 주석 처리 * fix : 채팅방 통신 수정 * style : 채팅 버블 스타일 변경 및 첫 렌더 링 시 스크롤 맨 아래로 이동 * feat : 채팅방에서 상대방 프로필 클릭 시 정보 조회 기능 추가 * chore : 사용되지 않는 import 문 제거 * Update handlers.ts * Update handlers.ts * [Fix] 카카오 로그인 성공 시 토큰 불러오는 함수 무한루프 제거 (#127) * chore : lint 에러 수정 * fix : 함수 무한루프 돌던 것 수정 * chore : lint 에러 수정 * chore : lint 에러 수정 * Update index.tsx (#129) * chore : baseURL 중복 제거 * chore : prettier 에러 수정 * feature: 관리자 페이지 MSW를 활용한 API 명세와 테스트 (#117) * style: AdminAppHeader 컴포넌트 추가 * style: AdminNavigationBar 컴포넌트 생성 * style: AdminNavigationBar 색 변경 * feat: AdminTabs 컴포넌트 추가 * refactor: 컴포넌트 변수명 변경 * refactor: 컴포넌트 변수명 변경 * feat: AdminApprovalList 컴포넌트 추가 * feat: outerwrapper 제거 * feat: AdminReportListRow 컴포넌트 예시 추가 * feat: AdminReportList 컴포넌트 예시 추가 * feat: AdminTabs 컴포넌트로 다른 컴포넌트들 연결 및 디자인 수정, 변수명 수정 * refactor: admin 컴포넌트 이전 * refactor: eslint 에러 수정 * refactor: import 경로 변경 * feat: AdminApprovalInfo 컴포넌트 1 * style: 예시 이미지 추가 * feat: AdminApprovalInfo 컴포넌트 추가 1 * feat: input text fontweight 속성 추가 * style: Input 속성 추가 * style: AdminApprovalInfo 컴포넌트 디자인 2 * style: AdminReportInfo 컴포넌트 1 * refactor: props명 수정 * style: AdminReportInfo 컴포넌트 1 * style: AdminReportInfoListRow 컴포넌트 * feat: useModal 컴포넌트 적용, 기타 스타일 수정 * feat: AdminReportInfo 컴포넌트 userModal 적용 * refactor: 불필요 컴포넌트 삭제 * refactor: 이름 수정 * feat: AdminReportListRow 속성 추가 * feat: 관리자페이지 신고자 목록 클릭 시, 정보 출력 * feat: AdminReportList 특정 목록 클릭 시, 해당 AdminReportInfo 출력 * feat: AdminReportList mockdata 추가, 함수 연결 * refactor: 이름 예시 변경 * refactor: 변수명 수정 (adminapprovalinfo와 구분) * feat: AdminTabs 승인 탭 추가 * refactor: 변수명 수정(구별필요) * feat: 승인 페이지 이름 적용, 불필요 컴포넌트 제거 * refactor: mock data 적용. 변수명 수정. * feat: 승인페이지 mock data 적용. 목록 클릭 함수 추가. interface 추가. * feat: adminapprovallistrow onclick 함수 속성 추가 * feat: msw handlers interface 파일들 * feat: 관리자페이지 - MSW 활용한 API request, response 명세. API 테스트. * style: 오류 관련 주석 처리 * feat: AdminPageHeader * feat: 관리자페이지 승인요청 사용자들 목록 불러오기 MSW API 요청 코드 완료. 테스트 완료. * feat: 관리자페이지 신고당한자 목록 API 코드 추가. 테스트 완료. * feat: 관리자페이지 승인요청자 세부정보 출력 1 * refactor: 불필요 코드 삭제 * refactor: 불필요코드 제거 2 * [Feature] 회사 정보 등록 페이지 구현 (#132) * feat : 회사 이메일 인증 및 직무 정보 등록 페이지 구현 * feat : 회사 정보 등록 페이지 구현 * chore : 안 쓰이는 변수 제거 * [Fix] provider 대문자로 수정 및 회사 등록 페이지 form 별로 예외 처리 (#135) * fix : provider 대문자로 수정 및 회사 정보 등록 페이지 각 폼 별로 분기 처리 * chore : 사용되지 않는 데이터 제거 * chore : console.log(response) 삭제 * fix: login 페이지 스크롤 속성 추가 (#140) * style: AdminAppHeader 컴포넌트 추가 * style: AdminNavigationBar 컴포넌트 생성 * style: AdminNavigationBar 색 변경 * feat: AdminTabs 컴포넌트 추가 * refactor: 컴포넌트 변수명 변경 * refactor: 컴포넌트 변수명 변경 * feat: AdminApprovalList 컴포넌트 추가 * feat: outerwrapper 제거 * feat: AdminReportListRow 컴포넌트 예시 추가 * feat: AdminReportList 컴포넌트 예시 추가 * feat: AdminTabs 컴포넌트로 다른 컴포넌트들 연결 및 디자인 수정, 변수명 수정 * refactor: admin 컴포넌트 이전 * refactor: eslint 에러 수정 * refactor: import 경로 변경 * feat: AdminApprovalInfo 컴포넌트 1 * style: 예시 이미지 추가 * feat: AdminApprovalInfo 컴포넌트 추가 1 * feat: input text fontweight 속성 추가 * style: Input 속성 추가 * style: AdminApprovalInfo 컴포넌트 디자인 2 * style: AdminReportInfo 컴포넌트 1 * refactor: props명 수정 * style: AdminReportInfo 컴포넌트 1 * style: AdminReportInfoListRow 컴포넌트 * feat: useModal 컴포넌트 적용, 기타 스타일 수정 * feat: AdminReportInfo 컴포넌트 userModal 적용 * refactor: 불필요 컴포넌트 삭제 * refactor: 이름 수정 * feat: AdminReportListRow 속성 추가 * feat: 관리자페이지 신고자 목록 클릭 시, 정보 출력 * feat: AdminReportList 특정 목록 클릭 시, 해당 AdminReportInfo 출력 * feat: AdminReportList mockdata 추가, 함수 연결 * refactor: 이름 예시 변경 * refactor: 변수명 수정 (adminapprovalinfo와 구분) * feat: AdminTabs 승인 탭 추가 * refactor: 변수명 수정(구별필요) * feat: 승인 페이지 이름 적용, 불필요 컴포넌트 제거 * refactor: mock data 적용. 변수명 수정. * feat: 승인페이지 mock data 적용. 목록 클릭 함수 추가. interface 추가. * feat: adminapprovallistrow onclick 함수 속성 추가 * feat: msw handlers interface 파일들 * feat: 관리자페이지 - MSW 활용한 API request, response 명세. API 테스트. * style: 오류 관련 주석 처리 * feat: AdminPageHeader * feat: 관리자페이지 승인요청 사용자들 목록 불러오기 MSW API 요청 코드 완료. 테스트 완료. * feat: 관리자페이지 신고당한자 목록 API 코드 추가. 테스트 완료. * feat: 관리자페이지 승인요청자 세부정보 출력 1 * refactor: 불필요 코드 삭제 * refactor: 불필요코드 제거 2 * feat: 숨겨진 관리자 로그인 버튼 추가 * feat: 관리자 페이지 라우터 설정 * feat: 관리자페이지 로그인 MSW API 요청 코드 추가, 관리자페이지 로그인 UI(react hook form) * refactor: 타입 오류 임시 주석처리 * refactor: import문 삭제 * feat: 관리자페이지 로그인 api 요청 1 * feat: 관리자페이지 로그인 API 요청 2 * feat: 관리자 로그인 페이지 post API 요청 * feat: 관리자 로그인 페이지 이동 * feat: 관리자 페이지 이동 * feat: 관리자 로그인 페이지 - 피그마 디자인, 구현 * feat: 문구수정 * refactor: useNavigate, api 요청 주소 변경 * feat: 관리자로그인페이지 디자인 수정 - emotion, register속성 적용 * feat: 관리자 승인 처리 API 요청. * feat: scroll * 🐛 [Bug]: OAuth 인증 코드 분리 로직 추가 (#141) * [Chore]: 불필요한 개행 제거 - lint fix * [Feature]: 최초 로그인 여부 전역 상태 추가 - isNewUser, setIsNewUser * [Feature]: LoginPending에 분기 처리 * [Chore]: 회원가입 완료 후 isNewUser 초기화 * chore : useEffect 의존성 배열 제거 * fix : eslint 에러 수정 * fix : navigate state 넘기는 방식 수정 * feature: 관리자 페이지 로그인 (현재까지 진행 사항 PR) (#131) * style: AdminAppHeader 컴포넌트 추가 * style: AdminNavigationBar 컴포넌트 생성 * style: AdminNavigationBar 색 변경 * feat: AdminTabs 컴포넌트 추가 * refactor: 컴포넌트 변수명 변경 * refactor: 컴포넌트 변수명 변경 * feat: AdminApprovalList 컴포넌트 추가 * feat: outerwrapper 제거 * feat: AdminReportListRow 컴포넌트 예시 추가 * feat: AdminReportList 컴포넌트 예시 추가 * feat: AdminTabs 컴포넌트로 다른 컴포넌트들 연결 및 디자인 수정, 변수명 수정 * refactor: admin 컴포넌트 이전 * refactor: eslint 에러 수정 * refactor: import 경로 변경 * feat: AdminApprovalInfo 컴포넌트 1 * style: 예시 이미지 추가 * feat: AdminApprovalInfo 컴포넌트 추가 1 * feat: input text fontweight 속성 추가 * style: Input 속성 추가 * style: AdminApprovalInfo 컴포넌트 디자인 2 * style: AdminReportInfo 컴포넌트 1 * refactor: props명 수정 * style: AdminReportInfo 컴포넌트 1 * style: AdminReportInfoListRow 컴포넌트 * feat: useModal 컴포넌트 적용, 기타 스타일 수정 * feat: AdminReportInfo 컴포넌트 userModal 적용 * refactor: 불필요 컴포넌트 삭제 * refactor: 이름 수정 * feat: AdminReportListRow 속성 추가 * feat: 관리자페이지 신고자 목록 클릭 시, 정보 출력 * feat: AdminReportList 특정 목록 클릭 시, 해당 AdminReportInfo 출력 * feat: AdminReportList mockdata 추가, 함수 연결 * refactor: 이름 예시 변경 * refactor: 변수명 수정 (adminapprovalinfo와 구분) * feat: AdminTabs 승인 탭 추가 * refactor: 변수명 수정(구별필요) * feat: 승인 페이지 이름 적용, 불필요 컴포넌트 제거 * refactor: mock data 적용. 변수명 수정. * feat: 승인페이지 mock data 적용. 목록 클릭 함수 추가. interface 추가. * feat: adminapprovallistrow onclick 함수 속성 추가 * feat: msw handlers interface 파일들 * feat: 관리자페이지 - MSW 활용한 API request, response 명세. API 테스트. * style: 오류 관련 주석 처리 * feat: AdminPageHeader * feat: 관리자페이지 승인요청 사용자들 목록 불러오기 MSW API 요청 코드 완료. 테스트 완료. * feat: 관리자페이지 신고당한자 목록 API 코드 추가. 테스트 완료. * feat: 관리자페이지 승인요청자 세부정보 출력 1 * refactor: 불필요 코드 삭제 * refactor: 불필요코드 제거 2 * feat: 숨겨진 관리자 로그인 버튼 추가 * feat: 관리자 페이지 라우터 설정 * feat: 관리자페이지 로그인 MSW API 요청 코드 추가, 관리자페이지 로그인 UI(react hook form) * refactor: 타입 오류 임시 주석처리 * refactor: import문 삭제 * feat: 관리자페이지 로그인 api 요청 1 * feat: 관리자페이지 로그인 API 요청 2 * feat: 관리자 로그인 페이지 post API 요청 * feat: 관리자 로그인 페이지 이동 * feat: 관리자 페이지 이동 * feat: 관리자 로그인 페이지 - 피그마 디자인, 구현 * feat: 문구수정 * refactor: useNavigate, api 요청 주소 변경 * feat: 관리자로그인페이지 디자인 수정 - emotion, register속성 적용 * feat: 관리자 승인 처리 API 요청. * feat: 관리자 승인요청, 신고 API 요청 * refactor: dev pull * feat: Admin Inquiry 추가 * style: 문의페이지 아이콘 추가 * refactor: import 절대 경로 수정 * refactor: MSW handler /api 경로 삭제 * Fix: 관리자 페이지 API 요청 주소 수정 (#152) * style: AdminAppHeader 컴포넌트 추가 * style: AdminNavigationBar 컴포넌트 생성 * style: AdminNavigationBar 색 변경 * feat: AdminTabs 컴포넌트 추가 * refactor: 컴포넌트 변수명 변경 * refactor: 컴포넌트 변수명 변경 * feat: AdminApprovalList 컴포넌트 추가 * feat: outerwrapper 제거 * feat: AdminReportListRow 컴포넌트 예시 추가 * feat: AdminReportList 컴포넌트 예시 추가 * feat: AdminTabs 컴포넌트로 다른 컴포넌트들 연결 및 디자인 수정, 변수명 수정 * refactor: admin 컴포넌트 이전 * refactor: eslint 에러 수정 * refactor: import 경로 변경 * feat: AdminApprovalInfo 컴포넌트 1 * style: 예시 이미지 추가 * feat: AdminApprovalInfo 컴포넌트 추가 1 * feat: input text fontweight 속성 추가 * style: Input 속성 추가 * style: AdminApprovalInfo 컴포넌트 디자인 2 * style: AdminReportInfo 컴포넌트 1 * refactor: props명 수정 * style: AdminReportInfo 컴포넌트 1 * style: AdminReportInfoListRow 컴포넌트 * feat: useModal 컴포넌트 적용, 기타 스타일 수정 * feat: AdminReportInfo 컴포넌트 userModal 적용 * refactor: 불필요 컴포넌트 삭제 * refactor: 이름 수정 * feat: AdminReportListRow 속성 추가 * feat: 관리자페이지 신고자 목록 클릭 시, 정보 출력 * feat: AdminReportList 특정 목록 클릭 시, 해당 AdminReportInfo 출력 * feat: AdminReportList mockdata 추가, 함수 연결 * refactor: 이름 예시 변경 * refactor: 변수명 수정 (adminapprovalinfo와 구분) * feat: AdminTabs 승인 탭 추가 * refactor: 변수명 수정(구별필요) * feat: 승인 페이지 이름 적용, 불필요 컴포넌트 제거 * refactor: mock data 적용. 변수명 수정. * feat: 승인페이지 mock data 적용. 목록 클릭 함수 추가. interface 추가. * feat: adminapprovallistrow onclick 함수 속성 추가 * feat: msw handlers interface 파일들 * feat: 관리자페이지 - MSW 활용한 API request, response 명세. API 테스트. * style: 오류 관련 주석 처리 * feat: AdminPageHeader * feat: 관리자페이지 승인요청 사용자들 목록 불러오기 MSW API 요청 코드 완료. 테스트 완료. * feat: 관리자페이지 신고당한자 목록 API 코드 추가. 테스트 완료. * feat: 관리자페이지 승인요청자 세부정보 출력 1 * refactor: 불필요 코드 삭제 * refactor: 불필요코드 제거 2 * feat: 숨겨진 관리자 로그인 버튼 추가 * feat: 관리자 페이지 라우터 설정 * feat: 관리자페이지 로그인 MSW API 요청 코드 추가, 관리자페이지 로그인 UI(react hook form) * refactor: 타입 오류 임시 주석처리 * refactor: import문 삭제 * feat: 관리자페이지 로그인 api 요청 1 * feat: 관리자페이지 로그인 API 요청 2 * feat: 관리자 로그인 페이지 post API 요청 * feat: 관리자 로그인 페이지 이동 * feat: 관리자 페이지 이동 * feat: 관리자 로그인 페이지 - 피그마 디자인, 구현 * feat: 문구수정 * refactor: useNavigate, api 요청 주소 변경 * feat: 관리자로그인페이지 디자인 수정 - emotion, register속성 적용 * feat: 관리자 승인 처리 API 요청. * feat: 관리자 승인요청, 신고 API 요청 * refactor: dev pull * feat: Admin Inquiry 추가 * style: 문의페이지 아이콘 추가 * refactor: import 절대 경로 수정 * refactor: MSW handler /api 경로 삭제 * fix: 관리자 페이지 Admin API 요청 주소 수정 * feature: 관리자 페이지 - 문의 리스트 컴포넌트 추가, 문의 상세 페이지 추가 (#153) * style: AdminAppHeader 컴포넌트 추가 * style: AdminNavigationBar 컴포넌트 생성 * style: AdminNavigationBar 색 변경 * feat: AdminTabs 컴포넌트 추가 * refactor: 컴포넌트 변수명 변경 * refactor: 컴포넌트 변수명 변경 * feat: AdminApprovalList 컴포넌트 추가 * feat: outerwrapper 제거 * feat: AdminReportListRow 컴포넌트 예시 추가 * feat: AdminReportList 컴포넌트 예시 추가 * feat: AdminTabs 컴포넌트로 다른 컴포넌트들 연결 및 디자인 수정, 변수명 수정 * refactor: admin 컴포넌트 이전 * refactor: eslint 에러 수정 * refactor: import 경로 변경 * feat: AdminApprovalInfo 컴포넌트 1 * style: 예시 이미지 추가 * feat: AdminApprovalInfo 컴포넌트 추가 1 * feat: input text fontweight 속성 추가 * style: Input 속성 추가 * style: AdminApprovalInfo 컴포넌트 디자인 2 * style: AdminReportInfo 컴포넌트 1 * refactor: props명 수정 * style: AdminReportInfo 컴포넌트 1 * style: AdminReportInfoListRow 컴포넌트 * feat: useModal 컴포넌트 적용, 기타 스타일 수정 * feat: AdminReportInfo 컴포넌트 userModal 적용 * refactor: 불필요 컴포넌트 삭제 * refactor: 이름 수정 * feat: AdminReportListRow 속성 추가 * feat: 관리자페이지 신고자 목록 클릭 시, 정보 출력 * feat: AdminReportList 특정 목록 클릭 시, 해당 AdminReportInfo 출력 * feat: AdminReportList mockdata 추가, 함수 연결 * refactor: 이름 예시 변경 * refactor: 변수명 수정 (adminapprovalinfo와 구분) * feat: AdminTabs 승인 탭 추가 * refactor: 변수명 수정(구별필요) * feat: 승인 페이지 이름 적용, 불필요 컴포넌트 제거 * refactor: mock data 적용. 변수명 수정. * feat: 승인페이지 mock data 적용. 목록 클릭 함수 추가. interface 추가. * feat: adminapprovallistrow onclick 함수 속성 추가 * feat: msw handlers interface 파일들 * feat: 관리자페이지 - MSW 활용한 API request, response 명세. API 테스트. * style: 오류 관련 주석 처리 * feat: AdminPageHeader * feat: 관리자페이지 승인요청 사용자들 목록 불러오기 MSW API 요청 코드 완료. 테스트 완료. * feat: 관리자페이지 신고당한자 목록 API 코드 추가. 테스트 완료. * feat: 관리자페이지 승인요청자 세부정보 출력 1 * refactor: 불필요 코드 삭제 * refactor: 불필요코드 제거 2 * feat: 숨겨진 관리자 로그인 버튼 추가 * feat: 관리자 페이지 라우터 설정 * feat: 관리자페이지 로그인 MSW API 요청 코드 추가, 관리자페이지 로그인 UI(react hook form) * refactor: 타입 오류 임시 주석처리 * refactor: import문 삭제 * feat: 관리자페이지 로그인 api 요청 1 * feat: 관리자페이지 로그인 API 요청 2 * feat: 관리자 로그인 페이지 post API 요청 * feat: 관리자 로그인 페이지 이동 * feat: 관리자 페이지 이동 * feat: 관리자 로그인 페이지 - 피그마 디자인, 구현 * feat: 문구수정 * refactor: useNavigate, api 요청 주소 변경 * feat: 관리자로그인페이지 디자인 수정 - emotion, register속성 적용 * feat: 관리자 승인 처리 API 요청. * feat: 관리자 승인요청, 신고 API 요청 * refactor: dev pull * feat: Admin Inquiry 추가 * style: 문의페이지 아이콘 추가 * refactor: import 절대 경로 수정 * refactor: MSW handler /api 경로 삭제 * feat: 관리자페이지 문의 API, UI - 1 * feat: 관리자 페이지 문의 상세 페이지 추가 * feat: 관리자 페이지 문의 UI, API 추가 2 * [Feature]: BE OAuth 인증 로직 변경에 따른 적용 (#154) * [Chore]: isNewUser 전역 상태 및 Setter 제거(#145) * [Feature]: useEffect 내부 분기 처리 로직 제거 (#145) * [Feature]: 2차 인증 로직 구현 (#145) * [Fix]: 회원가입 요청 body 수정 (#145) * [Fix]: setIsNewUser 추가 제거 (#145) * [Fix]: 셀렉터 변경 (#145) - 관심사 / 직무 선택 상황에 각각 활용할 수 있도록 변경 (type 프롭) - 직무 선택 정보를 저장하는 JobStore 상태 Store 정의 - 매우매우 하드코딩이라 리팩토링 필요 * [Fix]: 회사 정보 등록 시 액세스 토큰 대신 userId를 전송하도록 변경 (#145) * [Chore]: 로그인 요청 성공 시 응답 데이터 저장 또는 전달 (#145) - 스토리지에 저장 또는 홈 페이지로 전달 - 어떤 정보를 저장하고 전달할지는 논의 필요 * [Fix]: 회사 정보 등록 시 전달하는 formData 수정 (#145) * [Feature]: 로그인 상태가 아니면 로그인 페이지로 이동하도록 변경 (#145) * [Chore]: onSuccess 로직 변경 (#145) - 이제 응답으로 accessToken이 전송되지 않아 해당 코드 제거 * [Chore]: 회사 정보 등록 완료 시 로그인 페이지 리다이렉트 (#145) * [Feature]: 헤더 구성 정보 로그인한 계정 기반으로 표시하도록 일부 수정 (#145) * [Chore]: 로그아웃 적용 (#145) - 선언형 로직으로 변경 필요 * [Fix]: InqueryImage import 경로 수정 - Build Error fix * feature: 관리자 페이지 UI 개편 (#157) * style: AdminAppHeader 컴포넌트 추가 * style: AdminNavigationBar 컴포넌트 생성 * style: AdminNavigationBar 색 변경 * feat: AdminTabs 컴포넌트 추가 * refactor: 컴포넌트 변수명 변경 * refactor: 컴포넌트 변수명 변경 * feat: AdminApprovalList 컴포넌트 추가 * feat: outerwrapper 제거 * feat: AdminReportListRow 컴포넌트 예시 추가 * feat: AdminReportList 컴포넌트 예시 추가 * feat: AdminTabs 컴포넌트로 다른 컴포넌트들 연결 및 디자인 수정, 변수명 수정 * refactor: admin 컴포넌트 이전 * refactor: eslint 에러 수정 * refactor: import 경로 변경 * feat: AdminApprovalInfo 컴포넌트 1 * style: 예시 이미지 추가 * feat: AdminApprovalInfo 컴포넌트 추가 1 * feat: input text fontweight 속성 추가 * style: Input 속성 추가 * style: AdminApprovalInfo 컴포넌트 디자인 2 * style: AdminReportInfo 컴포넌트 1 * refactor: props명 수정 * style: AdminReportInfo 컴포넌트 1 * style: AdminReportInfoListRow 컴포넌트 * feat: useModal 컴포넌트 적용, 기타 스타일 수정 * feat: AdminReportInfo 컴포넌트 userModal 적용 * refactor: 불필요 컴포넌트 삭제 * refactor: 이름 수정 * feat: AdminReportListRow 속성 추가 * feat: 관리자페이지 신고자 목록 클릭 시, 정보 출력 * feat: AdminReportList 특정 목록 클릭 시, 해당 AdminReportInfo 출력 * feat: AdminReportList mockdata 추가, 함수 연결 * refactor: 이름 예시 변경 * refactor: 변수명 수정 (adminapprovalinfo와 구분) * feat: AdminTabs 승인 탭 추가 * refactor: 변수명 수정(구별필요) * feat: 승인 페이지 이름 적용, 불필요 컴포넌트 제거 * refactor: mock data 적용. 변수명 수정. * feat: 승인페이지 mock data 적용. 목록 클릭 함수 추가. interface 추가. * feat: adminapprovallistrow onclick 함수 속성 추가 * feat: msw handlers interface 파일들 * feat: 관리자페이지 - MSW 활용한 API request, response 명세. API 테스트. * style: 오류 관련 주석 처리 * feat: AdminPageHeader * feat: 관리자페이지 승인요청 사용자들 목록 불러오기 MSW API 요청 코드 완료. 테스트 완료. * feat: 관리자페이지 신고당한자 목록 API 코드 추가. 테스트 완료. * feat: 관리자페이지 승인요청자 세부정보 출력 1 * refactor: 불필요 코드 삭제 * refactor: 불필요코드 제거 2 * feat: 숨겨진 관리자 로그인 버튼 추가 * feat: 관리자 페이지 라우터 설정 * feat: 관리자페이지 로그인 MSW API 요청 코드 추가, 관리자페이지 로그인 UI(react hook form) * refactor: 타입 오류 임시 주석처리 * refactor: import문 삭제 * feat: 관리자페이지 로그인 api 요청 1 * feat: 관리자페이지 로그인 API 요청 2 * feat: 관리자 로그인 페이지 post API 요청 * feat: 관리자 로그인 페이지 이동 * feat: 관리자 페이지 이동 * feat: 관리자 로그인 페이지 - 피그마 디자인, 구현 * feat: 문구수정 * refactor: useNavigate, api 요청 주소 변경 * feat: 관리자로그인페이지 디자인 수정 - emotion, register속성 적용 * feat: 관리자 승인 처리 API 요청. * feat: 관리자 승인요청, 신고 API 요청 * refactor: dev pull * feat: Admin Inquiry 추가 * style: 문의페이지 아이콘 추가 * refactor: import 절대 경로 수정 * refactor: MSW handler /api 경로 삭제 * feat: 관리자페이지 문의 API, UI - 1 * feat: 관리자 페이지 문의 상세 페이지 추가 * feat: 관리자 페이지 문의 UI, API 추가 2 * feat: 관리자 문의 컴포넌트 수정 * feat: 관리자 페이지 탭 구조 개편 * feat: 불필요 라우팅 삭제 * feat: 문의 페이지 헤더 추가 * feat: 관리자 신고페이지 목록 * feat: 관리자 페이지 개편 * feat: 변수명사용-빌드 * refactor: import문 정렬 (dev pull) * [Feature] 이전 채팅방 디테일 페이지 구현 (#147) * feat : 이전 채팅방 Detail 페이지 구현 * chore : 주석제거 * fix : 이전 채팅방이 없을 때 처리 * chore : dev 브랜치 merge 과정에서 충돌 해결 * chore : import 문 lint 에러 수정 * [Feature] fcm 서비스 워커 세팅 및 랜덤 매칭 성공 시 web push 기능 구현 (#148) * feat : firebase 설치 및 service worker 설정 * chore : dev 브랜치 충돌 수정 반영 * feat : 서버에서 fcm push 받았을 경우 웹푸시 알림구현 * feat : 포그라운드 시 알림 처리 * feat : 서비스 워커에서 push 받았을 경우 indexedDB에 상태 저장 * chore : 주석제거 * chore : 사용되지 않는 함수 제거 * chore : 사용되지 않는 매개변수 제거 * chore : 사용되지 않는 함수 제거 * feat : 매칭 로직 수정 및 서버에서 유저의 상태 받아오기 * fix : 매칭 시작시간 정보가 없을 경우 현재 시간을 매칭 시작 시간으로 세팅 * chore : 사용되지 않는 props 제거 * [Feat] 마이 프로필 페이지 조회 기능 (#162) * feat : 마이 프로필 페이지 조회 기능 * style : 프로필 이미지 url 삽입 및 이메일 텍스트 fontWeight 축소 * Update App.tsx * Update AdminReportInfo.tsx * chore : props 변수명 불일치 수정 * chore : import문 lint 에러 수정 --------- Co-authored-by: Changuk Woo <43228743+wukdddang@users.noreply.github.com> Co-authored-by: wukddang <43228743+funkyblues@users.noreply.github.com> Co-authored-by: from1to2 <124763142+from1to2@users.noreply.github.com> Co-authored-by: Cheshier --- package-lock.json | 734 +++++++++++++++++- package.json | 1 + public/firebase-messaging-sw.js | 61 ++ setupProxy.ts | 10 - src/App.tsx | 16 +- src/apis/adminReport/AdminReportApi.ts | 7 + src/apis/axios.ts | 1 + src/apis/chatList/ChatListApi.ts | 4 +- src/apis/queryClient.ts | 4 +- src/components/chatList/ChatRoomBubbles.tsx | 23 +- .../IconButton/ParticularTopicButton.tsx | 7 +- .../IconButton/RandomMatchingButton.tsx | 8 +- .../NormalButton/NormalButtonStyles.ts | 12 +- .../common/ListRow/AdminInquiryList.tsx | 15 +- .../common/ListRow/AdminReportList.tsx | 32 +- .../common/ListRow/AdminReportListRow.tsx | 114 ++- .../ListRow/AdminReportListRowTitle.tsx | 73 ++ .../common/ListRow/AdminReportersList.tsx | 104 +++ .../common/ListRow/AdminReportersListRow.tsx | 63 ++ src/components/home/Card.tsx | 206 +++-- src/components/home/Tip.tsx | 2 +- src/firebase-messaging-sw.ts | 89 +++ src/mocks/handlers.ts | 12 +- src/mocks/handlersInterface.ts | 4 + src/pages/admin/AdminInquiry.tsx | 2 +- .../admin/components/AdminInquiryInfo.tsx | 12 +- .../admin/components/AdminReportInfo.tsx | 90 +-- src/pages/admin/components/AdminTabs.tsx | 136 ++-- src/pages/chatList/ChatList.tsx | 8 +- src/pages/chatListDetail/ChatListDetail.tsx | 99 +++ src/pages/chatListDetail/index.tsx | 13 + src/pages/chatting/Chatting.tsx | 4 +- src/pages/home/Home.tsx | 12 +- src/pages/profile/ProfileDefault.tsx | 52 +- src/pages/register/RegisterCompany.tsx | 1 - tsconfig.json | 4 +- vite.config.ts | 12 +- 37 files changed, 1679 insertions(+), 368 deletions(-) create mode 100644 public/firebase-messaging-sw.js create mode 100644 src/components/common/ListRow/AdminReportListRowTitle.tsx create mode 100644 src/components/common/ListRow/AdminReportersList.tsx create mode 100644 src/components/common/ListRow/AdminReportersListRow.tsx create mode 100644 src/firebase-messaging-sw.ts create mode 100644 src/pages/chatListDetail/ChatListDetail.tsx create mode 100644 src/pages/chatListDetail/index.tsx diff --git a/package-lock.json b/package-lock.json index 14692153..604433e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "axios": "^1.5.1", "d3": "^7.8.5", "emotion-reset": "^3.0.1", + "firebase": "^8.10.0", "framer-motion": "^10.16.4", "http-proxy-middleware": "^2.0.6", "react": "^18.2.0", @@ -1127,6 +1128,520 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@firebase/analytics": { + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.6.18.tgz", + "integrity": "sha512-FXNtYDxbs9ynPbzUVuG94BjFPOPpgJ7156660uvCBuKgoBCIVcNqKkJQQ7TH8384fqvGjbjdcgARY9jgAHbtog==", + "dependencies": { + "@firebase/analytics-types": "0.6.0", + "@firebase/component": "0.5.6", + "@firebase/installations": "0.4.32", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/analytics-types": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.6.0.tgz", + "integrity": "sha512-kbMawY0WRPyL/lbknBkme4CNLl+Gw+E9G4OpNeXAauqoQiNkBgpIvZYy7BRT4sNGhZbxdxXxXbruqUwDzLmvTw==" + }, + "node_modules/@firebase/app": { + "version": "0.6.30", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.30.tgz", + "integrity": "sha512-uAYEDXyK0mmpZ8hWQj5TNd7WVvfsU8PgsqKpGljbFBG/HhsH8KbcykWAAA+c1PqL7dt/dbt0Reh1y9zEdYzMhg==", + "dependencies": { + "@firebase/app-types": "0.6.3", + "@firebase/component": "0.5.6", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "dom-storage": "2.1.0", + "tslib": "^2.1.0", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/@firebase/app-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.3.2.tgz", + "integrity": "sha512-YjpsnV1xVTO1B836IKijRcDeceLgHQNJ/DWa+Vky9UHkm1Mi4qosddX8LZzldaWRTWKX7BN1MbZOLY8r7M/MZQ==", + "dependencies": { + "@firebase/app-check-interop-types": "0.1.0", + "@firebase/app-check-types": "0.3.1", + "@firebase/component": "0.5.6", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.1.0.tgz", + "integrity": "sha512-uZfn9s4uuRsaX5Lwx+gFP3B6YsyOKUE+Rqa6z9ojT4VSRAsZFko9FRn6OxQUA1z5t5d08fY4pf+/+Dkd5wbdbA==" + }, + "node_modules/@firebase/app-check-types": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.3.1.tgz", + "integrity": "sha512-KJ+BqJbdNsx4QT/JIT1yDj5p6D+QN97iJs3GuHnORrqL+DU3RWc9nSYQsrY6Tv9jVWcOkMENXAgDT484vzsm2w==" + }, + "node_modules/@firebase/app-types": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.6.3.tgz", + "integrity": "sha512-/M13DPPati7FQHEQ9Minjk1HGLm/4K4gs9bR4rzLCWJg64yGtVC0zNg9gDpkw9yc2cvol/mNFxqTtd4geGrwdw==" + }, + "node_modules/@firebase/auth": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.16.8.tgz", + "integrity": "sha512-mR0UXG4LirWIfOiCWxVmvz1o23BuKGxeItQ2cCUgXLTjNtWJXdcky/356iTUsd7ZV5A78s2NHeN5tIDDG6H4rg==", + "dependencies": { + "@firebase/auth-types": "0.10.3" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.6.tgz", + "integrity": "sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/auth-types": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.10.3.tgz", + "integrity": "sha512-zExrThRqyqGUbXOFrH/sowuh2rRtfKHp9SBVY2vOqKWdCX1Ztn682n9WLtlUDsiYVIbBcwautYWk2HyCGFv0OA==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.5.6.tgz", + "integrity": "sha512-GyQJ+2lrhsDqeGgd1VdS7W+Y6gNYyI0B51ovNTxeZVG/W8I7t9MwEiCWsCvfm5wQgfsKp9dkzOcJrL5k8oVO/Q==", + "dependencies": { + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.11.0.tgz", + "integrity": "sha512-b/kwvCubr6G9coPlo48PbieBDln7ViFBHOGeVt/bt82yuv5jYZBEYAac/mtOVSxpf14aMo/tAN+Edl6SWqXApw==", + "dependencies": { + "@firebase/auth-interop-types": "0.1.6", + "@firebase/component": "0.5.6", + "@firebase/database-types": "0.8.0", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "faye-websocket": "0.11.3", + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.8.0.tgz", + "integrity": "sha512-7IdjAFRfPWyG3b4wcXyghb3Y1CLCSJFZIg1xl5GbTVMttSQFT4B5NYdhsfA34JwAsv5pMzPpjOaS3/K9XJ2KiA==", + "dependencies": { + "@firebase/app-types": "0.6.3", + "@firebase/util": "1.3.0" + } + }, + "node_modules/@firebase/firestore": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-2.4.0.tgz", + "integrity": "sha512-PQ6+lWNrvh74GvFTHT4gCutFipDmtu8D1tNNawKe+/SyL6XFgeuMYgZIpKQgkTSezVDogC7EGQTJBFnewF9pOg==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/firestore-types": "2.4.0", + "@firebase/logger": "0.2.6", + "@firebase/util": "1.3.0", + "@firebase/webchannel-wrapper": "0.5.1", + "@grpc/grpc-js": "^1.3.2", + "@grpc/proto-loader": "^0.6.0", + "node-fetch": "2.6.1", + "tslib": "^2.1.0" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/firestore-types": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-2.4.0.tgz", + "integrity": "sha512-0dgwfuNP7EN6/OlK2HSNSQiQNGLGaRBH0gvgr1ngtKKJuJFuq0Z48RBMeJX9CGjV4TP9h2KaB+KrUKJ5kh1hMg==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/firestore/node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@firebase/functions": { + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.6.15.tgz", + "integrity": "sha512-b7RpLwFXi0N+HgkfK8cmkarSOoBeSrc1jNdadkCacQt+vIePkKM3E9EJXF4roWSa8GwTruodpBsvH+lK9iCAKQ==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/functions-types": "0.4.0", + "@firebase/messaging-types": "0.5.0", + "node-fetch": "2.6.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/functions-types": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.4.0.tgz", + "integrity": "sha512-3KElyO3887HNxtxNF1ytGFrNmqD+hheqjwmT3sI09FaDCuaxGbOnsXAXH2eQ049XRXw9YQpHMgYws/aUNgXVyQ==" + }, + "node_modules/@firebase/functions/node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@firebase/installations": { + "version": "0.4.32", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.32.tgz", + "integrity": "sha512-K4UlED1Vrhd2rFQQJih+OgEj8OTtrtH4+Izkx7ip2bhXSc+unk8ZhnF69D0kmh7zjXAqEDJrmHs9O5fI3rV6Tw==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations-types": "0.3.4", + "@firebase/util": "1.3.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/installations-types": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.3.4.tgz", + "integrity": "sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q==", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/installations/node_modules/idb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", + "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + }, + "node_modules/@firebase/logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.6.tgz", + "integrity": "sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw==" + }, + "node_modules/@firebase/messaging": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.8.0.tgz", + "integrity": "sha512-hkFHDyVe1kMcY9KEG+prjCbvS6MtLUgVFUbbQqq7JQfiv58E07YCzRUcMrJolbNi/1QHH6Jv16DxNWjJB9+/qA==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations": "0.4.32", + "@firebase/messaging-types": "0.5.0", + "@firebase/util": "1.3.0", + "idb": "3.0.2", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/messaging-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.5.0.tgz", + "integrity": "sha512-QaaBswrU6umJYb/ZYvjR5JDSslCGOH6D9P136PhabFAHLTR4TWjsaACvbBXuvwrfCXu10DtcjMxqfhdNIB1Xfg==", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/messaging/node_modules/idb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz", + "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw==" + }, + "node_modules/@firebase/performance": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.4.18.tgz", + "integrity": "sha512-lvZW/TVDne2TyOpWbv++zjRn277HZpbjxbIPfwtnmKjVY1gJ+H77Qi1c2avVIc9hg80uGX/5tNf4pOApNDJLVg==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations": "0.4.32", + "@firebase/logger": "0.2.6", + "@firebase/performance-types": "0.0.13", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/performance-types": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.0.13.tgz", + "integrity": "sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA==" + }, + "node_modules/@firebase/polyfill": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.36.tgz", + "integrity": "sha512-zMM9oSJgY6cT2jx3Ce9LYqb0eIpDE52meIzd/oe/y70F+v9u1LDqk5kUF5mf16zovGBWMNFmgzlsh6Wj0OsFtg==", + "dependencies": { + "core-js": "3.6.5", + "promise-polyfill": "8.1.3", + "whatwg-fetch": "2.0.4" + } + }, + "node_modules/@firebase/remote-config": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.43.tgz", + "integrity": "sha512-laNM4MN0CfeSp7XCVNjYOC4DdV6mj0l2rzUh42x4v2wLTweCoJ/kc1i4oWMX9TI7Jw8Am5Wl71Awn1J2pVe5xA==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/installations": "0.4.32", + "@firebase/logger": "0.2.6", + "@firebase/remote-config-types": "0.1.9", + "@firebase/util": "1.3.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/remote-config-types": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.1.9.tgz", + "integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA==" + }, + "node_modules/@firebase/storage": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.7.0.tgz", + "integrity": "sha512-ebDFKJbM5HOxVtZV+RhVEBVtlWHK+Z5L3kA5uDBA2jMYcn+8NV/crozJnEE+iRsGEco6dLK5JS+Er4qtKLpH5A==", + "dependencies": { + "@firebase/component": "0.5.6", + "@firebase/storage-types": "0.5.0", + "@firebase/util": "1.3.0", + "node-fetch": "2.6.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/storage-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.5.0.tgz", + "integrity": "sha512-6Wv3Lu7s18hsgW7HG4BFwycTquZ3m/C8bjBoOsmPu0TD6M1GKwCzOC7qBdN7L6tRYPh8ipTj5+rPFrmhGfUVKA==", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/storage/node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@firebase/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.3.0.tgz", + "integrity": "sha512-SESvmYwuKOVCZ1ZxLbberbx+9cnbxpCa4CG2FUSQYqN6Ab8KyltegMDIsqMw5KyIBZ4n1phfHoOa22xo5NzAlQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@firebase/webchannel-wrapper": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.5.1.tgz", + "integrity": "sha512-dZMzN0uAjwJXWYYAcnxIwXqRTZw3o14hGe7O6uhwjD1ZQWPVYA5lASgnNskEBra0knVBsOXB4KXg+HnlKewN/A==" + }, + "node_modules/@grpc/grpc-js": { + "version": "1.9.11", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.11.tgz", + "integrity": "sha512-QDhMfbTROOXUhLHMroow8f3EHiCKUOh6UwxMP5S3EuXMnWMNSVIhatGZRwkpg9OUTYdZPsDUVH3cOAkWhGFUJw==", + "dependencies": { + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/grpc-js/node_modules/@grpc/proto-loader": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.10.tgz", + "integrity": "sha512-CAqDfoaQ8ykFd9zqBDn4k6iWT9loLAlc2ETmDFS9JCD70gDcnA4L3AFEo2iV7KyAtAAHFW9ftq1Fz+Vsgq80RQ==", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/grpc-js/node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/@grpc/grpc-js/node_modules/protobufjs": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", + "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.6.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.13.tgz", + "integrity": "sha512-FjxPYDRTn6Ec3V0arm1FtSpmP6V50wuph2yILpyvTKzjc76oDdoihXqM1DzOW5ubvCC8GivfCnNtfaRE8myJ7g==", + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^6.11.3", + "yargs": "^16.2.0" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/@grpc/proto-loader/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/@grpc/proto-loader/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@grpc/proto-loader/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@grpc/proto-loader/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@grpc/proto-loader/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.12", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.12.tgz", @@ -1342,6 +1857,60 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, "node_modules/@remix-run/router": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.10.0.tgz", @@ -2518,6 +3087,11 @@ "dev": true, "peer": true }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, "node_modules/@types/node": { "version": "20.8.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", @@ -3077,7 +3651,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -3086,7 +3659,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -3627,7 +4199,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -3640,14 +4211,12 @@ "node_modules/cliui/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/cliui/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -3656,7 +4225,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -3670,7 +4238,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -3704,7 +4271,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -3715,8 +4281,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/colorette": { "version": "2.0.20", @@ -3779,6 +4344,17 @@ "url": "https://github.com/sponsors/mesqueeb" } }, + "node_modules/core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -4393,6 +4969,14 @@ "node": ">=6.0.0" } }, + "node_modules/dom-storage": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz", + "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q==", + "engines": { + "node": "*" + } + }, "node_modules/dot-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", @@ -4618,7 +5202,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -5196,6 +5779,17 @@ "reusify": "^1.0.4" } }, + "node_modules/faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -5264,6 +5858,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/firebase": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-8.10.0.tgz", + "integrity": "sha512-GCABTbJdo88QgzX5OH/vsfKBWvTRbLUylGlYXtO7uYo1VErfGd2BWW9ATlJP5Gxx+ClDfyvVTvcs2rcNWn3uUA==", + "dependencies": { + "@firebase/analytics": "0.6.18", + "@firebase/app": "0.6.30", + "@firebase/app-check": "0.3.2", + "@firebase/app-types": "0.6.3", + "@firebase/auth": "0.16.8", + "@firebase/database": "0.11.0", + "@firebase/firestore": "2.4.0", + "@firebase/functions": "0.6.15", + "@firebase/installations": "0.4.32", + "@firebase/messaging": "0.8.0", + "@firebase/performance": "0.4.18", + "@firebase/polyfill": "0.3.36", + "@firebase/remote-config": "0.1.43", + "@firebase/storage": "0.7.0", + "@firebase/util": "1.3.0" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, "node_modules/flat-cache": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", @@ -5432,7 +6051,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -5710,6 +6328,11 @@ "react-is": "^16.7.0" } }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, "node_modules/http-proxy": { "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", @@ -6731,6 +7354,11 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -6799,6 +7427,11 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -7554,6 +8187,11 @@ "node": ">=6.0.0" } }, + "node_modules/promise-polyfill": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz", + "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -7565,6 +8203,31 @@ "react-is": "^16.13.1" } }, + "node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -7779,7 +8442,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -8110,7 +8772,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -8454,7 +9115,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8986,6 +9646,32 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "dev": true }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -9149,11 +9835,18 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "engines": { "node": ">=10" } @@ -9176,7 +9869,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -9194,7 +9886,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "engines": { "node": ">=12" } @@ -9202,14 +9893,12 @@ "node_modules/yargs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/yargs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -9218,7 +9907,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", diff --git a/package.json b/package.json index a821a0af..c73d7707 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "axios": "^1.5.1", "d3": "^7.8.5", "emotion-reset": "^3.0.1", + "firebase": "^8.10.0", "framer-motion": "^10.16.4", "http-proxy-middleware": "^2.0.6", "react": "^18.2.0", diff --git a/public/firebase-messaging-sw.js b/public/firebase-messaging-sw.js new file mode 100644 index 00000000..8779ac00 --- /dev/null +++ b/public/firebase-messaging-sw.js @@ -0,0 +1,61 @@ +self.addEventListener('install', function (e) { + console.log('fcm sw install..') + self.skipWaiting() +}) + +self.addEventListener('activate', function (e) { + console.log('fcm sw activate..') +}) + +self.addEventListener('push', function (e) { + console.log('push: ', e.data.json()) + if (!e.data.json()) return + + const resultData = e.data.json().notification + const notificationTitle = resultData.title + const notificationOptions = { + body: resultData.body, + icon: resultData.image, + tag: resultData.tag, + ...resultData, + } + self.registration.showNotification(notificationTitle, notificationOptions) + console.log('push: ', { resultData, notificationTitle, notificationOptions }) + //indexedDB에 상태 저장하는 기능 추가 + saveDataToIndexedDB('isMatchingSuccess', true) +}) + +// IndexedDB에 데이터를 저장하는 함수 +function saveDataToIndexedDB(key, value) { + const request = indexedDB.open('matching-database') + + request.onupgradeneeded = function (event) { + const db = event.target.result + + db.createObjectStore('my-store', { autoIncrement: true }) + } + + request.onsuccess = function (event) { + const db = event.target.result + const tx = db.transaction('my-store', 'readwrite') + const store = tx.objectStore('my-store') + store.put(value, key) + + tx.oncomplete = function () { + db.close() + } + } + + request.onerror = function (event) { + console.error('Error opening IndexedDB:', event.target.error) + } +} + +self.addEventListener('notificationclick', function (event) { + console.log('notification click') + const url = '/' + event.notification.close() + + // eslint-disable-next-line no-undef + event.waitUntil(clients.openWindow(url)) +}) diff --git a/setupProxy.ts b/setupProxy.ts index 84d0e909..e69de29b 100644 --- a/setupProxy.ts +++ b/setupProxy.ts @@ -1,10 +0,0 @@ -// import { createProxyMiddleware } from 'http-proxy-middleware' - -// module.exports = (app) => { -// app.use( -// createProxyMiddleware('/api/chat-stomp', { -// target: process.env.VITE_BASE_URL, -// ws: true, -// }), -// ) -// } diff --git a/src/App.tsx b/src/App.tsx index db703e3c..749f75e1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,9 +1,13 @@ +import './firebase-messaging-sw.ts' + +import { useEffect } from 'react' import { Route, Routes } from 'react-router-dom' import Layout from '@/components/layouts/Layout' import AdminPage from '@/pages/admin' import AdminLoginPage from '@/pages/admin/AdminLogin' import ChatListPage from '@/pages/chatList' +import ChatListDetailPage from '@/pages/chatListDetail' import ChattingPage from '@/pages/chatting' import HomePage from '@/pages/home' import LandingPage from '@/pages/landing' @@ -14,9 +18,17 @@ import ProfilePage from '@/pages/profile' import PrivateRoute from '@/pages/redirect/PrivateRoute' import RegisterPage from '@/pages/register' -import AdminInquiry from './pages/admin/AdminInquiry' +import { getToken } from './firebase-messaging-sw.ts' const App = () => { + const firebaseMessageToken = async () => { + const token = await getToken() + console.log('token === ', token) + //추후 서버에 토큰을 저장하는 기능을 여기에 추가 + } + useEffect(() => { + firebaseMessageToken() + }, []) return ( }> @@ -25,6 +37,7 @@ const App = () => { } /> } /> } /> + } /> }> @@ -39,7 +52,6 @@ const App = () => { }> }> - }> }> }> diff --git a/src/apis/adminReport/AdminReportApi.ts b/src/apis/adminReport/AdminReportApi.ts index 1e6a53d9..914e2476 100644 --- a/src/apis/adminReport/AdminReportApi.ts +++ b/src/apis/adminReport/AdminReportApi.ts @@ -7,6 +7,13 @@ const AdminReportAPI = { data: response.data, } }, + GET_REPORTERS_LIST: async () => { + const response = await axiosAPI.get(`/v1/reporters`) + + return { + data: response.data, + } + }, GET_REPORT_INFO: async () => { const response = await axiosAPI.get(`/v1/reports/:reportId`) return { diff --git a/src/apis/axios.ts b/src/apis/axios.ts index 538a83e5..0547fcfe 100644 --- a/src/apis/axios.ts +++ b/src/apis/axios.ts @@ -16,6 +16,7 @@ axiosAPI.interceptors.request.use( // axios 설정값에 대해 작성합니다. config.headers['Authorization'] = `Bearer ${localStorage.getItem('jwt')}` + return config }, function (error) { diff --git a/src/apis/chatList/ChatListApi.ts b/src/apis/chatList/ChatListApi.ts index fa588a31..16cf9c2f 100644 --- a/src/apis/chatList/ChatListApi.ts +++ b/src/apis/chatList/ChatListApi.ts @@ -4,9 +4,7 @@ const ChatListApi = { // TODO: zustand로 AccessToken 받아서 요청하기 (백엔드 개발 완료 후) GET_CHAT_LIST: async () => { const response = await axiosAPI.get(`/v1/histories`) - return { - data: response.data, - } + return response.data }, } diff --git a/src/apis/queryClient.ts b/src/apis/queryClient.ts index 3fc3cdaf..afe9d5c8 100644 --- a/src/apis/queryClient.ts +++ b/src/apis/queryClient.ts @@ -14,8 +14,8 @@ export const queryClient = new QueryClient({ }, queryCache: new QueryCache({ onError: () => { - alert('에러 발생! 올바른 경로로 서비스를 이용해주세요.') - window.location.href = '/' + // alert('에러 발생! 올바른 경로로 서비스를 이용해주세요.') + // window.location.href = '/' }, }), }) diff --git a/src/components/chatList/ChatRoomBubbles.tsx b/src/components/chatList/ChatRoomBubbles.tsx index 3d50c91a..34626013 100644 --- a/src/components/chatList/ChatRoomBubbles.tsx +++ b/src/components/chatList/ChatRoomBubbles.tsx @@ -1,4 +1,5 @@ import styled from '@emotion/styled' +import { useNavigate } from 'react-router-dom' import ChatRoomBubble from './ChatRoomBubble' @@ -18,8 +19,9 @@ const StyledChatRoomBubbleWrapper = styled.div` padding: 30% 5% 5%; } ` - +const ChatRoomBubbleWrapper = styled.span`` type ChatRoom = { + id: string title: string participants: string[] createdAt: string @@ -31,17 +33,24 @@ type ChatRoomBubblesProps = { } const ChatRoomBubbles = ({ chatRoomList, isDarkMode }: ChatRoomBubblesProps) => { + const navigate = useNavigate() return ( {chatRoomList.map((chatRoom, idx) => { return ( - + onClick={() => { + navigate('/chat-list-detail', { state: { chatroomId: chatRoom.id } }) + }} + > + + ) })} diff --git a/src/components/common/Buttons/IconButton/ParticularTopicButton.tsx b/src/components/common/Buttons/IconButton/ParticularTopicButton.tsx index 39d92e99..11cffb8a 100644 --- a/src/components/common/Buttons/IconButton/ParticularTopicButton.tsx +++ b/src/components/common/Buttons/IconButton/ParticularTopicButton.tsx @@ -56,7 +56,12 @@ const ParticularTopicButton = ({ flex: 1, }} > - + {'특정 주제로 대화하기'} void } @@ -20,7 +20,7 @@ type RandomMatchingButtonProps = { * @param onClick - 랜덤매칭 버튼 클릭 이벤트 */ -const RandomMatchingButton = ({ date, isDarkMode, onClick }: RandomMatchingButtonProps) => { +const RandomMatchingButton = ({ isDarkMode, onClick }: RandomMatchingButtonProps) => { const setButtonType = isDarkMode ? 'random-matching-dark' : 'random-matching' return ( @@ -70,7 +70,7 @@ const RandomMatchingButton = ({ date, isDarkMode, onClick }: RandomMatchingButto alignItems: 'center', }} > - {'마지막 채팅: '} {`${getTimeDelta(date)}`} + {/* {'마지막 채팅: '} {`${getTimeDelta(date)}`} */} = { borderRadius: 50, }, matching: { - width: 123, - height: 45, - fontColor: palette.WHITE, - backgroundColor: palette.TERTIARY, - font: 'Body_14', + width: 63, + height: 30, + fontColor: palette.GRAY300, + backgroundColor: palette.GRAY100, + font: 'Body_12', fontWeight: 500, letterSpacing: -1, - boxShadow: '0px 4px 20px rgba(0, 0, 0, 0.15)', + borderRadius: 8, }, 'matching-dark': { diff --git a/src/components/common/ListRow/AdminInquiryList.tsx b/src/components/common/ListRow/AdminInquiryList.tsx index e9b9c1bf..201368f4 100644 --- a/src/components/common/ListRow/AdminInquiryList.tsx +++ b/src/components/common/ListRow/AdminInquiryList.tsx @@ -3,32 +3,34 @@ import { useQuery } from '@tanstack/react-query' import AdminInquiryAPI from '@/apis/adminInquiry/AdminInquiryApi' import AdminApprovalListRow from '@/components/common/ListRow/AdminApprovalListRow' +import AdminPageHeader from '@/pages/admin/components/AdminPageHeader' import { palette } from '@/styles/palette' interface AdminInquiryListProps { - onApproveSelectUserName: (nickname: string) => void + onInquirySelectUserName: (nickname: string) => void } interface InquiryListData { inquiryRequestUser: string inquiryRequestDate: string - onApproveSelectUserName: (nickname: string) => void + onInquirySelectUserName: (nickname: string) => void } interface InquiryListData { approvalRequestUser: string approvalRequestUserStatus: string } -const AdminInquiryList = ({ onApproveSelectUserName }: AdminInquiryListProps) => { +const AdminInquiryList = ({ onInquirySelectUserName }: AdminInquiryListProps) => { // API 요청 코드 const { data, isSuccess } = useQuery(['AdminInquiryList'], AdminInquiryAPI.GET_INQUIRY_LIST) - const handlePersonApproval = (nickname: string) => { - onApproveSelectUserName(nickname) + const handlePersonInquiry = (inquiryNickname: string) => { + onInquirySelectUserName(inquiryNickname) } const inquiryDatas = data?.data.inquiries return ( + {isSuccess && inquiryDatas.map((inquiryListData: InquiryListData, index: number) => ( @@ -38,7 +40,7 @@ const AdminInquiryList = ({ onApproveSelectUserName }: AdminInquiryListProps) => nickname={inquiryListData.inquiryRequestUser} infoMessage={inquiryListData.inquiryRequestDate} isDarkMode={false} - onClick={() => handlePersonApproval(inquiryListData.inquiryRequestUser)} + onClick={() => handlePersonInquiry(inquiryListData.inquiryRequestUser)} /> ))} @@ -48,6 +50,7 @@ const AdminInquiryList = ({ onApproveSelectUserName }: AdminInquiryListProps) => const AdminInquiryListContainerOuterWrapper = styled.div` background-color: ${palette.WHITE}; width: 100%; + height: 662px; ` const AdminInquiryListContainer = styled.div` background-color: ${palette.WHITE}; diff --git a/src/components/common/ListRow/AdminReportList.tsx b/src/components/common/ListRow/AdminReportList.tsx index d2c62ee7..1d054cc5 100644 --- a/src/components/common/ListRow/AdminReportList.tsx +++ b/src/components/common/ListRow/AdminReportList.tsx @@ -3,6 +3,7 @@ import { useQuery } from '@tanstack/react-query' import AdminReportAPI from '@/apis/adminReport/AdminReportApi' import AdminReportListRow from '@/components/common/ListRow/AdminReportListRow' +import AdminReportListRowTitle from '@/components/common/ListRow/AdminReportListRowTitle' import { palette } from '@/styles/palette' interface AdminReportListProps { @@ -10,7 +11,7 @@ interface AdminReportListProps { } interface ReportListData { reportedUserName: string - reportCount: number + reportCount: string } const AdminReportList = ({ onReportSelect }: AdminReportListProps) => { const { data, isSuccess } = useQuery(['ReportedUserList'], AdminReportAPI.GET_REPORT_LIST) @@ -22,17 +23,28 @@ const AdminReportList = ({ onReportSelect }: AdminReportListProps) => { return ( - {isSuccess && - ReportDatas.map((reportListData: ReportListData, index: number) => ( - + handlePersonReported(reportListData.reportedUserName)} - /> - ))} + reportedNickname={'신고 대상 닉네임'} + reportedDate={'신고 날짜'} + > + {ReportDatas.map((reportListData: ReportListData, index: number) => ( + handlePersonReported(reportListData.reportedUserName)} + /> + ))} + + )} ) diff --git a/src/components/common/ListRow/AdminReportListRow.tsx b/src/components/common/ListRow/AdminReportListRow.tsx index 22338ba0..edba70c4 100644 --- a/src/components/common/ListRow/AdminReportListRow.tsx +++ b/src/components/common/ListRow/AdminReportListRow.tsx @@ -5,72 +5,26 @@ import { palette } from '@/styles/palette' type AdminReportListRowProps = { height: number - nickname: string - infoMessage: string | number + chattingRoomName: string + reportedNickname: string + reportedDate: string isDarkMode: boolean onClick?: () => void } + const AdminReportListRow = ({ height, - nickname, - infoMessage, + chattingRoomName, + reportedNickname, + reportedDate, isDarkMode, onClick, }: AdminReportListRowProps) => { - const renderInfoMessage = () => { - if (typeof infoMessage === 'number') { - return ( - - - {'누적 '} - - - {infoMessage} - - - {' 회'} - - - ) - } - return ( - - {infoMessage} - - ) - } - + const displayChattingRoomName = + chattingRoomName.length > 4 ? `${chattingRoomName.substring(0, 4)}...` : chattingRoomName + const displayReportedNickname = + reportedNickname.length > 3 ? `${reportedNickname.substring(0, 3)}..` : reportedNickname return ( - - {nickname} - - {renderInfoMessage()} + + + {displayChattingRoomName} + + + {displayReportedNickname} + + + {reportedDate} + + ) } diff --git a/src/components/common/ListRow/AdminReportListRowTitle.tsx b/src/components/common/ListRow/AdminReportListRowTitle.tsx new file mode 100644 index 00000000..803f14f8 --- /dev/null +++ b/src/components/common/ListRow/AdminReportListRowTitle.tsx @@ -0,0 +1,73 @@ +import { FlexBox } from '@/components/common/Flexbox' +import { StyleList } from '@/components/common/ListRow/ProfileListRow' +import { Text } from '@/components/common/Text' +import { palette } from '@/styles/palette' + +type AdminReportListRowProps = { + height: number + chattingRoomName: string + reportedNickname: string + reportedDate: string + isDarkMode: boolean + + onClick?: () => void +} + +const AdminReportListRowTitle = ({ + height, + chattingRoomName, + reportedNickname, + reportedDate, + isDarkMode, + onClick, +}: AdminReportListRowProps) => { + return ( + + + + {chattingRoomName} + + + {reportedNickname} + + + {reportedDate} + + + + ) +} + +export default AdminReportListRowTitle diff --git a/src/components/common/ListRow/AdminReportersList.tsx b/src/components/common/ListRow/AdminReportersList.tsx new file mode 100644 index 00000000..2ba6907c --- /dev/null +++ b/src/components/common/ListRow/AdminReportersList.tsx @@ -0,0 +1,104 @@ +import styled from '@emotion/styled' +import { useQuery } from '@tanstack/react-query' +import { useMutation } from '@tanstack/react-query' + +import AdminReportAPI from '@/apis/adminReport/AdminReportApi' +import AdminReportersListRow from '@/components/common/ListRow/AdminReportersListRow' +import Spacing from '@/components/common/Spacing' +import { useModal } from '@/hooks/useModal' +import AdminPageHeader from '@/pages/admin/components/AdminPageHeader' +import { palette } from '@/styles/palette' + +import NormalButton from '../Buttons/NormalButton' + +interface AdminReportersListProps { + onReportSelect: (nickname: string) => void + selectedReportNickname: string +} +interface ReportersListData { + reporterUserName: string + reportedDate: string +} +const AdminReportersList = ({ + onReportSelect, + selectedReportNickname, +}: AdminReportersListProps) => { + const mutationReportAddCount = useMutation(AdminReportAPI.POST_REPORT_ADD, { + onSuccess: (data) => { + console.log(data) + }, + }) + const mutationReportIgnore = useMutation(AdminReportAPI.POST_REPORT_IGNORE, { + onSuccess: (data) => { + console.log(data) + }, + }) + const onReportAddCount = () => { + mutationReportAddCount.mutate() + } + const onReportIgnore = () => { + mutationReportIgnore.mutate() + } + const { openModal } = useModal() + const handleAccumulationAddBtn = () => { + openModal({ + type: 'confirm', + mainText: '신고를 누적하시겠습니까?', + okFunc: onReportAddCount, + }) + } + const { data, isSuccess } = useQuery(['ReporterUserList'], AdminReportAPI.GET_REPORTERS_LIST) + const handlePersonReported = (nickname: string) => { + onReportSelect(nickname) + } + const ReportersDatas = data?.data.reporters + return ( + + + + {isSuccess && ( + <> + {ReportersDatas.map((reporterListData: ReportersListData, index: number) => ( + handlePersonReported(reporterListData.reporterUserName)} + /> + ))} + + )} + + + + {'누적 추가'} + + + {'무시'} + + + + + ) +} +const StyledAdminReportersListContainer = styled.div` + background-color: ${palette.WHITE}; + overflow: scroll; + height: 662px; + width: 80%; + margin: auto; + cursor: pointer; +` +const StyledAdminReportersListContainerOuterWrapper = styled.div` + background-color: ${palette.WHITE}; + width: 100%; + height: 662px; +` +const StyledButtonsWrapper = styled.div` + display: flex; + justify-content: space-evenly; + padding: 60px 0 25px 0; +` +export default AdminReportersList diff --git a/src/components/common/ListRow/AdminReportersListRow.tsx b/src/components/common/ListRow/AdminReportersListRow.tsx new file mode 100644 index 00000000..f6196e42 --- /dev/null +++ b/src/components/common/ListRow/AdminReportersListRow.tsx @@ -0,0 +1,63 @@ +import { FlexBox } from '@/components/common/Flexbox' +import { StyleList } from '@/components/common/ListRow/ProfileListRow' +import { Text } from '@/components/common/Text' +import { palette } from '@/styles/palette' + +type AdminReportersListRowProps = { + height: number + reporterNickname: string + reportedDate: string + isDarkMode: boolean + + onClick?: () => void +} + +const AdminReportersListRow = ({ + height, + reporterNickname, + reportedDate, + isDarkMode, + onClick, +}: AdminReportersListRowProps) => { + const displayReporterNickname = + reporterNickname.length > 4 ? `${reporterNickname.substring(0, 4)}...` : reporterNickname + + return ( + + + + {displayReporterNickname} + + + {reportedDate} + + + + ) +} + +export default AdminReportersListRow diff --git a/src/components/home/Card.tsx b/src/components/home/Card.tsx index 1087ed60..090e7aaa 100644 --- a/src/components/home/Card.tsx +++ b/src/components/home/Card.tsx @@ -2,22 +2,26 @@ import styled from '@emotion/styled' import { timer } from 'd3' import { AnimatePresence, motion } from 'framer-motion' import { useEffect, useRef, useState } from 'react' +import { IoIosArrowForward } from 'react-icons/io' +import { useNavigate } from 'react-router-dom' import { PulseLoader } from 'react-spinners' +import { axiosAPI } from '@/apis/axios' import { RandomMatchingButton } from '@/components/common/Buttons/IconButton' import NormalButton from '@/components/common/Buttons/NormalButton' +import { FlexBox } from '@/components/common/Flexbox' import Spacing from '@/components/common/Spacing' import { Text } from '@/components/common/Text' +import useToast from '@/hooks/useToast' import { palette } from '@/styles/palette' +import { typo } from '@/styles/typo' import Tip from './Tip' type TimerRefType = ReturnType | null type CardProps = { - isMatching: boolean isDarkMode: boolean - onClick: () => void } /** @@ -26,16 +30,37 @@ type CardProps = { * @param onClick - 매칭 버튼 클릭 이벤트 */ -const Card = ({ isMatching, isDarkMode, onClick }: CardProps) => { +const Card = ({ isDarkMode }: CardProps) => { const [time, setTime] = useState(0) const timerRef = useRef(null) + const [matchingStartedAt, setMatchingStartedAt] = useState('') + const [isMatching, setIsMatching] = useState(false) + const [currentState, setCurrentState] = useState('IDLE') + const [chatroomId, setChatroomId] = useState('33') + const navigate = useNavigate() + const { showToast } = useToast() - const handleCancelClick = () => { + const handleMoveChatting = () => { + navigate('/chatting', { state: { chatroomId: chatroomId } }) + } + + const handleMatchingStart = async () => { + setIsMatching((prev) => !prev) + setCurrentState('MATCHING') + await axiosAPI.post('/v1/matching/start').then((response) => { + console.log(response) + setCurrentState('MATCHING') + }) + } + + const handleCancelClick = async () => { + setIsMatching((prev) => !prev) setTime(0) if (timerRef.current) { timerRef.current.stop() } - onClick() + setCurrentState('IDLE') + await axiosAPI.post('/v1/matchings/cancel') } const formatTime = (time: number) => { @@ -48,15 +73,38 @@ const Card = ({ isMatching, isDarkMode, onClick }: CardProps) => { return `${minutes}:${seconds}` } - const watingCounter = { + const waitingCounter = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { type: 'spring', damping: 12, duration: 0.5 } }, exit: { opacity: 0, transition: { duration: 1 } }, } + const getCurrentMatchingState = async () => { + await axiosAPI + .get('/v1/users/status') + .then((response) => { + if (currentState == response.data.userStatus) + showToast({ + message: '아직 매칭이 성사되지 않았습니다!', + type: 'info', + isDarkMode: isDarkMode, + }) + setCurrentState(response.data.userStatus) + response.data.userStatus === 'CHATTING_UNCONNECTED' && + setChatroomId(response.data.chattingRoomId) + response.data.userStatus === 'MATCHING' && setMatchingStartedAt(response.data.startedAt) + }) + .catch((err) => { + console.log(err) + }) + } useEffect(() => { - if (isMatching) { - const startTime = Date.now() + if (currentState === 'MATCHING') { + //startTime에 서버에서 시작시간 받아와 new Date객체 안에 넣은 후 스트링으로 바꿔서 Date.parse한 후 Date.now()에서 뺄 것 + const date = new Date(matchingStartedAt) + date.setHours(date.getHours() + 9) + const startTime = matchingStartedAt.length === 0 ? Date.now() : Date.parse(date.toString()) + const updateTimer = () => { const elapsedTime = Date.now() - startTime setTime(elapsedTime) @@ -75,46 +123,36 @@ const Card = ({ isMatching, isDarkMode, onClick }: CardProps) => { } }, [isMatching]) + useEffect(() => { + getCurrentMatchingState() + }, [currentState]) + return ( - {!isMatching ? ( + {currentState === 'IDLE' ? ( - + - ) : ( - - - - - {'3'} - - - {'/5'} - - - - - + { > {formatTime(time)} - - - {'매칭 취소'} - + + {'매칭 확인'} + + + { }} /> - - - + + + + {'매칭 취소'} + + + - - + + + ) : ( + <> + + {'매칭이 완료되었습니다!'} + + + + + + {'채팅방으로 이동'} + + + + + + )} ) } - +const StyleMoveChatButton = styled.button` + width: 200px; + height: 70px; + border-radius: 20px; + color: ${palette.WHITE}; + font-size: ${typo.Body_16(600)}; + box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.25); + background-image: linear-gradient( + to right, + ${palette.SECONDARY} 0%, + ${palette.SECONDARY} 50%, + ${palette.GRADIENT} 110% + ); +` +const StyleMatchingCancelWrapper = styled.span` + display: flex; + position: relative; + margin: 5px; +` +const StyleMatchingCheckButton = styled.button<{ isDarkMode: boolean }>` + width: 200px; + height: 60px; + border-radius: 20px; + color: ${palette.WHITE}; + font-size: ${typo.Body_16(600)}; + background-color: ${palette.SECONDARY}; +` const StyleCard = styled(motion.div)<{ isDarkMode: boolean }>` @@ -180,7 +275,7 @@ const StyleCard = styled(motion.div)<{ padding: 5% 1% 5%; ` -const StyleWatingWrapper = styled(motion.div)` +const StyleWaitingWrapper = styled(motion.div)` width: 100%; display: flex; flex-direction: column; @@ -188,24 +283,7 @@ const StyleWatingWrapper = styled(motion.div)` flex: 1; ` -const StyleWatingTopWrapper = styled.div` - width: 100%; - height: 38px; - display: flex; - justify-content: space-between; - align-items: center; - padding: 0 5%; - position: relative; -` - -const StyleWatingTopTextWrapper = styled.div` - display: flex; - height: inherit; - justify-content: center; - align-items: flex-end; -` - -const StyleWatingMidWrapper = styled.div` +const StyleWaitingMidWrapper = styled.div` flex: 1; display: flex; flex-direction: column; @@ -213,6 +291,6 @@ const StyleWatingMidWrapper = styled.div` align-items: center; ` -const StyleWatingBottomWrapper = styled.div`` +const StyleWaitingBottomWrapper = styled.div`` export default Card diff --git a/src/components/home/Tip.tsx b/src/components/home/Tip.tsx index 2230fe4a..cdc4e903 100644 --- a/src/components/home/Tip.tsx +++ b/src/components/home/Tip.tsx @@ -9,7 +9,7 @@ const StyledTipHeader = styled.div` flex-direction: column; height: 63.525px; padding: 11px 18px 0px; - border-top: 1px solid ${palette.GRAY200}; + border-top: 0.5px dotted ${palette.GRAY400}; ` const Tip = () => { diff --git a/src/firebase-messaging-sw.ts b/src/firebase-messaging-sw.ts new file mode 100644 index 00000000..d2f80395 --- /dev/null +++ b/src/firebase-messaging-sw.ts @@ -0,0 +1,89 @@ +// import 'firebase/messaging' + +// import firebase from 'firebase/app' + +// const firebaseConfig = { +// apiKey: import.meta.env.VITE_apiKey, +// authDomain: import.meta.env.VITE_authDomain, +// projectId: import.meta.env.VITE_projectId, +// storageBucket: import.meta.env.VITE_storageBucket, +// messagingSenderId: import.meta.env.VITE_messagingSenderId, +// appId: import.meta.env.VITE_appId, +// measurementId: import.meta.env.VITE_measurementId, +// } + +// firebase.initializeApp(firebaseConfig) + +// const messaging = firebase.messaging() + +// export function requestPermission() { +// void Notification.requestPermission().then((permission) => { +// if (permission === 'granted') { +// messaging +// .getToken({ vapidKey: import.meta.env.VITE_VAPID_KEY }) +// .then((token: string) => { +// console.log(`푸시 토큰 발급 완료 : ${token}`) +// return token +// }) +// // .then(function (token) { +// // console.log('알림 왜 안 울려') +// // messaging.onMessage((payload) => { +// // alert('알림:' + payload.notification.body) +// // }) +// // return token +// // }) +// .catch((err) => { +// console.log('푸시 토큰 가져오는 중에 에러 발생 : ', err) +// }) +// } else if (permission === 'denied') { +// console.log('푸시 권한 차단') +// } +// }) +// } +// requestPermission() + +// import 'firebase/messaging' + +import firebase from 'firebase' +const firebaseConfig = { + apiKey: import.meta.env.VITE_apiKey, + authDomain: import.meta.env.VITE_authDomain, + projectId: import.meta.env.VITE_projectId, + storageBucket: import.meta.env.VITE_storageBucket, + messagingSenderId: import.meta.env.VITE_messagingSenderId, + appId: import.meta.env.VITE_appId, + measurementId: import.meta.env.VITE_measurementId, +} + +firebase.initializeApp(firebaseConfig) +export async function getToken() { + if (firebase.messaging.isSupported() === false) { + console.log('isSupported: ', firebase.messaging.isSupported()) + return null + } + + const messaging = firebase.messaging() + const token = await messaging + .requestPermission() + .then(function () { + return messaging.getToken({ vapidKey: import.meta.env.VITE_VAPID_KEY }) + }) + .then(function (token) { + messaging.onMessage((payload) => { + console.log('onMessage!!') + alert('알림:' + payload.notification.body) + }) + return token + }) + .catch(function (err) { + console.debug('에러 : ', err) + return null + }) + messaging.onMessage((payload) => { + console.log('onMessage!!') + alert('알림:' + payload.notification.body) + }) + console.log('token:', token) + return token +} +getToken() diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 56b2bbf5..51e8dbd3 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -6,6 +6,7 @@ import { ApprovalInfo, ApprovalResult, Inquiry, + Reporters, ReportInfo, ReportResult, Reports, @@ -468,8 +469,8 @@ export const handlers = [ { reportedUserName: '박상민', reportCount: 2 }, { reportedUserName: '박은지', reportCount: 1 }, { reportedUserName: '주다현', reportCount: 1 }, - { reportedUserName: '남궁호수', reportCount: 1 }, { reportedUserName: '우창욱', reportCount: 1 }, + { reportedUserName: '남궁호수', reportCount: 1 }, { reportedUserName: '홍길동', reportCount: 0 }, { reportedUserName: '홍길동', reportCount: 2 }, { reportedUserName: '홍길동', reportCount: 3 }, @@ -481,6 +482,15 @@ export const handlers = [ ] return HttpResponse.json({ reports }) }), + // 신고자 목록 API 핸들러 + http.get('/v1/reporters', () => { + const reporters: Reporters[] = [ + { reporterUserName: '유명한', reportedDate: '2021.07.30' }, + { reporterUserName: '박상민', reportedDate: '2021.07.30' }, + { reporterUserName: '박은지', reportedDate: '2021.07.30' }, + ] + return HttpResponse.json({ reporters }) + }), // 신고 상세 정보 API 핸들러 http.get('/v1/reports/:reportId', (req) => { diff --git a/src/mocks/handlersInterface.ts b/src/mocks/handlersInterface.ts index 01277139..d661d4c6 100644 --- a/src/mocks/handlersInterface.ts +++ b/src/mocks/handlersInterface.ts @@ -17,6 +17,10 @@ export interface Reports { reportedUserName: string reportCount: number } +export interface Reporters { + reporterUserName: string + reportedDate: string +} export interface ReportInfo { reportedUserName: string reportDate: string diff --git a/src/pages/admin/AdminInquiry.tsx b/src/pages/admin/AdminInquiry.tsx index 68b26994..e8dfb70d 100644 --- a/src/pages/admin/AdminInquiry.tsx +++ b/src/pages/admin/AdminInquiry.tsx @@ -19,7 +19,7 @@ const AdminInquiry = () => { {/* */} - + diff --git a/src/pages/admin/components/AdminInquiryInfo.tsx b/src/pages/admin/components/AdminInquiryInfo.tsx index e1862906..2be4a96d 100644 --- a/src/pages/admin/components/AdminInquiryInfo.tsx +++ b/src/pages/admin/components/AdminInquiryInfo.tsx @@ -6,22 +6,29 @@ import InquiryImage from '@/assets/images/inquiryImage.svg' import Spacing from '@/components/common/Spacing' // import Spacing from '@/components/common/Spacing' import { Text } from '@/components/common/Text' +import AdminPageHeader from '@/pages/admin/components/AdminPageHeader' import { palette } from '@/styles/palette' -const AdminInquiryInfo = () => { +interface AdminInquiryInfoProps { + selectedInquiryNickname: string +} +const AdminInquiryInfo = (selectedInquiryNickname: AdminInquiryInfoProps) => { const { data, isSuccess } = useQuery( ['ApprovalRequestUserInfo'], AdminApprovalAPI.GET_APPROVAL_INFO, ) console.log(isSuccess && data) + const inquiryNickname = selectedInquiryNickname.selectedInquiryNickname return ( <> + + - {'유명한'} + {inquiryNickname} @@ -47,6 +54,7 @@ const AdminInquiryInfo = () => { const StyledAdminInquiryInfo = styled.div` background-color: ${palette.WHITE}; + height: 662px; ` const StyledInquiryContent = styled.div` position: relative; diff --git a/src/pages/admin/components/AdminReportInfo.tsx b/src/pages/admin/components/AdminReportInfo.tsx index 82e0083d..cc9f3a4d 100644 --- a/src/pages/admin/components/AdminReportInfo.tsx +++ b/src/pages/admin/components/AdminReportInfo.tsx @@ -1,50 +1,25 @@ import styled from '@emotion/styled' import { useQuery } from '@tanstack/react-query' -import { useMutation } from '@tanstack/react-query' import AdminReportAPI from '@/apis/adminReport/AdminReportApi' -import NormalButton from '@/components/common/Buttons/NormalButton' import AdminReportInfoListRow from '@/components/common/ListRow/AdminReportInfoListRow' import Spacing from '@/components/common/Spacing' -import { useModal } from '@/hooks/useModal' +import { Text } from '@/components/common/Text' import { palette } from '@/styles/palette' import AdminPageHeader from './AdminPageHeader' interface AdminReportInfoProps { - selectedReportNickname: string + selectedReporterNickname: string } -const AdminReportInfo = ({ selectedReportNickname }: AdminReportInfoProps) => { - const mutationReportAddCount = useMutation(AdminReportAPI.POST_REPORT_ADD, { - onSuccess: (data) => { - console.log(data) - }, - }) - const mutationReportIgnore = useMutation(AdminReportAPI.POST_REPORT_IGNORE, { - onSuccess: (data) => { - console.log(data) - }, - }) - const onReportAddCount = () => { - mutationReportAddCount.mutate() - } - const onReportIgnore = () => { - mutationReportIgnore.mutate() - } +const AdminReportInfo = ({ selectedReporterNickname }: AdminReportInfoProps) => { const { data, isSuccess } = useQuery(['ReportedUserInfo'], AdminReportAPI.GET_REPORT_INFO) console.log(isSuccess && data) - const { openModal } = useModal() - const handleAccumulationAddBtn = () => { - openModal({ - type: 'confirm', - mainText: '신고를 누적하시겠습니까?', - okFunc: onReportAddCount, - }) - } + return ( - + { infoMessage={'채팅방 내 잠수'} isDarkMode={false} /> - + { isDarkMode={false} /> + + + {'신고 상세 사유'} + + + + + {' '} + {'채팅방 내 잠수 기네스북 기록을 세웠어요 어쩌구 저쩌구'} + + + - - - - - - {'누적 추가'} - - - {'무시'} - - - - ) @@ -103,15 +72,6 @@ const StyledAdminReportInfoOuterWrapper = styled.div` height: 662px; ` -const StyledAdminReportInfoContainer = styled.div` - background-color: ${palette.WHITE}; -` - -const StyledButtonsWrapper = styled.div` - display: flex; - justify-content: space-evenly; - padding: 60px 0 25px 0; -` const StyledReportInfoListWrapper = styled.div` background-color: ${palette.WHITE}; width: 100%; @@ -127,4 +87,18 @@ const StyledReportInfoListOuterWrapper = styled.div` const StyledBelowWhiteSpace = styled.div` background-color: ${palette.WHITE}; ` +const StyledTextWrapper = styled.div` + padding-left: 35px; + padding-bottom: 16px; + padding-top: 30px; +` +const StyledReportSpecificContent = styled.div` + margin: 0 auto; + background-color: ${palette.GRAY100}; + width: 327px; + height: 170px; + border-radius: 20px; + padding: 20px; + overflow: scroll; +` export default AdminReportInfo diff --git a/src/pages/admin/components/AdminTabs.tsx b/src/pages/admin/components/AdminTabs.tsx index 405aeb27..5dc56656 100644 --- a/src/pages/admin/components/AdminTabs.tsx +++ b/src/pages/admin/components/AdminTabs.tsx @@ -2,88 +2,91 @@ import styled from '@emotion/styled' import { useState } from 'react' import AdminApprovalList from '@/components/common/ListRow/AdminApprovalList' +import AdminInquiryList from '@/components/common/ListRow/AdminInquiryList' +import AdminReportersList from '@/components/common/ListRow/AdminReportersList' import AdminReportList from '@/components/common/ListRow/AdminReportList' -import HomeNavigationBar from '@/components/common/NavigationBar/AdminNavigationBar' import { Text } from '@/components/common/Text' import AdminApprovalInfo from '@/pages/admin/components/AdminApprovalInfo' -import AdminInquiryBtn from '@/pages/admin/components/AdminInquiryBtn' import AdminReportInfo from '@/pages/admin/components/AdminReportInfo' import { palette } from '@/styles/palette' +import AdminInquiryInfo from './AdminInquiryInfo' + interface TabProps { isActive: boolean } -interface ReportListProps { - onPersonReportedSelected: (reportNickname: string) => void -} -interface ApprovalListProps { - onPersonApprovalSelected: (approvalNickname: string) => void -} - const AdminTabs = () => { const [activeTab, setActiveTab] = useState('approval') - const [selectedReportNickname, setSelectedReportNickname] = useState(null) - const [selectedApprovalNickname, setSelectedApprovalNickname] = useState(null) + const [selectedApprovalNickname, setSelectedApprovalNickname] = useState('') + const [selectedInquiryNickname, setSelectedInquiryNickname] = useState('') + const [selectedReportedNickname, setSelectedReportedNickname] = useState('') + const [selectedReporterNickname, setSelectedReporterNickname] = useState('') + console.log('신고자 닉네임: ' + selectedReporterNickname) - const handleReportSelectNickname = (reportNickname: string) => { - setSelectedReportNickname(reportNickname) - setActiveTab('reportInfo') - } const handleApprovalSelectUserName = (approvalNickname: string) => { setSelectedApprovalNickname(approvalNickname) setActiveTab('approvalInfo') } + const handleInquirySelectUserName = (inquiryNickname: string) => { + setSelectedInquiryNickname(inquiryNickname) + setActiveTab('inquiryInfo') + } + const handleReportSelectUserName = (reportedNickname: string) => { + setSelectedReportedNickname(reportedNickname) + setActiveTab('reportersList') + } + const handleReportersSelectUserName = (reporterNickname: string) => { + setSelectedReporterNickname(reporterNickname) + setActiveTab('reportInfo') + } - const ApprovalList = ({ onPersonApprovalSelected }: ApprovalListProps) => ( - - ) - const ReportList = ({ onPersonReportedSelected }: ReportListProps) => ( - - ) // 탭에서 보여줄 컴포넌트들 - + const renderTabContent = () => { + switch (activeTab) { + case 'approval': + return + case 'approvalInfo': + return + case 'inquiry': + return + case 'inquiryInfo': + return + case 'report': + return + case 'reportersList': + return ( + + ) + case 'reportInfo': + return + default: + return null + } + } return ( <> + {renderTabContent()} - setActiveTab('approval')}> - + setActiveTab('approval')}> + {'승인 대기 목록'} - - setActiveTab('report')}> - - {'사용자 신고 내역'} + + setActiveTab('inquiry')}> + + {'불편 사항 처리'} + + + setActiveTab('report')}> + + {'사용자 신고내역'} - + - - - {activeTab === 'approval' && ( - - )} - {activeTab === 'report' && ( - - )} - {activeTab === 'reportInfo' && selectedReportNickname && ( - - )} - {activeTab === 'approvalInfo' && selectedApprovalNickname && ( - - )} - - - ) } @@ -92,31 +95,24 @@ const StyledTabsContainer = styled.div` background-color: ${palette.PRIMARY}; display: flex; width: 100%; + height: 71px; + align-items: center; ` const StyledListContainer = styled.div` width: 100%; ` -const StyledLeftTab = styled.button` - flex: 1; - - padding: 27px 25px 23px 25px; - cursor: pointer; - background: ${(props) => (props.isActive ? palette.GRAY100 : palette.WHITE)}; - border: 1.5px solid ${palette.GRAY100}; - box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25); - border-radius: 30px 0 0 0; -` -const StyledRightTab = styled.button` - padding: 27px 25px 23px 25px; +const StyledTab = styled.div` flex: 1; + justify-content: center; + align-items: center; + padding: 27px 10px 24px 16px; cursor: pointer; background: ${(props) => (props.isActive ? palette.GRAY100 : palette.WHITE)}; border: 1.5px solid ${palette.GRAY100}; box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25); - - border-radius: 0 30px 0 0; + color: ${(props) => (props.isActive ? palette.GRAY300 : palette.GRAY300)}; ` export default AdminTabs diff --git a/src/pages/chatList/ChatList.tsx b/src/pages/chatList/ChatList.tsx index c5bf8d9e..f2e4f5f6 100644 --- a/src/pages/chatList/ChatList.tsx +++ b/src/pages/chatList/ChatList.tsx @@ -17,8 +17,6 @@ const ChatList = () => { const isDarkMode = useThemeStore((state) => state.isDarkMode) const navigate = useNavigate() - // TODO: TanStack의 useQuery를 사용하여 채팅방 목록 가져오기 - // 일단 MSW로 mock data를 만들어서 사용 const { data, isSuccess } = useQuery(['chatRoomList'], ChatListApi.GET_CHAT_LIST) const containerVariants = { @@ -54,7 +52,11 @@ const ChatList = () => { /> {isSuccess && ( - + {data?.data.length == 0 ? ( + '이전 채팅방이 없습니다!' + ) : ( + + )} )} diff --git a/src/pages/chatListDetail/ChatListDetail.tsx b/src/pages/chatListDetail/ChatListDetail.tsx new file mode 100644 index 00000000..86c2a1e2 --- /dev/null +++ b/src/pages/chatListDetail/ChatListDetail.tsx @@ -0,0 +1,99 @@ +import styled from '@emotion/styled' +import { useEffect, useRef, useState } from 'react' +import { BsArrowLeftShort } from 'react-icons/bs' +import { useLocation, useNavigate } from 'react-router-dom' + +import { axiosAPI } from '@/apis/axios' +import { Messages } from '@/apis/chatting/chattingType' +import Send from '@/assets/icons/Send.svg' +import { FlexBox } from '@/components/common/Flexbox' +import GradationBackground from '@/components/common/GradationBackground' +import PageContainer from '@/components/common/PageContainer' +import PageHeader from '@/components/common/PageHeader' +import Spacing from '@/components/common/Spacing' +import TextArea from '@/components/common/TextArea' +import MessageArea from '@/components/messageArea' +import { palette } from '@/styles/palette' + +const ChatListDetail = () => { + const navigate = useNavigate() + const { chatroomId } = useLocation().state + // const chatroomId = '1' + const [messages, setMessages] = useState([] as Messages[]) + + const messageWrapperRef = useRef(null) + const messageRef = useRef(null) + const divRef = useRef(null) + const navigateChatList = () => { + navigate('/chat-list') + } + const getChattingHistory = async () => { + await axiosAPI + .get(`/api/v1/histories/${chatroomId}`) + .then((response) => { + setMessages(response.data) + }) + .catch((err) => console.log(err)) + } + useEffect(() => { + getChattingHistory() + }, []) + return ( + <> + + + + + + } + rightIcon={null} + > + + {messages && } + + + + + + + + + + + + ) +} + +const StyleIcon = styled.img` + width: 30px; + height: 30px; +` +const StyleTypingFlexBox = styled(FlexBox)` + padding: 10px; + border-radius: 10px; +` +const StyleChattingWrapper = styled.span`` + +const StyleMessageWrapper = styled.div` + height: calc(100% - 145px); + flex: 1; + overflow-y: scroll; + scroll-behavior: smooth; +` + +const StyleSubmitButton = styled.button`` + +export default ChatListDetail diff --git a/src/pages/chatListDetail/index.tsx b/src/pages/chatListDetail/index.tsx new file mode 100644 index 00000000..32997d9c --- /dev/null +++ b/src/pages/chatListDetail/index.tsx @@ -0,0 +1,13 @@ +import { Route, Routes } from 'react-router-dom' + +import ChatListDetail from '@/pages/chatListDetail/ChatListDetail' + +const chatListDetailPage = () => { + return ( + + }> + + ) +} + +export default chatListDetailPage diff --git a/src/pages/chatting/Chatting.tsx b/src/pages/chatting/Chatting.tsx index cc4a586b..e8625b40 100644 --- a/src/pages/chatting/Chatting.tsx +++ b/src/pages/chatting/Chatting.tsx @@ -2,7 +2,7 @@ import styled from '@emotion/styled' import * as Stomp from '@stomp/stompjs' import { FormEvent, useEffect, useRef, useState } from 'react' import { BsArrowLeftShort } from 'react-icons/bs' -import { useNavigate } from 'react-router-dom' +import { useLocation, useNavigate } from 'react-router-dom' import { axiosAPI } from '@/apis/axios' import { ChattingApi } from '@/apis/chatting/chattingApi' @@ -25,7 +25,7 @@ import { palette } from '@/styles/palette' const Chatting = () => { const { openModal } = useModal() const navigate = useNavigate() - const chatroomId = '1' + const { chatroomId } = useLocation().state const [messages, setMessages] = useState([] as Messages[]) const [inputValue, setInputValue] = useState('') const { authTokens } = useAuthStore() diff --git a/src/pages/home/Home.tsx b/src/pages/home/Home.tsx index 6076430a..ecda8e72 100644 --- a/src/pages/home/Home.tsx +++ b/src/pages/home/Home.tsx @@ -19,10 +19,8 @@ const Home = () => { const isDarkMode = useThemeStore((state) => state.isDarkMode) const toggleDarkMode = useThemeStore((state) => state.toggleDarkMode) const { authTokens } = useAuthStore() - const [isMatching, setIsMatching] = useState(false) - const navigate = useNavigate() - const { showToast } = useToast() + const navigate = useNavigate() useEffect(() => { if (!authTokens) { @@ -65,13 +63,7 @@ const Home = () => { > {'진행중인 매칭'} - { - setIsMatching((prev) => !prev) - }} - isDarkMode={isDarkMode} - /> + { const navigate = useNavigate() const isDarkMode = useThemeStore((store) => store.isDarkMode) + const [myProfileData, setMyProfileData] = useState({ + nickname: '', + email: '', + profileImageUrl: '', + reportedCount: 0, + sanctionPeriod: '', + department: '', + interests: [''], + }) const { openModal } = useModal() const { showToast } = useToast() + const getProfileData = async () => { + await axiosAPI + .get('/v1/users/me') + .then((response) => { + setMyProfileData(response.data) + }) + .catch((err) => { + console.log(err) + }) + } const handleLogout = () => { openModal({ mainText: '로그아웃 하시겠습니까?', @@ -64,6 +95,9 @@ const ProfileDefault = () => { isDarkMode, }) } + useEffect(() => { + getProfileData() + }, []) return ( @@ -82,7 +116,11 @@ const ProfileDefault = () => { - + { alignItems: 'center', }} > - {`우땅`} + + {myProfileData && myProfileData.nickname} + - {`1998.01.20`} + + {myProfileData && myProfileData.email} + { isDarkMode={isDarkMode} > - {'커피밋 IT 부서'} + {myProfileData && myProfileData.department} @@ -122,7 +164,7 @@ const ProfileDefault = () => { diff --git a/src/pages/register/RegisterCompany.tsx b/src/pages/register/RegisterCompany.tsx index 556cd129..64b0b812 100644 --- a/src/pages/register/RegisterCompany.tsx +++ b/src/pages/register/RegisterCompany.tsx @@ -5,7 +5,6 @@ import { MdWbSunny } from 'react-icons/md' import { MdOutlinePhotoCamera } from 'react-icons/md' import { useLocation, useNavigate } from 'react-router-dom' - import { axiosAPI } from '@/apis/axios' import AlertText from '@/components/common/AlertText' import BackChevron from '@/components/common/BackChevron' diff --git a/tsconfig.json b/tsconfig.json index 0f1ca04b..dce68281 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "ES2020", "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], + // "lib": ["ES2020", "DOM", "DOM.Iterable"], // "typeRoots":["./node_modules/@types","./types"], "module": "ESNext", "skipLibCheck": true, @@ -35,6 +35,6 @@ "@/store/*": ["src/store/*"] } }, - "include": ["src"], + "include": ["src", "src/firebase-messaging-sw.js"], "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/vite.config.ts b/vite.config.ts index 2553920d..56b7e22f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -9,12 +9,12 @@ export default defineConfig({ alias: { '@/': `${process.cwd()}/src/` }, }, server: { - proxy: { - '/api': { - target: process.env.SERVER_EC2_URL, - changeOrigin: true, - }, - }, + // proxy: { + // '/api': { + // target: process.env.SERVER_EC2_URL, + // changeOrigin: true, + // }, + // }, // port: 3000, // https: true, // hmr: {