From 8461887c8f86e9c5143bdbee600b9ea8d68713fa Mon Sep 17 00:00:00 2001 From: Eugene Kim <67894159+eugene028@users.noreply.github.com> Date: Mon, 2 Sep 2024 23:51:35 +0900 Subject: [PATCH] =?UTF-8?q?[Deploy]=20=EC=99=80=EC=9A=B0=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=83=81=EC=9A=A9=EB=B0=B0=ED=8F=AC=20(1.0.0)=20(#?= =?UTF-8?q?113)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: client home으로 접속 시 my-study 페이지로 리다이렉트되도록 설정 * chore: typescript 설정 변경 * feat: ui css 파일 생성 * fix: client 패딩 동적 스타일링 적용 안 되는 문제 해결 * feat: admin home으로 접속 시 studies 페이지로 리다이렉트되도록 설정 * feat: admin Navbar 컴포넌트 구현 * feat: navBar 아이콘 파일 추가 * chore: Navbar와 children을 나란히 배치하도록 수정 * rename: my-homework url 구조 수정 * chore: client layout language 한국어로 변경 * feat: client navBar 멘토 페이지로 전환 버튼 추가 * feat: ui css 파일 변경 * feat: admin 폴더 구조 구축 * feat: admin 전역 스타일에 ui 스타일 추가 * feat: admin 전역 layout 구축 * refactor: Navbar 컴포넌트 div 태그 ul 태그로 변경 * refactor: NavItem 컴포넌트 리팩토링 * design: li 태그 listStyle none으로 수정 * feat: ui css 파일 변경 * feat:CI/CD 추가 * rename: 파일명 변경사항 반영 * chore: lock 파일 변경 사항 반영 * chore: ui 패키지 경로 상대 경로로 변경 * chore: ui 패키지 절대 경로 설정 수정 * rename: fetcher 관련 파일 utils 패키지로 이동 * chore: fetch request 함수 try-catch 문으로 감싸도록 수정 * chore: fetcher baseUrl 프로덕션, 개발 환경 구분하도록 수정 * chore: 응답 파싱 시 이미지도 수용할 수 있도록 수정 * chore: get 메서드에 쿼리 파라미터 기능 추가 * chore: 각 메서드 제네릭 타입 추가 * chore: 불필요한 eslint 규칙 삭제 * chore: request 에러 핸들링 부분 추가 * feat: get 메서드 쿼리 파라미터 관련 테스트 추가 * chore: handleError 비동기 관련 에러 해결 * feat: 에러 핸들링 관련 테스트 추가 * feat: admin, client에 wow-class/utils 패키지 설치 * chore: client jest 관련 속성 제거 * docs: 내비게이션 바 관련 컴포넌트 문서화 추가 * fix: useSelectedLayoutSegments null 관련 처리 추가 * refactor: 웹 접근성 관련 속성 추가 및 시맨틱 태그로 변경 * chore: 중복된 Navbar 컴포넌트 삭제 * chore: next config redirect 속성 변경 * chore: client 접속 시 auth 페이지로 접속하도록 수정 * rename: assets 폴더 내부 구조 변경 * chore: import문 에러 해결 * feat: Text 컴포넌트 제작 * feat: product sans 폰트 추가 * feat: ui 패키지 suit 폰트 추가 * feat: global css에 폰트 적용 * feat: client Header 컴포넌트 구현 * feat: ui 패키지 css 변경사항 반영 * feat: client에 wowds-tokens 패키지 설치 * feat: landing 페이지 레이아웃 구현 * chore: lock 파일 변경 사항 반영 * feat: auth 페이지 구현 * chore: 접속 시 landing 페이지로 리다이렉트되도록 수정 * feat: 많이 쓰는 타이포와 컬러로 디폴트 설정 * refactor: auth 페이지 시맨틱 태그로 변경 * refactor: landing 페이지 시맨틱 태그로 변경 * feat: AuthErrorAfterRecruitment 페이지 구현 * feat: AuthErrorDuringRecruitment 페이지 구현 * chore: Navbar 관련 컴포넌트 apps 패키지로 이동 * chore: panda config에서 components 폴더도 인식하도록 설정 수정 * feat: NavItem 컴포넌트 스토리 추가 * fix: 잘못된 import 경로 수정 * feat: 랜딩 페이지 배경 이미지 추가 * feat: ui 스타일 변경사항 반영 * refactor: 스타일 객체 분리하도록 수정 * rename: fetcher 내부 폴더 구조 변경 * chore: utils 패키지 배럴 파일 추가 * feat: LoginButton 추출 후 적용 * feat: auth server redirect 페이지 구현 * feat: 로그인 상태 관련 리다이렉트 처리 추가 * feat: 로그인 상태 관련 리다이렉트 처리 추가 * chore: use client 주석 삭제 * refactor: nav item text style 토큰 사용하도록 수정 * feat: ui 스타일 변경사항 반영 * refactor: header 색상 토큰 사용하도록 수정 * feat: 수강 신청 페이지 & 과제 페이지 마크업 * chore: 불필요한 세션 로그인 관련 로직 삭제 * chore: 폰트 패키지 생성 및 적용 * feat: 텍스트 컴포넌트 as 추가, typo 관련 panda 설정 panda-config 로 이동 * feat: 스토리북 경로 수정 * feat: NavItem 에 Text 반영 * chore: 리다이렉트 로직 middleware 사용하도록 수정 * feat: 내 과제 페이지까지 마크업 * chore: auth 페이지 이미지 크기 변경 * refactor: routePath 상수로 관리하도록 수정 * refactor: apiPath, tag 상수로 관리하도록 수정 * chore: routePath enum 대신 문자열 리터럴로 변경 * chore: routePath enum 대신 문자열 리터럴로 변경 * feat: px 로 수정 * feat: 토큰 반영 * feat: dot svg 반영 * refactor: 적절한 시맨틱 태그로 변경 * feat: 미들웨어 및 fetch 헤더 설정 테스트 * chore: 불필요한 테스트 로직 삭제 * refactor: dashboard api 별도 함수로 분리 * feat: middleware에서 로그인 여부 및 멤버 롤도 확인하도록 기능 구현 * feat: utils 패키지에 next 설치 * feat: fetcher에 토큰 관련 요청 인터셉터 추가 * chore: 불필요한 로직 삭제 * chore: fetcher에서 쿠키 관련 로직 삭제 * chore: middleware에서 Authorization header 설정해주도록 변경 * refactor: 상수 값 별도로 관리하도록 수정 * chore: wowds-ui 0.1.12 버전으로 변경 * feat: LoginButton에 github logo 추가 * refactor: Text 컴포넌트로 리팩토링 * fix: dashboardApi currentRecruitment 예외 처리 추가 * chore: 페이지명 컨벤션 통일 * rename: LoginButton auth 폴더 내부로 이동 * chore: 대시보드 api 헤더 주입 관련 주석 추가 * feat: Text,Space 컴포넌트로 변경 * feat: Table 스토리 추가 * refactor: base url 상수 값으로 관리하도록 수정 * feat: 폴더 구조, 컴포넌트 네이밍 변경 * feat: Text 컴포넌트로 교체 * feat: 수정된 스펙에 따라 Table 수정 * feat: styles.css 추가 * feat: 컴포넌트 네이밍 변경, 클라이언트 로직 추가 * feat: Icon 적영 * feat: codegen 스크립트 수정 * fix: Type suffix 붙이기 * chore: 스토리북 경로 shared 로 통일 * feat: wowds-icons 패키지 설치 * feat: 나의 스터디 페이지 헤더 컴포넌트 레이아웃 구현 * feat: 나의 스터디 페이지 스터디 공지 컴포넌트 레이아웃 구현 * feat: 나의 스터디 페이지 스터디 커리큘럼 컴포넌트 레이아웃 구현 * design: Navbar 컴포넌트 최소 너비 지정 * [Feature]: 스터디 개설 페이지 레이아웃 (#21) * chore: lock 패키지 변경 사항 반영 * chore: 중복된 Navbar 컴포넌트 삭제 * feat: 개설 스터디 기본 잡기 * feat: 스터디 개설 페이지 레이아웃 * fix: 찌그러짐 방지용 minWidth 추가 * feat: 스터디 개설하기 뷰 생성 * fix: 개설된 스터디로 화면 옮기기 * feat: auth 체크용 middleWare 생성 * fix: utils fetcher 함수 export 경로 변경 * feat: 스터디 생성하기 페이지 생성 * fix: router handler 삭제 * refactor: api path 상수로 수정 * feat: isAdmin 함수 추가 * fix: 코드리뷰 반영 * fix: admin여부에 따라 스터디 생성 박스 보이지 않도록 * chore: 패키지 설치 * fix: 빌드에러 고치기 * fix: isadmin 판별 로직 미들웨어에서 진행 * feat: 역할 논리 다시 * fix: 폴더명 변경 * fix: createStudy 경로 변경 * feat:wow-icons 추가 * fix: 폴더구조 변경 * fix: 폴더 복수형 변경 --------- Co-authored-by: ghdtjgus76 * chore: client afterLogin layout 하단 패딩 추가 * design: 스터디 커리큘럼 css 수정 * design: 스터디 공지 css 수정 * design: 나의 스터디 페이지 헤더 css 수정 * feat: 나의 스터디 페이지 오늘의 할 일 컴포넌트 추가 * feat: client afterLogin 배럴 파일 추가 * feat: 나의 스터디 페이지 구현 * feat: pnpm lock 파일 변경 사항 반영 * chore: ui 패키지 스타일 변경사항 반영 * feat: 스터디 신청 api 연결 및 응답 포맷팅 로직 추가 * feat: body 추가 * feat: 헤더 뺀 부분 * refactor: parseDate 상단에서 하도록 수정, padWitZero 유틸 추가 * feat: padWithZero export * feat: utils 패키지에 next 설치 * fix: fetcher 클래스 client, server 환경 분리 로직 추가 * chore: root 의존성 충돌 문제 해결 * chore: 불필요한 헤더 주입 로직 삭제 * chore: admin 헤더 관련 로직 삭제 * fix: 빌드 실패하는 문제 해결 * feat: lock 파일 변경사항 반영 * design: client layout width 변경 * feat: useHorizontalScroll 훅 추가 * feat: arrow-button 이미지 추가 * feat: 오늘의 할 일 캐러셀 기능 추가 * feat: async await 으로 변경, success 여부만 넘기는 것으로 * refactor: Table.Content 삭제, 핸들러 이름 변경 * feat: 에러 페이지 추가, header 제거 * feat: 나의 스터디 페이지 헤더 목데이터 기반 UI 구축 * design: 오늘의 할일 자잘한 디자인 수정 * feat: 스터디 공지 목데이터 기반 UI 구축 * design: 클라이언트 레이아웃 오른쪽 패딩 수정 * feat: 스터디 커리큘럼 목데이터 기반 UI 구축 * refactor: 오늘의 할 일 캐러셀 별도 컴포넌트로 분리 * feat: 나의 스터디 페이지 오늘의 할 일 목데이터 기반 UI 구축 * refactor: 공통 상수값 추출 * chore: parseISODate 함수 반환값 수정 * refactor: 타입 types 폴더로 분리 * fix: 빌드 에러 해결 * chore: 배럴 파일에서 import하도록 수정 * [Feature] 스터디 수강신청 api 연결 (#31) * feat: 스터디 신청 api 연결 및 응답 포맷팅 로직 추가 * feat: body 추가 * feat: 헤더 뺀 부분 * refactor: parseDate 상단에서 하도록 수정, padWitZero 유틸 추가 * feat: padWithZero export * feat: utils 패키지에 next 설치 * fix: fetcher 클래스 client, server 환경 분리 로직 추가 * chore: root 의존성 충돌 문제 해결 * chore: 불필요한 헤더 주입 로직 삭제 * chore: admin 헤더 관련 로직 삭제 * fix: 빌드 실패하는 문제 해결 * feat: async await 으로 변경, success 여부만 넘기는 것으로 * refactor: Table.Content 삭제, 핸들러 이름 변경 * feat: 에러 페이지 추가, header 제거 * feat: Table export 추가 및 빌드 스크립트 수정 * fix: 빌드 에러 수정 * feat: Table Content 부분 삭제 * fix: 구조분해할당으로 리팩토링 * fix: respose.ok 값 체크 * chore: 필요없는 주석 제거 * chore: notion link 로 열리게 수정 --------- Co-authored-by: ghdtjgus76 * refactor: formatWeekPeriod 함수로 리팩토링 * chore: 소개 링크 바로가기 버튼 텍스트 버튼으로 변경 * refactor: 목데이터 한 파일에서 관리하도록 수정 * refactor: map 하나의 객체로 관리하도록 수정 * chore: map 타입 명확하게 지정하도록 수정 * chore: 과제 제출 상태 dto에 맞게 반영 * chore: homework 부분 assignment로 네이밍 변경 * feat: 오늘의 할 일 버튼 조건부 활성화 기능 추가 * feat: ui 스타일 변경사항 반영 * [Feature] 모달 컴포넌트 (#25) * feat: 모달 기본 UI 구현 * feat: 라우팅으로 모달을 열고 닫기 위한 로직 추가 * feat: modal 병렬 라우팅 레이아웃 추가 및 JotaiProvider 삭제 * fix: Modal 닫기 버튼 onClick 함수 변경 및 title 정렬 * feat: Modal ui 패키지로 이동, hook 분리 * fix: 타입 경고 해결 * fix: hook 내보내기 위치 변경 * feat: ui style 재생성 * feat: 라우팅 활용 모달 예시 추가 * feat: jsdoc 추가 및 태그 수정 * fix: JotaiProvider 원복 * fix: title prop 삭제 * fix: open 함수 네이밍 변경 * fix: title 삭제에 따른 예시 prop 삭제 * feat: close 아이콘 적용 * refactor: PropsWithChildren 타입 사용 * feat: useClickOutside 훅 분리 * fix: 불필요한 코드 삭제 및 스토리북 수정 * fix: closeModal props 이름 변경 * refactor: any 타입 좁히기 * feat: setIsOpen 내보내기 추가 * fix: 빌드 에러 해결 * [Feature] 내 과제 페이지 api 연동 (#34) * feat: 과제 히스토리 api 연결, 클라이언트 단에서 목데이터 생성 * feat: histroy api 연동 및 구조 리팩토링 * feat: study-dashboard api 연결, HomeworkBox 분리 * feat: api 에 헤더 삭제 UI 수정 * feat: Table.Content 삭제 * chore: 안쓰는 유틸 지우기 * feat: LInk 로 교체 * chore: 공톧된 style 은 분리 * chore: Typer suffix 붙이기 * feat: Assignment 컴포넌트 분리 * chore: assignment 로 워딩 수정 * feat: 리뷰 반영 * chore: 목데이터 수정 * chore: 스타일 하단으로 분리, 네이밍 더 정확히 * chore: 얼리리턴으로 변경 * feat: 리뷰 반영 * feat: 가로스크롤 가능하게 추가 * chore: 카멜케이스로 변경 * chore: 타입 경로 common 으로 수정 * [Feature] 나의 스터디 페이지 모달 구현 (#39) * feat: client에 wowds-ui 패키지 설치 * feat: LinkButton 컴포넌트 추가 * feat: 오늘의 할 일 AssignmentStatusBox 라우팅 기능 추가 * chore: StudyCurriculum LinkButton으로 변경 * chore: Modal 컴포넌트 내부에서 className, style 커스텀할 수 있도록 변경 * chore: AttendanceStatusBox 버튼 링크 버튼으로 변경 * feat: 출석체크 모달 기능 추가 * feat: 출석체크 완료 모달 기능 추가 * chore: 모달 컴포넌트 기본 onClose는 router.back으로 지정하도록 수정 * chore: 모달 컴포넌트 onClose 핸들러 삭제 * feat: ui 변경사항 반영 * chore: 출석 체크 완료 모달 컴포넌트명 변경 * rename: check attendance -> attendance check로 네이밍 변경 * refactor: 모달 parallel route 한 폴더에서 관리하도록 수정 * chore: 나의 스터디 페이지 모달 조건부 렌더링 방식으로 변경 * feat: ui 패키지 스타일 변경사항 반영 * fix: 빌드 에러 해결 * fix: 스토리북 appDirectory 설정 추가 * [Feature]: 스터디 개설하기 api 연동 (#30) * chore: lock 패키지 변경 사항 반영 * chore: 중복된 Navbar 컴포넌트 삭제 * feat: 개설 스터디 기본 잡기 * feat: 스터디 개설 페이지 레이아웃 * fix: 찌그러짐 방지용 minWidth 추가 * feat: 스터디 개설하기 뷰 생성 * fix: 개설된 스터디로 화면 옮기기 * feat: auth 체크용 middleWare 생성 * fix: utils fetcher 함수 export 경로 변경 * feat: 스터디 생성하기 페이지 생성 * fix: router handler 삭제 * refactor: api path 상수로 수정 * feat: isAdmin 함수 추가 * fix: 코드리뷰 반영 * fix: admin여부에 따라 스터디 생성 박스 보이지 않도록 * chore: 패키지 설치 * fix: 빌드에러 고치기 * fix: isadmin 판별 로직 미들웨어에서 진행 * feat: 역할 논리 다시 * fix: 폴더명 변경 * fix: createStudy 경로 변경 * feat:wow-icons 추가 * refactor: 컴포넌트 폴더위치 변경 * chore:react-hook-form 설치 * feat: 복잡한 UI 설계 react-hook-form * feat: 스터디 수강 시작 날짜 지정 * chore: timepicker 패키지 설치 * feat: 스터디 신청 UI 완성 * fix: 쓸데없는 콘솔로그 제거 * feat: api 연결 * feat:api 호출 성공시 redirect * fix: 캐시 지워서 빌드에러 해결 * chore: 패키지 설치 * fix: api 관련 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: navbar 두개인것 고치기 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: 멘토 id 변경 --------- Co-authored-by: ghdtjgus76 * [Feature] 수강신청 페이지 모달 플로우 추가 (#45) * feat: 신청 모달, 취소 모달 * feat: 컴포넌트 로직 분리 * chore: 문구 수정 * chore: 헤더 제거 * chore: fetcher 주석 해제 * feat: api 추가된 필드에 대해 dto 추가 * feat: url 파람을 통해서 전달하지 않고 api fetch, 폴더 네이밍 변경 * feat: StudyApplication, StudyCancel 로 수정, url로 받는 것으로 수정 * fix: cancel 명사로 수정, StudyItem content min width 주기 * chore: my-assignment 파일 위치 옮기기 * [Feature] 과제 제출 api 연동 (#47) * [Feature] : 개설된 스터디 보기 api 연동 (#37) * feat: 스터디 리스트 보기 뷰 * fix: api 추가 및 하드코딩 제거 * fix:노션 경로 없는 경우 예외처리 * fix: 코드리뷰 반영 * fix: 빌드에러 해결 * fix: 코드리뷰 반영 * [Feature] 레포지토리 입력할 때 모달 플로우 추가 (#46) * feat: 신청 모달, 취소 모달 * feat: 컴포넌트 로직 분리 * chore: 문구 수정 * chore: 헤더 제거 * chore: fetcher 주석 해제 * feat: 레포지토리 입력 모달 * feat: 헤더 제거 * feat: match되는 studyHistoryId 찾는 훅 추가 * chore: modal 라우팅 경로 수정 * chore: my-study/my-assignment 로 이동 * chore: 이전 브랜치에 남은 로직 삭제 * feat: modal 라우팅 수정, url 쿼리paramter 넘기는 것으로 수정 * feat: 분기문 수정 * chore: 컴포넌트명 수정 * refactor: AssignmentBoxButtons 리팩토링 * feat: AssignmentBoxInfo 로 수정 * refactor: RepositorySubmissionBox 리팩토링 * feat: customRevalidate 삭제 * chore: 스타일 객체 하단으로 분리, 문구 수정 * feat: 추가된 히스토리 api dto 반영, 과제 없을 때 ui 추가 * feat: 입력할 때 빈 문자에 대한 validate 추가, 컴포넌트 하단 분리 * chore: 프로퍼티 스프레드로 * feat: 모달 url 변경 * feat: 에러 상태 핸들링 수정, 텍스트필드 height 고정 * chore: ui css반영 * feat: 모달 플로우 수정, 입력하기 버튼 누르면 모달 열리게 * [Feature] 마이페이지, 로그아웃 구현 (#50) * feat: 마이페이지, 로그아웃 구현 * chore: github-logo svg 이름 변경 * feat: 리뷰 반영 * feat: member api 추가 * [Feat] 나의 과제 페이지 Tooltip, Popover 컴포넌트 구현 (#49) * [Refactor] 나의 스터디 페이지 클라이언트 컴포넌트 서버 컴포넌트로 변경 (#41) * feat: LinkButton 추가 * design: 나의 스터디 페이지 하단 스페이싱 추가 * refactor: 모집 기간 이후 리다이렉트 페이지 서버 컴포넌트로 변경 * refactor: 모집 기간 중 리다이렉트 페이지 서버 컴포넌트로 변경 * refactor: 랜딩 페이지 서버 컴포넌트로 변경 * feat: wowds-ui 최신 버전 설치 * refactor: 라우팅 기능 버튼 asProp 사용해서 해결하도록 수정 * refactor: 자잘한 수정사항 반영 * feat: oauth 로그인 버튼 aria-label 추가 * chore: 변경된 이미지 url 반영 * [Feature] 스터디 기본 정보 조회하기 UI 생성 및 api 연결 (#42) * chore: lock 패키지 변경 사항 반영 * chore: 중복된 Navbar 컴포넌트 삭제 * feat: 개설 스터디 기본 잡기 * feat: 스터디 개설 페이지 레이아웃 * fix: 찌그러짐 방지용 minWidth 추가 * feat: 스터디 개설하기 뷰 생성 * fix: 개설된 스터디로 화면 옮기기 * feat: auth 체크용 middleWare 생성 * fix: utils fetcher 함수 export 경로 변경 * feat: 스터디 생성하기 페이지 생성 * fix: router handler 삭제 * refactor: api path 상수로 수정 * feat: isAdmin 함수 추가 * fix: 코드리뷰 반영 * fix: admin여부에 따라 스터디 생성 박스 보이지 않도록 * chore: 패키지 설치 * fix: 빌드에러 고치기 * fix: isadmin 판별 로직 미들웨어에서 진행 * feat: 역할 논리 다시 * fix: 폴더명 변경 * fix: createStudy 경로 변경 * feat:wow-icons 추가 * refactor: 컴포넌트 폴더위치 변경 * chore:react-hook-form 설치 * feat: 복잡한 UI 설계 react-hook-form * feat: 스터디 수강 시작 날짜 지정 * chore: timepicker 패키지 설치 * feat: 스터디 신청 UI 완성 * fix: 쓸데없는 콘솔로그 제거 * feat: api 연결 * feat:api 호출 성공시 redirect * fix: 캐시 지워서 빌드에러 해결 * chore: 패키지 설치 * feat: 스터디 리스트 보기 뷰 * fix: api 관련 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: navbar 두개인것 고치기 * feat: Header, 기본 레이아웃 세팅 * feat: Header 생성 * feat: 출석 보기 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: api 추가 및 하드코딩 제거 * feat: 과제 목록 보기 api 연결 * feat: 과제 목록 생성 * feat: 스터디 커리큘럼 생성 기능 및 api 연결 * feat: 스터디 기본 정보 대시보드 * fix: 노션 링크 없을 때에 에러페이지 안뜨게끔 수정 * fix: padwithzero 추가 * fix: 노션 null 처리 진행 * fix: 중복 요소 제거 * fix: 코드리뷰 반영 및 모든 mock 데이터 제거 * fix: 필요없는 console 삭제 * fix: 코드리뷰 반영 --------- Co-authored-by: ghdtjgus76 * [Feature] 클라이언트 페이지 not-found, error 페이지 추가 (#53) * feat: wowds-ui 최신 버전 설치 * feat: client not-found 페이지 추가 * feat: ui 패키지 스타일 변경사항 반영 * feat: not-found 버튼 aria-label 추가 * feat: 클라이언트 에러 페이지 추가 * feat: 어드민 화면 에러페이지 추가 * fix: 빌드에러 해결 * chore: error html, body 태그 삭제 * feat: pnpm lock 파일 변경사항 반영 --------- Co-authored-by: Eugene Kim * [Fix] 프로덕션/개발 환경 구분 환경 변수 VERCEL_ENV로 변경 (#67) * fix: 프로덕션/개발 환경 구분 환경 변수 변경 * chore: 환경 변수 NEXT_PUBLIC 구문 추가 * [Feature] 내비게이션 바 역할에 따라 멘토 페이지 전환 버튼 보여주기 여부 조정 (#58) * chore: 불필요한 미들웨어 로직 삭제 * chore: dashboardApi 반환값 추가 * chore: NavItem 경로 상대 경로로 전환 * chore: 변경된 대시보드 dto 반영 * feat: Navbar 멘토 페이지 전환 버튼 역할에 따라 다르게 띄우도록 설정 * [Feature] 클라이언트 페이지 메타데이터 추가 (#60) * feat: root layout 메타데이터 추가 * feat: beforeLogin 라우트 그룹 내 페이지 메타데이터 추가 * feat: afterLogin 라우트 그룹 내 페이지 메타데이터 추가 * chore: 나의 과제 페이지 메타데이터 타이틀 변경 * chore: og-image 변경 * chore: 메타데이터 대문자 수정 * [Feature] 나의 스터디 페이지 api 연결 (#44) * feat: client에 wowds-ui 패키지 설치 * feat: LinkButton 컴포넌트 추가 * feat: 오늘의 할 일 AssignmentStatusBox 라우팅 기능 추가 * chore: StudyCurriculum LinkButton으로 변경 * chore: Modal 컴포넌트 내부에서 className, style 커스텀할 수 있도록 변경 * chore: AttendanceStatusBox 버튼 링크 버튼으로 변경 * feat: 출석체크 모달 기능 추가 * feat: 출석체크 완료 모달 기능 추가 * chore: 모달 컴포넌트 기본 onClose는 router.back으로 지정하도록 수정 * chore: 모달 컴포넌트 onClose 핸들러 삭제 * feat: ui 변경사항 반영 * chore: 출석 체크 완료 모달 컴포넌트명 변경 * rename: check attendance -> attendance check로 네이밍 변경 * chore: 대시보드 api no store cache 속성 설정 * feat: 스터디 기본 정보 조회 api 호출 함수 작성 * feat: 나의 스터디 페이지 헤더 스터디 정보 조회 api 연결 * feat: 스터디 공지 조회 api 호출 함수 작성 * feat: 나의 스터디 페이지 스터디 공지 조회 api 연결 * rename: StudyNotice -> StudyAnnouncementList로 네이밍 변경 * chore: 불필요한 목데이터 삭제 * design: layout shift 방지용 헤더 최소 높이 지정 * feat: 스터디 출석체크 api 호출 함수 작성 * feat: 스터디 출석체크 api 연결 * refactor: 모달 parallel route 한 폴더에서 관리하도록 수정 * feat: 수강 중인 스터디 정보 조회 api 함수 작성 * feat: 수강 중인 스터디 정보가 없는 경우 예외 처리 추가 * feat: 수강 중인 스터디 정보 조회 시 캐시 사용하도록 설정 * rename: 모달 url 경로 수정 * feat: 수강 중인 스터디 태그 추가 * rename: 모달 url 경로 수정에 따른 변경 사항 반영 * chore: 스터디 기본 정보 조회 시 api 요청으로 받은 스터디 아이디 사용하도록 수정 * chore: 스터디 공지 조회 시 api 요청으로 받은 스터디 아이디 사용하도록 수정 * chore: 잘못 머지한 부분 수정 * chore: 스터디 커리큘럼 변경된 dto에 맞게 목데이터 변경 * feat: 나의 스터디 커리큘럼 조회 api 호출 함수 작성 * feat: 나의 스터디 커리큘럼 조회 api 연결 * feat: 현재 주차 표시 기능 추가 * feat: 스터디 커리큘럼 휴강 주차 분기 처리 추가 * feat: 오늘의 할 일 api 조회 함수 추가 * chore: 오늘의 할일 dto 기반으로 목데이터 변경 * chore: dto 타입 제네릭 사용하도록 변경 * chore: 불필요한 목데이터 삭제 * feat: 오늘의 할일 api 연결 * chore: 변수명 변경 * feat: 커리큘럼 조회 dto에 과제 제출 링크 추가 * refactor: studyInfoData fetching 관련 내용 훅으로 분리 * refactor: Time 타입 재사용 * refactor: attendanceCheckModalInfoData fetching 관련 내용 훅으로 분리 * chore: 시간 포맷팅 안 된 부분 수정 * chore: DailyTask key 값 studyDetailId로 변경 * fix: 수강 신청/취소 시 revalidate 로직 추가 * chore: 수강 신청 정보 조회 api no-store로 변경 * refactor: 공통 타입 리팩토링 * [Feature] 스터디 공지 수정, 삭제, 작성 (#48) * [Design] 클라이언트 페이지 디자인 및 수정 사항 반영 (#71) * feat: wowds-ui 최신 버전 설치 * feat: client not-found 페이지 추가 * feat: ui 패키지 스타일 변경사항 반영 * feat: not-found 버튼 aria-label 추가 * feat: 클라이언트 에러 페이지 추가 * feat: 어드민 화면 에러페이지 추가 * fix: 빌드에러 해결 * chore: 내비게이션 바에서 나의 과제 페이지 삭제 * design: 수강 신청 페이지 스터디 한 줄 소개 ellipsis 처리 추가 * design: 버튼 maxWidth 지정 * design: 내비게이션 바 active 상태 안 보이는 부분 수정 * design: navbar 고정되도록 수정 --------- Co-authored-by: Eugene Kim * [Chore] 클라이언트 스터디 커리큘럼 api 엔드 포인트 및 dto 변경사항 반영 (#74) * chore: 커리큘럼 조회 api 엔드포인트 변경사항 반영 * chore: 스터디 커리큘럼 dto 변경사항 반영 * fix: 과제 스터디의 경우 시간 - 보여주도록 수정 (#82) * fix: 모달 컴포넌트 position 변경 (#80) * fix: QA용 어드민 권한 꺼두기 * fix: middleware 복구 * fix: 환경변수 변경 * [Feature] 스터디 생성 모달 창을 만들고, 스터디 생성 관련 예외처리를 진행해요. (#72) * chore: lock 패키지 변경 사항 반영 * chore: 중복된 Navbar 컴포넌트 삭제 * feat: 개설 스터디 기본 잡기 * feat: 스터디 개설 페이지 레이아웃 * fix: 찌그러짐 방지용 minWidth 추가 * feat: 스터디 개설하기 뷰 생성 * fix: 개설된 스터디로 화면 옮기기 * feat: auth 체크용 middleWare 생성 * fix: utils fetcher 함수 export 경로 변경 * feat: 스터디 생성하기 페이지 생성 * fix: router handler 삭제 * refactor: api path 상수로 수정 * feat: isAdmin 함수 추가 * fix: 코드리뷰 반영 * fix: admin여부에 따라 스터디 생성 박스 보이지 않도록 * chore: 패키지 설치 * fix: 빌드에러 고치기 * fix: isadmin 판별 로직 미들웨어에서 진행 * feat: 역할 논리 다시 * fix: 폴더명 변경 * fix: createStudy 경로 변경 * feat:wow-icons 추가 * refactor: 컴포넌트 폴더위치 변경 * chore:react-hook-form 설치 * feat: 복잡한 UI 설계 react-hook-form * feat: 스터디 수강 시작 날짜 지정 * chore: timepicker 패키지 설치 * feat: 스터디 신청 UI 완성 * fix: 쓸데없는 콘솔로그 제거 * feat: api 연결 * feat:api 호출 성공시 redirect * fix: 캐시 지워서 빌드에러 해결 * chore: 패키지 설치 * feat: 스터디 리스트 보기 뷰 * fix: api 관련 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: navbar 두개인것 고치기 * feat: Header, 기본 레이아웃 세팅 * feat: Header 생성 * feat: 출석 보기 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: api 추가 및 하드코딩 제거 * feat: 과제 목록 보기 api 연결 * feat: 과제 목록 생성 * feat: 스터디 커리큘럼 생성 기능 및 api 연결 * feat: 스터디 기본 정보 대시보드 * fix: 노션 링크 없을 때에 에러페이지 안뜨게끔 수정 * fix: padwithzero 추가 * fix: 노션 null 처리 진행 * feat: 공지 생성 기능 * fix: 스터디 공지 수정, 삭제 모달창 구현 * fix: 코드리뷰 반영 * feat: 멘토일 경우 나의 스터디만 볼 수 있게끔 로직 추가 * fix: client 레포에 존재하는 wow-ui 패키지 삭제 * feat: 스터디 생성 확인 모달창 생성 * fix: dropdown 옵션 잘못된 부분 수정, 스터디 형식에 따른 예외처리 진행 * fix: undefined인 경우 null처리 * fix: parse 함수 제거 * fix: 사용하지 않는 import문 제거 * fix: routerPath 수정 * fix: 캐시 지우고 다시 시도 * fix: 코드리뷰 반영 * fix: 모달창 구조 수정 * fix: 폴더명 변경 * fix: 코드리뷰 반영 --------- Co-authored-by: ghdtjgus76 * [Feature]: 스터디 상세 정보 작성 (#56) * chore: lock 패키지 변경 사항 반영 * chore: 중복된 Navbar 컴포넌트 삭제 * feat: 개설 스터디 기본 잡기 * feat: 스터디 개설 페이지 레이아웃 * fix: 찌그러짐 방지용 minWidth 추가 * feat: 스터디 개설하기 뷰 생성 * fix: 개설된 스터디로 화면 옮기기 * feat: auth 체크용 middleWare 생성 * fix: utils fetcher 함수 export 경로 변경 * feat: 스터디 생성하기 페이지 생성 * fix: router handler 삭제 * refactor: api path 상수로 수정 * feat: isAdmin 함수 추가 * fix: 코드리뷰 반영 * fix: admin여부에 따라 스터디 생성 박스 보이지 않도록 * chore: 패키지 설치 * fix: 빌드에러 고치기 * fix: isadmin 판별 로직 미들웨어에서 진행 * feat: 역할 논리 다시 * fix: 폴더명 변경 * fix: createStudy 경로 변경 * feat:wow-icons 추가 * refactor: 컴포넌트 폴더위치 변경 * chore:react-hook-form 설치 * feat: 복잡한 UI 설계 react-hook-form * feat: 스터디 수강 시작 날짜 지정 * chore: timepicker 패키지 설치 * feat: 스터디 신청 UI 완성 * fix: 쓸데없는 콘솔로그 제거 * feat: api 연결 * feat:api 호출 성공시 redirect * fix: 캐시 지워서 빌드에러 해결 * chore: 패키지 설치 * feat: 스터디 리스트 보기 뷰 * fix: api 관련 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: navbar 두개인것 고치기 * feat: Header, 기본 레이아웃 세팅 * feat: Header 생성 * feat: 출석 보기 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: api 추가 및 하드코딩 제거 * feat: 과제 목록 보기 api 연결 * feat: 과제 목록 생성 * feat: 스터디 커리큘럼 생성 기능 및 api 연결 * feat: 스터디 기본 정보 대시보드 * fix: 노션 링크 없을 때에 에러페이지 안뜨게끔 수정 * fix: padwithzero 추가 * fix: 노션 null 처리 진행 * fix: 중복 요소 제거 * fix: 코드리뷰 반영 및 모든 mock 데이터 제거 * fix: 필요없는 console 삭제 * fix: entity 관리하기 쉽게 분리 * feat: 스터디 상세 정보 생성 api 연결 * feat: StudyInfobox 컴포넌트 구성 완료 * feat: 스터디 상세 정보 입력 api 연결 * fix: timeType 추가 * fix: type 고치기 * fix: next-cache 쓸데없이 하는 부분 제거 * feat: 스터디 상세 정보 입력 모달창 생성 * fix: entity 분리한거 합치기 * fix: 코드리뷰 반영 * feat: 커스텀 훅으로 로직 분리 * fix: 코드리뷰 반영, 빌드에러 해결 * fix: 폴더명 수정 * fix: 빌드에러 해결 * fix: 캐시 지우고 폴더명 다시 시도 * fix: 파일명 오류 수정 * fix: 빌드 캐시 지우기 * fix: 새로운 폴더 생성 * fix: 폴더명 다시 되돌림 * fix: 폴더명 명확하게 변경 * fix: 빌드에러 해결 * fix: sessions로 API 변경, 선언적인 코드로 변경 * fix: 세션을커리큘럼으로 바꾸어요 * fix: 스터디 시간 없을 경우 예외처리 * fix: layout overscroll 처리 * fix: query사용 방법 수정 * fix: 스타일 수정 * fix: 코드리뷰 반영 --------- Co-authored-by: ghdtjgus76 * fix: 빌드에러 수정 * [Bug] 스터디 개설 validation 처리, querystring 사용 방식 개선 (#77) * chore: lock 패키지 변경 사항 반영 * chore: 중복된 Navbar 컴포넌트 삭제 * feat: 개설 스터디 기본 잡기 * feat: 스터디 개설 페이지 레이아웃 * fix: 찌그러짐 방지용 minWidth 추가 * feat: 스터디 개설하기 뷰 생성 * fix: 개설된 스터디로 화면 옮기기 * feat: auth 체크용 middleWare 생성 * fix: utils fetcher 함수 export 경로 변경 * feat: 스터디 생성하기 페이지 생성 * fix: router handler 삭제 * refactor: api path 상수로 수정 * feat: isAdmin 함수 추가 * fix: 코드리뷰 반영 * fix: admin여부에 따라 스터디 생성 박스 보이지 않도록 * chore: 패키지 설치 * fix: 빌드에러 고치기 * fix: isadmin 판별 로직 미들웨어에서 진행 * feat: 역할 논리 다시 * fix: 폴더명 변경 * fix: createStudy 경로 변경 * feat:wow-icons 추가 * refactor: 컴포넌트 폴더위치 변경 * chore:react-hook-form 설치 * feat: 복잡한 UI 설계 react-hook-form * feat: 스터디 수강 시작 날짜 지정 * chore: timepicker 패키지 설치 * feat: 스터디 신청 UI 완성 * fix: 쓸데없는 콘솔로그 제거 * feat: api 연결 * feat:api 호출 성공시 redirect * fix: 캐시 지워서 빌드에러 해결 * chore: 패키지 설치 * feat: 스터디 리스트 보기 뷰 * fix: api 관련 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: navbar 두개인것 고치기 * feat: Header, 기본 레이아웃 세팅 * feat: Header 생성 * feat: 출석 보기 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: 코드리뷰 반영 * fix: api 추가 및 하드코딩 제거 * feat: 과제 목록 보기 api 연결 * feat: 과제 목록 생성 * feat: 스터디 커리큘럼 생성 기능 및 api 연결 * feat: 스터디 기본 정보 대시보드 * fix: 노션 링크 없을 때에 에러페이지 안뜨게끔 수정 * fix: padwithzero 추가 * fix: 노션 null 처리 진행 * feat: 공지 생성 기능 * fix: 스터디 공지 수정, 삭제 모달창 구현 * fix: 중복 요소 제거 * fix: 코드리뷰 반영 및 모든 mock 데이터 제거 * fix: 필요없는 console 삭제 * fix: entity 관리하기 쉽게 분리 * feat: 스터디 상세 정보 생성 api 연결 * feat: StudyInfobox 컴포넌트 구성 완료 * feat: 스터디 상세 정보 입력 api 연결 * fix: timeType 추가 * fix: type 고치기 * fix: next-cache 쓸데없이 하는 부분 제거 * fix: 코드리뷰 반영 * feat: 멘토일 경우 나의 스터디만 볼 수 있게끔 로직 추가 * fix: client 레포에 존재하는 wow-ui 패키지 삭제 * feat: 스터디 생성 확인 모달창 생성 * fix: dropdown 옵션 잘못된 부분 수정, 스터디 형식에 따른 예외처리 진행 * fix: undefined인 경우 null처리 * fix: parse 함수 제거 * fix: 사용하지 않는 import문 제거 * feat: 스터디 상세 정보 입력 모달창 생성 * fix: entity 분리한거 합치기 * fix: 코드리뷰 반영 * feat: 커스텀 훅으로 로직 분리 * fix: 코드리뷰 반영, 빌드에러 해결 * fix: routerPath 수정 * fix: 폴더명 수정 * fix: 빌드에러 해결 * fix: 캐시 지우고 다시 시도 * fix: 캐시 지우고 폴더명 다시 시도 * fix: 파일명 오류 수정 * fix: 빌드 캐시 지우기 * fix: 코드리뷰 반영 * fix: 새로운 폴더 생성 * fix: 폴더명 다시 되돌림 * fix: 폴더명 명확하게 변경 * fix: 빌드에러 해결 * fix: sessions로 API 변경, 선언적인 코드로 변경 * fix: 모달창 구조 수정 * fix: 폴더명 변경 * fix: 세션을커리큘럼으로 바꾸어요 * fix: 빌드에러 해결 * fix: 스터디 일정 수정 * fix: validation 수동 변경 * fix: 스터디 코스 먼저 선택하도록 변경 * fix: default 시간 변경 * fix: 스터디 개설 쿼리스트링 방식 개선 * fix: 코드리뷰 반영 * fix: 스터디 코스 선택에 따라 스터디 진행 기간 재 변경 --------- Co-authored-by: ghdtjgus76 * [Bug] 나의 스터디 페이지 QA 반영 (#87) * refactor: LinkButton 대신 Button asProp 활용하도록 수정 * chore: navbar 로고 클릭 시 홈으로 가도록 수정 * chore: 외부 링크 새 탭으로 열리도록 수정 * chore: navbar 멘토 페이지로 전환 버튼 클릭 시 멘토 페이지로 전환되도록 수정 * fix: notionLink null인 경우 예외 처리 * chore: 헤더 반응형 스타일 적용 * feat: ui 패키지 스타일 변경사항 반영 * fix: og image 안 보이는 문제 해결 * feat: 출석 체크 후 모달 사라지게 하는 로직 추가 * feat: 출석 체크 후 모달 사라지게 하는 로직 추가 * chore: NavItem href 경로 상대 경로로 변경 * rename: useModalRoute 모달 닫는 함수 onClose로 네이밍 변경 * chore: 로고 클릭 시 나의 스터디 페이지로 가도록 수정 * [Chore] 클라이언트 페이지 성능 최적화 (#88) * chore: 폰트 ttf에서 woff2로 변경 * chore: woff2, woff, ttf 순으로 브라우저에서 지원하는 폰트 사용하도록 설정 * feat: my-page, my-study, study-apply 중 한 페이지 초기 접속 시에만 미들웨어 동작하는 로직 추가 * chore: 로그아웃 시 middleware-executed 쿠키 삭제 로직 추가 * chore: 미들웨어에서 로그인 안 한 사용자는 헤더 캐시 속성 없어도 확인하도록 수정 * chore: aria 속성 잘못 설정된 부분 삭제 * chore: 자잘한 태그 변경 * feat: ui 패키지 스타일 변경 사항 반영 * refactor: cookieKey constants에서 관리하도록 수정 * chore: 불필요한 api 호출 에러 처리 삭제 * chore: cookieKey 객체로 관리하도록 수정 * chore: 과제 제출 상태 넘어오지 않는 경우 예외 처리 추가 * refactor: 스타일 객체 분리 * chore: baseUrl hostname으로 지정하도록 수정 * feat: ui 패키지 변경사항 반영 * chore: 불필요한 변수 삭제 * fix: 스터디 기본 정보 시작시간 및 종료시간 널 처리 추가 * feat: ui 패키지 변경사항 변경 * [Feat] 수강 신청,마이 페이지 관련 QA 반영 (#84) * [Feature] 과제 개설, 수정, 조회 UI 및 API 연결 (#76) * feat: 과제 페이지 기본 UI * feat: 과제 위치 이동 및 폰트 적용 * feat: 과제 관련 DTO 추가 * chore: react-hook-form 설치 * feat: 과제 정보 입력 페이지 * feat: 과제 조회 페이지 * fix: 불필요한 use client 삭제 * feat: layout 타입 추가 * fix: 텍스트필드 onChange 에러 임시 주석처리 * fix: 렌더링 오류 수정 * fix: 과제 폴더구조 수정 및 라우팅 추가 * feat: Modal 컴포넌트 forwardRef 추가 * feat: 과제 생성 성공 모달, [id] 폴더 [week] 변경 및 모달 위치 변경 * rename: assignments 폴더 위치 변경 * rename: week -> studyDetailId 폴더구조 변경 * feat: 과제 개설 라우팅 * feat: 과제 내용 보기 페이지 API 연결 * fix: 과제 내용보기 라우팅 변경 * feat: 과제 조회 API 추가 * feat: 과제 수정/생성 페이지 과제 기본정보 API 연결 * feat: 과제 생성/수정 성공 모달 라우팅이 아닌 state로 관리하기 * feat: 과제 수정/생성 API 연결 * fix: 불필요한 모달 관련 코드 삭제 * fix: Modal로 내려주는 prop 타입에러 해결 * fix: assignment null 체크 * chore: TODO 주석 * feat: 과제 휴강 처리 보완 * feat: react-hook-form useController 활용해서 CustomTextField 만들기 * chore: defaultValue 적용 안됨 * rename: edit -> edit-assignment * fix: 과제 리스트 revalidate * refactor: 중복 로직 삼항연산자로 개선 * fix: defaultValue 적용 안되는 문제 * fix: 빌드 에러 수정 * chore: AssignemtPage 네이밍 변경 * fix: descriptionLink null로 오는 경우 가드 * feat: ItemSeparator 컴포넌트 분리, 적용 * chore: 타이틀 주차 색상 적용 * chore: 중복된 패딩 제거 * refactor: 수강 상태 텍스트 변환 함수에서 객체로 바꾸기 * chore: 불필요한 toString 사용 삭제 * fix: 디테일 페이지 과제 휴강 버튼 삭제 * refactor: 복잡한 삼항연산자 개선 * refactor: 과제 관련 router 상수화 * fix: 잘못된 변수명 수정 * chore: 불필요한 use client 삭제 * fix: 빌드 에러 수정 * [Feature] 어드민 페이지 메타데이터 설정 및 UX 개선 (#91) * feat: og-image 추가 * feat: 루트 레이아웃 메타데이터 작성 * feat: 하위 페이지 title 작성 * feat: 로고 및 네비게이션 UX 고려하기 * design: studies 페이지 하위 overflow scroll 적용 * fix: 모달 뒷배경 스크롤 막기 * fix: 불필요한 prop 삭제 * chore: title 워딩 수정 * chore: 빌드 에러 수정 * fix: 누락된 modal props * fix: 에러 해결을 위해 generateMetadata page로 이동, page 컴포넌트 서버컴포넌트로 만들기 * chore: 임시용 mentor id 설정 * [Design] 나의 스터디 페이지 스터디 커리큘럼 반응형 디자인 적용 (#98) * chore: 이전에 반영되지 않았던 변수명 변경 * design: 스터디 커리큘럼 반응형 디자인 적용 * [Chore] 클라이언트 나의 스터디 페이지 및 자잘한 QA 사항 반영 (#102) * design: 수강 중인 스터디 없는 경우 디자인 수정사항 반영 * chore: wowds-ui 0.1.15 버전으로 변경 * refactor: DailyTaskItem 별도 파일로 분리 * chore: 오늘의 할 일 과제 박스 시간 포맷팅 안 된 부분 적용 * fix: ISODate 가져올 때 날짜 잘못 가져오는 문제 해결 * chore: 스터디 커리큘럼 현재 주차 외의 버튼은 다 disabled 상태로 변경 * chore: 커리큘럼 과제 휴강인 경우 버튼 disabled 처리 * chore: 메타데이터 타이틀 변경 * [Refactor] : 어드민 서비스 미들웨어 로직 추가 및 스터디 리스트 레이아웃 조정 (#94) * chore: middleware 캐시 로직 추가 * fix: 오타 수정 * fix: 커리큘럼을 스터디로 변경해요 * feat: Navbar 클릭하면 메인페이지로 이동 * fix: 절대경로 변경 * fix: 스터디 상세 레이아웃 수정 * fix: url constants로 분리 * fix: error처리 삭제, 이름 변경 * fix: 어드민 전용으로 쿠키 이름 변경 * fix: 만료 시간 제거 * [Feat] 수강신청 페이지 큐에이 반영 (#105) * feat: 큐에이 반영 * fix: 소문자로 변경 * [Fix] 네비게이션 관련 QA 이슈 해결 (#103) * fix: 네비게이션 따로 스크롤 * fix: 수강생 관리 메뉴 주석처리 * feat: 멘티 페이지로 이동 * fix: clientUrl 환경변수 관리 * [Design] nav-item 경로 이슈 때문에 색 적용 안 되는 문제 해결 (#110) * [Feature] 출결번호 API 연결 (#104) * feat: 출석 조회 API * feat: AttendaceItem 컴포넌트 * fix: studyId 넘겨주는 방법 변경 * feat: AttendaceList 컴포넌트 * feat: 출결번호 상태체크 및 UI 렌더링 * rename: statusmap 경로수정 * rename: 파일명 타이포 수정 * fix: 출결 상태에 따라 출결번호 색상 변경 * fix: 비활성화 색상 변경 * [Feature] 과제 Picker 컴포넌트 도입 및 QA사항 반영 (#99) * fix: 과제 DTO 변경 * feat: formatDateToISOString util함수 추가 * feat: Picker 컴포넌트 도입 * fix: 시간 형식 변경 * chore: 과제 선택 가능 범위? * fix: 과제 response DTO 수정으로 인한 로직 변경 * chore: 버튼 활성화 관련 TODO * fix: API 요청 포맷에 맞게 수정 * chore: wowds-ui, wowds-icons 버전업 * fix: getIsCurrentWeek 로직 수정 * fix: 과제 휴강 후 revalidate * fix: 휴강완료 버튼 이벤트 막기 * fix: Date 선택해야 버튼 활성화되도록 수정 * refactor: assignment 구조분해할당 * fix: defaultValue 없을 때 props 넘겨주지 않도록 * fix: useEffect 로직 수정 * fix: 같은 역할을 하는 유틸함수 삭제 * fix: 메타데이터 수정 * feat: studyTitle 추가 * [Fix] 스터디 상세, 스터디 생성 관련 QA 이슈 해결 (#106) * feat: 수정 아이콘 추가 * fix: 난이도 옆에 실제 값 반영되도록 수정 * fix: Header arrow 방향 수정 * fix: 개설된 스터디 -> 담당 스터디 * fix: 스터디 정보 수정 이후 커리큘럼 업데이트되도록 수정 * fix: 스터디 상세 정보 수정 * fix: 필요없는 콘솔로그 제거 * fix: 스터디 생성일 validation 처리 * fix: 스터디 시작-종료 시간 validation 추가 * fix: url 문제 해결 * fix: edit 아이콘 위치 변경 * fix: 휴강 여부도 수정할 수 있도록 변경 * [Fix] 스터디 공지 관련 QA 이슈 해결 (#109) * fix: 공지 작성시 container height 같이 커지도록 수정 * fix: 스터디 공지 작성하면 textfield 값 비우기 * fix: 스터디 수정 UX 개선, 스터디 공지 수정 이후 바로 반영되게끔 * feat: 멘토 페이지로 전환 링크 동작하도록 변경 * fix: 스터디 상세 보기 레이아웃 잡기 * fix: 스터디 삭제 바로 반영 * fix: 외부 링크로 이동하는 경우 _blank처리 * fix: 멘티 전환 페이지 수정 * [Feature] 스터디 멘토 검색 기능 추가 (#111) * feat: 스터디 멘토 검색 기능 추가 * chore: cursor pointer 스타일 추가 * fix: 빌드 에러 해결 --------- Co-authored-by: ghdtjgus76 Co-authored-by: SeieunYoo <101736358+SeieunYoo@users.noreply.github.com> Co-authored-by: SeieunYoo Co-authored-by: 이현영 <89445100+hamo-o@users.noreply.github.com> --- .eslintignore | 2 + .github/CODEOWNERS | 1 + .github/workflows/auto_assign.yml | 27 + .github/workflows/build.yml | 40 + .github/workflows/deploy-chromatic.yml | 54 + .gitignore | 39 + .husky/commit-msg | 14 + .husky/pre-commit | 1 + .husky/pre-push | 1 + .npmrc | 0 .prettierignore | 1 + .prettierrc | 9 + .vscode/settings.json | 13 + README.md | 81 + apps/admin/.eslintrc.js | 9 + apps/admin/.gitignore | 36 + apps/admin/README.md | 36 + apps/admin/apis/auth/dashboardApi.ts | 32 + apps/admin/apis/study/createStudyApi.ts | 36 + apps/admin/apis/study/studyApi.ts | 141 + .../admin/app/@modal/(.)participants/page.tsx | 23 + apps/admin/app/@modal/default.tsx | 5 + apps/admin/app/error.tsx | 47 + apps/admin/app/global.css | 13 + apps/admin/app/layout.tsx | 59 + apps/admin/app/not-found.tsx | 54 + apps/admin/app/page.tsx | 17 + apps/admin/app/participants/page.tsx | 5 + .../@modal/(.)announcement-delete/page.tsx | 46 + .../@modal/(.)announcement-modify/page.tsx | 156 + .../app/studies/[studyId]/@modal/default.tsx | 5 + .../announcement/CreateStudyAnnouncement.tsx | 158 + .../announcement/StudyAnnouncement.tsx | 122 + .../assignment/AssignmentButtons.tsx | 72 + .../_components/assignment/AssignmentList.tsx | 30 + .../assignment/AssignmentListItem.tsx | 89 + .../_components/attendance/AttendanceItem.tsx | 67 + .../_components/attendance/AttendanceList.tsx | 27 + .../_components/curriculum/CurriculumList.tsx | 30 + .../curriculum/CurriculumListItem.tsx | 101 + .../curriculum/EmptyCurriculumList.tsx | 27 + .../[studyId]/_components/header/Header.tsx | 185 + .../[studyId]/announcement-delete/page.tsx | 8 + .../[studyId]/announcement-modify/page.tsx | 7 + apps/admin/app/studies/[studyId]/default.tsx | 5 + .../[studyId]/hooks/usePrefillAnnouncement.ts | 26 + apps/admin/app/studies/[studyId]/layout.tsx | 21 + apps/admin/app/studies/[studyId]/page.tsx | 68 + .../studies/_components/EmptyStudyList.tsx | 28 + .../app/studies/_components/StudyList.tsx | 29 + .../app/studies/_components/StudyListItem.tsx | 105 + .../_components/AssignmentForm.tsx | 68 + .../_components/AssignmentHeader.tsx | 80 + .../_components/CustomTextField.tsx | 37 + .../_components/SuccessModal.tsx | 39 + .../[studyDetailId]/edit-assignment/page.tsx | 81 + .../assignments/[studyDetailId]/page.tsx | 86 + apps/admin/app/studies/assignments/layout.tsx | 15 + .../@modal/(.)created-study-check/page.tsx | 66 + .../studies/create-study/@modal/default.tsx | 5 + .../_components/CreateStudyButton.tsx | 57 + .../StudyApplyDatePick.tsx | 143 + .../StudyCourseSelect.tsx | 47 + .../StudyDayOfWeekSelect.tsx | 33 + .../StudyFormatSelect.tsx | 64 + .../StudySemesterSelect.tsx | 39 + .../StudyStartDatePick.tsx | 168 + .../StudyBasicInformation/StudyTime.tsx | 79 + .../StudyBasicInformation/index.tsx | 34 + .../_components/StudyMentorSelect.tsx | 98 + .../_components/StudyNameTextField.tsx | 51 + .../studies/create-study/_components/index.ts | 4 + .../create-study/created-study-check/page.tsx | 8 + .../app/studies/create-study/default.tsx | 5 + .../admin/app/studies/create-study/layout.tsx | 22 + apps/admin/app/studies/create-study/page.tsx | 64 + .../_hooks/useSubmitStudyDetailInfo.ts | 38 + .../@modal/(.)detail-Info-check/page.tsx | 112 + .../detail-info/[studyId]/@modal/default.tsx | 5 + .../_components/CreateStudyDetailInfo.tsx | 89 + .../[studyId]/_components/StudyCurriculum.tsx | 51 + .../_components/StudyDescription.tsx | 136 + .../StudyInfoBox/StudyInfoDifficulty.tsx | 95 + .../StudyInfoBox/StudyInfoStatus.tsx | 48 + .../StudyInfoBox/StudyTextInfo.tsx | 95 + .../StudyInfoBox/StudyTimeline.tsx | 41 + .../_components/StudyInfoBox/index.tsx | 71 + .../_hooks/usePrefillStudyDetailInfo.ts | 36 + .../studies/detail-info/[studyId]/default.tsx | 5 + .../[studyId]/detail-info-check/page.tsx | 8 + .../studies/detail-info/[studyId]/layout.tsx | 21 + .../studies/detail-info/[studyId]/page.tsx | 26 + apps/admin/app/studies/layout.tsx | 28 + apps/admin/app/studies/page.tsx | 21 + apps/admin/components/ItemSeparator.tsx | 18 + apps/admin/components/JotaiProvider.tsx | 8 + apps/admin/components/Navbar.tsx | 128 + apps/admin/constants/apiPath.ts | 13 + apps/admin/constants/cookieKey.ts | 4 + apps/admin/constants/date.ts | 0 apps/admin/constants/dayToKorean.ts | 19 + apps/admin/constants/router/routerPath.ts | 42 + .../constants/status/assignmentStatusMap.ts | 10 + .../constants/status/attendanceStatusMap.ts | 10 + apps/admin/constants/tags.ts | 10 + apps/admin/constants/url.ts | 4 + apps/admin/hooks/useClickOutSide.tsx | 21 + apps/admin/hooks/useForm.tsx | 3 + apps/admin/hooks/useParseSearchParams.ts | 49 + apps/admin/middleware.ts | 43 + apps/admin/next.config.mjs | 15 + apps/admin/package.json | 36 + apps/admin/panda.config.ts | 7 + apps/admin/postcss.config.cjs | 5 + apps/admin/public/images/administrator.svg | 13 + apps/admin/public/images/arrow.svg | 3 + apps/admin/public/images/dot.svg | 3 + apps/admin/public/images/empty.svg | 23 + apps/admin/public/images/error.svg | 29 + apps/admin/public/images/folder.svg | 4 + apps/admin/public/images/home.svg | 5 + apps/admin/public/images/link.svg | 4 + apps/admin/public/images/logo.svg | 9 + apps/admin/public/images/not-found.svg | 34 + apps/admin/public/images/og-image.png | Bin 0 -> 56931 bytes apps/admin/public/images/particpant.svg | 15 + apps/admin/styled-system/css/conditions.js | 36 + apps/admin/styled-system/css/conditions.mjs | 36 + apps/admin/styled-system/css/css.d.ts | 22 + apps/admin/styled-system/css/css.js | 49 + apps/admin/styled-system/css/css.mjs | 49 + apps/admin/styled-system/css/cva.d.ts | 6 + apps/admin/styled-system/css/cva.js | 101 + apps/admin/styled-system/css/cva.mjs | 101 + apps/admin/styled-system/css/cx.d.ts | 5 + apps/admin/styled-system/css/cx.js | 15 + apps/admin/styled-system/css/cx.mjs | 15 + apps/admin/styled-system/css/index.d.ts | 5 + apps/admin/styled-system/css/index.js | 4 + apps/admin/styled-system/css/index.mjs | 4 + apps/admin/styled-system/css/sva.d.ts | 4 + apps/admin/styled-system/css/sva.js | 49 + apps/admin/styled-system/css/sva.mjs | 49 + apps/admin/styled-system/helpers.js | 359 + apps/admin/styled-system/helpers.mjs | 346 + .../admin/styled-system/jsx/aspect-ratio.d.ts | 14 + apps/admin/styled-system/jsx/aspect-ratio.js | 16 + apps/admin/styled-system/jsx/bleed.d.ts | 11 + apps/admin/styled-system/jsx/bleed.js | 14 + apps/admin/styled-system/jsx/box.d.ts | 11 + apps/admin/styled-system/jsx/box.js | 14 + apps/admin/styled-system/jsx/center.d.ts | 11 + apps/admin/styled-system/jsx/center.js | 14 + apps/admin/styled-system/jsx/circle.d.ts | 11 + apps/admin/styled-system/jsx/circle.js | 14 + apps/admin/styled-system/jsx/container.d.ts | 11 + apps/admin/styled-system/jsx/container.js | 16 + apps/admin/styled-system/jsx/cq.d.ts | 11 + apps/admin/styled-system/jsx/cq.js | 14 + apps/admin/styled-system/jsx/divider.d.ts | 11 + apps/admin/styled-system/jsx/divider.js | 18 + .../admin/styled-system/jsx/factory-helper.js | 27 + apps/admin/styled-system/jsx/factory.d.ts | 3 + apps/admin/styled-system/jsx/factory.js | 122 + apps/admin/styled-system/jsx/flex.d.ts | 11 + apps/admin/styled-system/jsx/flex.js | 22 + apps/admin/styled-system/jsx/float.d.ts | 11 + apps/admin/styled-system/jsx/float.js | 19 + apps/admin/styled-system/jsx/grid-item.d.ts | 11 + apps/admin/styled-system/jsx/grid-item.js | 23 + apps/admin/styled-system/jsx/grid.d.ts | 11 + apps/admin/styled-system/jsx/grid.js | 20 + apps/admin/styled-system/jsx/hstack.d.ts | 11 + apps/admin/styled-system/jsx/hstack.js | 14 + apps/admin/styled-system/jsx/index.d.ts | 24 + apps/admin/styled-system/jsx/index.js | 22 + .../styled-system/jsx/is-valid-prop.d.ts | 18 + apps/admin/styled-system/jsx/is-valid-prop.js | 20 + .../admin/styled-system/jsx/link-overlay.d.ts | 11 + apps/admin/styled-system/jsx/link-overlay.js | 16 + apps/admin/styled-system/jsx/spacer.d.ts | 11 + apps/admin/styled-system/jsx/spacer.js | 14 + apps/admin/styled-system/jsx/square.d.ts | 11 + apps/admin/styled-system/jsx/square.js | 14 + apps/admin/styled-system/jsx/stack.d.ts | 11 + apps/admin/styled-system/jsx/stack.js | 19 + .../styled-system/jsx/visually-hidden.d.ts | 11 + .../styled-system/jsx/visually-hidden.js | 16 + apps/admin/styled-system/jsx/vstack.d.ts | 11 + apps/admin/styled-system/jsx/vstack.js | 14 + apps/admin/styled-system/jsx/wrap.d.ts | 11 + apps/admin/styled-system/jsx/wrap.js | 20 + .../styled-system/patterns/aspect-ratio.d.ts | 24 + .../styled-system/patterns/aspect-ratio.js | 39 + .../styled-system/patterns/aspect-ratio.mjs | 39 + apps/admin/styled-system/patterns/bleed.d.ts | 22 + apps/admin/styled-system/patterns/bleed.js | 26 + apps/admin/styled-system/patterns/bleed.mjs | 26 + apps/admin/styled-system/patterns/box.d.ts | 19 + apps/admin/styled-system/patterns/box.js | 16 + apps/admin/styled-system/patterns/box.mjs | 16 + apps/admin/styled-system/patterns/center.d.ts | 21 + apps/admin/styled-system/patterns/center.js | 22 + apps/admin/styled-system/patterns/center.mjs | 22 + apps/admin/styled-system/patterns/circle.d.ts | 21 + apps/admin/styled-system/patterns/circle.js | 26 + apps/admin/styled-system/patterns/circle.mjs | 26 + .../styled-system/patterns/container.d.ts | 19 + .../admin/styled-system/patterns/container.js | 22 + .../styled-system/patterns/container.mjs | 22 + apps/admin/styled-system/patterns/cq.d.ts | 24 + apps/admin/styled-system/patterns/cq.js | 22 + apps/admin/styled-system/patterns/cq.mjs | 22 + .../admin/styled-system/patterns/divider.d.ts | 23 + apps/admin/styled-system/patterns/divider.js | 30 + apps/admin/styled-system/patterns/divider.mjs | 30 + apps/admin/styled-system/patterns/flex.d.ts | 27 + apps/admin/styled-system/patterns/flex.js | 36 + apps/admin/styled-system/patterns/flex.mjs | 36 + apps/admin/styled-system/patterns/float.d.ts | 34 + apps/admin/styled-system/patterns/float.js | 53 + apps/admin/styled-system/patterns/float.mjs | 53 + .../styled-system/patterns/grid-item.d.ts | 26 + .../admin/styled-system/patterns/grid-item.js | 27 + .../styled-system/patterns/grid-item.mjs | 27 + apps/admin/styled-system/patterns/grid.d.ts | 25 + apps/admin/styled-system/patterns/grid.js | 36 + apps/admin/styled-system/patterns/grid.mjs | 36 + apps/admin/styled-system/patterns/hstack.d.ts | 22 + apps/admin/styled-system/patterns/hstack.js | 25 + apps/admin/styled-system/patterns/hstack.mjs | 25 + apps/admin/styled-system/patterns/index.d.ts | 21 + apps/admin/styled-system/patterns/index.js | 20 + apps/admin/styled-system/patterns/index.mjs | 20 + .../styled-system/patterns/link-overlay.d.ts | 19 + .../styled-system/patterns/link-overlay.js | 25 + .../styled-system/patterns/link-overlay.mjs | 25 + apps/admin/styled-system/patterns/spacer.d.ts | 21 + apps/admin/styled-system/patterns/spacer.js | 22 + apps/admin/styled-system/patterns/spacer.mjs | 22 + apps/admin/styled-system/patterns/square.d.ts | 21 + apps/admin/styled-system/patterns/square.js | 25 + apps/admin/styled-system/patterns/square.mjs | 25 + apps/admin/styled-system/patterns/stack.d.ts | 24 + apps/admin/styled-system/patterns/stack.js | 25 + apps/admin/styled-system/patterns/stack.mjs | 25 + .../patterns/visually-hidden.d.ts | 19 + .../styled-system/patterns/visually-hidden.js | 19 + .../patterns/visually-hidden.mjs | 19 + apps/admin/styled-system/patterns/vstack.d.ts | 22 + apps/admin/styled-system/patterns/vstack.js | 25 + apps/admin/styled-system/patterns/vstack.mjs | 25 + apps/admin/styled-system/patterns/wrap.d.ts | 25 + apps/admin/styled-system/patterns/wrap.js | 33 + apps/admin/styled-system/patterns/wrap.mjs | 33 + apps/admin/styled-system/tokens/index.d.ts | 9 + apps/admin/styled-system/tokens/index.js | 592 + apps/admin/styled-system/tokens/index.mjs | 1895 ++ apps/admin/styled-system/tokens/tokens.d.ts | 372 + .../styled-system/types/composition.d.ts | 138 + .../admin/styled-system/types/conditions.d.ts | 236 + apps/admin/styled-system/types/csstype.d.ts | 23197 ++++++++++++++++ apps/admin/styled-system/types/global.d.ts | 43 + apps/admin/styled-system/types/index.d.ts | 8 + apps/admin/styled-system/types/jsx.d.ts | 87 + apps/admin/styled-system/types/parts.d.ts | 8 + apps/admin/styled-system/types/pattern.d.ts | 87 + apps/admin/styled-system/types/prop-type.d.ts | 733 + apps/admin/styled-system/types/recipe.d.ts | 211 + apps/admin/styled-system/types/selectors.d.ts | 62 + .../admin/styled-system/types/static-css.d.ts | 51 + .../styled-system/types/style-props.d.ts | 8925 ++++++ .../styled-system/types/system-types.d.ts | 123 + apps/admin/tsconfig.json | 23 + apps/admin/types/dtos/announcement.ts | 6 + apps/admin/types/dtos/assignmentList.ts | 17 + apps/admin/types/dtos/attendance.ts | 6 + apps/admin/types/dtos/auth.ts | 47 + apps/admin/types/dtos/createStudy.ts | 17 + apps/admin/types/dtos/curriculumList.ts | 16 + apps/admin/types/dtos/searchStudyMentor.ts | 18 + apps/admin/types/dtos/studyBasicInfo.ts | 23 + apps/admin/types/dtos/studyDetailInfo.ts | 7 + apps/admin/types/dtos/studyList.ts | 31 + apps/admin/types/entities/assignment.ts | 1 + apps/admin/types/entities/auth.ts | 1 + apps/admin/types/entities/dayofweek.ts | 8 + apps/admin/types/entities/study.ts | 30 + apps/admin/types/entities/time.ts | 6 + apps/admin/types/role.ts | 3 + apps/admin/types/status.ts | 2 + apps/admin/types/user.ts | 33 + apps/admin/utils/checkThisWeek.ts | 11 + apps/admin/utils/createQueryString.ts | 15 + apps/admin/utils/getIsCurrentWeek.ts | 12 + apps/admin/utils/isAdmin.ts | 8 + apps/admin/utils/revalidateTagByName.ts | 7 + apps/admin/utils/setExpireTime.ts | 8 + apps/admin/utils/validate/studyDetailInfo.ts | 15 + apps/client/.eslintrc.js | 9 + apps/client/.gitignore | 36 + apps/client/README.md | 36 + apps/client/apis/authApi.ts | 10 + apps/client/apis/dashboardApi.ts | 26 + apps/client/apis/membersApi.ts | 18 + apps/client/apis/myStudyApi.ts | 79 + apps/client/apis/studyApplyApi.ts | 31 + apps/client/apis/studyDetailApi.ts | 17 + apps/client/apis/studyHistoryApi.ts | 37 + apps/client/app/(afterLogin)/layout.tsx | 28 + .../my-page/@modal/(.)logout/page.tsx | 73 + .../(afterLogin)/my-page/@modal/default.tsx | 5 + .../my-page/_components/MyInfoBox.tsx | 64 + .../app/(afterLogin)/my-page/default.tsx | 5 + .../app/(afterLogin)/my-page/layout.tsx | 22 + .../app/(afterLogin)/my-page/logout/page.tsx | 8 + apps/client/app/(afterLogin)/my-page/page.tsx | 15 + .../@modal/(.)attendance-check/page.tsx | 174 + .../(afterLogin)/my-study/@modal/default.tsx | 5 + .../_components/AssignmentStatusBox.tsx | 114 + .../_components/AttendanceStatusBox.tsx | 93 + .../_components/DailyTaskCarousel.tsx | 80 + .../my-study/_components/DailyTaskItem.tsx | 40 + .../my-study/_components/DailyTasks.tsx | 36 + .../my-study/_components/EmptyStudy.tsx | 27 + .../my-study/_components/Header.tsx | 186 + .../_components/StudyAnnouncementList.tsx | 62 + .../my-study/_components/StudyCurriculum.tsx | 220 + .../my-study/_components/index.ts | 9 + .../my-study/attendance-check/page.tsx | 8 + .../app/(afterLogin)/my-study/default.tsx | 5 + .../app/(afterLogin)/my-study/layout.tsx | 27 + .../(.)repository-url/confirmation/page.tsx | 46 + .../@modal/(.)repository-url/default.tsx | 5 + .../my-study/my-assignment/@modal/default.tsx | 5 + .../AssignmentBoxButtons.tsx | 119 + .../AssignmentBoxInfo.tsx | 53 + .../AssignmentBoxTitle.tsx | 53 + .../AssignmentOverviewBox/FailurePopover.tsx | 69 + .../AssignmentOverviewBox/index.tsx | 56 + .../AssignmentContent/EmptyAssignmentBox.tsx | 25 + .../RepositorySubmissionBox.tsx | 185 + .../_components/AssignmentContent/index.tsx | 49 + .../_components/AssignmentDescription.tsx | 38 + .../_components/AssignmentHeader.tsx | 18 + .../AssignmentHistoryItem.tsx | 102 + .../_components/AssignmentHistory/index.tsx | 48 + .../my-assignment/_components/index.ts | 3 + .../my-study/my-assignment/default.tsx | 5 + .../my-study/my-assignment/layout.tsx | 24 + .../my-study/my-assignment/page.tsx | 21 + .../repository-url/confirmation/page.tsx | 8 + .../client/app/(afterLogin)/my-study/page.tsx | 31 + .../(.)study-application/[studyId]/page.tsx | 92 + .../(.)study-cancellation/[studyId]/page.tsx | 91 + .../study-apply/@modal/default.tsx | 5 + .../study-apply/_components/StudyItem.tsx | 210 + .../study-apply/_components/index.ts | 1 + .../app/(afterLogin)/study-apply/default.tsx | 5 + .../app/(afterLogin)/study-apply/layout.tsx | 22 + .../app/(afterLogin)/study-apply/page.tsx | 30 + .../study-application/[studyId]/page.tsx | 8 + .../study-cancellation/[studyId]/page.tsx | 8 + .../auth-error-after-recruitment/page.tsx | 90 + .../auth-error-during-recruitment/page.tsx | 99 + apps/client/app/(beforeLogin)/auth/page.tsx | 115 + .../client/app/(beforeLogin)/landing/page.tsx | 92 + .../social-login/redirect/page.tsx | 26 + apps/client/app/api/my-page/logout/route.ts | 17 + apps/client/app/error.tsx | 47 + apps/client/app/global.css | 10 + apps/client/app/layout.tsx | 62 + apps/client/app/not-found.tsx | 54 + apps/client/app/page.tsx | 5 + apps/client/components/JotaiProvider.tsx | 8 + apps/client/components/Navbar.tsx | 114 + apps/client/components/Popover.tsx | 75 + apps/client/components/Tooltip.tsx | 53 + apps/client/constants/apiPath.ts | 15 + apps/client/constants/assignmentMockData.ts | 132 + .../assignmentSubmissionStatusMap.ts | 12 + apps/client/constants/attendanceStatusMap.ts | 12 + apps/client/constants/cookieKey.ts | 4 + apps/client/constants/dayToKorean.ts | 9 + apps/client/constants/environment.ts | 4 + apps/client/constants/navMenu.ts | 33 + apps/client/constants/routePath.ts | 26 + apps/client/constants/tags.ts | 12 + .../useFetchAttendanceCheckModalInfoData.ts | 45 + .../hooks/useFetchBasicStudyInfoData.ts | 30 + apps/client/hooks/useHorizontalScroll.ts | 18 + apps/client/hooks/useMatchedStudyHistoryId.ts | 33 + apps/client/middleware.ts | 41 + apps/client/next.config.mjs | 15 + apps/client/package.json | 32 + apps/client/panda.config.ts | 7 + apps/client/postcss.config.cjs | 5 + apps/client/public/images/administrator.svg | 13 + apps/client/public/images/arrow-button.svg | 18 + apps/client/public/images/arrow.svg | 3 + apps/client/public/images/auth-background.svg | 91 + apps/client/public/images/avatar.svg | 23 + apps/client/public/images/check.svg | 3 + apps/client/public/images/dot.svg | 3 + apps/client/public/images/empty-history.png | Bin 0 -> 60228 bytes apps/client/public/images/empty.svg | 23 + apps/client/public/images/error.svg | 29 + apps/client/public/images/folder.svg | 4 + .../public/images/github-logo-black.svg | 10 + .../public/images/github-logo-white.svg | 3 + apps/client/public/images/home.svg | 5 + .../public/images/landing-background.svg | 34 + apps/client/public/images/link.svg | 4 + apps/client/public/images/logo.svg | 9 + apps/client/public/images/not-found.svg | 34 + apps/client/public/images/og-image.png | Bin 0 -> 56612 bytes apps/client/public/images/particpant.svg | 15 + apps/client/public/images/person.svg | 11 + apps/client/public/images/schedule.svg | 8 + apps/client/styled-system/css/conditions.js | 36 + apps/client/styled-system/css/conditions.mjs | 36 + apps/client/styled-system/css/css.d.ts | 22 + apps/client/styled-system/css/css.js | 49 + apps/client/styled-system/css/css.mjs | 49 + apps/client/styled-system/css/cva.d.ts | 6 + apps/client/styled-system/css/cva.js | 101 + apps/client/styled-system/css/cva.mjs | 101 + apps/client/styled-system/css/cx.d.ts | 5 + apps/client/styled-system/css/cx.js | 15 + apps/client/styled-system/css/cx.mjs | 15 + apps/client/styled-system/css/index.d.ts | 5 + apps/client/styled-system/css/index.js | 4 + apps/client/styled-system/css/index.mjs | 4 + apps/client/styled-system/css/sva.d.ts | 4 + apps/client/styled-system/css/sva.js | 49 + apps/client/styled-system/css/sva.mjs | 49 + apps/client/styled-system/helpers.js | 359 + apps/client/styled-system/helpers.mjs | 346 + .../styled-system/jsx/aspect-ratio.d.ts | 14 + apps/client/styled-system/jsx/aspect-ratio.js | 16 + apps/client/styled-system/jsx/bleed.d.ts | 11 + apps/client/styled-system/jsx/bleed.js | 14 + apps/client/styled-system/jsx/box.d.ts | 11 + apps/client/styled-system/jsx/box.js | 14 + apps/client/styled-system/jsx/center.d.ts | 11 + apps/client/styled-system/jsx/center.js | 14 + apps/client/styled-system/jsx/circle.d.ts | 11 + apps/client/styled-system/jsx/circle.js | 14 + apps/client/styled-system/jsx/container.d.ts | 11 + apps/client/styled-system/jsx/container.js | 16 + apps/client/styled-system/jsx/cq.d.ts | 11 + apps/client/styled-system/jsx/cq.js | 14 + apps/client/styled-system/jsx/divider.d.ts | 11 + apps/client/styled-system/jsx/divider.js | 18 + .../styled-system/jsx/factory-helper.js | 27 + apps/client/styled-system/jsx/factory.d.ts | 3 + apps/client/styled-system/jsx/factory.js | 122 + apps/client/styled-system/jsx/flex.d.ts | 11 + apps/client/styled-system/jsx/flex.js | 22 + apps/client/styled-system/jsx/float.d.ts | 11 + apps/client/styled-system/jsx/float.js | 19 + apps/client/styled-system/jsx/grid-item.d.ts | 11 + apps/client/styled-system/jsx/grid-item.js | 23 + apps/client/styled-system/jsx/grid.d.ts | 11 + apps/client/styled-system/jsx/grid.js | 20 + apps/client/styled-system/jsx/hstack.d.ts | 11 + apps/client/styled-system/jsx/hstack.js | 14 + apps/client/styled-system/jsx/index.d.ts | 24 + apps/client/styled-system/jsx/index.js | 22 + .../styled-system/jsx/is-valid-prop.d.ts | 18 + .../client/styled-system/jsx/is-valid-prop.js | 20 + .../styled-system/jsx/link-overlay.d.ts | 11 + apps/client/styled-system/jsx/link-overlay.js | 16 + apps/client/styled-system/jsx/spacer.d.ts | 11 + apps/client/styled-system/jsx/spacer.js | 14 + apps/client/styled-system/jsx/square.d.ts | 11 + apps/client/styled-system/jsx/square.js | 14 + apps/client/styled-system/jsx/stack.d.ts | 11 + apps/client/styled-system/jsx/stack.js | 19 + .../styled-system/jsx/visually-hidden.d.ts | 11 + .../styled-system/jsx/visually-hidden.js | 16 + apps/client/styled-system/jsx/vstack.d.ts | 11 + apps/client/styled-system/jsx/vstack.js | 14 + apps/client/styled-system/jsx/wrap.d.ts | 11 + apps/client/styled-system/jsx/wrap.js | 20 + .../styled-system/patterns/aspect-ratio.d.ts | 24 + .../styled-system/patterns/aspect-ratio.js | 39 + .../styled-system/patterns/aspect-ratio.mjs | 39 + apps/client/styled-system/patterns/bleed.d.ts | 22 + apps/client/styled-system/patterns/bleed.js | 26 + apps/client/styled-system/patterns/bleed.mjs | 26 + apps/client/styled-system/patterns/box.d.ts | 19 + apps/client/styled-system/patterns/box.js | 16 + apps/client/styled-system/patterns/box.mjs | 16 + .../client/styled-system/patterns/center.d.ts | 21 + apps/client/styled-system/patterns/center.js | 22 + apps/client/styled-system/patterns/center.mjs | 22 + .../client/styled-system/patterns/circle.d.ts | 21 + apps/client/styled-system/patterns/circle.js | 26 + apps/client/styled-system/patterns/circle.mjs | 26 + .../styled-system/patterns/container.d.ts | 19 + .../styled-system/patterns/container.js | 22 + .../styled-system/patterns/container.mjs | 22 + apps/client/styled-system/patterns/cq.d.ts | 24 + apps/client/styled-system/patterns/cq.js | 22 + apps/client/styled-system/patterns/cq.mjs | 22 + .../styled-system/patterns/divider.d.ts | 23 + apps/client/styled-system/patterns/divider.js | 30 + .../client/styled-system/patterns/divider.mjs | 30 + apps/client/styled-system/patterns/flex.d.ts | 27 + apps/client/styled-system/patterns/flex.js | 36 + apps/client/styled-system/patterns/flex.mjs | 36 + apps/client/styled-system/patterns/float.d.ts | 34 + apps/client/styled-system/patterns/float.js | 53 + apps/client/styled-system/patterns/float.mjs | 53 + .../styled-system/patterns/grid-item.d.ts | 26 + .../styled-system/patterns/grid-item.js | 27 + .../styled-system/patterns/grid-item.mjs | 27 + apps/client/styled-system/patterns/grid.d.ts | 25 + apps/client/styled-system/patterns/grid.js | 36 + apps/client/styled-system/patterns/grid.mjs | 36 + .../client/styled-system/patterns/hstack.d.ts | 22 + apps/client/styled-system/patterns/hstack.js | 25 + apps/client/styled-system/patterns/hstack.mjs | 25 + apps/client/styled-system/patterns/index.d.ts | 21 + apps/client/styled-system/patterns/index.js | 20 + apps/client/styled-system/patterns/index.mjs | 20 + .../styled-system/patterns/link-overlay.d.ts | 19 + .../styled-system/patterns/link-overlay.js | 25 + .../styled-system/patterns/link-overlay.mjs | 25 + .../client/styled-system/patterns/spacer.d.ts | 21 + apps/client/styled-system/patterns/spacer.js | 22 + apps/client/styled-system/patterns/spacer.mjs | 22 + .../client/styled-system/patterns/square.d.ts | 21 + apps/client/styled-system/patterns/square.js | 25 + apps/client/styled-system/patterns/square.mjs | 25 + apps/client/styled-system/patterns/stack.d.ts | 24 + apps/client/styled-system/patterns/stack.js | 25 + apps/client/styled-system/patterns/stack.mjs | 25 + .../patterns/visually-hidden.d.ts | 19 + .../styled-system/patterns/visually-hidden.js | 19 + .../patterns/visually-hidden.mjs | 19 + .../client/styled-system/patterns/vstack.d.ts | 22 + apps/client/styled-system/patterns/vstack.js | 25 + apps/client/styled-system/patterns/vstack.mjs | 25 + apps/client/styled-system/patterns/wrap.d.ts | 25 + apps/client/styled-system/patterns/wrap.js | 33 + apps/client/styled-system/patterns/wrap.mjs | 33 + apps/client/styled-system/tokens/index.d.ts | 9 + apps/client/styled-system/tokens/index.js | 592 + apps/client/styled-system/tokens/index.mjs | 1895 ++ apps/client/styled-system/tokens/tokens.d.ts | 372 + .../styled-system/types/composition.d.ts | 138 + .../styled-system/types/conditions.d.ts | 236 + apps/client/styled-system/types/csstype.d.ts | 23197 ++++++++++++++++ apps/client/styled-system/types/global.d.ts | 43 + apps/client/styled-system/types/index.d.ts | 8 + apps/client/styled-system/types/jsx.d.ts | 87 + apps/client/styled-system/types/parts.d.ts | 8 + apps/client/styled-system/types/pattern.d.ts | 87 + .../client/styled-system/types/prop-type.d.ts | 733 + apps/client/styled-system/types/recipe.d.ts | 211 + .../client/styled-system/types/selectors.d.ts | 62 + .../styled-system/types/static-css.d.ts | 51 + .../styled-system/types/style-props.d.ts | 8925 ++++++ .../styled-system/types/system-types.d.ts | 123 + apps/client/tsconfig.json | 23 + apps/client/types/dtos/applyStudy.ts | 22 + apps/client/types/dtos/auth.ts | 47 + apps/client/types/dtos/members.ts | 3 + apps/client/types/dtos/myStudy.ts | 82 + apps/client/types/dtos/studyDetail.ts | 25 + apps/client/types/dtos/studyHistory.ts | 15 + .../types/entities/common/assignment.ts | 7 + apps/client/types/entities/common/auth.ts | 5 + apps/client/types/entities/common/study.ts | 1 + apps/client/types/entities/common/time.ts | 17 + apps/client/types/entities/myAssignment.ts | 4 + apps/client/types/entities/myStudy.ts | 24 + apps/client/utils/getIsCurrentWeek.ts | 10 + apps/client/utils/index.ts | 1 + apps/client/utils/isDeadlinePassed.ts | 7 + apps/client/utils/revalidateTagByName.ts | 7 + apps/client/utils/validateAttendanceNumber.ts | 3 + package.json | 51 + packages/eslint-config/basic.js | 126 + packages/eslint-config/next.js | 4 + packages/eslint-config/package.json | 24 + packages/fonts/ProductSans-Bold.ttf | Bin 0 -> 55548 bytes packages/fonts/ProductSans-Bold.woff | Bin 0 -> 42340 bytes packages/fonts/ProductSans-Bold.woff2 | Bin 0 -> 32828 bytes packages/fonts/ProductSans-Regular.ttf | Bin 0 -> 41116 bytes packages/fonts/ProductSans-Regular.woff | Bin 0 -> 50044 bytes packages/fonts/ProductSans-Regular.woff2 | Bin 0 -> 37420 bytes packages/fonts/SUIT-Bold.ttf | Bin 0 -> 589892 bytes packages/fonts/SUIT-Bold.woff | Bin 0 -> 236448 bytes packages/fonts/SUIT-Bold.woff2 | Bin 0 -> 171380 bytes packages/fonts/SUIT-ExtraBold.ttf | Bin 0 -> 586272 bytes packages/fonts/SUIT-ExtraBold.woff | Bin 0 -> 236540 bytes packages/fonts/SUIT-ExtraBold.woff2 | Bin 0 -> 172040 bytes packages/fonts/SUIT-ExtraLight.ttf | Bin 0 -> 600984 bytes packages/fonts/SUIT-ExtraLight.woff | Bin 0 -> 233164 bytes packages/fonts/SUIT-ExtraLight.woff2 | Bin 0 -> 165792 bytes packages/fonts/SUIT-Heavy.ttf | Bin 0 -> 583792 bytes packages/fonts/SUIT-Heavy.woff | Bin 0 -> 230624 bytes packages/fonts/SUIT-Heavy.woff2 | Bin 0 -> 166684 bytes packages/fonts/SUIT-Light.ttf | Bin 0 -> 598200 bytes packages/fonts/SUIT-Light.woff | Bin 0 -> 235616 bytes packages/fonts/SUIT-Light.woff2 | Bin 0 -> 169156 bytes packages/fonts/SUIT-Medium.ttf | Bin 0 -> 592832 bytes packages/fonts/SUIT-Medium.woff | Bin 0 -> 236280 bytes packages/fonts/SUIT-Medium.woff2 | Bin 0 -> 170956 bytes packages/fonts/SUIT-Regular.ttf | Bin 0 -> 594324 bytes packages/fonts/SUIT-Regular.woff | Bin 0 -> 234592 bytes packages/fonts/SUIT-Regular.woff2 | Bin 0 -> 167672 bytes packages/fonts/SUIT-SemiBold.ttf | Bin 0 -> 591696 bytes packages/fonts/SUIT-SemiBold.woff | Bin 0 -> 236928 bytes packages/fonts/SUIT-SemiBold.woff2 | Bin 0 -> 171164 bytes packages/fonts/SUIT-Thin.ttf | Bin 0 -> 604912 bytes packages/fonts/SUIT-Thin.woff | Bin 0 -> 224068 bytes packages/fonts/SUIT-Thin.woff2 | Bin 0 -> 157156 bytes packages/fonts/index.css | 103 + packages/fonts/package.json | 8 + packages/panda-config/common-config.ts | 42 + packages/panda-config/package.json | 8 + packages/typescript-config/basic.json | 23 + packages/typescript-config/next.json | 12 + packages/typescript-config/package.json | 5 + packages/ui/.eslintrc.js | 15 + packages/ui/.storybook/main.ts | 33 + packages/ui/.storybook/preview.ts | 18 + packages/ui/package.json | 40 + packages/ui/panda.config.ts | 8 + packages/ui/postcss.config.cjs | 5 + packages/ui/src/assets/images/arrow.svg | 3 + packages/ui/src/assets/images/close.svg | 4 + packages/ui/src/assets/images/folder.svg | 4 + packages/ui/src/assets/images/home.svg | 5 + packages/ui/src/assets/images/logo.svg | 9 + .../src/components/Header/Header.stories.tsx | 20 + packages/ui/src/components/Header/index.tsx | 71 + .../ui/src/components/Modal/Modal.stories.tsx | 65 + packages/ui/src/components/Modal/index.tsx | 92 + .../components/NavItem/NavItem.stories.tsx | 61 + packages/ui/src/components/NavItem/index.tsx | 148 + packages/ui/src/components/Space/index.tsx | 37 + .../ui/src/components/Table/Table.stories.tsx | 32 + packages/ui/src/components/Table/index.tsx | 62 + .../ui/src/components/Text/Text.stories.tsx | 61 + packages/ui/src/components/Text/index.tsx | 53 + packages/ui/src/components/index.ts | 6 + packages/ui/src/hooks/index.ts | 3 + packages/ui/src/hooks/useClickOutside.ts | 28 + packages/ui/src/hooks/useModalRoute.ts | 14 + packages/ui/src/hooks/useOpenState.ts | 17 + packages/ui/src/index.css | 6 + packages/ui/src/styles.css | 846 + packages/ui/src/types/svg.d.ts | 4 + packages/ui/styled-system/css/conditions.js | 36 + packages/ui/styled-system/css/conditions.mjs | 36 + packages/ui/styled-system/css/css.d.ts | 22 + packages/ui/styled-system/css/css.js | 49 + packages/ui/styled-system/css/css.mjs | 49 + packages/ui/styled-system/css/cva.d.ts | 6 + packages/ui/styled-system/css/cva.js | 101 + packages/ui/styled-system/css/cva.mjs | 101 + packages/ui/styled-system/css/cx.d.ts | 5 + packages/ui/styled-system/css/cx.js | 15 + packages/ui/styled-system/css/cx.mjs | 15 + packages/ui/styled-system/css/index.d.ts | 5 + packages/ui/styled-system/css/index.js | 4 + packages/ui/styled-system/css/index.mjs | 4 + packages/ui/styled-system/css/sva.d.ts | 4 + packages/ui/styled-system/css/sva.js | 49 + packages/ui/styled-system/css/sva.mjs | 49 + packages/ui/styled-system/helpers.js | 359 + packages/ui/styled-system/helpers.mjs | 346 + .../ui/styled-system/jsx/aspect-ratio.d.ts | 14 + packages/ui/styled-system/jsx/aspect-ratio.js | 16 + packages/ui/styled-system/jsx/bleed.d.ts | 11 + packages/ui/styled-system/jsx/bleed.js | 14 + packages/ui/styled-system/jsx/box.d.ts | 11 + packages/ui/styled-system/jsx/box.js | 14 + packages/ui/styled-system/jsx/center.d.ts | 11 + packages/ui/styled-system/jsx/center.js | 14 + packages/ui/styled-system/jsx/circle.d.ts | 11 + packages/ui/styled-system/jsx/circle.js | 14 + packages/ui/styled-system/jsx/container.d.ts | 11 + packages/ui/styled-system/jsx/container.js | 16 + packages/ui/styled-system/jsx/cq.d.ts | 11 + packages/ui/styled-system/jsx/cq.js | 14 + packages/ui/styled-system/jsx/divider.d.ts | 11 + packages/ui/styled-system/jsx/divider.js | 18 + .../ui/styled-system/jsx/factory-helper.js | 27 + packages/ui/styled-system/jsx/factory.d.ts | 3 + packages/ui/styled-system/jsx/factory.js | 122 + packages/ui/styled-system/jsx/flex.d.ts | 11 + packages/ui/styled-system/jsx/flex.js | 22 + packages/ui/styled-system/jsx/float.d.ts | 11 + packages/ui/styled-system/jsx/float.js | 19 + packages/ui/styled-system/jsx/grid-item.d.ts | 11 + packages/ui/styled-system/jsx/grid-item.js | 23 + packages/ui/styled-system/jsx/grid.d.ts | 11 + packages/ui/styled-system/jsx/grid.js | 20 + packages/ui/styled-system/jsx/hstack.d.ts | 11 + packages/ui/styled-system/jsx/hstack.js | 14 + packages/ui/styled-system/jsx/index.d.ts | 24 + packages/ui/styled-system/jsx/index.js | 22 + .../ui/styled-system/jsx/is-valid-prop.d.ts | 18 + .../ui/styled-system/jsx/is-valid-prop.js | 20 + .../ui/styled-system/jsx/link-overlay.d.ts | 11 + packages/ui/styled-system/jsx/link-overlay.js | 16 + packages/ui/styled-system/jsx/spacer.d.ts | 11 + packages/ui/styled-system/jsx/spacer.js | 14 + packages/ui/styled-system/jsx/square.d.ts | 11 + packages/ui/styled-system/jsx/square.js | 14 + packages/ui/styled-system/jsx/stack.d.ts | 11 + packages/ui/styled-system/jsx/stack.js | 19 + .../ui/styled-system/jsx/visually-hidden.d.ts | 11 + .../ui/styled-system/jsx/visually-hidden.js | 16 + packages/ui/styled-system/jsx/vstack.d.ts | 11 + packages/ui/styled-system/jsx/vstack.js | 14 + packages/ui/styled-system/jsx/wrap.d.ts | 11 + packages/ui/styled-system/jsx/wrap.js | 20 + .../styled-system/patterns/aspect-ratio.d.ts | 24 + .../ui/styled-system/patterns/aspect-ratio.js | 39 + .../styled-system/patterns/aspect-ratio.mjs | 39 + packages/ui/styled-system/patterns/bleed.d.ts | 22 + packages/ui/styled-system/patterns/bleed.js | 26 + packages/ui/styled-system/patterns/bleed.mjs | 26 + packages/ui/styled-system/patterns/box.d.ts | 19 + packages/ui/styled-system/patterns/box.js | 16 + packages/ui/styled-system/patterns/box.mjs | 16 + .../ui/styled-system/patterns/center.d.ts | 21 + packages/ui/styled-system/patterns/center.js | 22 + packages/ui/styled-system/patterns/center.mjs | 22 + .../ui/styled-system/patterns/circle.d.ts | 21 + packages/ui/styled-system/patterns/circle.js | 26 + packages/ui/styled-system/patterns/circle.mjs | 26 + .../ui/styled-system/patterns/container.d.ts | 19 + .../ui/styled-system/patterns/container.js | 22 + .../ui/styled-system/patterns/container.mjs | 22 + packages/ui/styled-system/patterns/cq.d.ts | 24 + packages/ui/styled-system/patterns/cq.js | 22 + packages/ui/styled-system/patterns/cq.mjs | 22 + .../ui/styled-system/patterns/divider.d.ts | 23 + packages/ui/styled-system/patterns/divider.js | 30 + .../ui/styled-system/patterns/divider.mjs | 30 + packages/ui/styled-system/patterns/flex.d.ts | 27 + packages/ui/styled-system/patterns/flex.js | 36 + packages/ui/styled-system/patterns/flex.mjs | 36 + packages/ui/styled-system/patterns/float.d.ts | 34 + packages/ui/styled-system/patterns/float.js | 53 + packages/ui/styled-system/patterns/float.mjs | 53 + .../ui/styled-system/patterns/grid-item.d.ts | 26 + .../ui/styled-system/patterns/grid-item.js | 27 + .../ui/styled-system/patterns/grid-item.mjs | 27 + packages/ui/styled-system/patterns/grid.d.ts | 25 + packages/ui/styled-system/patterns/grid.js | 36 + packages/ui/styled-system/patterns/grid.mjs | 36 + .../ui/styled-system/patterns/hstack.d.ts | 22 + packages/ui/styled-system/patterns/hstack.js | 25 + packages/ui/styled-system/patterns/hstack.mjs | 25 + packages/ui/styled-system/patterns/index.d.ts | 21 + packages/ui/styled-system/patterns/index.js | 20 + packages/ui/styled-system/patterns/index.mjs | 20 + .../styled-system/patterns/link-overlay.d.ts | 19 + .../ui/styled-system/patterns/link-overlay.js | 25 + .../styled-system/patterns/link-overlay.mjs | 25 + .../ui/styled-system/patterns/spacer.d.ts | 21 + packages/ui/styled-system/patterns/spacer.js | 22 + packages/ui/styled-system/patterns/spacer.mjs | 22 + .../ui/styled-system/patterns/square.d.ts | 21 + packages/ui/styled-system/patterns/square.js | 25 + packages/ui/styled-system/patterns/square.mjs | 25 + packages/ui/styled-system/patterns/stack.d.ts | 24 + packages/ui/styled-system/patterns/stack.js | 25 + packages/ui/styled-system/patterns/stack.mjs | 25 + .../patterns/visually-hidden.d.ts | 19 + .../styled-system/patterns/visually-hidden.js | 19 + .../patterns/visually-hidden.mjs | 19 + .../ui/styled-system/patterns/vstack.d.ts | 22 + packages/ui/styled-system/patterns/vstack.js | 25 + packages/ui/styled-system/patterns/vstack.mjs | 25 + packages/ui/styled-system/patterns/wrap.d.ts | 25 + packages/ui/styled-system/patterns/wrap.js | 33 + packages/ui/styled-system/patterns/wrap.mjs | 33 + packages/ui/styled-system/tokens/index.d.ts | 9 + packages/ui/styled-system/tokens/index.js | 592 + packages/ui/styled-system/tokens/index.mjs | 1895 ++ packages/ui/styled-system/tokens/tokens.d.ts | 372 + .../ui/styled-system/types/composition.d.ts | 138 + .../ui/styled-system/types/conditions.d.ts | 236 + packages/ui/styled-system/types/csstype.d.ts | 23197 ++++++++++++++++ packages/ui/styled-system/types/global.d.ts | 43 + packages/ui/styled-system/types/index.d.ts | 8 + packages/ui/styled-system/types/jsx.d.ts | 87 + packages/ui/styled-system/types/parts.d.ts | 8 + packages/ui/styled-system/types/pattern.d.ts | 87 + .../ui/styled-system/types/prop-type.d.ts | 733 + packages/ui/styled-system/types/recipe.d.ts | 211 + .../ui/styled-system/types/selectors.d.ts | 62 + .../ui/styled-system/types/static-css.d.ts | 51 + .../ui/styled-system/types/style-props.d.ts | 8925 ++++++ .../ui/styled-system/types/system-types.d.ts | 123 + packages/ui/tsconfig.json | 12 + packages/ui/turbo/generators/config.ts | 46 + .../turbo/generators/templates/component.hbs | 16 + .../turbo/generators/templates/storybook.hbs | 51 + packages/utils/.eslintrc.js | 11 + packages/utils/jest.config.cjs | 10 + packages/utils/jest.setup.ts | 3 + packages/utils/package.json | 23 + packages/utils/src/fetcher/fetcher.test.ts | 126 + packages/utils/src/fetcher/index.ts | 193 + packages/utils/src/formatDate.ts | 108 + packages/utils/src/formatTime.ts | 22 + packages/utils/src/index.ts | 3 + packages/utils/tsconfig.json | 8 + pnpm-lock.yaml | 15399 ++++++++++ pnpm-workspace.yaml | 3 + turbo.json | 19 + 822 files changed, 150099 insertions(+) create mode 100644 .eslintignore create mode 100644 .github/CODEOWNERS create mode 100644 .github/workflows/auto_assign.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/deploy-chromatic.yml create mode 100644 .gitignore create mode 100755 .husky/commit-msg create mode 100644 .husky/pre-commit create mode 100644 .husky/pre-push create mode 100644 .npmrc create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .vscode/settings.json create mode 100644 README.md create mode 100644 apps/admin/.eslintrc.js create mode 100644 apps/admin/.gitignore create mode 100644 apps/admin/README.md create mode 100644 apps/admin/apis/auth/dashboardApi.ts create mode 100644 apps/admin/apis/study/createStudyApi.ts create mode 100644 apps/admin/apis/study/studyApi.ts create mode 100644 apps/admin/app/@modal/(.)participants/page.tsx create mode 100644 apps/admin/app/@modal/default.tsx create mode 100644 apps/admin/app/error.tsx create mode 100644 apps/admin/app/global.css create mode 100644 apps/admin/app/layout.tsx create mode 100644 apps/admin/app/not-found.tsx create mode 100644 apps/admin/app/page.tsx create mode 100644 apps/admin/app/participants/page.tsx create mode 100644 apps/admin/app/studies/[studyId]/@modal/(.)announcement-delete/page.tsx create mode 100644 apps/admin/app/studies/[studyId]/@modal/(.)announcement-modify/page.tsx create mode 100644 apps/admin/app/studies/[studyId]/@modal/default.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/announcement/CreateStudyAnnouncement.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/announcement/StudyAnnouncement.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/assignment/AssignmentButtons.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/assignment/AssignmentList.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/assignment/AssignmentListItem.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/attendance/AttendanceItem.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/attendance/AttendanceList.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/curriculum/CurriculumList.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/curriculum/CurriculumListItem.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/curriculum/EmptyCurriculumList.tsx create mode 100644 apps/admin/app/studies/[studyId]/_components/header/Header.tsx create mode 100644 apps/admin/app/studies/[studyId]/announcement-delete/page.tsx create mode 100644 apps/admin/app/studies/[studyId]/announcement-modify/page.tsx create mode 100644 apps/admin/app/studies/[studyId]/default.tsx create mode 100644 apps/admin/app/studies/[studyId]/hooks/usePrefillAnnouncement.ts create mode 100644 apps/admin/app/studies/[studyId]/layout.tsx create mode 100644 apps/admin/app/studies/[studyId]/page.tsx create mode 100644 apps/admin/app/studies/_components/EmptyStudyList.tsx create mode 100644 apps/admin/app/studies/_components/StudyList.tsx create mode 100644 apps/admin/app/studies/_components/StudyListItem.tsx create mode 100644 apps/admin/app/studies/assignments/[studyDetailId]/_components/AssignmentForm.tsx create mode 100644 apps/admin/app/studies/assignments/[studyDetailId]/_components/AssignmentHeader.tsx create mode 100644 apps/admin/app/studies/assignments/[studyDetailId]/_components/CustomTextField.tsx create mode 100644 apps/admin/app/studies/assignments/[studyDetailId]/_components/SuccessModal.tsx create mode 100644 apps/admin/app/studies/assignments/[studyDetailId]/edit-assignment/page.tsx create mode 100644 apps/admin/app/studies/assignments/[studyDetailId]/page.tsx create mode 100644 apps/admin/app/studies/assignments/layout.tsx create mode 100644 apps/admin/app/studies/create-study/@modal/(.)created-study-check/page.tsx create mode 100644 apps/admin/app/studies/create-study/@modal/default.tsx create mode 100644 apps/admin/app/studies/create-study/_components/CreateStudyButton.tsx create mode 100644 apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyApplyDatePick.tsx create mode 100644 apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyCourseSelect.tsx create mode 100644 apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyDayOfWeekSelect.tsx create mode 100644 apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyFormatSelect.tsx create mode 100644 apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudySemesterSelect.tsx create mode 100644 apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyStartDatePick.tsx create mode 100644 apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyTime.tsx create mode 100644 apps/admin/app/studies/create-study/_components/StudyBasicInformation/index.tsx create mode 100644 apps/admin/app/studies/create-study/_components/StudyMentorSelect.tsx create mode 100644 apps/admin/app/studies/create-study/_components/StudyNameTextField.tsx create mode 100644 apps/admin/app/studies/create-study/_components/index.ts create mode 100644 apps/admin/app/studies/create-study/created-study-check/page.tsx create mode 100644 apps/admin/app/studies/create-study/default.tsx create mode 100644 apps/admin/app/studies/create-study/layout.tsx create mode 100644 apps/admin/app/studies/create-study/page.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/@modal/(.)detail-Info-check/_hooks/useSubmitStudyDetailInfo.ts create mode 100644 apps/admin/app/studies/detail-info/[studyId]/@modal/(.)detail-Info-check/page.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/@modal/default.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/_components/CreateStudyDetailInfo.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/_components/StudyCurriculum.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/_components/StudyDescription.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/_components/StudyInfoBox/StudyInfoDifficulty.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/_components/StudyInfoBox/StudyInfoStatus.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/_components/StudyInfoBox/StudyTextInfo.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/_components/StudyInfoBox/StudyTimeline.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/_components/StudyInfoBox/index.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/_hooks/usePrefillStudyDetailInfo.ts create mode 100644 apps/admin/app/studies/detail-info/[studyId]/default.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/detail-info-check/page.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/layout.tsx create mode 100644 apps/admin/app/studies/detail-info/[studyId]/page.tsx create mode 100644 apps/admin/app/studies/layout.tsx create mode 100644 apps/admin/app/studies/page.tsx create mode 100644 apps/admin/components/ItemSeparator.tsx create mode 100644 apps/admin/components/JotaiProvider.tsx create mode 100644 apps/admin/components/Navbar.tsx create mode 100644 apps/admin/constants/apiPath.ts create mode 100644 apps/admin/constants/cookieKey.ts create mode 100644 apps/admin/constants/date.ts create mode 100644 apps/admin/constants/dayToKorean.ts create mode 100644 apps/admin/constants/router/routerPath.ts create mode 100644 apps/admin/constants/status/assignmentStatusMap.ts create mode 100644 apps/admin/constants/status/attendanceStatusMap.ts create mode 100644 apps/admin/constants/tags.ts create mode 100644 apps/admin/constants/url.ts create mode 100644 apps/admin/hooks/useClickOutSide.tsx create mode 100644 apps/admin/hooks/useForm.tsx create mode 100644 apps/admin/hooks/useParseSearchParams.ts create mode 100644 apps/admin/middleware.ts create mode 100644 apps/admin/next.config.mjs create mode 100644 apps/admin/package.json create mode 100644 apps/admin/panda.config.ts create mode 100644 apps/admin/postcss.config.cjs create mode 100644 apps/admin/public/images/administrator.svg create mode 100644 apps/admin/public/images/arrow.svg create mode 100644 apps/admin/public/images/dot.svg create mode 100644 apps/admin/public/images/empty.svg create mode 100644 apps/admin/public/images/error.svg create mode 100644 apps/admin/public/images/folder.svg create mode 100644 apps/admin/public/images/home.svg create mode 100644 apps/admin/public/images/link.svg create mode 100644 apps/admin/public/images/logo.svg create mode 100644 apps/admin/public/images/not-found.svg create mode 100644 apps/admin/public/images/og-image.png create mode 100644 apps/admin/public/images/particpant.svg create mode 100644 apps/admin/styled-system/css/conditions.js create mode 100644 apps/admin/styled-system/css/conditions.mjs create mode 100644 apps/admin/styled-system/css/css.d.ts create mode 100644 apps/admin/styled-system/css/css.js create mode 100644 apps/admin/styled-system/css/css.mjs create mode 100644 apps/admin/styled-system/css/cva.d.ts create mode 100644 apps/admin/styled-system/css/cva.js create mode 100644 apps/admin/styled-system/css/cva.mjs create mode 100644 apps/admin/styled-system/css/cx.d.ts create mode 100644 apps/admin/styled-system/css/cx.js create mode 100644 apps/admin/styled-system/css/cx.mjs create mode 100644 apps/admin/styled-system/css/index.d.ts create mode 100644 apps/admin/styled-system/css/index.js create mode 100644 apps/admin/styled-system/css/index.mjs create mode 100644 apps/admin/styled-system/css/sva.d.ts create mode 100644 apps/admin/styled-system/css/sva.js create mode 100644 apps/admin/styled-system/css/sva.mjs create mode 100644 apps/admin/styled-system/helpers.js create mode 100644 apps/admin/styled-system/helpers.mjs create mode 100644 apps/admin/styled-system/jsx/aspect-ratio.d.ts create mode 100644 apps/admin/styled-system/jsx/aspect-ratio.js create mode 100644 apps/admin/styled-system/jsx/bleed.d.ts create mode 100644 apps/admin/styled-system/jsx/bleed.js create mode 100644 apps/admin/styled-system/jsx/box.d.ts create mode 100644 apps/admin/styled-system/jsx/box.js create mode 100644 apps/admin/styled-system/jsx/center.d.ts create mode 100644 apps/admin/styled-system/jsx/center.js create mode 100644 apps/admin/styled-system/jsx/circle.d.ts create mode 100644 apps/admin/styled-system/jsx/circle.js create mode 100644 apps/admin/styled-system/jsx/container.d.ts create mode 100644 apps/admin/styled-system/jsx/container.js create mode 100644 apps/admin/styled-system/jsx/cq.d.ts create mode 100644 apps/admin/styled-system/jsx/cq.js create mode 100644 apps/admin/styled-system/jsx/divider.d.ts create mode 100644 apps/admin/styled-system/jsx/divider.js create mode 100644 apps/admin/styled-system/jsx/factory-helper.js create mode 100644 apps/admin/styled-system/jsx/factory.d.ts create mode 100644 apps/admin/styled-system/jsx/factory.js create mode 100644 apps/admin/styled-system/jsx/flex.d.ts create mode 100644 apps/admin/styled-system/jsx/flex.js create mode 100644 apps/admin/styled-system/jsx/float.d.ts create mode 100644 apps/admin/styled-system/jsx/float.js create mode 100644 apps/admin/styled-system/jsx/grid-item.d.ts create mode 100644 apps/admin/styled-system/jsx/grid-item.js create mode 100644 apps/admin/styled-system/jsx/grid.d.ts create mode 100644 apps/admin/styled-system/jsx/grid.js create mode 100644 apps/admin/styled-system/jsx/hstack.d.ts create mode 100644 apps/admin/styled-system/jsx/hstack.js create mode 100644 apps/admin/styled-system/jsx/index.d.ts create mode 100644 apps/admin/styled-system/jsx/index.js create mode 100644 apps/admin/styled-system/jsx/is-valid-prop.d.ts create mode 100644 apps/admin/styled-system/jsx/is-valid-prop.js create mode 100644 apps/admin/styled-system/jsx/link-overlay.d.ts create mode 100644 apps/admin/styled-system/jsx/link-overlay.js create mode 100644 apps/admin/styled-system/jsx/spacer.d.ts create mode 100644 apps/admin/styled-system/jsx/spacer.js create mode 100644 apps/admin/styled-system/jsx/square.d.ts create mode 100644 apps/admin/styled-system/jsx/square.js create mode 100644 apps/admin/styled-system/jsx/stack.d.ts create mode 100644 apps/admin/styled-system/jsx/stack.js create mode 100644 apps/admin/styled-system/jsx/visually-hidden.d.ts create mode 100644 apps/admin/styled-system/jsx/visually-hidden.js create mode 100644 apps/admin/styled-system/jsx/vstack.d.ts create mode 100644 apps/admin/styled-system/jsx/vstack.js create mode 100644 apps/admin/styled-system/jsx/wrap.d.ts create mode 100644 apps/admin/styled-system/jsx/wrap.js create mode 100644 apps/admin/styled-system/patterns/aspect-ratio.d.ts create mode 100644 apps/admin/styled-system/patterns/aspect-ratio.js create mode 100644 apps/admin/styled-system/patterns/aspect-ratio.mjs create mode 100644 apps/admin/styled-system/patterns/bleed.d.ts create mode 100644 apps/admin/styled-system/patterns/bleed.js create mode 100644 apps/admin/styled-system/patterns/bleed.mjs create mode 100644 apps/admin/styled-system/patterns/box.d.ts create mode 100644 apps/admin/styled-system/patterns/box.js create mode 100644 apps/admin/styled-system/patterns/box.mjs create mode 100644 apps/admin/styled-system/patterns/center.d.ts create mode 100644 apps/admin/styled-system/patterns/center.js create mode 100644 apps/admin/styled-system/patterns/center.mjs create mode 100644 apps/admin/styled-system/patterns/circle.d.ts create mode 100644 apps/admin/styled-system/patterns/circle.js create mode 100644 apps/admin/styled-system/patterns/circle.mjs create mode 100644 apps/admin/styled-system/patterns/container.d.ts create mode 100644 apps/admin/styled-system/patterns/container.js create mode 100644 apps/admin/styled-system/patterns/container.mjs create mode 100644 apps/admin/styled-system/patterns/cq.d.ts create mode 100644 apps/admin/styled-system/patterns/cq.js create mode 100644 apps/admin/styled-system/patterns/cq.mjs create mode 100644 apps/admin/styled-system/patterns/divider.d.ts create mode 100644 apps/admin/styled-system/patterns/divider.js create mode 100644 apps/admin/styled-system/patterns/divider.mjs create mode 100644 apps/admin/styled-system/patterns/flex.d.ts create mode 100644 apps/admin/styled-system/patterns/flex.js create mode 100644 apps/admin/styled-system/patterns/flex.mjs create mode 100644 apps/admin/styled-system/patterns/float.d.ts create mode 100644 apps/admin/styled-system/patterns/float.js create mode 100644 apps/admin/styled-system/patterns/float.mjs create mode 100644 apps/admin/styled-system/patterns/grid-item.d.ts create mode 100644 apps/admin/styled-system/patterns/grid-item.js create mode 100644 apps/admin/styled-system/patterns/grid-item.mjs create mode 100644 apps/admin/styled-system/patterns/grid.d.ts create mode 100644 apps/admin/styled-system/patterns/grid.js create mode 100644 apps/admin/styled-system/patterns/grid.mjs create mode 100644 apps/admin/styled-system/patterns/hstack.d.ts create mode 100644 apps/admin/styled-system/patterns/hstack.js create mode 100644 apps/admin/styled-system/patterns/hstack.mjs create mode 100644 apps/admin/styled-system/patterns/index.d.ts create mode 100644 apps/admin/styled-system/patterns/index.js create mode 100644 apps/admin/styled-system/patterns/index.mjs create mode 100644 apps/admin/styled-system/patterns/link-overlay.d.ts create mode 100644 apps/admin/styled-system/patterns/link-overlay.js create mode 100644 apps/admin/styled-system/patterns/link-overlay.mjs create mode 100644 apps/admin/styled-system/patterns/spacer.d.ts create mode 100644 apps/admin/styled-system/patterns/spacer.js create mode 100644 apps/admin/styled-system/patterns/spacer.mjs create mode 100644 apps/admin/styled-system/patterns/square.d.ts create mode 100644 apps/admin/styled-system/patterns/square.js create mode 100644 apps/admin/styled-system/patterns/square.mjs create mode 100644 apps/admin/styled-system/patterns/stack.d.ts create mode 100644 apps/admin/styled-system/patterns/stack.js create mode 100644 apps/admin/styled-system/patterns/stack.mjs create mode 100644 apps/admin/styled-system/patterns/visually-hidden.d.ts create mode 100644 apps/admin/styled-system/patterns/visually-hidden.js create mode 100644 apps/admin/styled-system/patterns/visually-hidden.mjs create mode 100644 apps/admin/styled-system/patterns/vstack.d.ts create mode 100644 apps/admin/styled-system/patterns/vstack.js create mode 100644 apps/admin/styled-system/patterns/vstack.mjs create mode 100644 apps/admin/styled-system/patterns/wrap.d.ts create mode 100644 apps/admin/styled-system/patterns/wrap.js create mode 100644 apps/admin/styled-system/patterns/wrap.mjs create mode 100644 apps/admin/styled-system/tokens/index.d.ts create mode 100644 apps/admin/styled-system/tokens/index.js create mode 100644 apps/admin/styled-system/tokens/index.mjs create mode 100644 apps/admin/styled-system/tokens/tokens.d.ts create mode 100644 apps/admin/styled-system/types/composition.d.ts create mode 100644 apps/admin/styled-system/types/conditions.d.ts create mode 100644 apps/admin/styled-system/types/csstype.d.ts create mode 100644 apps/admin/styled-system/types/global.d.ts create mode 100644 apps/admin/styled-system/types/index.d.ts create mode 100644 apps/admin/styled-system/types/jsx.d.ts create mode 100644 apps/admin/styled-system/types/parts.d.ts create mode 100644 apps/admin/styled-system/types/pattern.d.ts create mode 100644 apps/admin/styled-system/types/prop-type.d.ts create mode 100644 apps/admin/styled-system/types/recipe.d.ts create mode 100644 apps/admin/styled-system/types/selectors.d.ts create mode 100644 apps/admin/styled-system/types/static-css.d.ts create mode 100644 apps/admin/styled-system/types/style-props.d.ts create mode 100644 apps/admin/styled-system/types/system-types.d.ts create mode 100644 apps/admin/tsconfig.json create mode 100644 apps/admin/types/dtos/announcement.ts create mode 100644 apps/admin/types/dtos/assignmentList.ts create mode 100644 apps/admin/types/dtos/attendance.ts create mode 100644 apps/admin/types/dtos/auth.ts create mode 100644 apps/admin/types/dtos/createStudy.ts create mode 100644 apps/admin/types/dtos/curriculumList.ts create mode 100644 apps/admin/types/dtos/searchStudyMentor.ts create mode 100644 apps/admin/types/dtos/studyBasicInfo.ts create mode 100644 apps/admin/types/dtos/studyDetailInfo.ts create mode 100644 apps/admin/types/dtos/studyList.ts create mode 100644 apps/admin/types/entities/assignment.ts create mode 100644 apps/admin/types/entities/auth.ts create mode 100644 apps/admin/types/entities/dayofweek.ts create mode 100644 apps/admin/types/entities/study.ts create mode 100644 apps/admin/types/entities/time.ts create mode 100644 apps/admin/types/role.ts create mode 100644 apps/admin/types/status.ts create mode 100644 apps/admin/types/user.ts create mode 100644 apps/admin/utils/checkThisWeek.ts create mode 100644 apps/admin/utils/createQueryString.ts create mode 100644 apps/admin/utils/getIsCurrentWeek.ts create mode 100644 apps/admin/utils/isAdmin.ts create mode 100644 apps/admin/utils/revalidateTagByName.ts create mode 100644 apps/admin/utils/setExpireTime.ts create mode 100644 apps/admin/utils/validate/studyDetailInfo.ts create mode 100644 apps/client/.eslintrc.js create mode 100644 apps/client/.gitignore create mode 100644 apps/client/README.md create mode 100644 apps/client/apis/authApi.ts create mode 100644 apps/client/apis/dashboardApi.ts create mode 100644 apps/client/apis/membersApi.ts create mode 100644 apps/client/apis/myStudyApi.ts create mode 100644 apps/client/apis/studyApplyApi.ts create mode 100644 apps/client/apis/studyDetailApi.ts create mode 100644 apps/client/apis/studyHistoryApi.ts create mode 100644 apps/client/app/(afterLogin)/layout.tsx create mode 100644 apps/client/app/(afterLogin)/my-page/@modal/(.)logout/page.tsx create mode 100644 apps/client/app/(afterLogin)/my-page/@modal/default.tsx create mode 100644 apps/client/app/(afterLogin)/my-page/_components/MyInfoBox.tsx create mode 100644 apps/client/app/(afterLogin)/my-page/default.tsx create mode 100644 apps/client/app/(afterLogin)/my-page/layout.tsx create mode 100644 apps/client/app/(afterLogin)/my-page/logout/page.tsx create mode 100644 apps/client/app/(afterLogin)/my-page/page.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/@modal/(.)attendance-check/page.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/@modal/default.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/_components/AssignmentStatusBox.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/_components/AttendanceStatusBox.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/_components/DailyTaskCarousel.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/_components/DailyTaskItem.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/_components/DailyTasks.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/_components/EmptyStudy.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/_components/Header.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/_components/StudyAnnouncementList.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/_components/StudyCurriculum.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/_components/index.ts create mode 100644 apps/client/app/(afterLogin)/my-study/attendance-check/page.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/default.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/layout.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/confirmation/page.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/@modal/(.)repository-url/default.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/@modal/default.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxButtons.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxInfo.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/AssignmentBoxTitle.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/FailurePopover.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/AssignmentOverviewBox/index.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/EmptyAssignmentBox.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/RepositorySubmissionBox.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentContent/index.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentDescription.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHeader.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/AssignmentHistoryItem.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/AssignmentHistory/index.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/_components/index.ts create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/default.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/layout.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/page.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/my-assignment/repository-url/confirmation/page.tsx create mode 100644 apps/client/app/(afterLogin)/my-study/page.tsx create mode 100644 apps/client/app/(afterLogin)/study-apply/@modal/(.)study-application/[studyId]/page.tsx create mode 100644 apps/client/app/(afterLogin)/study-apply/@modal/(.)study-cancellation/[studyId]/page.tsx create mode 100644 apps/client/app/(afterLogin)/study-apply/@modal/default.tsx create mode 100644 apps/client/app/(afterLogin)/study-apply/_components/StudyItem.tsx create mode 100644 apps/client/app/(afterLogin)/study-apply/_components/index.ts create mode 100644 apps/client/app/(afterLogin)/study-apply/default.tsx create mode 100644 apps/client/app/(afterLogin)/study-apply/layout.tsx create mode 100644 apps/client/app/(afterLogin)/study-apply/page.tsx create mode 100644 apps/client/app/(afterLogin)/study-apply/study-application/[studyId]/page.tsx create mode 100644 apps/client/app/(afterLogin)/study-apply/study-cancellation/[studyId]/page.tsx create mode 100644 apps/client/app/(beforeLogin)/(auth-error)/auth-error-after-recruitment/page.tsx create mode 100644 apps/client/app/(beforeLogin)/(auth-error)/auth-error-during-recruitment/page.tsx create mode 100644 apps/client/app/(beforeLogin)/auth/page.tsx create mode 100644 apps/client/app/(beforeLogin)/landing/page.tsx create mode 100644 apps/client/app/(beforeLogin)/social-login/redirect/page.tsx create mode 100644 apps/client/app/api/my-page/logout/route.ts create mode 100644 apps/client/app/error.tsx create mode 100644 apps/client/app/global.css create mode 100644 apps/client/app/layout.tsx create mode 100644 apps/client/app/not-found.tsx create mode 100644 apps/client/app/page.tsx create mode 100644 apps/client/components/JotaiProvider.tsx create mode 100644 apps/client/components/Navbar.tsx create mode 100644 apps/client/components/Popover.tsx create mode 100644 apps/client/components/Tooltip.tsx create mode 100644 apps/client/constants/apiPath.ts create mode 100644 apps/client/constants/assignmentMockData.ts create mode 100644 apps/client/constants/assignmentSubmissionStatusMap.ts create mode 100644 apps/client/constants/attendanceStatusMap.ts create mode 100644 apps/client/constants/cookieKey.ts create mode 100644 apps/client/constants/dayToKorean.ts create mode 100644 apps/client/constants/environment.ts create mode 100644 apps/client/constants/navMenu.ts create mode 100644 apps/client/constants/routePath.ts create mode 100644 apps/client/constants/tags.ts create mode 100644 apps/client/hooks/useFetchAttendanceCheckModalInfoData.ts create mode 100644 apps/client/hooks/useFetchBasicStudyInfoData.ts create mode 100644 apps/client/hooks/useHorizontalScroll.ts create mode 100644 apps/client/hooks/useMatchedStudyHistoryId.ts create mode 100644 apps/client/middleware.ts create mode 100644 apps/client/next.config.mjs create mode 100644 apps/client/package.json create mode 100644 apps/client/panda.config.ts create mode 100644 apps/client/postcss.config.cjs create mode 100644 apps/client/public/images/administrator.svg create mode 100644 apps/client/public/images/arrow-button.svg create mode 100644 apps/client/public/images/arrow.svg create mode 100644 apps/client/public/images/auth-background.svg create mode 100644 apps/client/public/images/avatar.svg create mode 100644 apps/client/public/images/check.svg create mode 100644 apps/client/public/images/dot.svg create mode 100644 apps/client/public/images/empty-history.png create mode 100644 apps/client/public/images/empty.svg create mode 100644 apps/client/public/images/error.svg create mode 100644 apps/client/public/images/folder.svg create mode 100644 apps/client/public/images/github-logo-black.svg create mode 100644 apps/client/public/images/github-logo-white.svg create mode 100644 apps/client/public/images/home.svg create mode 100644 apps/client/public/images/landing-background.svg create mode 100644 apps/client/public/images/link.svg create mode 100644 apps/client/public/images/logo.svg create mode 100644 apps/client/public/images/not-found.svg create mode 100644 apps/client/public/images/og-image.png create mode 100644 apps/client/public/images/particpant.svg create mode 100644 apps/client/public/images/person.svg create mode 100644 apps/client/public/images/schedule.svg create mode 100644 apps/client/styled-system/css/conditions.js create mode 100644 apps/client/styled-system/css/conditions.mjs create mode 100644 apps/client/styled-system/css/css.d.ts create mode 100644 apps/client/styled-system/css/css.js create mode 100644 apps/client/styled-system/css/css.mjs create mode 100644 apps/client/styled-system/css/cva.d.ts create mode 100644 apps/client/styled-system/css/cva.js create mode 100644 apps/client/styled-system/css/cva.mjs create mode 100644 apps/client/styled-system/css/cx.d.ts create mode 100644 apps/client/styled-system/css/cx.js create mode 100644 apps/client/styled-system/css/cx.mjs create mode 100644 apps/client/styled-system/css/index.d.ts create mode 100644 apps/client/styled-system/css/index.js create mode 100644 apps/client/styled-system/css/index.mjs create mode 100644 apps/client/styled-system/css/sva.d.ts create mode 100644 apps/client/styled-system/css/sva.js create mode 100644 apps/client/styled-system/css/sva.mjs create mode 100644 apps/client/styled-system/helpers.js create mode 100644 apps/client/styled-system/helpers.mjs create mode 100644 apps/client/styled-system/jsx/aspect-ratio.d.ts create mode 100644 apps/client/styled-system/jsx/aspect-ratio.js create mode 100644 apps/client/styled-system/jsx/bleed.d.ts create mode 100644 apps/client/styled-system/jsx/bleed.js create mode 100644 apps/client/styled-system/jsx/box.d.ts create mode 100644 apps/client/styled-system/jsx/box.js create mode 100644 apps/client/styled-system/jsx/center.d.ts create mode 100644 apps/client/styled-system/jsx/center.js create mode 100644 apps/client/styled-system/jsx/circle.d.ts create mode 100644 apps/client/styled-system/jsx/circle.js create mode 100644 apps/client/styled-system/jsx/container.d.ts create mode 100644 apps/client/styled-system/jsx/container.js create mode 100644 apps/client/styled-system/jsx/cq.d.ts create mode 100644 apps/client/styled-system/jsx/cq.js create mode 100644 apps/client/styled-system/jsx/divider.d.ts create mode 100644 apps/client/styled-system/jsx/divider.js create mode 100644 apps/client/styled-system/jsx/factory-helper.js create mode 100644 apps/client/styled-system/jsx/factory.d.ts create mode 100644 apps/client/styled-system/jsx/factory.js create mode 100644 apps/client/styled-system/jsx/flex.d.ts create mode 100644 apps/client/styled-system/jsx/flex.js create mode 100644 apps/client/styled-system/jsx/float.d.ts create mode 100644 apps/client/styled-system/jsx/float.js create mode 100644 apps/client/styled-system/jsx/grid-item.d.ts create mode 100644 apps/client/styled-system/jsx/grid-item.js create mode 100644 apps/client/styled-system/jsx/grid.d.ts create mode 100644 apps/client/styled-system/jsx/grid.js create mode 100644 apps/client/styled-system/jsx/hstack.d.ts create mode 100644 apps/client/styled-system/jsx/hstack.js create mode 100644 apps/client/styled-system/jsx/index.d.ts create mode 100644 apps/client/styled-system/jsx/index.js create mode 100644 apps/client/styled-system/jsx/is-valid-prop.d.ts create mode 100644 apps/client/styled-system/jsx/is-valid-prop.js create mode 100644 apps/client/styled-system/jsx/link-overlay.d.ts create mode 100644 apps/client/styled-system/jsx/link-overlay.js create mode 100644 apps/client/styled-system/jsx/spacer.d.ts create mode 100644 apps/client/styled-system/jsx/spacer.js create mode 100644 apps/client/styled-system/jsx/square.d.ts create mode 100644 apps/client/styled-system/jsx/square.js create mode 100644 apps/client/styled-system/jsx/stack.d.ts create mode 100644 apps/client/styled-system/jsx/stack.js create mode 100644 apps/client/styled-system/jsx/visually-hidden.d.ts create mode 100644 apps/client/styled-system/jsx/visually-hidden.js create mode 100644 apps/client/styled-system/jsx/vstack.d.ts create mode 100644 apps/client/styled-system/jsx/vstack.js create mode 100644 apps/client/styled-system/jsx/wrap.d.ts create mode 100644 apps/client/styled-system/jsx/wrap.js create mode 100644 apps/client/styled-system/patterns/aspect-ratio.d.ts create mode 100644 apps/client/styled-system/patterns/aspect-ratio.js create mode 100644 apps/client/styled-system/patterns/aspect-ratio.mjs create mode 100644 apps/client/styled-system/patterns/bleed.d.ts create mode 100644 apps/client/styled-system/patterns/bleed.js create mode 100644 apps/client/styled-system/patterns/bleed.mjs create mode 100644 apps/client/styled-system/patterns/box.d.ts create mode 100644 apps/client/styled-system/patterns/box.js create mode 100644 apps/client/styled-system/patterns/box.mjs create mode 100644 apps/client/styled-system/patterns/center.d.ts create mode 100644 apps/client/styled-system/patterns/center.js create mode 100644 apps/client/styled-system/patterns/center.mjs create mode 100644 apps/client/styled-system/patterns/circle.d.ts create mode 100644 apps/client/styled-system/patterns/circle.js create mode 100644 apps/client/styled-system/patterns/circle.mjs create mode 100644 apps/client/styled-system/patterns/container.d.ts create mode 100644 apps/client/styled-system/patterns/container.js create mode 100644 apps/client/styled-system/patterns/container.mjs create mode 100644 apps/client/styled-system/patterns/cq.d.ts create mode 100644 apps/client/styled-system/patterns/cq.js create mode 100644 apps/client/styled-system/patterns/cq.mjs create mode 100644 apps/client/styled-system/patterns/divider.d.ts create mode 100644 apps/client/styled-system/patterns/divider.js create mode 100644 apps/client/styled-system/patterns/divider.mjs create mode 100644 apps/client/styled-system/patterns/flex.d.ts create mode 100644 apps/client/styled-system/patterns/flex.js create mode 100644 apps/client/styled-system/patterns/flex.mjs create mode 100644 apps/client/styled-system/patterns/float.d.ts create mode 100644 apps/client/styled-system/patterns/float.js create mode 100644 apps/client/styled-system/patterns/float.mjs create mode 100644 apps/client/styled-system/patterns/grid-item.d.ts create mode 100644 apps/client/styled-system/patterns/grid-item.js create mode 100644 apps/client/styled-system/patterns/grid-item.mjs create mode 100644 apps/client/styled-system/patterns/grid.d.ts create mode 100644 apps/client/styled-system/patterns/grid.js create mode 100644 apps/client/styled-system/patterns/grid.mjs create mode 100644 apps/client/styled-system/patterns/hstack.d.ts create mode 100644 apps/client/styled-system/patterns/hstack.js create mode 100644 apps/client/styled-system/patterns/hstack.mjs create mode 100644 apps/client/styled-system/patterns/index.d.ts create mode 100644 apps/client/styled-system/patterns/index.js create mode 100644 apps/client/styled-system/patterns/index.mjs create mode 100644 apps/client/styled-system/patterns/link-overlay.d.ts create mode 100644 apps/client/styled-system/patterns/link-overlay.js create mode 100644 apps/client/styled-system/patterns/link-overlay.mjs create mode 100644 apps/client/styled-system/patterns/spacer.d.ts create mode 100644 apps/client/styled-system/patterns/spacer.js create mode 100644 apps/client/styled-system/patterns/spacer.mjs create mode 100644 apps/client/styled-system/patterns/square.d.ts create mode 100644 apps/client/styled-system/patterns/square.js create mode 100644 apps/client/styled-system/patterns/square.mjs create mode 100644 apps/client/styled-system/patterns/stack.d.ts create mode 100644 apps/client/styled-system/patterns/stack.js create mode 100644 apps/client/styled-system/patterns/stack.mjs create mode 100644 apps/client/styled-system/patterns/visually-hidden.d.ts create mode 100644 apps/client/styled-system/patterns/visually-hidden.js create mode 100644 apps/client/styled-system/patterns/visually-hidden.mjs create mode 100644 apps/client/styled-system/patterns/vstack.d.ts create mode 100644 apps/client/styled-system/patterns/vstack.js create mode 100644 apps/client/styled-system/patterns/vstack.mjs create mode 100644 apps/client/styled-system/patterns/wrap.d.ts create mode 100644 apps/client/styled-system/patterns/wrap.js create mode 100644 apps/client/styled-system/patterns/wrap.mjs create mode 100644 apps/client/styled-system/tokens/index.d.ts create mode 100644 apps/client/styled-system/tokens/index.js create mode 100644 apps/client/styled-system/tokens/index.mjs create mode 100644 apps/client/styled-system/tokens/tokens.d.ts create mode 100644 apps/client/styled-system/types/composition.d.ts create mode 100644 apps/client/styled-system/types/conditions.d.ts create mode 100644 apps/client/styled-system/types/csstype.d.ts create mode 100644 apps/client/styled-system/types/global.d.ts create mode 100644 apps/client/styled-system/types/index.d.ts create mode 100644 apps/client/styled-system/types/jsx.d.ts create mode 100644 apps/client/styled-system/types/parts.d.ts create mode 100644 apps/client/styled-system/types/pattern.d.ts create mode 100644 apps/client/styled-system/types/prop-type.d.ts create mode 100644 apps/client/styled-system/types/recipe.d.ts create mode 100644 apps/client/styled-system/types/selectors.d.ts create mode 100644 apps/client/styled-system/types/static-css.d.ts create mode 100644 apps/client/styled-system/types/style-props.d.ts create mode 100644 apps/client/styled-system/types/system-types.d.ts create mode 100644 apps/client/tsconfig.json create mode 100644 apps/client/types/dtos/applyStudy.ts create mode 100644 apps/client/types/dtos/auth.ts create mode 100644 apps/client/types/dtos/members.ts create mode 100644 apps/client/types/dtos/myStudy.ts create mode 100644 apps/client/types/dtos/studyDetail.ts create mode 100644 apps/client/types/dtos/studyHistory.ts create mode 100644 apps/client/types/entities/common/assignment.ts create mode 100644 apps/client/types/entities/common/auth.ts create mode 100644 apps/client/types/entities/common/study.ts create mode 100644 apps/client/types/entities/common/time.ts create mode 100644 apps/client/types/entities/myAssignment.ts create mode 100644 apps/client/types/entities/myStudy.ts create mode 100644 apps/client/utils/getIsCurrentWeek.ts create mode 100644 apps/client/utils/index.ts create mode 100644 apps/client/utils/isDeadlinePassed.ts create mode 100644 apps/client/utils/revalidateTagByName.ts create mode 100644 apps/client/utils/validateAttendanceNumber.ts create mode 100644 package.json create mode 100644 packages/eslint-config/basic.js create mode 100644 packages/eslint-config/next.js create mode 100644 packages/eslint-config/package.json create mode 100644 packages/fonts/ProductSans-Bold.ttf create mode 100644 packages/fonts/ProductSans-Bold.woff create mode 100644 packages/fonts/ProductSans-Bold.woff2 create mode 100644 packages/fonts/ProductSans-Regular.ttf create mode 100644 packages/fonts/ProductSans-Regular.woff create mode 100644 packages/fonts/ProductSans-Regular.woff2 create mode 100644 packages/fonts/SUIT-Bold.ttf create mode 100644 packages/fonts/SUIT-Bold.woff create mode 100644 packages/fonts/SUIT-Bold.woff2 create mode 100644 packages/fonts/SUIT-ExtraBold.ttf create mode 100644 packages/fonts/SUIT-ExtraBold.woff create mode 100644 packages/fonts/SUIT-ExtraBold.woff2 create mode 100644 packages/fonts/SUIT-ExtraLight.ttf create mode 100644 packages/fonts/SUIT-ExtraLight.woff create mode 100644 packages/fonts/SUIT-ExtraLight.woff2 create mode 100644 packages/fonts/SUIT-Heavy.ttf create mode 100644 packages/fonts/SUIT-Heavy.woff create mode 100644 packages/fonts/SUIT-Heavy.woff2 create mode 100644 packages/fonts/SUIT-Light.ttf create mode 100644 packages/fonts/SUIT-Light.woff create mode 100644 packages/fonts/SUIT-Light.woff2 create mode 100644 packages/fonts/SUIT-Medium.ttf create mode 100644 packages/fonts/SUIT-Medium.woff create mode 100644 packages/fonts/SUIT-Medium.woff2 create mode 100644 packages/fonts/SUIT-Regular.ttf create mode 100644 packages/fonts/SUIT-Regular.woff create mode 100644 packages/fonts/SUIT-Regular.woff2 create mode 100644 packages/fonts/SUIT-SemiBold.ttf create mode 100644 packages/fonts/SUIT-SemiBold.woff create mode 100644 packages/fonts/SUIT-SemiBold.woff2 create mode 100644 packages/fonts/SUIT-Thin.ttf create mode 100644 packages/fonts/SUIT-Thin.woff create mode 100644 packages/fonts/SUIT-Thin.woff2 create mode 100644 packages/fonts/index.css create mode 100644 packages/fonts/package.json create mode 100644 packages/panda-config/common-config.ts create mode 100644 packages/panda-config/package.json create mode 100644 packages/typescript-config/basic.json create mode 100644 packages/typescript-config/next.json create mode 100644 packages/typescript-config/package.json create mode 100644 packages/ui/.eslintrc.js create mode 100644 packages/ui/.storybook/main.ts create mode 100644 packages/ui/.storybook/preview.ts create mode 100644 packages/ui/package.json create mode 100644 packages/ui/panda.config.ts create mode 100644 packages/ui/postcss.config.cjs create mode 100644 packages/ui/src/assets/images/arrow.svg create mode 100644 packages/ui/src/assets/images/close.svg create mode 100644 packages/ui/src/assets/images/folder.svg create mode 100644 packages/ui/src/assets/images/home.svg create mode 100644 packages/ui/src/assets/images/logo.svg create mode 100644 packages/ui/src/components/Header/Header.stories.tsx create mode 100644 packages/ui/src/components/Header/index.tsx create mode 100644 packages/ui/src/components/Modal/Modal.stories.tsx create mode 100644 packages/ui/src/components/Modal/index.tsx create mode 100644 packages/ui/src/components/NavItem/NavItem.stories.tsx create mode 100644 packages/ui/src/components/NavItem/index.tsx create mode 100644 packages/ui/src/components/Space/index.tsx create mode 100644 packages/ui/src/components/Table/Table.stories.tsx create mode 100644 packages/ui/src/components/Table/index.tsx create mode 100644 packages/ui/src/components/Text/Text.stories.tsx create mode 100644 packages/ui/src/components/Text/index.tsx create mode 100644 packages/ui/src/components/index.ts create mode 100644 packages/ui/src/hooks/index.ts create mode 100644 packages/ui/src/hooks/useClickOutside.ts create mode 100644 packages/ui/src/hooks/useModalRoute.ts create mode 100644 packages/ui/src/hooks/useOpenState.ts create mode 100644 packages/ui/src/index.css create mode 100644 packages/ui/src/styles.css create mode 100644 packages/ui/src/types/svg.d.ts create mode 100644 packages/ui/styled-system/css/conditions.js create mode 100644 packages/ui/styled-system/css/conditions.mjs create mode 100644 packages/ui/styled-system/css/css.d.ts create mode 100644 packages/ui/styled-system/css/css.js create mode 100644 packages/ui/styled-system/css/css.mjs create mode 100644 packages/ui/styled-system/css/cva.d.ts create mode 100644 packages/ui/styled-system/css/cva.js create mode 100644 packages/ui/styled-system/css/cva.mjs create mode 100644 packages/ui/styled-system/css/cx.d.ts create mode 100644 packages/ui/styled-system/css/cx.js create mode 100644 packages/ui/styled-system/css/cx.mjs create mode 100644 packages/ui/styled-system/css/index.d.ts create mode 100644 packages/ui/styled-system/css/index.js create mode 100644 packages/ui/styled-system/css/index.mjs create mode 100644 packages/ui/styled-system/css/sva.d.ts create mode 100644 packages/ui/styled-system/css/sva.js create mode 100644 packages/ui/styled-system/css/sva.mjs create mode 100644 packages/ui/styled-system/helpers.js create mode 100644 packages/ui/styled-system/helpers.mjs create mode 100644 packages/ui/styled-system/jsx/aspect-ratio.d.ts create mode 100644 packages/ui/styled-system/jsx/aspect-ratio.js create mode 100644 packages/ui/styled-system/jsx/bleed.d.ts create mode 100644 packages/ui/styled-system/jsx/bleed.js create mode 100644 packages/ui/styled-system/jsx/box.d.ts create mode 100644 packages/ui/styled-system/jsx/box.js create mode 100644 packages/ui/styled-system/jsx/center.d.ts create mode 100644 packages/ui/styled-system/jsx/center.js create mode 100644 packages/ui/styled-system/jsx/circle.d.ts create mode 100644 packages/ui/styled-system/jsx/circle.js create mode 100644 packages/ui/styled-system/jsx/container.d.ts create mode 100644 packages/ui/styled-system/jsx/container.js create mode 100644 packages/ui/styled-system/jsx/cq.d.ts create mode 100644 packages/ui/styled-system/jsx/cq.js create mode 100644 packages/ui/styled-system/jsx/divider.d.ts create mode 100644 packages/ui/styled-system/jsx/divider.js create mode 100644 packages/ui/styled-system/jsx/factory-helper.js create mode 100644 packages/ui/styled-system/jsx/factory.d.ts create mode 100644 packages/ui/styled-system/jsx/factory.js create mode 100644 packages/ui/styled-system/jsx/flex.d.ts create mode 100644 packages/ui/styled-system/jsx/flex.js create mode 100644 packages/ui/styled-system/jsx/float.d.ts create mode 100644 packages/ui/styled-system/jsx/float.js create mode 100644 packages/ui/styled-system/jsx/grid-item.d.ts create mode 100644 packages/ui/styled-system/jsx/grid-item.js create mode 100644 packages/ui/styled-system/jsx/grid.d.ts create mode 100644 packages/ui/styled-system/jsx/grid.js create mode 100644 packages/ui/styled-system/jsx/hstack.d.ts create mode 100644 packages/ui/styled-system/jsx/hstack.js create mode 100644 packages/ui/styled-system/jsx/index.d.ts create mode 100644 packages/ui/styled-system/jsx/index.js create mode 100644 packages/ui/styled-system/jsx/is-valid-prop.d.ts create mode 100644 packages/ui/styled-system/jsx/is-valid-prop.js create mode 100644 packages/ui/styled-system/jsx/link-overlay.d.ts create mode 100644 packages/ui/styled-system/jsx/link-overlay.js create mode 100644 packages/ui/styled-system/jsx/spacer.d.ts create mode 100644 packages/ui/styled-system/jsx/spacer.js create mode 100644 packages/ui/styled-system/jsx/square.d.ts create mode 100644 packages/ui/styled-system/jsx/square.js create mode 100644 packages/ui/styled-system/jsx/stack.d.ts create mode 100644 packages/ui/styled-system/jsx/stack.js create mode 100644 packages/ui/styled-system/jsx/visually-hidden.d.ts create mode 100644 packages/ui/styled-system/jsx/visually-hidden.js create mode 100644 packages/ui/styled-system/jsx/vstack.d.ts create mode 100644 packages/ui/styled-system/jsx/vstack.js create mode 100644 packages/ui/styled-system/jsx/wrap.d.ts create mode 100644 packages/ui/styled-system/jsx/wrap.js create mode 100644 packages/ui/styled-system/patterns/aspect-ratio.d.ts create mode 100644 packages/ui/styled-system/patterns/aspect-ratio.js create mode 100644 packages/ui/styled-system/patterns/aspect-ratio.mjs create mode 100644 packages/ui/styled-system/patterns/bleed.d.ts create mode 100644 packages/ui/styled-system/patterns/bleed.js create mode 100644 packages/ui/styled-system/patterns/bleed.mjs create mode 100644 packages/ui/styled-system/patterns/box.d.ts create mode 100644 packages/ui/styled-system/patterns/box.js create mode 100644 packages/ui/styled-system/patterns/box.mjs create mode 100644 packages/ui/styled-system/patterns/center.d.ts create mode 100644 packages/ui/styled-system/patterns/center.js create mode 100644 packages/ui/styled-system/patterns/center.mjs create mode 100644 packages/ui/styled-system/patterns/circle.d.ts create mode 100644 packages/ui/styled-system/patterns/circle.js create mode 100644 packages/ui/styled-system/patterns/circle.mjs create mode 100644 packages/ui/styled-system/patterns/container.d.ts create mode 100644 packages/ui/styled-system/patterns/container.js create mode 100644 packages/ui/styled-system/patterns/container.mjs create mode 100644 packages/ui/styled-system/patterns/cq.d.ts create mode 100644 packages/ui/styled-system/patterns/cq.js create mode 100644 packages/ui/styled-system/patterns/cq.mjs create mode 100644 packages/ui/styled-system/patterns/divider.d.ts create mode 100644 packages/ui/styled-system/patterns/divider.js create mode 100644 packages/ui/styled-system/patterns/divider.mjs create mode 100644 packages/ui/styled-system/patterns/flex.d.ts create mode 100644 packages/ui/styled-system/patterns/flex.js create mode 100644 packages/ui/styled-system/patterns/flex.mjs create mode 100644 packages/ui/styled-system/patterns/float.d.ts create mode 100644 packages/ui/styled-system/patterns/float.js create mode 100644 packages/ui/styled-system/patterns/float.mjs create mode 100644 packages/ui/styled-system/patterns/grid-item.d.ts create mode 100644 packages/ui/styled-system/patterns/grid-item.js create mode 100644 packages/ui/styled-system/patterns/grid-item.mjs create mode 100644 packages/ui/styled-system/patterns/grid.d.ts create mode 100644 packages/ui/styled-system/patterns/grid.js create mode 100644 packages/ui/styled-system/patterns/grid.mjs create mode 100644 packages/ui/styled-system/patterns/hstack.d.ts create mode 100644 packages/ui/styled-system/patterns/hstack.js create mode 100644 packages/ui/styled-system/patterns/hstack.mjs create mode 100644 packages/ui/styled-system/patterns/index.d.ts create mode 100644 packages/ui/styled-system/patterns/index.js create mode 100644 packages/ui/styled-system/patterns/index.mjs create mode 100644 packages/ui/styled-system/patterns/link-overlay.d.ts create mode 100644 packages/ui/styled-system/patterns/link-overlay.js create mode 100644 packages/ui/styled-system/patterns/link-overlay.mjs create mode 100644 packages/ui/styled-system/patterns/spacer.d.ts create mode 100644 packages/ui/styled-system/patterns/spacer.js create mode 100644 packages/ui/styled-system/patterns/spacer.mjs create mode 100644 packages/ui/styled-system/patterns/square.d.ts create mode 100644 packages/ui/styled-system/patterns/square.js create mode 100644 packages/ui/styled-system/patterns/square.mjs create mode 100644 packages/ui/styled-system/patterns/stack.d.ts create mode 100644 packages/ui/styled-system/patterns/stack.js create mode 100644 packages/ui/styled-system/patterns/stack.mjs create mode 100644 packages/ui/styled-system/patterns/visually-hidden.d.ts create mode 100644 packages/ui/styled-system/patterns/visually-hidden.js create mode 100644 packages/ui/styled-system/patterns/visually-hidden.mjs create mode 100644 packages/ui/styled-system/patterns/vstack.d.ts create mode 100644 packages/ui/styled-system/patterns/vstack.js create mode 100644 packages/ui/styled-system/patterns/vstack.mjs create mode 100644 packages/ui/styled-system/patterns/wrap.d.ts create mode 100644 packages/ui/styled-system/patterns/wrap.js create mode 100644 packages/ui/styled-system/patterns/wrap.mjs create mode 100644 packages/ui/styled-system/tokens/index.d.ts create mode 100644 packages/ui/styled-system/tokens/index.js create mode 100644 packages/ui/styled-system/tokens/index.mjs create mode 100644 packages/ui/styled-system/tokens/tokens.d.ts create mode 100644 packages/ui/styled-system/types/composition.d.ts create mode 100644 packages/ui/styled-system/types/conditions.d.ts create mode 100644 packages/ui/styled-system/types/csstype.d.ts create mode 100644 packages/ui/styled-system/types/global.d.ts create mode 100644 packages/ui/styled-system/types/index.d.ts create mode 100644 packages/ui/styled-system/types/jsx.d.ts create mode 100644 packages/ui/styled-system/types/parts.d.ts create mode 100644 packages/ui/styled-system/types/pattern.d.ts create mode 100644 packages/ui/styled-system/types/prop-type.d.ts create mode 100644 packages/ui/styled-system/types/recipe.d.ts create mode 100644 packages/ui/styled-system/types/selectors.d.ts create mode 100644 packages/ui/styled-system/types/static-css.d.ts create mode 100644 packages/ui/styled-system/types/style-props.d.ts create mode 100644 packages/ui/styled-system/types/system-types.d.ts create mode 100644 packages/ui/tsconfig.json create mode 100644 packages/ui/turbo/generators/config.ts create mode 100644 packages/ui/turbo/generators/templates/component.hbs create mode 100644 packages/ui/turbo/generators/templates/storybook.hbs create mode 100644 packages/utils/.eslintrc.js create mode 100644 packages/utils/jest.config.cjs create mode 100644 packages/utils/jest.setup.ts create mode 100644 packages/utils/package.json create mode 100644 packages/utils/src/fetcher/fetcher.test.ts create mode 100644 packages/utils/src/fetcher/index.ts create mode 100644 packages/utils/src/formatDate.ts create mode 100644 packages/utils/src/formatTime.ts create mode 100644 packages/utils/src/index.ts create mode 100644 packages/utils/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 turbo.json diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..3b0fc39c --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +# .eslintignore +packages/panda-config/ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..d96a5b1e --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @ghdtjgus76 @eugene028 @hamo-o @SeieunYoo \ No newline at end of file diff --git a/.github/workflows/auto_assign.yml b/.github/workflows/auto_assign.yml new file mode 100644 index 00000000..29134e24 --- /dev/null +++ b/.github/workflows/auto_assign.yml @@ -0,0 +1,27 @@ +name: Auto Assign + +on: + pull_request: + types: [opened, ready_for_review, converted_to_draft] + issues: + types: [opened] + +jobs: + assign_pull_request: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - uses: hkusu/review-assign-action@v1 + with: + assignees: ${{ github.actor }} + + auto_assign_issue: + runs-on: ubuntu-latest + if: github.event_name == 'issues' + permissions: + issues: write + steps: + - name: "Auto-assign issue" + uses: pozil/auto-assign-issue@v2 + with: + assignees: ${{ github.actor }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..79f73e92 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,40 @@ +name: build + +on: + push: + branches: + - main + - dev + pull_request: + types: [opened, ready_for_review, converted_to_draft, synchronize] + branches: + - main + - dev + +jobs: + build: + runs-on: ubuntu-latest + env: + TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} + TURBO_TEAM: ${{ vars.TURBO_TEAM }} + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Node.js 20.x + uses: actions/setup-node@v2 + with: + node-version: 20.x + + - name: Install pnpm + uses: pnpm/action-setup@v3 + with: + version: 8 + run_install: false + + - name: Install dependencies + run: pnpm install --no-frozen-lockfile + + - name: Run build + run: pnpm run build diff --git a/.github/workflows/deploy-chromatic.yml b/.github/workflows/deploy-chromatic.yml new file mode 100644 index 00000000..22ab17a5 --- /dev/null +++ b/.github/workflows/deploy-chromatic.yml @@ -0,0 +1,54 @@ +name: "deploy-chromatic" + +on: + pull_request: + branches: + - dev + paths: + - packages/ui/src/** + +jobs: + chromatic-deployment: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: 20.x + + - name: Cache Dependencies + uses: actions/cache@v2 + with: + path: ~/.pnpm-store + key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm- + + - name: Install pnpm + uses: pnpm/action-setup@v3 + with: + version: 8 + run_install: false + + - name: Install Dependencies + run: pnpm install --no-frozen-lockfile + working-directory: packages/ui + + - name: Publish Chromatic + id: chromatic + uses: chromaui/action@v1 + with: + workingDir: packages/ui/src + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + token: ${{ secrets.TOKEN }} + + - name: Create comment PR + uses: thollander/actions-comment-pull-request@v1 + env: + GITHUB_TOKEN: ${{ secrets.TOKEN }} + with: + message: "🚀 storybook: ${{ steps.chromatic.outputs.storybookUrl }}" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2ba88bc2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# Dependencies +node_modules +.pnp +.pnp.js + +# Local env files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Testing +coverage + +# Turbo +.turbo + +# Vercel +.vercel + +# Build Outputs +.next/ +out/ +build +dist + + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Misc +.DS_Store +*.pem +*storybook.log \ No newline at end of file diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 00000000..dde57c8f --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,14 @@ +message="$(cat $1)" +requiredPattern="^(feat|fix|refactor|rename|chore|docs|design):.*$" +if ! [[ $message =~ $requiredPattern ]]; +then + echo "==========================================================================" + echo "================= 🚨 커밋 메시지를 수정해 주세요 🚨 ==================" + echo "==========================================================================" + echo "== 커밋 컨벤션 ⏩ [prefix]: [작업 내용] ==" + echo "== 허용되는 접두사 ⏩ feat, fix, refactor, chore, rename, design, docs ==" + echo "== 예시 ⏩ feat: Google login ==" + echo "==========================================================================" + echo "==========================================================================" + exit 1 +fi \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000..dff836df --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +pnpm exec lint-staged \ No newline at end of file diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100644 index 00000000..1688382e --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1 @@ +pnpm codegen:build \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..e69de29b diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..5acb4c91 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +*.hbs \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..f9c527d4 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "useTabs": false, + "trailingComma": "es5", + "printWidth": 80, + "arrowParens": "always", +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..8a5fd2a3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit", + "source.fixAll.stylelint": "explicit" + }, + "eslint.workingDirectories": [ + { + "mode": "auto" + } + ], + "typescript.tsdk": "node_modules/typescript/lib", + "editor.defaultFormatter": "esbenp.prettier-vscode" +} diff --git a/README.md b/README.md new file mode 100644 index 00000000..7a4658aa --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# Turborepo starter + +This is an official starter Turborepo. + +## Using this example + +Run the following command: + +```sh +npx create-turbo@latest +``` + +## What's inside? + +This Turborepo includes the following packages/apps: + +### Apps and Packages + +- `docs`: a [Next.js](https://nextjs.org/) app +- `web`: another [Next.js](https://nextjs.org/) app +- `@repo/ui`: a stub React component library shared by both `web` and `docs` applications +- `@repo/eslint-config`: `eslint` configurations (includes `eslint-config-next` and `eslint-config-prettier`) +- `@repo/typescript-config`: `tsconfig.json`s used throughout the monorepo + +Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). + +### Utilities + +This Turborepo has some additional tools already setup for you: + +- [TypeScript](https://www.typescriptlang.org/) for static type checking +- [ESLint](https://eslint.org/) for code linting +- [Prettier](https://prettier.io) for code formatting + +### Build + +To build all apps and packages, run the following command: + +``` +cd my-turborepo +pnpm build +``` + +### Develop + +To develop all apps and packages, run the following command: + +``` +cd my-turborepo +pnpm dev +``` + +### Remote Caching + +Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. + +By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup), then enter the following commands: + +``` +cd my-turborepo +npx turbo login +``` + +This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). + +Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo: + +``` +npx turbo link +``` + +## Useful Links + +Learn more about the power of Turborepo: + +- [Tasks](https://turbo.build/repo/docs/core-concepts/monorepos/running-tasks) +- [Caching](https://turbo.build/repo/docs/core-concepts/caching) +- [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) +- [Filtering](https://turbo.build/repo/docs/core-concepts/monorepos/filtering) +- [Configuration Options](https://turbo.build/repo/docs/reference/configuration) +- [CLI Usage](https://turbo.build/repo/docs/reference/command-line-reference) diff --git a/apps/admin/.eslintrc.js b/apps/admin/.eslintrc.js new file mode 100644 index 00000000..42f861d6 --- /dev/null +++ b/apps/admin/.eslintrc.js @@ -0,0 +1,9 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + root: true, + extends: ["@wow-class/eslint-config/next.js"], + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, + }, +}; diff --git a/apps/admin/.gitignore b/apps/admin/.gitignore new file mode 100644 index 00000000..f206ea41 --- /dev/null +++ b/apps/admin/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# env files (can opt-in for commiting if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts \ No newline at end of file diff --git a/apps/admin/README.md b/apps/admin/README.md new file mode 100644 index 00000000..a98bfa81 --- /dev/null +++ b/apps/admin/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/apps/admin/apis/auth/dashboardApi.ts b/apps/admin/apis/auth/dashboardApi.ts new file mode 100644 index 00000000..2e42a4ba --- /dev/null +++ b/apps/admin/apis/auth/dashboardApi.ts @@ -0,0 +1,32 @@ +import { fetcher } from "@wow-class/utils"; +import { apiPath, mentorApiPath } from "constants/apiPath"; +import { tags } from "constants/tags"; +import type { DashboardApiResponseDto } from "types/dtos/auth"; +import type { MyStudyListApiResponseDto } from "types/dtos/studyList"; + +export const dashboardApi = { + getDashboardInfo: async () => { + const response = await fetcher.get( + apiPath.dashboard, + { + next: { tags: [tags.dashboard] }, + cache: "no-store", + } + ); + + const studyRole = response.data?.member.studyRole; + const manageRole = response.data?.member.manageRole; + + return { studyRole, manageRole }; + }, + getMyStudyList: async () => { + const response = await fetcher.get( + mentorApiPath.studyList, + { + next: { tags: [tags.dashboard] }, + cache: "force-cache", + } + ); + return response.data; + }, +}; diff --git a/apps/admin/apis/study/createStudyApi.ts b/apps/admin/apis/study/createStudyApi.ts new file mode 100644 index 00000000..1f57e3d0 --- /dev/null +++ b/apps/admin/apis/study/createStudyApi.ts @@ -0,0 +1,36 @@ +import { fetcher } from "@wow-class/utils"; +import { apiPath } from "constants/apiPath"; +import { tags } from "constants/tags"; +import type { CreateStudyApiRequestDto } from "types/dtos/createStudy"; +import type { SearchStudyMentorResponseDto } from "types/dtos/searchStudyMentor"; +import type { CreateStudyDetailInfoApiRequestDto } from "types/dtos/studyDetailInfo"; + +export const createStudyApi = { + postCreateStudy: async (data: CreateStudyApiRequestDto) => { + const response = await fetcher.post(apiPath.createStudy, data); + + return { success: response.ok }; + }, + postStudyDetailInfo: async ( + data: CreateStudyDetailInfoApiRequestDto, + studyId: number + ) => { + const response = await fetcher.patch( + `${apiPath.createStudyDetailInfo}/${studyId}`, + data + ); + return { success: response.ok }; + }, + searchStudyMentor: async ( + name: string + ): Promise => { + const response = await fetcher.get( + `${apiPath.searchMentor}?name=${name}&roles=REGULAR`, + { + next: { tags: [tags.memberList] }, + cache: "force-cache", + } + ); + return response.data.content; + }, +}; diff --git a/apps/admin/apis/study/studyApi.ts b/apps/admin/apis/study/studyApi.ts new file mode 100644 index 00000000..c849ed96 --- /dev/null +++ b/apps/admin/apis/study/studyApi.ts @@ -0,0 +1,141 @@ +import { fetcher } from "@wow-class/utils"; +import { apiPath, mentorApiPath } from "constants/apiPath"; +import { tags } from "constants/tags"; +import type { AnnouncementApiResponseDto } from "types/dtos/announcement"; +import type { + AssignmentApiRequestDto, + AssignmentApiResponseDto, +} from "types/dtos/assignmentList"; +import type { AttendanceApiResponseDto } from "types/dtos/attendance"; +import type { CurriculumApiResponseDto } from "types/dtos/curriculumList"; +import type { StudyBasicInfoApiResponseDto } from "types/dtos/studyBasicInfo"; +import type { StudyAnnouncementType } from "types/entities/study"; + +import type { StudyListApiResponseDto } from "../../types/dtos/studyList"; + +export const studyApi = { + getStudyList: async () => { + const response = await fetcher.get( + apiPath.studyList, + { + next: { tags: [tags.studyList] }, + } + ); + + return response.data; + }, + getStudyBasicInfo: async (studyId: number) => { + const response = await fetcher.get( + `/common/studies/${studyId}`, + { + next: { tags: [tags.studyBasicInfo] }, + cache: "force-cache", + } + ); + return response.data; + }, + getAssignmentList: async (studyId: number) => { + const response = await fetcher.get( + `${mentorApiPath.assignments}?studyId=${studyId}`, + { + next: { tags: [tags.assignments] }, + cache: "force-cache", + } + ); + return response.data; + }, + getAssignment: async (studyDetailId: number) => { + const response = await fetcher.get( + `/mentor/study-details/${studyDetailId}/assignments`, + { + next: { tags: [`${tags.assignments} ${studyDetailId}`] }, + cache: "force-cache", + } + ); + return response.data; + }, + createAssignment: async ( + studyDetailId: number, + data: AssignmentApiRequestDto + ) => { + const response = await fetcher.put( + `/mentor/study-details/${studyDetailId}/assignments`, + data + ); + return { success: response.ok }; + }, + patchAssignment: async ( + studyDetailId: number, + data: AssignmentApiRequestDto + ) => { + const response = await fetcher.patch( + `/mentor/study-details/${studyDetailId}/assignments`, + data + ); + return { success: response.ok }; + }, + cancelAssignment: async (studyDetailId: number) => { + const response = await fetcher.patch( + `/mentor/study-details/${studyDetailId}/assignments/cancel`, + {} + ); + + return { success: response.ok }; + }, + getCurriculumList: async (studyId: number) => { + const response = await fetcher.get( + `${mentorApiPath.curriculums}?studyId=${studyId}`, + { + next: { tags: [tags.curriculums] }, + cache: "force-cache", + } + ); + return response.data; + }, + publishStudyAnnouncement: async ( + studyId: number, + announcement: StudyAnnouncementType + ) => { + const response = await fetcher.post( + `/mentor/studies/${studyId}/announcements`, + announcement + ); + return { success: response.ok }; + }, + getStudyAnnouncement: async (studyId: number) => { + const response = await fetcher.get( + `/common/studies/${studyId}/announcements`, + { + next: { tags: [tags.announcements] }, + cache: "force-cache", + } + ); + return response.data; + }, + modifyStudyAnnouncement: async ( + studyAnnouncementId: number, + announcement: StudyAnnouncementType + ) => { + const response = await fetcher.put( + `/mentor/studies/announcements/${studyAnnouncementId}`, + announcement + ); + return { success: response.ok }; + }, + deleteStudyAnnouncement: async (studyAnnouncementId: number) => { + const response = await fetcher.delete( + `/mentor/studies/announcements/${studyAnnouncementId}` + ); + return { success: response.ok }; + }, + getStudyAttendances: async (studyId: number) => { + const response = await fetcher.get( + `/mentor/study-details/attendances?studyId=${studyId}`, + { + next: { tags: [tags.attendances] }, + cache: "force-cache", + } + ); + return response.data; + }, +}; diff --git a/apps/admin/app/@modal/(.)participants/page.tsx b/apps/admin/app/@modal/(.)participants/page.tsx new file mode 100644 index 00000000..b90748d3 --- /dev/null +++ b/apps/admin/app/@modal/(.)participants/page.tsx @@ -0,0 +1,23 @@ +"use client"; + +import { Flex } from "@styled-system/jsx"; +import { Modal } from "@wow-class/ui"; +import { useModalRoute } from "@wow-class/ui/hooks"; +import Button from "wowds-ui/Button"; + +const TestModal = () => { + const { onClose } = useModalRoute(); + + return ( + + + + + + + ); +}; + +export default TestModal; diff --git a/apps/admin/app/@modal/default.tsx b/apps/admin/app/@modal/default.tsx new file mode 100644 index 00000000..395785b9 --- /dev/null +++ b/apps/admin/app/@modal/default.tsx @@ -0,0 +1,5 @@ +const Default = () => { + return null; +}; + +export default Default; diff --git a/apps/admin/app/error.tsx b/apps/admin/app/error.tsx new file mode 100644 index 00000000..c97d1030 --- /dev/null +++ b/apps/admin/app/error.tsx @@ -0,0 +1,47 @@ +"use client"; + +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Header, Text } from "@wow-class/ui"; +import Image from "next/image"; +import Button from "wowds-ui/Button"; + +const ErrorPage = ({ reset }: { reset: () => void }) => { + const handleClickResetButton = () => { + reset(); + }; + + return ( + +
+
+ error + + 에러가 발생했어요 + + +
+ + ); +}; + +export default ErrorPage; + +const errorPageContentStyle = css({ + display: "flex", + flexDirection: "column", + justifyContent: "center", + alignItems: "center", + gap: "48px", + height: "100%", +}); + +const buttonStyle = { + maxWidth: 328, +}; diff --git a/apps/admin/app/global.css b/apps/admin/app/global.css new file mode 100644 index 00000000..1fa83117 --- /dev/null +++ b/apps/admin/app/global.css @@ -0,0 +1,13 @@ +@layer reset, base, tokens, recipes, utilities; +@import url("@wow-class/ui/styles.css"); +@import url("@wow-class/fonts/index.css"); + +body { + font-family: "SUIT" !important; + display: flex; + flex-direction: row; + min-height: 100vh; +} +::-webkit-scrollbar { + display: none; +} diff --git a/apps/admin/app/layout.tsx b/apps/admin/app/layout.tsx new file mode 100644 index 00000000..2129b180 --- /dev/null +++ b/apps/admin/app/layout.tsx @@ -0,0 +1,59 @@ +import "./global.css"; +import "wowds-ui/styles.css"; +import "@wow-class/ui/styles.css"; + +import { JotaiProvider } from "components/JotaiProvider"; +import type { Metadata } from "next"; +import type { ReactNode } from "react"; + +export const metadata: Metadata = { + title: { + default: "와우 클래스: 멘토 | GDSC Hongik 스터디 서비스", + template: "%s | 와우클래스 멘토", + }, + description: "와우클래스는 GDSC Hongik이 제공하는 스터디 관리 플랫폼입니다.", + openGraph: { + title: "와우 클래스: 멘토 | GDSC Hongik 스터디 서비스", + description: + "와우클래스는 GDSC Hongik이 제공하는 스터디 관리 플랫폼입니다.", + images: ["/images/og-image.png"], + siteName: "와우 클래스: 멘토 | GDSC Hongik 스터디 서비스", + type: "website", + }, + robots: { + index: false, + follow: false, + }, + icons: { + icon: "/images/logo.svg", + apple: "/images/logo.svg", + other: [ + { + rel: "icon", + type: "image/svg+xml", + url: "/images/logo.svg", + }, + ], + }, +}; + +const RootLayout = ({ + children, + modal, +}: Readonly<{ + children: ReactNode; + modal: ReactNode; +}>) => { + return ( + + + + {children} + {modal} + + + + ); +}; + +export default RootLayout; diff --git a/apps/admin/app/not-found.tsx b/apps/admin/app/not-found.tsx new file mode 100644 index 00000000..22d43769 --- /dev/null +++ b/apps/admin/app/not-found.tsx @@ -0,0 +1,54 @@ +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Header, Text } from "@wow-class/ui"; +import { routerPath } from "constants/router/routerPath"; +import Image from "next/image"; +import Link from "next/link"; +import Button from "wowds-ui/Button"; + +const NotFoundPage = () => { + return ( + +
+
+ not-found + + + 오류가 발생했어요 + + + 요청하신 페이지를 찾을 수 없어요 + + + +
+ + ); +}; + +export default NotFoundPage; + +const notFoundPageContentStyle = css({ + display: "flex", + flexDirection: "column", + justifyContent: "center", + alignItems: "center", + gap: "48px", + height: "100%", +}); + +const buttonStyle = { + maxWidth: 328, +}; diff --git a/apps/admin/app/page.tsx b/apps/admin/app/page.tsx new file mode 100644 index 00000000..5fd1edf4 --- /dev/null +++ b/apps/admin/app/page.tsx @@ -0,0 +1,17 @@ +import { styled } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; + +const Home = () => { + return ( +
+ Home + sdf + sdf + + 헤딩1 + +
+ ); +}; + +export default Home; diff --git a/apps/admin/app/participants/page.tsx b/apps/admin/app/participants/page.tsx new file mode 100644 index 00000000..19a3c50b --- /dev/null +++ b/apps/admin/app/participants/page.tsx @@ -0,0 +1,5 @@ +const Participants = () => { + return
Participants
; +}; + +export default Participants; diff --git a/apps/admin/app/studies/[studyId]/@modal/(.)announcement-delete/page.tsx b/apps/admin/app/studies/[studyId]/@modal/(.)announcement-delete/page.tsx new file mode 100644 index 00000000..720b7f40 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/@modal/(.)announcement-delete/page.tsx @@ -0,0 +1,46 @@ +"use client"; + +import { Flex } from "@styled-system/jsx"; +import { Modal, Space, Text } from "@wow-class/ui"; +import { useModalRoute } from "@wow-class/ui/hooks"; +import { studyApi } from "apis/study/studyApi"; +import { tags } from "constants/tags"; +import { useSearchParams } from "next/navigation"; +import { revalidateTagByName } from "utils/revalidateTagByName"; +import Button from "wowds-ui/Button"; + +const AnnouncementDeleteModal = () => { + const searchParams = useSearchParams(); + + const studyAnnouncementId = searchParams.get("studyAnnouncementId"); + + const { onClose } = useModalRoute(); + + const handleClickDeleteButton = async () => { + const result = await studyApi.deleteStudyAnnouncement( + Number(studyAnnouncementId) + ); + if (result.success) { + await revalidateTagByName(tags.announcements); + onClose(); + } + }; + + return ( + + + 공지를 삭제하시겠어요? + + + + + + + + + ); +}; + +export default AnnouncementDeleteModal; diff --git a/apps/admin/app/studies/[studyId]/@modal/(.)announcement-modify/page.tsx b/apps/admin/app/studies/[studyId]/@modal/(.)announcement-modify/page.tsx new file mode 100644 index 00000000..8b69beeb --- /dev/null +++ b/apps/admin/app/studies/[studyId]/@modal/(.)announcement-modify/page.tsx @@ -0,0 +1,156 @@ +"use client"; + +import { css, cva } from "@styled-system/css"; +import { Flex, styled } from "@styled-system/jsx"; +import { Modal, Space, Text } from "@wow-class/ui"; +import { useModalRoute } from "@wow-class/ui/hooks"; +import { studyApi } from "apis/study/studyApi"; +import { tags } from "constants/tags"; +import { useSearchParams } from "next/navigation"; +import { useEffect, useState } from "react"; +import type { StudyAnnouncementType } from "types/entities/study"; +import { revalidateTagByName } from "utils/revalidateTagByName"; +import Button from "wowds-ui/Button"; + +import usePrefillAnnouncement from "../../hooks/usePrefillAnnouncement"; + +const AnnouncementModifyModal = ({ + params, +}: { + params: { studyId: string }; +}) => { + const searchParams = useSearchParams(); + const { studyId } = params; + const studyAnnouncementId = Number(searchParams.get("studyAnnouncementId")); + const prefillData = usePrefillAnnouncement( + Number(studyId), + studyAnnouncementId + ); + const [studyAnnouncement, setStudyAnnouncement] = + useState({ title: "", link: "" }); + + useEffect(() => { + setStudyAnnouncement(prefillData); + }, [prefillData]); + const { onClose } = useModalRoute(); + const handleClickModifyButton = async () => { + const result = await studyApi.modifyStudyAnnouncement( + studyAnnouncementId, + studyAnnouncement + ); + if (result.success) { + await revalidateTagByName(tags.announcements); + onClose(); + } + }; + + return ( + + + 공지를 수정해주세요 + + + + 공지 제목 + 0 ? "typed" : "default", + })} + onChange={(e) => { + setStudyAnnouncement({ + ...studyAnnouncement, + title: e.target.value, + }); + }} + /> + + + 공지 링크 + 0 ? "typed" : "default", + })} + onChange={(e) => { + setStudyAnnouncement({ + ...studyAnnouncement, + link: e.target.value, + }); + }} + /> + + + + + + + + + + ); +}; + +export default AnnouncementModifyModal; + +const labelStyle = css({ + display: "flex", + justifyContent: "space-between", + alignItems: "center", + textStyle: "label2", + color: "sub", +}); + +const textareaStyle = cva({ + base: { + borderRadius: "sm", + borderWidth: "button", + borderStyle: "solid", + paddingX: "sm", + paddingY: "xs", + textStyle: "body1", + height: "2.625rem", + maxHeight: "7.5rem", + overflowY: "hidden", + resize: "none", + backgroundColor: "backgroundNormal", + _placeholder: { + color: "outline", + }, + _focus: { + outline: "none", + borderColor: "primary", + }, + _scrollbar: { + width: "2px", + }, + _scrollbarThumb: { + width: "2px", + height: "65px", + borderRadius: "sm", + backgroundColor: "outline", + }, + _scrollbarTrack: { + marginTop: "2px", + marginBottom: "2px", + }, + }, + variants: { + type: { + default: { + borderColor: "outline", + color: "outline", + }, + typed: { + borderColor: "sub", + color: "textBlack", + }, + }, + }, +}); diff --git a/apps/admin/app/studies/[studyId]/@modal/default.tsx b/apps/admin/app/studies/[studyId]/@modal/default.tsx new file mode 100644 index 00000000..395785b9 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/@modal/default.tsx @@ -0,0 +1,5 @@ +const Default = () => { + return null; +}; + +export default Default; diff --git a/apps/admin/app/studies/[studyId]/_components/announcement/CreateStudyAnnouncement.tsx b/apps/admin/app/studies/[studyId]/_components/announcement/CreateStudyAnnouncement.tsx new file mode 100644 index 00000000..00a152a1 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/announcement/CreateStudyAnnouncement.tsx @@ -0,0 +1,158 @@ +"use client"; + +import { css, cva } from "@styled-system/css"; +import { Flex, styled } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { studyApi } from "apis/study/studyApi"; +import { tags } from "constants/tags"; +import { useState } from "react"; +import type { StudyAnnouncementType } from "types/entities/study"; +import { revalidateTagByName } from "utils/revalidateTagByName"; +import Button from "wowds-ui/Button"; + +const CreateStudyAnnouncement = ({ studyId }: { studyId: string }) => { + const [studyAnnouncement, setStudyAnnouncement] = + useState({ + title: "", + link: "", + }); + + const handlePublishAnnouncement = async (studyId: string) => { + const { success } = await studyApi.publishStudyAnnouncement( + parseInt(studyId, 10), + studyAnnouncement + ); + if (success) { + revalidateTagByName(tags.announcements); + setStudyAnnouncement({ + title: "", + link: "", + }); + } else { + console.log("공지 생성 실패"); + } + }; + return ( +
+ 공지를 작성해주세요. + + + + 공지 제목 + 0 ? "typed" : "default", + })} + onChange={(e) => { + setStudyAnnouncement({ + ...studyAnnouncement, + title: e.target.value, + }); + }} + /> + + + 공지 링크 + 0 ? "typed" : "default", + })} + onChange={(e) => { + setStudyAnnouncement({ + ...studyAnnouncement, + link: e.target.value, + }); + }} + /> + + + + +
+ ); +}; + +export default CreateStudyAnnouncement; + +const StudyAnnouncementBoxStyle = css({ + width: "100%", + minHeight: "171px", + backgroundColor: "backgroundAlternative", + borderRadius: "md", + display: "flex", + flexDirection: "column", + gap: "24px", + padding: "30px", +}); + +const labelStyle = css({ + display: "flex", + justifyContent: "space-between", + alignItems: "center", + textStyle: "label2", + color: "sub", +}); + +const textareaStyle = cva({ + base: { + borderRadius: "sm", + borderWidth: "button", + borderStyle: "solid", + paddingX: "sm", + paddingY: "xs", + textStyle: "body1", + height: "2.625rem", + maxHeight: "7.5rem", + overflowY: "hidden", + resize: "none", + backgroundColor: "backgroundNormal", + _placeholder: { + color: "outline", + }, + _focus: { + outline: "none", + borderColor: "primary", + }, + _scrollbar: { + width: "2px", + }, + _scrollbarThumb: { + width: "2px", + height: "65px", + borderRadius: "sm", + backgroundColor: "outline", + }, + _scrollbarTrack: { + marginTop: "2px", + marginBottom: "2px", + }, + }, + variants: { + type: { + default: { + borderColor: "outline", + color: "outline", + }, + typed: { + borderColor: "sub", + color: "textBlack", + }, + }, + }, +}); diff --git a/apps/admin/app/studies/[studyId]/_components/announcement/StudyAnnouncement.tsx b/apps/admin/app/studies/[studyId]/_components/announcement/StudyAnnouncement.tsx new file mode 100644 index 00000000..8163d7ac --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/announcement/StudyAnnouncement.tsx @@ -0,0 +1,122 @@ +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Space, Table, Text } from "@wow-class/ui"; +import { studyApi } from "apis/study/studyApi"; +import { routerPath } from "constants/router/routerPath"; +import Image from "next/image"; +import Link from "next/link"; +import { space } from "wowds-tokens"; +import Button from "wowds-ui/Button"; +import TextButton from "wowds-ui/TextButton"; + +import CreateStudyAnnouncement from "./CreateStudyAnnouncement"; + +const StudyAnnouncement = async ({ studyId }: { studyId: string }) => { + const announcementList = await studyApi.getStudyAnnouncement( + parseInt(studyId, 10) + ); + + return ( +
+ 스터디 공지 + + + {!announcementList ? null : ( + <> + {announcementList?.map( + ({ studyAnnounceId, title, link, createdDate }, index) => { + return ( + + + + + {title} + + + + + + + + {createdDate.replaceAll("-", ".")} + + + + + + + + + + + + + + +
+ ); + } + )} + + )} +
+ ); +}; + +export default StudyAnnouncement; + +const textButtonStyle = { + padding: `${space.sm} 0`, +}; + +const linkStyle = css({ + display: "flex", + alignItems: "center", + cursor: "pointer", + gap: "4px", + flex: 2, +}); diff --git a/apps/admin/app/studies/[studyId]/_components/assignment/AssignmentButtons.tsx b/apps/admin/app/studies/[studyId]/_components/assignment/AssignmentButtons.tsx new file mode 100644 index 00000000..166b45b6 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/assignment/AssignmentButtons.tsx @@ -0,0 +1,72 @@ +"use client"; +import { Flex } from "@styled-system/jsx"; +import { studyApi } from "apis/study/studyApi"; +import { routerPath } from "constants/router/routerPath"; +import { tags } from "constants/tags"; +import Link from "next/link"; +import type { StudyAssignmentStatusType } from "types/entities/study"; +import { revalidateTagByName } from "utils/revalidateTagByName"; +import Button from "wowds-ui/Button"; + +const AssignmentButtons = ({ + studyDetailId, + assignmentStatus, +}: { + studyDetailId: number; + assignmentStatus: StudyAssignmentStatusType; +}) => { + const handleCancelAssignment = async () => { + const { success } = await studyApi.cancelAssignment(studyDetailId); + if (success) { + console.log("휴강 처리에 성공했어요."); + revalidateTagByName(tags.assignments); + revalidateTagByName(`${tags.assignments} ${studyDetailId}`); + } else { + console.log("휴강 처리에 실패했어요."); + } + }; + + if (assignmentStatus === "OPEN") { + return ( + + ); + } + + if (assignmentStatus === "CANCELLED") { + return ( + + + + + ); + } + + return ( + + + + + ); +}; + +export default AssignmentButtons; diff --git a/apps/admin/app/studies/[studyId]/_components/assignment/AssignmentList.tsx b/apps/admin/app/studies/[studyId]/_components/assignment/AssignmentList.tsx new file mode 100644 index 00000000..6f813399 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/assignment/AssignmentList.tsx @@ -0,0 +1,30 @@ +import { Space, Text } from "@wow-class/ui"; +import { studyApi } from "apis/study/studyApi"; + +import AssignmentListItem from "./AssignmentListItem"; + +const AssignmentList = async ({ studyId }: { studyId: string }) => { + const assignmentList = await studyApi.getAssignmentList( + parseInt(studyId, 10) + ); + const study = await studyApi.getStudyBasicInfo(+studyId); + const studyStartDate = study?.period?.startDate; + + return ( +
+ 주차별 과제 + + {assignmentList?.map((assignment, index) => { + return ( + + ); + })} +
+ ); +}; + +export default AssignmentList; diff --git a/apps/admin/app/studies/[studyId]/_components/assignment/AssignmentListItem.tsx b/apps/admin/app/studies/[studyId]/_components/assignment/AssignmentListItem.tsx new file mode 100644 index 00000000..add0cd7b --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/assignment/AssignmentListItem.tsx @@ -0,0 +1,89 @@ +import { cva } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Table, Text } from "@wow-class/ui"; +import { padWithZero, parseISODate } from "@wow-class/utils"; +import type { AssignmentApiResponseDto } from "types/dtos/assignmentList"; +import getIsCurrentWeek from "utils/getIsCurrentWeek"; + +import AssignmentButtons from "./AssignmentButtons"; + +const AssignmentListItem = ({ + assignment, + studyStartDate, +}: { + assignment: AssignmentApiResponseDto; + studyStartDate?: string; +}) => { + const { studyDetailId, title, deadline, week, assignmentStatus } = assignment; + + const formatDateToEndString = (date: string | null) => { + if (!date) return "-"; + + const { year, month, day, hours, minutes } = parseISODate(date); + return `종료 : ${year}년 ${month}월 ${day}일 ${padWithZero(hours)}:${padWithZero(minutes)}`; + }; + + const thisWeekAssignment = + studyStartDate && getIsCurrentWeek(studyStartDate, week); + const studyDeadline = formatDateToEndString(deadline); + + return ( + + + +
+ {week}주차 + + + + {title || "-"} + + + {studyDeadline} + + + + + + +
+ ); +}; +export default AssignmentListItem; + +const ThisWeekBarStyle = cva({ + base: { + width: "4px", + height: "18px", + }, + variants: { + type: { + thisWeek: { + backgroundColor: "primary", + }, + notThisWeek: { + backgroundColor: "transparent", + }, + }, + }, +}); + +const TableLeftStyle = { + display: "flex", + alignItems: "center", + gap: "47px", +}; + +const AssignmentTitleStyle = { + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + maxWidth: "680px", +}; diff --git a/apps/admin/app/studies/[studyId]/_components/attendance/AttendanceItem.tsx b/apps/admin/app/studies/[studyId]/_components/attendance/AttendanceItem.tsx new file mode 100644 index 00000000..89f9d408 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/attendance/AttendanceItem.tsx @@ -0,0 +1,67 @@ +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { padWithZero, parseISODate } from "@wow-class/utils"; +import { attendanceStatusMap } from "constants/status/attendanceStatusMap"; +import type { AttendanceApiResponseDto } from "types/dtos/attendance"; +import Box from "wowds-ui/Box"; +import Tag from "wowds-ui/Tag"; + +const AttendanceItem = ({ + attendance, +}: { + attendance: AttendanceApiResponseDto; +}) => { + const { week, deadLine, attendanceNumber } = attendance; + const { year, month, day, hours, minutes } = parseISODate(deadLine); + + const getIsCurrentWeek = () => { + const diffInTime = new Date(deadLine).getTime() - new Date().getTime(); + const diffInDays = Math.floor(diffInTime / (1000 * 60 * 60 * 24)); + + return diffInDays < 7 ? "ONGOING_ATTENDANCE" : "BEFORE_ATTENDANCE"; + }; + + const state = getIsCurrentWeek(); + const { label, color } = attendanceStatusMap[state]; + + return ( + + + {week}주차 출결번호 + + {label} + + + + {year}년 {month}월 {day}일 00:00 - {padWithZero(hours)}: + {padWithZero(minutes)}까지 + + + {attendanceNumber} + + + } + /> + ); +}; + +export default AttendanceItem; + +const AttendanceBoxStyle = { + width: "282px", +}; + +const AttendanceNumberStyle = { + fontSize: "40px", + fontWeight: 700, +}; diff --git a/apps/admin/app/studies/[studyId]/_components/attendance/AttendanceList.tsx b/apps/admin/app/studies/[studyId]/_components/attendance/AttendanceList.tsx new file mode 100644 index 00000000..d036c363 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/attendance/AttendanceList.tsx @@ -0,0 +1,27 @@ +import { Flex } from "@styled-system/jsx"; +import { Space, Text } from "@wow-class/ui"; +import { studyApi } from "apis/study/studyApi"; +import type { AttendanceApiResponseDto } from "types/dtos/attendance"; + +import AttendanceItem from "./AttendanceItem"; + +const AttendanceList = async ({ studyId }: { studyId: string }) => { + const attendanceList = await studyApi.getStudyAttendances(+studyId); + + return ( +
+ 주차별 출결번호 + + + {attendanceList?.map((attendance: AttendanceApiResponseDto, index) => ( + + ))} + +
+ ); +}; + +export default AttendanceList; diff --git a/apps/admin/app/studies/[studyId]/_components/curriculum/CurriculumList.tsx b/apps/admin/app/studies/[studyId]/_components/curriculum/CurriculumList.tsx new file mode 100644 index 00000000..edf155a1 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/curriculum/CurriculumList.tsx @@ -0,0 +1,30 @@ +import { Space, Text } from "@wow-class/ui"; +import { studyApi } from "apis/study/studyApi"; + +import CurriculumListItem from "./CurriculumListItem"; +import EmptyCurriculumList from "./EmptyCurriculumList"; + +const CurriculumList = async ({ studyId }: { studyId: string }) => { + const curriculumList = await studyApi.getCurriculumList( + parseInt(studyId, 10) + ); + + if (curriculumList?.length === 0) { + return ; + } + + return ( +
+ 스터디 커리큘럼 + + {curriculumList?.map((curriculum) => ( + + ))} +
+ ); +}; + +export default CurriculumList; diff --git a/apps/admin/app/studies/[studyId]/_components/curriculum/CurriculumListItem.tsx b/apps/admin/app/studies/[studyId]/_components/curriculum/CurriculumListItem.tsx new file mode 100644 index 00000000..ca507ed0 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/curriculum/CurriculumListItem.tsx @@ -0,0 +1,101 @@ +import { cva } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Table, Text } from "@wow-class/ui"; +import { padWithZero, parseISODate } from "@wow-class/utils"; +import type { ComponentProps } from "react"; +import type { CurriculumApiResponseDto } from "types/dtos/curriculumList"; +import type { StudyDifficultyType } from "types/entities/study"; +import getIsCurrentWeek from "utils/getIsCurrentWeek"; +import Tag from "wowds-ui/Tag"; + +const CurriculumListItem = ({ + curriculum, +}: { + curriculum: CurriculumApiResponseDto; +}) => { + const { description = "", period, week, title, difficulty } = curriculum; + const { startDate, endDate } = period; + const { month: startMonth, day: startDay } = parseISODate(startDate); + const { month: endMonth, day: endDay } = parseISODate(endDate); + + const curriculumTimeLine = `${padWithZero(startMonth)}.${padWithZero(startDay)} - ${padWithZero(endMonth)}.${padWithZero(endDay)}`; + const thisWeekAssignment = getIsCurrentWeek(startDate, week); + + return ( + + + + +
+ {week}주차 + + + + {title || "-"} + {difficulty && ( + + {DifficultyMap[difficulty].text} + + )} + + + {description || "스터디 상세 설명을 작성해주세요."} + + + + + + {curriculumTimeLine} + +
+ ); +}; + +export default CurriculumListItem; + +const ThisWeekBarStyle = cva({ + base: { + width: "4px", + height: "18px", + }, + variants: { + type: { + thisWeek: { + backgroundColor: "primary", + }, + notThisWeek: { + backgroundColor: "transparent", + }, + }, + }, +}); + +const DifficultyMap: Record< + StudyDifficultyType, + { text: string; color: ComponentProps["color"] } +> = { + HIGH: { + text: "고급", + color: "red", + }, + MEDIUM: { + text: "중급", + color: "green", + }, + LOW: { + text: "기초", + color: "blue", + }, + BASIC: { + text: "초급", + color: "yellow", + }, +}; + +const CurriculumDescriptionStyle = { + maxWidth: "650px", +}; diff --git a/apps/admin/app/studies/[studyId]/_components/curriculum/EmptyCurriculumList.tsx b/apps/admin/app/studies/[studyId]/_components/curriculum/EmptyCurriculumList.tsx new file mode 100644 index 00000000..54e49387 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/curriculum/EmptyCurriculumList.tsx @@ -0,0 +1,27 @@ +import { Flex } from "@styled-system/jsx"; +import { Space, Text } from "@wow-class/ui"; +import Image from "next/image"; + +const EmptyCurriculumList = () => { + return ( +
+ 스터디 커리큘럼 + + + + empty-curriculum + + 생성된 스터디 커리큘럼이 없어요. + + + +
+ ); +}; + +export default EmptyCurriculumList; diff --git a/apps/admin/app/studies/[studyId]/_components/header/Header.tsx b/apps/admin/app/studies/[studyId]/_components/header/Header.tsx new file mode 100644 index 00000000..4fdbfdfa --- /dev/null +++ b/apps/admin/app/studies/[studyId]/_components/header/Header.tsx @@ -0,0 +1,185 @@ +"use client"; + +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Space, Text } from "@wow-class/ui"; +import { padWithZero, parseISODate } from "@wow-class/utils"; +import { studyApi } from "apis/study/studyApi"; +import ItemSeparator from "components/ItemSeparator"; +import { dayToKorean } from "constants/dayToKorean"; +import Link from "next/link"; +import { useEffect, useState } from "react"; +import type { StudyBasicInfoApiResponseDto } from "types/dtos/studyBasicInfo"; +import { DownArrow } from "wowds-icons"; +import TextButton from "wowds-ui/TextButton"; + +const Header = ({ + studyId, + isCompact = false, +}: { + studyId: string; + isCompact?: boolean; +}) => { + const [showIntro, setShowIntro] = useState(false); + const [studyInfo, setStudyInfo] = useState< + StudyBasicInfoApiResponseDto | undefined + >(undefined); + + useEffect(() => { + const fetchData = async () => { + if (studyId) { + const data = await studyApi.getStudyBasicInfo(parseInt(studyId, 10)); + if (data) setStudyInfo(data); + } + }; + + fetchData(); + }, [studyId]); + + const handleClickShowIntro = () => { + setShowIntro((prev) => !prev); + }; + + const introSectionButtonAriaLabel = showIntro + ? "Collapse introduction" + : "Expand introduction"; + const introSectionIconAriaLabel = showIntro + ? "Collapse introduction icon" + : "Expand introduction icon"; + + if (!studyInfo) return null; + const { + title, + academicYear, + semester, + mentorName, + studyType, + dayOfWeek, + startTime, + endTime, + totalWeek, + period: { startDate, endDate }, + introduction, + notionLink, + } = studyInfo; + + const studySchedule = () => { + if (startTime && endDate) { + const { hour: startHour, minute: startMinute } = startTime; + const { hour: endHour, minute: endMinute } = endTime; + return `${dayToKorean[dayOfWeek]} ${startHour}:${padWithZero(startMinute)}- + ${endHour}:${padWithZero(endMinute)}`; + } else { + null; + } + }; + + const { month: startMonth, day: startDay } = parseISODate(startDate); + const { month: endMonth, day: endDay } = parseISODate(endDate); + const studySemester = `${academicYear}-${semester === "FIRST" ? 1 : 2}`; + + const studyPeriod = `${padWithZero(startMonth)}.${padWithZero(startDay)}- + ${padWithZero(endMonth)}.${padWithZero(endDay)}`; + + return ( +
+
+ + + {title} + + + +
+
+ + + + {studySemester} + + + + {mentorName} 멘토 + + + + {studyType} + + +
+ {showIntro && ( +
+
+ + + + 스터디 일정 + + + {startTime && ( + + + {studySchedule()} + + + + )} + + {totalWeek}주 코스 + + + + {studyPeriod} + + + +
+
+ + + + 스터디 소개 + + + + + + + {introduction} + + + +
+
+ )} +
+ ); +}; + +export default Header; + +const downArrowIconStyle = css({ + cursor: "pointer", +}); diff --git a/apps/admin/app/studies/[studyId]/announcement-delete/page.tsx b/apps/admin/app/studies/[studyId]/announcement-delete/page.tsx new file mode 100644 index 00000000..f1a83887 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/announcement-delete/page.tsx @@ -0,0 +1,8 @@ +import { routerPath } from "constants/router/routerPath"; +import { redirect } from "next/navigation"; + +const AnnouncementDeletePage = () => { + return redirect(routerPath.root.href); +}; + +export default AnnouncementDeletePage; diff --git a/apps/admin/app/studies/[studyId]/announcement-modify/page.tsx b/apps/admin/app/studies/[studyId]/announcement-modify/page.tsx new file mode 100644 index 00000000..49ffc7bf --- /dev/null +++ b/apps/admin/app/studies/[studyId]/announcement-modify/page.tsx @@ -0,0 +1,7 @@ +import { routerPath } from "constants/router/routerPath"; +import { redirect } from "next/navigation"; +const AnnouncementModifyPage = () => { + return redirect(routerPath.root.href); +}; + +export default AnnouncementModifyPage; diff --git a/apps/admin/app/studies/[studyId]/default.tsx b/apps/admin/app/studies/[studyId]/default.tsx new file mode 100644 index 00000000..395785b9 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/default.tsx @@ -0,0 +1,5 @@ +const Default = () => { + return null; +}; + +export default Default; diff --git a/apps/admin/app/studies/[studyId]/hooks/usePrefillAnnouncement.ts b/apps/admin/app/studies/[studyId]/hooks/usePrefillAnnouncement.ts new file mode 100644 index 00000000..3268b37e --- /dev/null +++ b/apps/admin/app/studies/[studyId]/hooks/usePrefillAnnouncement.ts @@ -0,0 +1,26 @@ +import { studyApi } from "apis/study/studyApi"; +import { useEffect, useState } from "react"; +const usePrefillAnnouncement = (studyId: number, studyAnnounceId: number) => { + const [prefillAnnouncement, setPrefillAnnouncement] = useState({ + link: "", + title: "", + }); + useEffect(() => { + const fetchData = async () => { + const announcementList = await studyApi.getStudyAnnouncement(studyId); + const prefillData = announcementList?.filter( + (data) => data.studyAnnounceId === studyAnnounceId + )[0]; + if (prefillData) { + setPrefillAnnouncement({ + title: prefillData.title, + link: prefillData.link, + }); + } + }; + fetchData(); + }, [studyId, studyAnnounceId]); + return prefillAnnouncement; +}; + +export default usePrefillAnnouncement; diff --git a/apps/admin/app/studies/[studyId]/layout.tsx b/apps/admin/app/studies/[studyId]/layout.tsx new file mode 100644 index 00000000..05e232d2 --- /dev/null +++ b/apps/admin/app/studies/[studyId]/layout.tsx @@ -0,0 +1,21 @@ +const StudyLayout = ({ + children, + modal, +}: Readonly<{ + children: React.ReactNode; + modal: React.ReactNode; +}>) => { + return ( +
+ {children} + {modal} +
+ ); +}; + +const MainLayoutStyle = { + height: "100%", + overflow: "auto", +}; + +export default StudyLayout; diff --git a/apps/admin/app/studies/[studyId]/page.tsx b/apps/admin/app/studies/[studyId]/page.tsx new file mode 100644 index 00000000..1ce4381c --- /dev/null +++ b/apps/admin/app/studies/[studyId]/page.tsx @@ -0,0 +1,68 @@ +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Space } from "@wow-class/ui"; +import { studyApi } from "apis/study/studyApi"; +import { routerPath } from "constants/router/routerPath"; +import Link from "next/link"; +import { Edit } from "wowds-icons"; +import Divider from "wowds-ui/Divider"; + +import StudyAnnouncement from "./_components/announcement/StudyAnnouncement"; +import AssignmentList from "./_components/assignment/AssignmentList"; +import AttendanceList from "./_components/attendance/AttendanceList"; +import CurriculumList from "./_components/curriculum/CurriculumList"; +import Header from "./_components/header/Header"; + +export const generateMetadata = async ({ + params: { studyId }, +}: { + params: { studyId: string }; +}) => { + const study = await studyApi.getStudyBasicInfo(+studyId); + return { + title: study ? study.title : "스터디", + }; +}; + +const StudyPage = ({ params }: { params: { studyId: string } }) => { + const { studyId } = params; + return ( + +
+
+ + + +
+ + + + + + + + +
+ ); +}; + +export default StudyPage; + +const MinHeightFullDividerStyle = { + minHeight: "1.2px", +}; + +const EditIconStyle = { + position: "absolute", + right: "0px", + top: "0px", + cursor: "pointer", +}; + +const HeaderWrapper = css({ + position: "relative", + height: "fit-content", +}); diff --git a/apps/admin/app/studies/_components/EmptyStudyList.tsx b/apps/admin/app/studies/_components/EmptyStudyList.tsx new file mode 100644 index 00000000..7c410165 --- /dev/null +++ b/apps/admin/app/studies/_components/EmptyStudyList.tsx @@ -0,0 +1,28 @@ +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import Image from "next/image"; + +const EmptyStudyList = () => { + return ( + + study-empty + + 개설된 스터디가 없어요 + + + ); +}; + +export default EmptyStudyList; diff --git a/apps/admin/app/studies/_components/StudyList.tsx b/apps/admin/app/studies/_components/StudyList.tsx new file mode 100644 index 00000000..f3cbccb7 --- /dev/null +++ b/apps/admin/app/studies/_components/StudyList.tsx @@ -0,0 +1,29 @@ +import { css } from "@styled-system/css"; +import { studyApi } from "apis/study/studyApi"; + +import EmptyStudyList from "./EmptyStudyList"; +import StudyListItem from "./StudyListItem"; + +const StudyList = async () => { + const studyList = await studyApi.getStudyList(); + + if (studyList?.length === 0) { + return ; + } + return ( +
+ {studyList?.map((studyItem, index) => ( + + ))} +
+ ); +}; + +export default StudyList; + +const SectionStyle = css({ + width: "100%", + height: "100%", + overflow: "scroll", + scrollbarWidth: "none", +}); diff --git a/apps/admin/app/studies/_components/StudyListItem.tsx b/apps/admin/app/studies/_components/StudyListItem.tsx new file mode 100644 index 00000000..5fecb740 --- /dev/null +++ b/apps/admin/app/studies/_components/StudyListItem.tsx @@ -0,0 +1,105 @@ +import { Flex } from "@styled-system/jsx"; +import { Table, Text } from "@wow-class/ui"; +import { routerPath } from "constants/router/routerPath"; +import Link from "next/link"; +import type { ComponentProps } from "react"; +import type { StudyListApiResponseDto } from "types/dtos/studyList"; +import type { StudyKoreanType } from "types/entities/study"; +import isAdmin from "utils/isAdmin"; +import { Link as WowLinkIcon } from "wowds-icons"; +import Button from "wowds-ui/Button"; +import Tag from "wowds-ui/Tag"; +import TextButton from "wowds-ui/TextButton"; + +const StudyListItem = async ({ study }: { study: StudyListApiResponseDto }) => { + const adminStatus = await isAdmin(); + const { + studyId, + title, + studyType, + notionLink, + mentorName, + academicYear, + semesterType, + } = study; + + return ( + + + + {academicYear}-{semesterType === "FIRST" ? "1" : "2"} + + + + {title} + + + {studyType} + + + + + {mentorName} 멘토 + + + + + + {adminStatus && ( + + )} + + + + +
+ ); +}; + +export default StudyListItem; + +const studyTypeColorMap: Record< + StudyKoreanType, + ComponentProps["color"] +> = { + "과제 스터디": "green", + "온라인 스터디": "blue", + "오프라인 스터디": "yellow", +}; + +const LinkStyle = { + display: "flex", + alignItems: "center", + color: "sub", + gap: "4px", +}; + +const TableLeftStyle = { + display: "flex", + flex: 2, + alignItems: "center", + gap: "31px", +}; + +const TableRightStyle = { + display: "flex", + flex: 3, + alignItems: "center", + gap: "64px", +}; + +const StudyNameStyle = { + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + maxWidth: "150px", +}; diff --git a/apps/admin/app/studies/assignments/[studyDetailId]/_components/AssignmentForm.tsx b/apps/admin/app/studies/assignments/[studyDetailId]/_components/AssignmentForm.tsx new file mode 100644 index 00000000..f8421a6f --- /dev/null +++ b/apps/admin/app/studies/assignments/[studyDetailId]/_components/AssignmentForm.tsx @@ -0,0 +1,68 @@ +"use client"; + +import { Flex } from "@styled-system/jsx"; +import { formatDateToISOString } from "@wow-class/utils"; +import { useState } from "react"; +import { useFormContext } from "react-hook-form"; +import type { + AssignmentApiRequestDto, + AssignmentApiResponseDto, +} from "types/dtos/assignmentList"; +import PickerGroup from "wowds-ui/PickerGroup"; +import SingleDatePicker from "wowds-ui/SingleDatePicker"; +import TimePicker from "wowds-ui/TimePicker"; + +import CustomTextField from "./CustomTextField"; + +const AssignmentForm = ({ + assignment, +}: { + assignment: AssignmentApiResponseDto; +}) => { + const { control, setValue } = useFormContext(); + const { title, descriptionLink, deadline } = assignment; + const [selectedDate, setSelectedDate] = useState( + deadline ? new Date(deadline) : undefined + ); + + return ( + + + + { + setSelectedDate(date); + if (date) { + setValue("deadLine", formatDateToISOString(date), { + shouldValidate: true, + }); + } + }} + > + + + + + ); +}; + +export default AssignmentForm; diff --git a/apps/admin/app/studies/assignments/[studyDetailId]/_components/AssignmentHeader.tsx b/apps/admin/app/studies/assignments/[studyDetailId]/_components/AssignmentHeader.tsx new file mode 100644 index 00000000..f2803f10 --- /dev/null +++ b/apps/admin/app/studies/assignments/[studyDetailId]/_components/AssignmentHeader.tsx @@ -0,0 +1,80 @@ +"use client"; + +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { studyApi } from "apis/study/studyApi"; +import { tags } from "constants/tags"; +import { useFormContext } from "react-hook-form"; +import type { + AssignmentApiRequestDto, + AssignmentApiResponseDto, +} from "types/dtos/assignmentList"; +import { revalidateTagByName } from "utils/revalidateTagByName"; +import Button from "wowds-ui/Button"; + +interface AssignmentHeaderProps { + assignment: AssignmentApiResponseDto; + disabled: boolean; +} + +const AssignmentHeader = ({ assignment, disabled }: AssignmentHeaderProps) => { + const { studyDetailId, week, assignmentStatus } = assignment; + const methods = useFormContext< + AssignmentApiRequestDto & { + onOpen: () => void; + } + >(); + + const onOpen = methods.getValues("onOpen"); + + const handleClickSubmit = async () => { + if (assignmentStatus === "CANCELLED") return; + + const data = { + title: methods.getValues("title"), + descriptionNotionLink: methods.getValues("descriptionNotionLink"), + deadLine: methods.getValues("deadLine"), + }; + + const { success } = + assignmentStatus === "NONE" + ? await studyApi.createAssignment(studyDetailId, data) + : await studyApi.patchAssignment(studyDetailId, data); + if (success) { + revalidateTagByName(`${tags.assignments} ${studyDetailId}`); + revalidateTagByName(tags.assignments); + onOpen(); + } + }; + + return ( +
+ + + 과제 정보를 입력해주세요 + + + {week}주차 과제 + + + +
+ ); +}; + +const headerStyle = css({ + width: "100%", + display: "flex", + alignItems: "top", + justifyContent: "space-between", +}); + +export default AssignmentHeader; diff --git a/apps/admin/app/studies/assignments/[studyDetailId]/_components/CustomTextField.tsx b/apps/admin/app/studies/assignments/[studyDetailId]/_components/CustomTextField.tsx new file mode 100644 index 00000000..28979eba --- /dev/null +++ b/apps/admin/app/studies/assignments/[studyDetailId]/_components/CustomTextField.tsx @@ -0,0 +1,37 @@ +"use client"; + +import { useController } from "react-hook-form"; +import type { TextFieldProps } from "wowds-ui/TextField"; +import TextField from "wowds-ui/TextField"; + +interface CustomTextFieldProps extends TextFieldProps { + name: string; + control: any; +} + +const CustomTextField = ({ + name, + control, + defaultValue, + ...rest +}: CustomTextFieldProps) => { + const { field } = useController({ + name, + control, + rules: { required: true }, + defaultValue, + }); + + return ( + + ); +}; + +export default CustomTextField; diff --git a/apps/admin/app/studies/assignments/[studyDetailId]/_components/SuccessModal.tsx b/apps/admin/app/studies/assignments/[studyDetailId]/_components/SuccessModal.tsx new file mode 100644 index 00000000..fa8d1421 --- /dev/null +++ b/apps/admin/app/studies/assignments/[studyDetailId]/_components/SuccessModal.tsx @@ -0,0 +1,39 @@ +"use client"; + +import { Flex, styled } from "@styled-system/jsx"; +import { Modal, Text } from "@wow-class/ui"; +import Link from "next/link"; +import Button from "wowds-ui/Button"; + +interface SuccesModalProps { + studyName: string; + week: number; + type: "개설" | "수정"; + studyDetailId: string; +} + +const SuccessModal = ({ + studyName, + week, + type, + studyDetailId, +}: SuccesModalProps) => { + return ( + + + + + {studyName} {week}주차 + +
+ 과제가 {type}되었어요 +
+ +
+
+ ); +}; + +export default SuccessModal; diff --git a/apps/admin/app/studies/assignments/[studyDetailId]/edit-assignment/page.tsx b/apps/admin/app/studies/assignments/[studyDetailId]/edit-assignment/page.tsx new file mode 100644 index 00000000..ed927bd8 --- /dev/null +++ b/apps/admin/app/studies/assignments/[studyDetailId]/edit-assignment/page.tsx @@ -0,0 +1,81 @@ +"use client"; + +import { useOpenState } from "@wow-class/ui/hooks"; +import { studyApi } from "apis/study/studyApi"; +import { assignmentStatusMap } from "constants/status/assignmentStatusMap"; +import { useEffect, useState } from "react"; +import { FormProvider, useForm } from "react-hook-form"; +import type { + AssignmentApiRequestDto, + AssignmentApiResponseDto, +} from "types/dtos/assignmentList"; + +import AssignmentForm from "../_components/AssignmentForm"; +import AssignmentHeader from "../_components/AssignmentHeader"; +import SuccessModal from "../_components/SuccessModal"; + +const Assignments = ({ + params: { studyDetailId }, +}: { + params: { study: string; studyDetailId: string }; +}) => { + const { open, onOpen } = useOpenState(); + + const [assignment, setAssignment] = useState( + null + ); + + useEffect(() => { + const fetchAssignment = async () => { + if (studyDetailId) { + const data = await studyApi.getAssignment(+studyDetailId); + if (data) setAssignment(data); + } + }; + fetchAssignment(); + }, [studyDetailId]); + + const { title, deadline, descriptionLink } = assignment || {}; + const methods = useForm< + AssignmentApiRequestDto & { + onOpen: () => void; + } + >({ + defaultValues: { + title: title || undefined, + deadLine: deadline || undefined, + descriptionNotionLink: descriptionLink || undefined, + onOpen: onOpen, + }, + }); + + const isDeadlineValid = methods.watch("deadLine"); + + if (!assignment) return null; + const { assignmentStatus, week, studyTitle } = assignment; + + // TODO: 휴강된 경우 진입 막기 + if (assignmentStatus === "CANCELLED") return null; + + return ( + <> + {open && ( + + )} + + + + + + ); +}; + +export default Assignments; diff --git a/apps/admin/app/studies/assignments/[studyDetailId]/page.tsx b/apps/admin/app/studies/assignments/[studyDetailId]/page.tsx new file mode 100644 index 00000000..a7c9a2de --- /dev/null +++ b/apps/admin/app/studies/assignments/[studyDetailId]/page.tsx @@ -0,0 +1,86 @@ +import { css } from "@styled-system/css"; +import { Flex, styled } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { padWithZero, parseISODate } from "@wow-class/utils"; +import { studyApi } from "apis/study/studyApi"; +import ItemSeparator from "components/ItemSeparator"; +import { routerPath } from "constants/router/routerPath"; +import Link from "next/link"; +import Button from "wowds-ui/Button"; +import TextButton from "wowds-ui/TextButton"; + +const AssignmentsPage = async ({ + params: { studyDetailId }, +}: { + params: { studyDetailId: string }; +}) => { + const assignment = await studyApi.getAssignment(+studyDetailId); + if (!assignment) return null; + const { week, title, studyTitle, descriptionLink, deadline } = assignment; + console.log(assignment); + + if (!deadline) return null; + const { year, month, day, hours, minutes } = parseISODate(deadline); + + return ( + <> +
+ + {studyTitle} + + {week}주차 과제 + + + +
+ + + 과제 제목 + + {title} + + + + 과제 명세 링크 + + + + 과제 기한 + + {year}년 {month}월 {day}일 {padWithZero(hours)}: + {padWithZero(minutes)} + + + + + ); +}; + +const headerStyle = css({ + width: "100%", + display: "flex", + justifyContent: "space-between", +}); + +const textButtonStyle = css({ + color: "sub", +}); + +export default AssignmentsPage; diff --git a/apps/admin/app/studies/assignments/layout.tsx b/apps/admin/app/studies/assignments/layout.tsx new file mode 100644 index 00000000..e79da0ff --- /dev/null +++ b/apps/admin/app/studies/assignments/layout.tsx @@ -0,0 +1,15 @@ +import { Flex } from "@styled-system/jsx"; + +const AssignmentsLayout = ({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) => { + return ( + + {children} + + ); +}; + +export default AssignmentsLayout; diff --git a/apps/admin/app/studies/create-study/@modal/(.)created-study-check/page.tsx b/apps/admin/app/studies/create-study/@modal/(.)created-study-check/page.tsx new file mode 100644 index 00000000..4b2bcbbe --- /dev/null +++ b/apps/admin/app/studies/create-study/@modal/(.)created-study-check/page.tsx @@ -0,0 +1,66 @@ +"use client"; + +import { Flex } from "@styled-system/jsx"; +import { Modal, Space, Text } from "@wow-class/ui"; +import { useModalRoute } from "@wow-class/ui/hooks"; +import { createStudyApi } from "apis/study/createStudyApi"; +import ItemSeparator from "components/ItemSeparator"; +import { routerPath } from "constants/router/routerPath"; +import { tags } from "constants/tags"; +import useParseSearchParams from "hooks/useParseSearchParams"; +import { useRouter, useSearchParams } from "next/navigation"; +import type { CreateStudyApiRequestDto } from "types/dtos/createStudy"; +import { revalidateTagByName } from "utils/revalidateTagByName"; +import Button from "wowds-ui/Button"; + +const CreatedStudyCheckModal = () => { + const { parseQueryString } = useParseSearchParams(); + const searchParams = useSearchParams(); + const router = useRouter(); + const { onClose } = useModalRoute(); + + const data = parseQueryString( + searchParams.toString() + ); + + const studyName = data.title; + const semester = `${data.academicYear}-${data.semesterType === "FIRST" ? "1" : "2"}`; + + const handleClickSubmitButton = async () => { + const result = await createStudyApi.postCreateStudy(data); + + if (result.success) { + await revalidateTagByName(tags.studyList); + window.alert("스터디 생성에 성공했어요."); + router.push(`${routerPath.root.href}`); + } else { + window.alert("스터디 생성에 실패했어요."); + } + }; + + return ( + + + + + {studyName} + + + + {semester} + + + 새로운 스터디를 개설하시겠어요? + + + + + + + + ); +}; + +export default CreatedStudyCheckModal; diff --git a/apps/admin/app/studies/create-study/@modal/default.tsx b/apps/admin/app/studies/create-study/@modal/default.tsx new file mode 100644 index 00000000..395785b9 --- /dev/null +++ b/apps/admin/app/studies/create-study/@modal/default.tsx @@ -0,0 +1,5 @@ +const Default = () => { + return null; +}; + +export default Default; diff --git a/apps/admin/app/studies/create-study/_components/CreateStudyButton.tsx b/apps/admin/app/studies/create-study/_components/CreateStudyButton.tsx new file mode 100644 index 00000000..cfd0893d --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/CreateStudyButton.tsx @@ -0,0 +1,57 @@ +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { routerPath } from "constants/router/routerPath"; +import Link from "next/link"; +import isAdmin from "utils/isAdmin"; +import { Plus } from "wowds-icons"; + +const CreateStudyButton = async () => { + const adminStatus = await isAdmin(); + + if (!adminStatus) return null; + + return ( + + + + ); +}; + +export default CreateStudyButton; + +const createStudyButtonStyle = css({ + width: "100%", + display: "flex", + justifyContent: "center", + borderRadius: "md", + borderStyle: "dashed", + borderWidth: "1px", + borderColor: "outline", + padding: "32px", + _hover: { + backgroundColor: "backgroundAlternative", + borderWidth: "0px", + cursor: "pointer", + }, +}); + +const PlusIconStyle = css({ + display: "flex", + justifyContent: "center", + alignItems: "center", + width: "20px", + height: "20px", + borderRadius: "full", + backgroundColor: "primary", + color: "white", +}); diff --git a/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyApplyDatePick.tsx b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyApplyDatePick.tsx new file mode 100644 index 00000000..d0ee6b8d --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyApplyDatePick.tsx @@ -0,0 +1,143 @@ +import "react-day-picker/style.css"; + +import { cva } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { dateToFormatString, formatStringToDate } from "@wow-class/utils"; +import useClickOutside from "hooks/useClickOutSide"; +import { useRef, useState } from "react"; +import type { DateRange } from "react-day-picker"; +import { DayPicker } from "react-day-picker"; +import { Controller, useFormContext } from "react-hook-form"; + +const StudyApplyDatePick = () => { + const [studyDate, setStudyDate] = useState({ + fromValue: "", + toValue: "", + }); + const datepickerRef = useRef(null); + const today = new Date(); + const yesterday = new Date(today); + yesterday.setDate(yesterday.getDate() - 1); + + const [isOpen, setIsOpen] = useState(false); + const { control, setValue, watch } = useFormContext(); + const [inputValue, setInputValue] = useState(""); + const studyStartDate = formatStringToDate(watch("startDate") || ""); + const studyStartDateYearLater = new Date(studyStartDate); + studyStartDateYearLater.setFullYear(studyStartDate.getFullYear() + 1); + + useClickOutside(datepickerRef, () => { + setIsOpen(false); + }); + + const handleStudyDateSelect = (triggerDate: DateRange | undefined) => { + if (!triggerDate) return; + const startDateString = dateToFormatString(triggerDate.from!!); + const endDateString = dateToFormatString(triggerDate.to!!); + setStudyDate({ + fromValue: startDateString, + toValue: endDateString, + }); + setInputValue(`${startDateString} ~ ${endDateString}`); + setValue("applicationStartDate", startDateString, { shouldValidate: true }); + setValue("applicationEndDate", endDateString, { shouldValidate: true }); + }; + + const disableDateList = [ + { + from: new Date(0), + to: yesterday, + }, + ...(watch("startDate") + ? [ + { + from: studyStartDate, + to: studyStartDateYearLater, + }, + ] + : []), + ]; + return ( + + + 스터디 신청 기간 + + ( + { + setIsOpen(!isOpen); + }} + /> + )} + rules={{ + required: true, + }} + /> + + {isOpen && ( +
+ { + handleStudyDateSelect(triggerDate); + }} + /> +
+ )} +
+ ); +}; + +export default StudyApplyDatePick; + +const StudyDatePickerStyle = cva({ + base: { + width: "100%", + maxWidth: "358px", + border: "1px solid", + borderRadius: "sm", + borderColor: "outline", + height: "44px", + padding: "8px 12px", + caretColor: "transparent", + cursor: "pointer", + _placeholder: { + color: "outline", + }, + _focus: { + outline: "none", + borderColor: "primary", + }, + }, + variants: { + type: { + selected: { + borderColor: "sub", + }, + unSelected: { + borderColor: "outline", + }, + }, + }, +}); diff --git a/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyCourseSelect.tsx b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyCourseSelect.tsx new file mode 100644 index 00000000..1d162c92 --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyCourseSelect.tsx @@ -0,0 +1,47 @@ +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { Controller, useFormContext } from "react-hook-form"; +import DropDown from "wowds-ui/DropDown"; +import DropDownOption from "wowds-ui/DropDownOption"; + +const StudyCourseSelect = () => { + const { control } = useFormContext(); + return ( + + ( + { + field.onChange(Number(selectedValue)); + }} + > + + + + + + + + + + + + )} + rules={{ + required: true, + }} + /> + + * 휴강 주차 포함 + + + ); +}; + +export default StudyCourseSelect; diff --git a/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyDayOfWeekSelect.tsx b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyDayOfWeekSelect.tsx new file mode 100644 index 00000000..b3386cb5 --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyDayOfWeekSelect.tsx @@ -0,0 +1,33 @@ +import { dayToKoreanList } from "constants/dayToKorean"; +import { Controller, useFormContext } from "react-hook-form"; +import DropDown from "wowds-ui/DropDown"; +import DropDownOption from "wowds-ui/DropDownOption"; + +const StudyDayOfWeekSelect = () => { + const { control } = useFormContext(); + return ( + ( + { + field.onChange(selectedValue); + }} + > + {dayToKoreanList.map(({ text, value }) => ( + + ))} + + )} + rules={{ + required: true, + }} + /> + ); +}; + +export default StudyDayOfWeekSelect; diff --git a/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyFormatSelect.tsx b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyFormatSelect.tsx new file mode 100644 index 00000000..50327ff9 --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyFormatSelect.tsx @@ -0,0 +1,64 @@ +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { Controller, useFormContext } from "react-hook-form"; +import DropDown from "wowds-ui/DropDown"; +import DropDownOption from "wowds-ui/DropDownOption"; + +const StudyFormatSelect = () => { + const { control } = useFormContext(); + return ( + ( + { + field.onChange(selectedValue); + }} + > + + 오프라인 스터디 + + 오프라인으로 진행해요. + + + } + /> + + 온라인 스터디 + + 온라인으로 진행해요. + + + } + /> + + 과제 스터디 + + 별도 강의 없이 과제만 진행해요. + + + } + /> + + )} + rules={{ + required: true, + }} + /> + ); +}; + +export default StudyFormatSelect; diff --git a/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudySemesterSelect.tsx b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudySemesterSelect.tsx new file mode 100644 index 00000000..438cec94 --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudySemesterSelect.tsx @@ -0,0 +1,39 @@ +import { useState } from "react"; +import { Controller, useFormContext } from "react-hook-form"; +import DropDown from "wowds-ui/DropDown"; +import DropDownOption from "wowds-ui/DropDownOption"; + +const StudySemesterSelect = () => { + const { control, setValue } = useFormContext(); + const [semesterValue, setSemesterValue] = useState(""); + return ( + ( + { + setSemesterValue(selectedValue); + const [year, semester] = selectedValue.split("-"); + if (year && semester) { + setValue("academicYear", Number(year), { shouldValidate: true }); + setValue("semesterType", semester, { shouldValidate: true }); + } + }} + > + + + + )} + rules={{ + required: true, + }} + /> + ); +}; + +export default StudySemesterSelect; diff --git a/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyStartDatePick.tsx b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyStartDatePick.tsx new file mode 100644 index 00000000..55e4ffa3 --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyStartDatePick.tsx @@ -0,0 +1,168 @@ +import "react-day-picker/style.css"; + +import { cva } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { + dateToFormatString, + formatStringToDate, + getStudyEndDate, +} from "@wow-class/utils"; +import useClickOutside from "hooks/useClickOutSide"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { DayPicker } from "react-day-picker"; +import { Controller, useFormContext } from "react-hook-form"; + +const StudyStartDatePick = () => { + const [studyDate, setStudyDate] = useState({ + fromValue: "", + toValue: "", + }); + const datepickerRef = useRef(null); + const today = new Date(); + const yesterday = new Date(today); + const [isOpen, setIsOpen] = useState(false); + const { control, setValue, watch } = useFormContext(); + const [inputValue, setInputValue] = useState(""); + + const week = watch("totalWeek"); + const studyApplyEndDate = formatStringToDate( + watch("applicationEndDate") || "" + ); + const studyApplyDateYearLater = new Date(studyApplyEndDate); + studyApplyDateYearLater.setFullYear(studyApplyEndDate.getFullYear() + 1); + + useClickOutside(datepickerRef, () => { + setIsOpen(false); + }); + + const handleStudyDateSelect = useCallback( + (week: unknown, date: Date) => { + if (week && date) { + const startDateString = dateToFormatString(date); + const endDateString = dateToFormatString( + getStudyEndDate(date, Number(week)) + ); + setStudyDate({ + fromValue: startDateString, + toValue: endDateString, + }); + setInputValue(`${startDateString} ~ ${endDateString}`); + setValue("startDate", startDateString, { shouldValidate: true }); + setIsOpen(false); + } + }, + [setValue] + ); + + useEffect(() => { + if (studyDate.toValue) { + handleStudyDateSelect(week, formatStringToDate(studyDate.fromValue)); + } + }, [handleStudyDateSelect, studyDate.fromValue, studyDate.toValue, week]); + + const disableDateList = [ + { + from: new Date(0), + to: yesterday, + }, + ...(watch("applicationEndDate") + ? [ + { + from: new Date(0), + to: studyApplyEndDate, + }, + ] + : []), + ]; + + return ( + + + 스터디 진행 기간 + + ( + + { + if (!week) { + return window.alert("스터디 코스를 먼저 선택해주세요"); + } + setIsOpen(!isOpen); + }} + /> + + * 휴강 주차 포함 + + + )} + rules={{ + required: true, + }} + /> + + {isOpen && ( +
+ { + handleStudyDateSelect(week, selected); + }} + /> +
+ )} +
+ ); +}; + +export default StudyStartDatePick; + +const StudyDatePickerStyle = cva({ + base: { + width: "100%", + maxWidth: "358px", + border: "1px solid", + borderRadius: "sm", + borderColor: "outline", + height: "44px", + padding: "8px 12px", + caretColor: "transparent", + cursor: "pointer", + _placeholder: { + color: "outline", + }, + _focus: { + outline: "none", + }, + }, + variants: { + type: { + selected: { + borderColor: "sub", + }, + unSelected: { + borderColor: "outline", + }, + }, + }, +}); diff --git a/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyTime.tsx b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyTime.tsx new file mode 100644 index 00000000..72444cdc --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/StudyTime.tsx @@ -0,0 +1,79 @@ +import "@wojtekmaj/react-timerange-picker/dist/TimeRangePicker.css"; +import "react-clock/dist/Clock.css"; + +import { Flex } from "@styled-system/jsx"; +import TimeRangePicker from "@wojtekmaj/react-timerange-picker"; +import { Text } from "@wow-class/ui"; +import { useState } from "react"; +import { Controller, useFormContext } from "react-hook-form"; + +type ValuePiece = Date | string | null; +type Value = ValuePiece | [ValuePiece, ValuePiece]; + +const StudyTime = () => { + const { control, setValue, watch } = useFormContext(); + const [value, onChange] = useState(""); + + const isAssignmentStudy = watch("studyType") === "ASSIGNMENT"; + + const handleSetTime = (value: Value) => { + if (!value) return; + onChange(value); + if (Array.isArray(value) && value.length === 2) { + const startTime = value[0]?.toString().split(":"); + const endTime = value[1]?.toString().split(":"); + + if (startTime && endTime) { + if (startTime > endTime) { + window.alert("스터디 종료 시간은 스터디 시작 시간 이후여야 합니다!"); + return; + } + setValue( + "studyStartTime", + { + hour: Number(startTime[0]), + minute: Number(startTime[1]), + second: 0, + nano: 0, + }, + { shouldValidate: true } + ); + + setValue( + "studyEndTime", + { + hour: Number(endTime[0]), + minute: Number(endTime[1]), + second: 0, + nano: 0, + }, + { shouldValidate: true } + ); + } + } + }; + return ( + + + 스터디 시간 + + ( + + )} + rules={{ + required: !isAssignmentStudy, + }} + /> + + ); +}; + +export default StudyTime; diff --git a/apps/admin/app/studies/create-study/_components/StudyBasicInformation/index.tsx b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/index.tsx new file mode 100644 index 00000000..8fbaf4ca --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/StudyBasicInformation/index.tsx @@ -0,0 +1,34 @@ +"use client"; +import { Flex, Grid } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; + +import StudyApplyDatePick from "./StudyApplyDatePick"; +import StudyCourseSelect from "./StudyCourseSelect"; +import StudyDayOfWeekSelect from "./StudyDayOfWeekSelect"; +import StudyFormatSelect from "./StudyFormatSelect"; +import StudySemesterSelect from "./StudySemesterSelect"; +import StudyStartDatePick from "./StudyStartDatePick"; +import StudyTime from "./StudyTime"; + +const StudyBasicInformation = () => { + return ( + + 스터디 기본 설정 + + + + + + + + + + + ); +}; + +export default StudyBasicInformation; diff --git a/apps/admin/app/studies/create-study/_components/StudyMentorSelect.tsx b/apps/admin/app/studies/create-study/_components/StudyMentorSelect.tsx new file mode 100644 index 00000000..3c33152a --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/StudyMentorSelect.tsx @@ -0,0 +1,98 @@ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ +"use client"; +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { createStudyApi } from "apis/study/createStudyApi"; +import { useState } from "react"; +import { useFormContext } from "react-hook-form"; +import SearchBar from "wowds-ui/SearchBar"; + +type MentorListType = { + memberId: number; + name: string; +}; + +const StudyMentorSelect = () => { + const { setValue } = useFormContext(); + const [memberList, setMemberList] = useState([]); + const [openPopup, setOpenPopup] = useState(false); + const [mentor, setMentor] = useState(""); + + const fetchStudyMentor = async (name: string) => { + const response = await createStudyApi.searchStudyMentor(name); + const formatMentorList = response.map((data) => { + return { + memberId: data.memberId, + name: data.name, + }; + }); + setMemberList([...formatMentorList]); + setOpenPopup(true); + }; + + return ( + + 스터디 멘토 +
+ { + setMentor(value); + fetchStudyMentor(value); + }} + /> + {openPopup && mentor.length > 0 && ( +
    + {memberList.length > 0 ? ( + <> + {memberList.map((data) => ( +
  • { + setValue("mentorId", data.memberId, { + shouldValidate: true, + }); + setOpenPopup(false); + setMentor(data.name); + }} + > + + {data.name} + +
  • + ))} + + ) : ( + + 일치하는 결과가 없어요. + + )} +
+ )} +
+
+ ); +}; + +export default StudyMentorSelect; + +const MemberListPopupStyle = css({ + position: "absolute", + top: "50px", + width: "320px", + zIndex: 999, + borderRadius: "8px", + backgroundColor: "white", + shadow: "mono", + padding: "xs", +}); + +const MemberListItemStyle = css({ + marginY: "5px", + cursor: "pointer", +}); diff --git a/apps/admin/app/studies/create-study/_components/StudyNameTextField.tsx b/apps/admin/app/studies/create-study/_components/StudyNameTextField.tsx new file mode 100644 index 00000000..ab366de5 --- /dev/null +++ b/apps/admin/app/studies/create-study/_components/StudyNameTextField.tsx @@ -0,0 +1,51 @@ +"use client"; +import { css } from "@styled-system/css"; +import { Flex } from "@styled-system/jsx"; +import { Text } from "@wow-class/ui"; +import { Controller, useFormContext } from "react-hook-form"; + +const StudyNameTextField = () => { + const { control } = useFormContext(); + return ( + ( + + + 새로 개설할 스터디 정보를 입력해주세요 + +