From 30b6f5e50c93b176284146e2f74a06bc3190e82d Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:27:41 +0900 Subject: [PATCH] Fe dev (#664) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe * design: 전역 스타일링 설정 Co-authored-by: pakxe * feat: 라우터 셋팅 Co-authored-by: pakxe * feat: 앱의 진입점 설정 Co-authored-by: pakxe * feat: 라우트 경로 설정 Co-authored-by: pakxe * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe * feat: 인원 관리 기능구현 Co-authored-by: pakxe * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha * feat: Input component 구현 Co-authored-by: soi-ha * feat: Title component 구현 Co-authored-by: soi-ha * feat: BottomSheet component 구현 Co-authored-by: soi-ha * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha Co-authored-by: Soyeon Choe * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 Co-authored-by: Soyeon Choe Co-authored-by: pakxe * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee * refactor: 메서드 분리 Co-authored-by: kunsanglee * refactor: 코드 컨벤션 Co-authored-by: kunsanglee * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: 메서드 순서 변경 Co-authored-by: Arachne --------- Co-authored-by: kunsanglee Co-authored-by: Arachne authored-by: khabh * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh --------- Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee Co-authored-by: Arachneee Co-authored-by: khabh * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 Co-authored-by: 김진호 Co-authored-by: pakxe * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 Co-authored-by: pakxe * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 서버 코드 삭제 * [FE] 스프린트3 디자인 수정 (#162) * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 * chore: branch 변경에 따른 yml 파일 수정 (#165) * fix: 스토리북 워크플로우 오류 (#168) * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 * feat: 토스트 생성 (#166) * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim Co-authored-by: Soyeon Choe --------- Co-authored-by: pakxe Co-authored-by: JinHo Kim Co-authored-by: Soyeon Choe * fix: client 디렉토리 reset, 전역 스타일 GlobalStyle을 사용하는 것으로 변경 (#173) * refactor: css를 global style로 수정 Co-authored-by: Pakxe * refactor: global style app과 index에 적용 Co-authored-by: Pakxe * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe --------- Co-authored-by: Pakxe * design: Button이 disabled일 때 커서가 포인터가 아니도록 수정 (#171) * feat: Input 컴포넌트 관련한 기능 수정, useDynamic-* 훅 관련 오류 수정, 네이밍 통일, 의미를 명확하게 담도록 네이밍 수정 (#143, #183) * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * style: lint 적용 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 Co-authored-by: Soyeon Choe Co-authored-by: Soyeon Choe Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe Co-authored-by: jinhokim98 * feat: 변경된 API endpoint로 수정 (#196) * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: 디자인시스템 hover, mouse, transition animation (#198) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * [FE] ListButton component 생성 (#203) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * feat: 개별 ActionItem 컨트롤을 위한 StepItem 및 BillItem / InOutItem component 구조 변경 (#211) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 * feat: 삭제 아이콘을 위한 IconButton component 수정 (#209) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 * feat: 멤버 액션 삭제 기능 구현 + 바뀐 디자인시스템 적용 (#214) * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA Co-authored-by: Arachne * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe Co-authored-by: JUHA Co-authored-by: Arachne Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * fix: FixedButton의 delete button type "button"으로 변경 (#234) * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 * feat: 행사생성 flow에서 admin 접근을 위한 비밀번호를 입력받는 기능 추가 (#226) * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 * feat: 지출 액션 수정, 삭제 기능 구현 (#230) * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 * feat: 전체 참여자 BottomSheet 내부 디자인 퍼블리싱 (#228) * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 * feat: api에러 등의 에러를 잡아 핸들링 (#232) * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 * chore: 빌드 환경 prod와 dev로 구분 (#217) * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 * fix: merge를 통해 발생한 에러 해결 (#246) * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 * fix: input value 수정이 되지 않는 문제 (#253) * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 * fix: useToast 에러바운더리 문제 해결 (#264) * fix: 디자인시스템 Text 컴포넌트 color prop 받도록 변경 (#257) * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 * fix: 디자인시스템 Input value 동기화 오류 수정 (#266) * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish * fix: 행동디자인 Search 컴포넌트 기능 제거 (#260) * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 * feat: 행사 생성 완료 페이지 유저 친화적으로 변경 (#271) * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 * feat: 인원 탈주 시 인원 검색 기능 구현 (#270) * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 데이터 요청하고 출력하기 (#250) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 이름 수정 및 삭제 (#276) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 * feat: sentry 적용 (#262) * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 3차 데모데이 merge 중 발생한 문제 수정 (#280) * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 * feat: requestPost에 대해 response가 있는 post와 없는 post로 분기해 사용하도록함 (#281) * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 * feat: 홈에서 액션 수정 삭제 바텀시트 활성화 버그 (#285) * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 * feat: cookie가 없는 경우 비밀번호 입력 페이지로 이동 (#286) * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 * feat: 데모데이를 위해 페이지 약간 수정 (#289) * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 * fix: import 가 안되어있는 부분 수정 (#293) * fix: 인원 탈주 검색 인풋 오류 (#299) * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 * chore: hooks폴더 구조 정리 (#312) * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 * feat: 전체 참여자 수정 및 삭제 수정 (#315) * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 * feat: 차수 멤버 확인, useFetch 확장, BottomSheet 활성화 수정 (#311) * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 * feat: 참여 인원 확인 임시 버튼 삭제 (#318) * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 * feat: bottomSheet maxWidth 768px 되도록 변경 (#321) * feat: 메인, 관리 페이지 설명 글 수정 (#324) * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 * fix: useDynamicInput 버그 수정 (#327) * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 * feat: 홈 및 관리 페이지에서 링크 복사 기능 추가 (#329) * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: pr issue close workflow 생성 (#328) * test: cypress 적용 및 행사 생성 flow e2e 테스트 작성 (#331) * chore: cypress 설정 Co-authored-by: JinHo Kim * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim * fix: 토큰이 없을 때, 관리페이지로 이동하면 오류가 발생하는 부분 수정 (#338) * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 * fix: 인원 탈주 추가 시 disable 버그 (#339) * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 * feat: Sentry prod 환경에서만 돌아가도록 fetcher 설정 (#343) * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 * feat: 환경 변수 타입 선언 (#345) * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * feat: useDeleteMemberAction 토스트 함수 결합도 제거 (#347) * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 * feat: 사용성 개선 - Title component 변경 및 UX writing 수정 (#352) * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 * feat: 비밀번호 입력 페이지 커스텀 훅으로 분리 (#354) * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 * fix: 탭 클릭 시 전체가 클릭되는 것처럼 보이는 현상 해결 (#356) * feat: 사용성 개선 - 지출 내역 입력 아이템 구현 (#357) * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * refactor: 행사 생성 완료 페이지에서 불필요한 상태 제거 (#350) * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 * fix: 인원 탈주 시 검색이 되지 않는 버그 해결 (#368) * fix: 머지하면서 신경쓰지 못한 코드오류 해결 (#381) * feat: Input 검증 에러 메시지 타입 구조 변경 (#376) * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 * feat: 공통 input 코드를 useInput hook으로 분리 (#379) * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 * test: 훅에 필요한 테스트 추가 (#358) * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 * refactor: 멤버 액션 삭제 훅 리팩토링 (#383) * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. * refactor: 이벤트 생성 페이지 리팩토링 (#385) * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 * test: useError, useToast 테스트코드 작성 (#387) * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 * feat: Zustand, react-query 도입 및 적용 (#388) * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 Co-authored-by: Soyeon Choe * fix: valideMemberName의 조건문 name은 1 이하일 수 없다를 제거 (#396) Co-authored-by: Soyeon Choe * feat: 총액 업데이트 로직을 store안으로 이동 (#401) * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 * fix: action log가 길어질 때 heigth 잘리는 버그 수정 (#408) * feat: 전체 인원 수정 '삭제' api 로직 롤백 수정 (#409) * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 * feat: EditableItem.Input이 동적인 width를 갖도록 수정 (#411) * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 * feat: 차등 정산 기능 구현 및 테스트 작성 (#406) * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 * feat: 차등 적용 적용 중 지원되지 않는 기능 수정 (#423) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: 차등 적용 can submit이 valid 하지만 false되는 버그 (#428) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 * feat: 지출 내역 추가 변경사항 적용 (#414) * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 * feat: 지출 내역 아이템 클릭시 뜨는 차등 정산 모달 퍼블리싱 (#431) * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 * feat: BottomSheet 지출 부분 삭제 & input autoFocus (#433) * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim Co-authored-by: Pakxe * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe * design: 기본 css style 초기화 작업 Co-authored-by: pakxe * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe * design: 전역 스타일링 설정 Co-authored-by: pakxe * feat: 라우터 셋팅 Co-authored-by: pakxe * feat: 앱의 진입점 설정 Co-authored-by: pakxe * feat: 라우트 경로 설정 Co-authored-by: pakxe * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe * feat: 인원 관리 기능구현 Co-authored-by: pakxe * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha * feat: Input component 구현 Co-authored-by: soi-ha * feat: Title component 구현 Co-authored-by: soi-ha * feat: BottomSheet component 구현 Co-authored-by: soi-ha * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha Co-authored-by: Soyeon Choe * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 Co-authored-by: Soyeon Choe Co-authored-by: pakxe * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee * refactor: 메서드 분리 Co-authored-by: kunsanglee * refactor: 코드 컨벤션 Co-authored-by: kunsanglee * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: 메서드 순서 변경 Co-authored-by: Arachne --------- Co-authored-by: kunsanglee Co-authored-by: Arachne authored-by: khabh * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh --------- Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee Co-authored-by: Arachneee Co-authored-by: khabh * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 Co-authored-by: 김진호 Co-authored-by: pakxe * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 Co-authored-by: pakxe * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 서버 코드 삭제 * [FE] 스프린트3 디자인 수정 (#162) * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 * chore: branch 변경에 따른 yml 파일 수정 (#165) * fix: 스토리북 워크플로우 오류 (#168) * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 * feat: 토스트 생성 (#166) * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim Co-authored-by: Soyeon Choe --------- Co-authored-by: pakxe Co-authored-by: JinHo Kim Co-authored-by: Soyeon Choe * fix: client 디렉토리 reset, 전역 스타일 GlobalStyle을 사용하는 것으로 변경 (#173) * refactor: css를 global style로 수정 Co-authored-by: Pakxe * refactor: global style app과 index에 적용 Co-authored-by: Pakxe * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe --------- Co-authored-by: Pakxe * design: Button이 disabled일 때 커서가 포인터가 아니도록 수정 (#171) * feat: Input 컴포넌트 관련한 기능 수정, useDynamic-* 훅 관련 오류 수정, 네이밍 통일, 의미를 명확하게 담도록 네이밍 수정 (#143, #183) * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * style: lint 적용 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 Co-authored-by: Soyeon Choe Co-authored-by: Soyeon Choe Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe Co-authored-by: jinhokim98 * feat: 변경된 API endpoint로 수정 (#196) * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: 디자인시스템 hover, mouse, transition animation (#198) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * [FE] ListButton component 생성 (#203) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * feat: 개별 ActionItem 컨트롤을 위한 StepItem 및 BillItem / InOutItem component 구조 변경 (#211) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 * feat: 삭제 아이콘을 위한 IconButton component 수정 (#209) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 * feat: 멤버 액션 삭제 기능 구현 + 바뀐 디자인시스템 적용 (#214) * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA Co-authored-by: Arachne * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe Co-authored-by: JUHA Co-authored-by: Arachne Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * fix: FixedButton의 delete button type "button"으로 변경 (#234) * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 * feat: 행사생성 flow에서 admin 접근을 위한 비밀번호를 입력받는 기능 추가 (#226) * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 * feat: 지출 액션 수정, 삭제 기능 구현 (#230) * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 * feat: 전체 참여자 BottomSheet 내부 디자인 퍼블리싱 (#228) * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 * feat: api에러 등의 에러를 잡아 핸들링 (#232) * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 * chore: 빌드 환경 prod와 dev로 구분 (#217) * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 * fix: merge를 통해 발생한 에러 해결 (#246) * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 * fix: input value 수정이 되지 않는 문제 (#253) * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 * fix: useToast 에러바운더리 문제 해결 (#264) * fix: 디자인시스템 Text 컴포넌트 color prop 받도록 변경 (#257) * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 * fix: 디자인시스템 Input value 동기화 오류 수정 (#266) * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish * fix: 행동디자인 Search 컴포넌트 기능 제거 (#260) * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 * feat: 행사 생성 완료 페이지 유저 친화적으로 변경 (#271) * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 * feat: 인원 탈주 시 인원 검색 기능 구현 (#270) * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 데이터 요청하고 출력하기 (#250) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 이름 수정 및 삭제 (#276) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 * feat: sentry 적용 (#262) * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 3차 데모데이 merge 중 발생한 문제 수정 (#280) * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 * feat: requestPost에 대해 response가 있는 post와 없는 post로 분기해 사용하도록함 (#281) * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 * feat: 홈에서 액션 수정 삭제 바텀시트 활성화 버그 (#285) * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 * feat: cookie가 없는 경우 비밀번호 입력 페이지로 이동 (#286) * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 * feat: 데모데이를 위해 페이지 약간 수정 (#289) * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 * fix: import 가 안되어있는 부분 수정 (#293) * fix: 인원 탈주 검색 인풋 오류 (#299) * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 * chore: hooks폴더 구조 정리 (#312) * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 * feat: 전체 참여자 수정 및 삭제 수정 (#315) * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 * feat: 차수 멤버 확인, useFetch 확장, BottomSheet 활성화 수정 (#311) * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 * feat: 참여 인원 확인 임시 버튼 삭제 (#318) * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 * feat: bottomSheet maxWidth 768px 되도록 변경 (#321) * feat: 메인, 관리 페이지 설명 글 수정 (#324) * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 * fix: useDynamicInput 버그 수정 (#327) * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 * feat: 홈 및 관리 페이지에서 링크 복사 기능 추가 (#329) * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: pr issue close workflow 생성 (#328) * test: cypress 적용 및 행사 생성 flow e2e 테스트 작성 (#331) * chore: cypress 설정 Co-authored-by: JinHo Kim * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim * fix: 토큰이 없을 때, 관리페이지로 이동하면 오류가 발생하는 부분 수정 (#338) * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 * fix: 인원 탈주 추가 시 disable 버그 (#339) * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 * feat: Sentry prod 환경에서만 돌아가도록 fetcher 설정 (#343) * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 * feat: 환경 변수 타입 선언 (#345) * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * feat: useDeleteMemberAction 토스트 함수 결합도 제거 (#347) * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 * feat: 사용성 개선 - Title component 변경 및 UX writing 수정 (#352) * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 * feat: 비밀번호 입력 페이지 커스텀 훅으로 분리 (#354) * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 * fix: 탭 클릭 시 전체가 클릭되는 것처럼 보이는 현상 해결 (#356) * feat: 사용성 개선 - 지출 내역 입력 아이템 구현 (#357) * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * refactor: 행사 생성 완료 페이지에서 불필요한 상태 제거 (#350) * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 * fix: 인원 탈주 시 검색이 되지 않는 버그 해결 (#368) * fix: 머지하면서 신경쓰지 못한 코드오류 해결 (#381) * feat: Input 검증 에러 메시지 타입 구조 변경 (#376) * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 * feat: 공통 input 코드를 useInput hook으로 분리 (#379) * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 * test: 훅에 필요한 테스트 추가 (#358) * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 * refactor: 멤버 액션 삭제 훅 리팩토링 (#383) * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. * refactor: 이벤트 생성 페이지 리팩토링 (#385) * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 * test: useError, useToast 테스트코드 작성 (#387) * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 * feat: Zustand, react-query 도입 및 적용 (#388) * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 Co-authored-by: Soyeon Choe * fix: valideMemberName의 조건문 name은 1 이하일 수 없다를 제거 (#396) Co-authored-by: Soyeon Choe * feat: 총액 업데이트 로직을 store안으로 이동 (#401) * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 * fix: action log가 길어질 때 heigth 잘리는 버그 수정 (#408) * feat: 전체 인원 수정 '삭제' api 로직 롤백 수정 (#409) * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 * feat: EditableItem.Input이 동적인 width를 갖도록 수정 (#411) * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 * feat: 차등 정산 기능 구현 및 테스트 작성 (#406) * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 * feat: 차등 적용 적용 중 지원되지 않는 기능 수정 (#423) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: 차등 적용 can submit이 valid 하지만 false되는 버그 (#428) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 * feat: 지출 내역 추가 변경사항 적용 (#414) * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 * feat: 지출 내역 아이템 클릭시 뜨는 차등 정산 모달 퍼블리싱 (#431) * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 * fix: 사용하지 않는 지출 Modal Input 삭제 * remove: 지출 추가 로직 변경으로 인해 사용하지 않는 파일 제거 * feat: 첫번째 Input에 focus 적용 * feat: 첫번째 DynamicInput에 autoFocus 적용 * fix: StepListProps 속성이 없어서 발생하는 에러 해결 --------- Co-authored-by: 이태훈 Co-authored-by: pakxe , soi-ha , jinhokim98 Co-authored-by: JinHo Kim Co-authored-by: Pakxe Co-authored-by: pakxe Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: kunsanglee Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: Soyeon Choe Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> Co-authored-by: Arachneee Co-authored-by: juha Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> Co-authored-by: JUHA <84626225+khabh@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JUHA Co-authored-by: Arachne * fix: height가 짤리는 버그 해결 (#434) * fix: 차등 적용 인원이 2명일 때 계산되지 않는 버그 (#435) * fix: 나머지 1명만 조정치가 아닐 때 계산이 되지 않았던 버그 수정 * test: 2명일 때의 테스트 진행 * fix: 마지막 사람이 값이 변경될 수 없으므로 (input = disabled 처리) 관련 로직 훅에서 제거 * test: 발생할 수 없는 테스트 제거 * feat: 랜딩페이지 구현 (#418) * feat: 랜딩페이지 구현 * style: lint 적용 * fix: 문구 수정 * style: lint 적용 * fix: 랜딩페이지 화면의 변화에 따른 e2e 테스트 코드 변경 --------- Co-authored-by: 김진호 * fix: 랜딩페이지 Nav 버그 수정 (#438) * chore: 사용하지 않는 import 제거 * fix: maxWidth를 추가하여 데스크탑에서 Nav가 정상적으로 렌더링되도록 수정 * fix: totalPrice를 새로운 입력값으로 넘겨주지 않았던 문제 해결 (#442) * fix: 배경색상 height 버그 (#443) * chore: 사용하지 않는 코드 제거 * fix: 배경 heigth가 잘리는 문제를 background color를 넣어 해결 * fix: 백그라운드 수정 (#447) * fix: 멤버가 변동됐을 때 지출 상세 정보 데이터가 날라가지 않는 버그 수정 (#448) * fix: 차등 정산 모달에서 수정 완료 버튼을 누를 때 보내는 2개의 api의 순서를 보장하고 변동이 없으면 요청을 보내지 않도록 함 (#455) * feat: callback을 넘겨받아 api 요청 순서를 보장할 수 있도록 함 * fix: 지출 내역을 수정하고 나서 정상 응답이 와야 차등 정산 요청을 보내도록 함 * feat: 변경이 발생한 것에 대해서만 요청이 가도록 수정 * feat: 모달 자동 닫히도록 onClose전달 * feat: onClose를 전달해 모달을 닫는 함수를 스스로 호출하도록 함 * test: 훅에서 받는 인자가 수정되었으므로 이를 반영 * feat: onSuccessCallBack 을 없앰 * feat: Step에 stepName 반영하기 (#452) * feat: 서버로 부터 받은 stepName 출력 * feat: 마지막 action의 stepName에서 1을 더한 값을 새로 생성한 stepName에 넣기 * chore: 백엔드의 요청으로 인해 인원수 click시 BottomSheet가 띄워지지 않도록 주석처리 * fix: async, await 이 없어서 api 순서 보장이 안되기 때문에 추가 (#462) * [FE] 지출 Input 금액 default 변경 및 autoFocus (#470) * feat: 지출 내역 금액 default가 0이 아닌 ‘’로 변경 * feat: 지출 내역을 추가하면 title에 autoFocus * feat: enter 키를 눌렀을 때 handleBlurBillRequest가 실행되는 기능 추가 * feat: StepList에 isFixed 디자인시스템 반영 (#465) * chore: v0.1.77 배포 * chore: 디자인 시스템 적용 * fix: 변동된 금액인지를 나타내는 isFixed prop 추가 * feat: 차등 정산 적용시 신선한 데이터가 바로 반영되지 않고 시간차를 두고 반영되는 부분 수정 (#458) * feat: 차등 정산 내용이 수정되었을 경우 낙관적 업데이트 적용 * feat: any제거하고 타입 적용 * fix: 차등정산 수정 후 다시 로드 시 깜빡이는 현상 해결 --------- Co-authored-by: 김진호 * feat: 관리자 로그인 페이지에서 스위치가 관리로 활성화되지 않는 버그 (#469) * fix: 관리페이지 로그인에서도 top nav 관리 탭으로 활성화 되도록 수정 * refactor: useEventLogin으로 훅 분리 * refactor: DB 데이터를 drop 할 수 없도록 DB user 권한 수정합니다. (#485) * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim Co-authored-by: Pakxe * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe * design: 기본 css style 초기화 작업 Co-authored-by: pakxe * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe * design: 전역 스타일링 설정 Co-authored-by: pakxe * feat: 라우터 셋팅 Co-authored-by: pakxe * feat: 앱의 진입점 설정 Co-authored-by: pakxe * feat: 라우트 경로 설정 Co-authored-by: pakxe * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe * feat: 인원 관리 기능구현 Co-authored-by: pakxe * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha * feat: Input component 구현 Co-authored-by: soi-ha * feat: Title component 구현 Co-authored-by: soi-ha * feat: BottomSheet component 구현 Co-authored-by: soi-ha * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha Co-authored-by: Soyeon Choe * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 Co-authored-by: Soyeon Choe Co-authored-by: pakxe * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee * refactor: 메서드 분리 Co-authored-by: kunsanglee * refactor: 코드 컨벤션 Co-authored-by: kunsanglee * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: 메서드 순서 변경 Co-authored-by: Arachne --------- Co-authored-by: kunsanglee Co-authored-by: Arachne authored-by: khabh * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh --------- Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee Co-authored-by: Arachneee Co-authored-by: khabh * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 Co-authored-by: 김진호 Co-authored-by: pakxe * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 Co-authored-by: pakxe * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 클라이언트 코드 삭제 * refactor: CD workflow main, develop 분리 (#163) * refactor: CD workflow main, develop 분리 및 dockerfile 수정 * refactor: trigger test 브랜치 추가 * refactor: feature/#147 에 push test * refactor: github actions self-hosted runner tag 추가 * refactor: feature/#147 runner 구분 테스트 * refactor: feature/#147 prod runner 구분 테스트 * refactor: feature/#147 prod runner 구분 테스트2 * refactor: feature/#147 prod runner 구분 테스트3 * refactor: feature/#147 prod runner 구분 테스트3 * refactor: prod, dev yml 분리 완료 및 서버 테스트 완료 * feat: 로그 모니터링 환경 구축 (#169) * feat: 예외메시지 구체화 (#161) * feat: 예외 핸들링 추가 * refactor: 예외 메시지 구체화 및 검증 역할 변경 * feat: 에러 코드 추가 * style: 개행 제거 * refactor: 멤버 액션 예외 ErrorCode 분리 * feat: 로깅 추가 * refactor: 액션 이력 조회 리펙토링 (#141) * feat: 멤버 액션 삭제 기능 구현 (#181) * feat: 액션 삭제 기능 구현 중 지출 삭제 가능, 인원 삭제는 아직입니다. * feat: 멤버 액션 삭제 구현 Co-authored-by: pakxe Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee * feat: 맴버 액션 삭제 기능 구현 * refactor: api 매개변수에 값 넣도록 수정 * fix: 테스트 코드에 action 올바르게 사용하도록 수정 --------- Co-authored-by: 김진호 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: pakxe * feat: ERD svg 생성하여 스키마 변경에 대한 이력 관리 (#190) * feat: 지출 액션 수정 기능 구현 (#180) * feat: 지출 액션 삭제 기능 구현 (#179) * feat: 행사의 전체 참여자 중 특정 참여자의 멤버 액션을 모두 삭제하는 기능 구현 (#185) * feat: 행사의 전체 참여자 중 특정 참여자의 멤버 액션을 모두 삭제하는 기능 구현 * test: eventId String으로 변경 * fix: 다른 행사에 있는 멤버 액션도 지워지는 버그 수정 * refactor: 전체 참여자 중에서 특정 참여자를 전부 삭제하는 메서드명 변경 * refactor: 전체 참여자 중에서 특정 참여자를 전부 삭제하는 메서드명 변경 * refactor: MemberActionController 메서드 파라미터 컨벤션 반영 * refactor: conflict resolve * refactor: conflict resolve * feat: 행사에 참여한 전체 인원 조회 기능 구현 (#195) * feat: 행사에 참여한 전체 인원 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * refactor: EventServiceTest, MemberActionRepository 코드 리팩터링 * fix: workflows runs-on self-hosted로 변경 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: workflows runs-on self-hosted로 변경 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: workflows runs-on self-hosted로 변경 Co-authored-by: 3juhwan <13selfesteem91@naver.com> --------- Co-authored-by: kunsanglee * feat: 행사 참여 인원 이름 변경 기능 구현 (#197) * feat: 행사 참여 인원 이름 변경 기능 구현 * refactor: 지출 액션 수정 기능 리펙토링 --------- Co-authored-by: Arachneee * refactor: API 엔드포인트 수정 (#200) * refactor: 멤버 액션, 지출 액션 관련 API 엔드포인트 수정 * refactor: 요청 url에 token을 eventId로 수정 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * feat: 테스트 데이터 클리너 구현 (#199) * feat: 테스트 데이터 클리너 구현 * feat: 테스트 클리너 상수, 메서드 분리 * refactor: 데이터베이스 클리너 적용 * feat: 행사 관리자 비밀번호 추가 (#213) * feat: 이벤트 비밀번호 추 * test: 테스트 공통 설정 클래스 분리 * feat: 어드민 인터셉터 추가 및 jwt 설정 추가 * feat: 이벤트 로그인 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh * feat: 쿠키 설정 분리 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh * submodule 업데이트 * style: 주석 제거 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh * refactor: 로컬 환경 쿠키 secure 옵션 제거 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh * test: 접근제어자 수정 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh * test: 개행 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh * fix: 쿠키 인증 버그 수정 (#222) Co-authored-by: khabh * fix: 쿠키 인증 버그 수정 (#235) * refactor: 에러 코드 재정의 (#227) * refactor: 에러 코드 재정의 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: 변수를 받는 예외 메세지 수정 Co-authored-by: 3juhwan <13selfesteem91@naver.com> --------- Co-authored-by: kunsanglee Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * fix: 쿠키 저장 오류 2차 수정 (#237) * fix: 쿠키 인증 버그 수정 Co-authored-by: khabh * fix: 쿠키 인증 버그 수정 --------- Co-authored-by: khabh * feat: REST docs를 통한 문서화 (#238) * feat: REST Docs 적용 * feat: REST Docs prettyPrint 및 snippets 적용 * feat: REST Docs에 예외 항목 추가 * test: 행사 액션 이력 조회 테스트 추가 * refactor: 중복된 http-request snippet 제거 * refactor: 사용되지 않는 snippet 제거 * refactor: 빌드 시 자동으로 문서 최신화하도록 gradle 설정 추가 * fix: CookieProperties에 sameSite 옵션 추가 --------- Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * fix: JWT 유효기간 만료 버그 수정 (#248) * fix: JWT 기간 오류 수정 * fix: JWT 기간 오류 수정 * feat: 관리자 권한 확인 API 구현 (#259) * feat: 관리자 권한 확인 API 구현 * backend-pull-request workflow 파일 수정 * feat: HTTP Method를 POST에서 GET으로 변경 * fix: 참여자 삭제 서비스 메서드에 Transactional 추가 (#265) Co-authored-by: 3juhwan <13selfesteem91@naver.com> * refactor: application.yml metrics 추가 (#269) * feat: CI/CD 숙제 (#290) * feat: CI/CD 숙제 (#291) * refactor: 행사 참여 인원 이름 변경 api 수정 (#268) * refactor: 회원 이름 변경 api 여러명으로 추가 * style: 메소드 순서 변경 * fix: rest docs 저장 파일 위치 변경 (#273) * fix: 어드민 권한 확인 불가 버그 수정 (#275) * fix: 행사 로그인 불가 버그 수정 (#283) * fix: CI/CD 트리거 조건에서 server 폴더 조건 제거 (#308) * fix: CI 트리거 조건을 수정 * feat: be-dev CD 트리거 조건에서 server 폴더 제거 * feat: pr 머지시 issue close 기능 추가 (#309) * refactor: yml, Dockerfile TZ Asia/Seoul 적용 (#305) Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * refactor: actuator health 엔드포인트 설정 변경 (#303) * feat: actuator health 엔드포인트 설정 변경 * refactor: AdminInterceptor log level 변경 --------- Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * feat: 서버 로그 볼륨 마운트 설정 (#300) * feat: 로그 파일 볼륨 설정 * feat: 볼륨 이름 지정 * feat: LogBack 롤링 정책 수정, 로그 레벨에 따른 분리 (#332) * feat: Logback 로그 레벨 분리 * feat: Lockback 로그 레벨 분리 --------- Co-authored-by: Arachneee * fix: 서브 모듈 프로파일 오타 수정 (#334) * refactor: 현재 참여 인원 목록 조회 API 반환 형식 수정 (#361) * feat: BillActionDetail 베이스 코드 생성 (#363) * feat: 액션 이력 조회 v2 기능 구현 (#375) * [BE] 행사 참여 인원 또는 지출 총액 변동시 차등 정산 초기화 기능 구현 (#370) * feat: 지출 액션 수정시 지출 디테일 초기화 기능 구현 * feat: 맴버 액션 삭제시 지출 디테일 초기화 기능 구현 * feat: 맴버 삭제시 지출 디테일 초기화 기능 구현 * fix: 버그 수정 * fix: 버그 수정 * feat: 요구사항 변경에 따른 지출 내역 추가, 지출 액션 삭제 API 수정 (#373) * feat: 지출 내역 추가 시, 상세 내역 생성 로직 추가 * feat: 지출 내역 삭제 시, 상세 내역 삭제 로직 추가 * fix: 멤버가 없는 상황에 대해 0으로 나누는 상황 방지 * refactor: 참여자별 정산 현황 조회 및 액션 이력 조회 수정 (#377) * refactor: BillActionDetail 변경 사항을 반영하여 참여자별 정산 현황 조회하도록 수정 * refactor: 액션 이력 조회 시 지출 액션 고정 금액 설정 여부 필드 추가 * refactor: isFixed 필드 삭제 * refactor: 메서드 이름 변경 * fix: BillAction 변경 로직 수정 * feat: 참여자 개별 지출 금액 수정 및 조회 기능 구현 (#378) * feat: 참여자 개별 지출 금액 수정 기능 구현 * refactor: BillActionDetailService 코드 리팩터링 * docs: restdocs 작성 * feat: 참여자별 지출 금액 조회 기능 구현 * docs: index.adoc에 billActionDetail.adoc 추가 * refactor: 충돌 해결 * feat: 에러를 재현할 수 있는 로그로 수정 (#392) * feat: 로깅에 요청 정보 포함 * feat: 개발 환경 ddl update로 변경 * feat: 예외 처리 및 로깅 형식 수정 (#394) * fix: 리스트 형태의 요청 바디에 null을 넣으면 500이 뜨는 에러 수정 * feat: 로그를 json 형태로 수정 * feat: 예외 처리 및 로깅 형식 수정 (#395) * fix: 리스트 형태의 요청 바디에 null을 넣으면 500이 뜨는 에러 수정 * feat: 로그를 json 형태로 수정 * feat: 로그를 json 인덴트 추가 * refactor: BillActionDetail isFixed 추가 (#405) * fix: 로깅 적용 후 예외 응답 불가 버그 수정 (#413) * feat: 액션 이력 조회 stepName 추가 (#420) * feat: 이슈, PR 템플릿 추가 (#160) (#426) * fix: BillAction 수정시 BillDetail 초기화 안되는 버그 수정 * fix: BillAction 수정시 BillDetail 초기화 안되는 버그 수정 * fix: BillAction 수정시 BillDetail 초기화 안되는 버그 수정 * docs: pr issue close 삭제 * feat: 행사 비밀번호 암호화 추가 (#429) * feat: 행사 비밀번호 암호화 추가 * refactor: 비밀번호 암호화 로직 수정 * fix: MessageDigest를 싱글톤으로 관리하지 않도록 수정 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: BillActionDetail 초기화시 totalPrice와 정합성 안맞는 버그 수정 (#460) * fix: BillActionDetail 초기화시 totalPrice와 정합성 안맞는 버그 수정 * refactor: BillActionDetail 초기화 로직 BillAction으로 위임 * style: 메소드 이름 수정 * refactor: BillActionDetail 계산 공통 로직 메소드 분리 * fix: price 분배 로직 버그 수정 * style: 미사용 필드 제거 --------- Co-authored-by: Arachneee * refactor: DB 데이터를 drop 할 수 없도록 DB user 권한 수정 (#484) --------- Co-authored-by: 이태훈 Co-authored-by: pakxe , soi-ha , jinhokim98 Co-authored-by: JinHo Kim Co-authored-by: Pakxe Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Soyeon Choe Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> Co-authored-by: Arachneee Co-authored-by: juha Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> Co-authored-by: JUHA <84626225+khabh@users.noreply.github.com> Co-authored-by: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * fix: 배경 색이 잘리는 문제 해결 (#466) * design: 생성 페이지 background 설정 * design: 메인 레이아웃 light gray 색 추가 * design: 홈페이지 padding bottom 2rem 추가 * design: root의 height auto로 설정 및 배경색 제거 * design: 효과없는 height 100% 제거 * design: 바텀시트 삭제로 어드민 페이지 패딩 바텀 조정 * feat: Flex prop min height 속성 추가, 알고보니 min-height 속성이 있어야 화면이 꽉 채워짐 * feat: title과 price에 값이 존재하지 않을 경우 지출 input 닫기 (#472) * feat: 디자인시스템 일부 수정 (#475) * design: 통일성 위해 디자인 수정 * chore: v0.1.78 배포 * chore: hdesign 0.1.78 적용 * chore: v0.1.79 배포 및 적용 * feat: 버튼 로딩 구현 및 이벤트 생성 페이지에 적용 (#476) * design: 통일성 위해 디자인 수정 * chore: v0.1.78 배포 * chore: hdesign 0.1.78 적용 * chore: v0.1.79 배포 및 적용 * chore: lottie-react dependency 추가 * chore: json file 읽을 수 있도록 설정 * feat: button의 loading variants 추가 * chore: v0.1.80 배포 * chore: hdesign 신규 버전 적용 * feat: 행사 생성이 pending 상태이면 button isLoading으로 변경 * style: lint 적용 * chore: lottie-react import ignore 하도록 변경 * fix: lottie-react를 mocking하여 lottie가 렌더링 시 테스트가 실패하지 않도록 변경 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * fix: 행사 생성 완료 페이지 변경 (#478) * fix: placeholder 추가 (#480) * fix: 지출 내역 금액 부분에 문자가 입력되던 오류 수정 (#491) * fix: dropdown animation 버그 수정 (#493) * chore: React-Query devtools 환경 설정 (#463) * chore: devtools 설치 * chore: stale time, gctime 셋팅 임시로 1분 설정 * chore: amplitude 적용 (#335) * feat: react-query에 맞는 error handling 적용 (#415) * chore: 디자인시스템 버전 적용 * rename: 파일 이름 변경 * fix: 사용하지 않는 Error 처리 로직 삭제 * feat: 전역 에러 상태 생성 * fix: 바뀐 파일 이름 적용 * fix: ToastProvider 내에서 에러 처리 로직 제거 * refactor: AppErrorBoundary 및 QueryClientBoundary를 통한 에러 처리 * fix: 사용하지 않는 코드 임시적으로 주석 처리 TODO: 테스트 코드 역할 위임 * mover: AppErrorBoundary, QueryClientBoundary 코드 위치 변경 * fix: test 코드 변경 * chore: jest path alias 적용 * test: AppErrorBoundary 테스트코드 작성 * remove: 사용하지 않는 코드 삭제 * fix: 사용하지 않는 코드 주석처리 * fix: AppErrorBoundary, QueryClientBoundary 로직 수정 * test: AppErrorBoundary test코드 작성 * style: lint 적용 * feat: App에 ErrorBoundary 추가 * feat: UnhandledErrorBoundary 컴포넌트 구현 * feat: 에러를 구독하며 핸들링되는 에러면 토스트, 핸들링 불가능한 에러면 에러 바운더리를 띄우도록 하는 캐처 구현 * feat: 에러 페이지에 메일 추가 * feat: errorInfo를 안에서 구현하는 것이 아닌 구현된 것을 인자로 받도록 수정 * chore: 파일 위치 수정에 따라 import 경로 수정 * chore: 불필요해진 파일 제거 * chore: 개행 추가 * feat: ErrorCatcher에 대한 테스트 코드 작성 * feat: Toast의 showingTime 을 옵셔널로 수정 * chore: 없어진 컴포넌트를 renderHook에서 제거 * refactor: return문이 반복되는 부분을 리펙터링 * feat: useToast에 대한 테스트코드 작성 * chore: 사용하지 않는 파일 제거 * chore: 불필요한 파일이 커버리지에 뜨지 않도록 ignore에 추가 * rename: 파일명 오타 수정 * chore: import 경로 수정 * chore: 병힙 * chore: 라이브러리 오류로 인해 테스트 통과가 안되므로 디자인 시스템 라이브러리 다운그레이드 --------- Co-authored-by: pakxe * fix 행사 인원 이름 변경시 지출 상세의 이름이 변경되지 않는 버그 수정 (#500) * fix: 로딩 라이브러리 도입으로 인해 테스트가 터지는 문제를 해결 (#501) * fix: canvas를 로딩하기 위한 라이브러리 설치후 jest.setup에 적용 * chore: 불필요한 import 제거 * fix: 참여자 이름 변경시 지출 상세 이름 변경 안되는 버그 수정 (#508) * feat: 비밀번호 4자리 넘게 적용되는 오류 수정 (#503) * chore: v0.1.81 배포 * fix: 비밀번호 4자리 넘게 입력 가능한 오류 수정 * fix: BottomSheet가 조건부 렌더링 되도록 변경 (#506) * feat: 홈페이지에서 지출 내역 눌렀을 때 차등 정산 모달 뜨기 (#507) * feat: 홈화면에서 지출 내역 상세 모달이 뜨도록 함 * chore: 사용하지 않는 코드 제거 * feat: 행동대장 흔듯콘(파비콘), 로고 적용 (#496) * feat: 새로운 행동 강아지 삽입 * feat: favicon 적용 * fix: 흔듯콘 logo에 사용 * style: lint 적용 --------- Co-authored-by: Soyeon Choe Co-authored-by: 이태훈 * feat: meta tag 링크 복사 이미지와 설명 추가 (#510) * feat: og tag 설정 (링크 붙여넣기 할 때 이미지와 소개글 나오도록 설정) * feat: 행댕이 이미지 삽입 * feat: description 수정 * fix: 지출 내역 및 전체 참여자 버그 (#511) * fix: 전체 참여자 삭제 후 수정 요청 순서 보장 * fix: 이름 변경 수정이 존재하지 않는 상황에서도 nameChange api 요청이 전송되지 않도록 수정 * fix: 현재 필요하지 않는 hasDragHandler를 false로 변경 * fix: 인원 변동 요청을 한 후 input에 value 값이 초기화 되지 않는 버그 해결 * fix: bill 액션이 없는 상태에서 BillInput을 닫을 때 BillContainer가 사리지지 않는 버그 해결 * chore: console.log 삭제 * fix: build를 위한 없는 파일 import 제거 (#513) * fix: default 값이 빈문자열로 변경 * chore: build를 방해하는 import 제거 * fix: og tag 이미지 해상도 변경 (#515) * feat: 행동대장 v1.0.0 (#516) * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim Co-authored-by: Pakxe * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe * design: 기본 css style 초기화 작업 Co-authored-by: pakxe * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe * design: 전역 스타일링 설정 Co-authored-by: pakxe * feat: 라우터 셋팅 Co-authored-by: pakxe * feat: 앱의 진입점 설정 Co-authored-by: pakxe * feat: 라우트 경로 설정 Co-authored-by: pakxe * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe * feat: 인원 관리 기능구현 Co-authored-by: pakxe * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha * feat: Input component 구현 Co-authored-by: soi-ha * feat: Title component 구현 Co-authored-by: soi-ha * feat: BottomSheet component 구현 Co-authored-by: soi-ha * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha Co-authored-by: Soyeon Choe * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 Co-authored-by: Soyeon Choe Co-authored-by: pakxe * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee * refactor: 메서드 분리 Co-authored-by: kunsanglee * refactor: 코드 컨벤션 Co-authored-by: kunsanglee * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: 메서드 순서 변경 Co-authored-by: Arachne --------- Co-authored-by: kunsanglee Co-authored-by: Arachne authored-by: khabh * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh --------- Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee Co-authored-by: Arachneee Co-authored-by: khabh * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 Co-authored-by: 김진호 Co-authored-by: pakxe * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 Co-authored-by: pakxe * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 서버 코드 삭제 * [FE] 스프린트3 디자인 수정 (#162) * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 * chore: branch 변경에 따른 yml 파일 수정 (#165) * fix: 스토리북 워크플로우 오류 (#168) * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 * feat: 토스트 생성 (#166) * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim Co-authored-by: Soyeon Choe --------- Co-authored-by: pakxe Co-authored-by: JinHo Kim Co-authored-by: Soyeon Choe * fix: client 디렉토리 reset, 전역 스타일 GlobalStyle을 사용하는 것으로 변경 (#173) * refactor: css를 global style로 수정 Co-authored-by: Pakxe * refactor: global style app과 index에 적용 Co-authored-by: Pakxe * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe --------- Co-authored-by: Pakxe * design: Button이 disabled일 때 커서가 포인터가 아니도록 수정 (#171) * feat: Input 컴포넌트 관련한 기능 수정, useDynamic-* 훅 관련 오류 수정, 네이밍 통일, 의미를 명확하게 담도록 네이밍 수정 (#143, #183) * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * style: lint 적용 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 Co-authored-by: Soyeon Choe Co-authored-by: Soyeon Choe Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe Co-authored-by: jinhokim98 * feat: 변경된 API endpoint로 수정 (#196) * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: 디자인시스템 hover, mouse, transition animation (#198) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * [FE] ListButton component 생성 (#203) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * feat: 개별 ActionItem 컨트롤을 위한 StepItem 및 BillItem / InOutItem component 구조 변경 (#211) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 * feat: 삭제 아이콘을 위한 IconButton component 수정 (#209) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 * feat: 멤버 액션 삭제 기능 구현 + 바뀐 디자인시스템 적용 (#214) * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA Co-authored-by: Arachne * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe Co-authored-by: JUHA Co-authored-by: Arachne Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * fix: FixedButton의 delete button type "button"으로 변경 (#234) * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 * feat: 행사생성 flow에서 admin 접근을 위한 비밀번호를 입력받는 기능 추가 (#226) * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 * feat: 지출 액션 수정, 삭제 기능 구현 (#230) * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 * feat: 전체 참여자 BottomSheet 내부 디자인 퍼블리싱 (#228) * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 * feat: api에러 등의 에러를 잡아 핸들링 (#232) * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 * chore: 빌드 환경 prod와 dev로 구분 (#217) * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 * fix: merge를 통해 발생한 에러 해결 (#246) * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 * fix: input value 수정이 되지 않는 문제 (#253) * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 * fix: useToast 에러바운더리 문제 해결 (#264) * fix: 디자인시스템 Text 컴포넌트 color prop 받도록 변경 (#257) * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 * fix: 디자인시스템 Input value 동기화 오류 수정 (#266) * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish * fix: 행동디자인 Search 컴포넌트 기능 제거 (#260) * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 * feat: 행사 생성 완료 페이지 유저 친화적으로 변경 (#271) * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 * feat: 인원 탈주 시 인원 검색 기능 구현 (#270) * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 데이터 요청하고 출력하기 (#250) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 이름 수정 및 삭제 (#276) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 * feat: sentry 적용 (#262) * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 3차 데모데이 merge 중 발생한 문제 수정 (#280) * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 * feat: requestPost에 대해 response가 있는 post와 없는 post로 분기해 사용하도록함 (#281) * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 * feat: 홈에서 액션 수정 삭제 바텀시트 활성화 버그 (#285) * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 * feat: cookie가 없는 경우 비밀번호 입력 페이지로 이동 (#286) * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 * feat: 데모데이를 위해 페이지 약간 수정 (#289) * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 * fix: import 가 안되어있는 부분 수정 (#293) * fix: 인원 탈주 검색 인풋 오류 (#299) * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 * chore: hooks폴더 구조 정리 (#312) * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 * feat: 전체 참여자 수정 및 삭제 수정 (#315) * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 * feat: 차수 멤버 확인, useFetch 확장, BottomSheet 활성화 수정 (#311) * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 * feat: 참여 인원 확인 임시 버튼 삭제 (#318) * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 * feat: bottomSheet maxWidth 768px 되도록 변경 (#321) * feat: 메인, 관리 페이지 설명 글 수정 (#324) * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 * fix: useDynamicInput 버그 수정 (#327) * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 * feat: 홈 및 관리 페이지에서 링크 복사 기능 추가 (#329) * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: pr issue close workflow 생성 (#328) * test: cypress 적용 및 행사 생성 flow e2e 테스트 작성 (#331) * chore: cypress 설정 Co-authored-by: JinHo Kim * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim * fix: 토큰이 없을 때, 관리페이지로 이동하면 오류가 발생하는 부분 수정 (#338) * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 * fix: 인원 탈주 추가 시 disable 버그 (#339) * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 * feat: Sentry prod 환경에서만 돌아가도록 fetcher 설정 (#343) * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 * feat: 환경 변수 타입 선언 (#345) * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * feat: useDeleteMemberAction 토스트 함수 결합도 제거 (#347) * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 * feat: 사용성 개선 - Title component 변경 및 UX writing 수정 (#352) * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 * feat: 비밀번호 입력 페이지 커스텀 훅으로 분리 (#354) * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 * fix: 탭 클릭 시 전체가 클릭되는 것처럼 보이는 현상 해결 (#356) * feat: 사용성 개선 - 지출 내역 입력 아이템 구현 (#357) * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * refactor: 행사 생성 완료 페이지에서 불필요한 상태 제거 (#350) * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 * fix: 인원 탈주 시 검색이 되지 않는 버그 해결 (#368) * fix: 머지하면서 신경쓰지 못한 코드오류 해결 (#381) * feat: Input 검증 에러 메시지 타입 구조 변경 (#376) * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 * feat: 공통 input 코드를 useInput hook으로 분리 (#379) * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 * test: 훅에 필요한 테스트 추가 (#358) * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 * refactor: 멤버 액션 삭제 훅 리팩토링 (#383) * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. * refactor: 이벤트 생성 페이지 리팩토링 (#385) * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 * test: useError, useToast 테스트코드 작성 (#387) * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 * feat: Zustand, react-query 도입 및 적용 (#388) * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 Co-authored-by: Soyeon Choe * fix: valideMemberName의 조건문 name은 1 이하일 수 없다를 제거 (#396) Co-authored-by: Soyeon Choe * feat: 총액 업데이트 로직을 store안으로 이동 (#401) * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 * fix: action log가 길어질 때 heigth 잘리는 버그 수정 (#408) * feat: 전체 인원 수정 '삭제' api 로직 롤백 수정 (#409) * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 * feat: EditableItem.Input이 동적인 width를 갖도록 수정 (#411) * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 * feat: 차등 정산 기능 구현 및 테스트 작성 (#406) * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 * feat: 차등 적용 적용 중 지원되지 않는 기능 수정 (#423) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: 차등 적용 can submit이 valid 하지만 false되는 버그 (#428) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 * feat: 지출 내역 추가 변경사항 적용 (#414) * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 * feat: 지출 내역 아이템 클릭시 뜨는 차등 정산 모달 퍼블리싱 (#431) * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 * feat: BottomSheet 지출 부분 삭제 & input autoFocus (#433) * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim Co-authored-by: Pakxe * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe * chore: css파일을 처리하기 위한 webpack 세팅 Co-author… * feat: 지출 내역이 없을 때 홈페이지에서 없다고 띄우기 (#520) * feat: 데이터가 없는 경우 없다고 띄우는 기능 추가 * feat: 지출 상세 데이터를 return하도록 함 * chore: 라이브러리 업데이트 (#525) * chore: 충돌 해결 * feat: 행동대장 v1.0.1 * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim Co-authored-by: Pakxe * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe * design: 기본 css style 초기화 작업 Co-authored-by: pakxe * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe * design: 전역 스타일링 설정 Co-authored-by: pakxe * feat: 라우터 셋팅 Co-authored-by: pakxe * feat: 앱의 진입점 설정 Co-authored-by: pakxe * feat: 라우트 경로 설정 Co-authored-by: pakxe * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe * feat: 인원 관리 기능구현 Co-authored-by: pakxe * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha * feat: Input component 구현 Co-authored-by: soi-ha * feat: Title component 구현 Co-authored-by: soi-ha * feat: BottomSheet component 구현 Co-authored-by: soi-ha * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha Co-authored-by: Soyeon Choe * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 Co-authored-by: Soyeon Choe Co-authored-by: pakxe * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee * refactor: 메서드 분리 Co-authored-by: kunsanglee * refactor: 코드 컨벤션 Co-authored-by: kunsanglee * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: 메서드 순서 변경 Co-authored-by: Arachne --------- Co-authored-by: kunsanglee Co-authored-by: Arachne authored-by: khabh * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh --------- Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee Co-authored-by: Arachneee Co-authored-by: khabh * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 Co-authored-by: 김진호 Co-authored-by: pakxe * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 Co-authored-by: pakxe * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 서버 코드 삭제 * [FE] 스프린트3 디자인 수정 (#162) * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 * chore: branch 변경에 따른 yml 파일 수정 (#165) * fix: 스토리북 워크플로우 오류 (#168) * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 * feat: 토스트 생성 (#166) * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim Co-authored-by: Soyeon Choe --------- Co-authored-by: pakxe Co-authored-by: JinHo Kim Co-authored-by: Soyeon Choe * fix: client 디렉토리 reset, 전역 스타일 GlobalStyle을 사용하는 것으로 변경 (#173) * refactor: css를 global style로 수정 Co-authored-by: Pakxe * refactor: global style app과 index에 적용 Co-authored-by: Pakxe * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe --------- Co-authored-by: Pakxe * design: Button이 disabled일 때 커서가 포인터가 아니도록 수정 (#171) * feat: Input 컴포넌트 관련한 기능 수정, useDynamic-* 훅 관련 오류 수정, 네이밍 통일, 의미를 명확하게 담도록 네이밍 수정 (#143, #183) * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * style: lint 적용 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe Co-authored-by: jinhokim98 * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 Co-authored-by: Soyeon Choe Co-authored-by: Soyeon Choe Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe Co-authored-by: jinhokim98 * feat: 변경된 API endpoint로 수정 (#196) * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: 디자인시스템 hover, mouse, transition animation (#198) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * [FE] ListButton component 생성 (#203) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * feat: 개별 ActionItem 컨트롤을 위한 StepItem 및 BillItem / InOutItem component 구조 변경 (#211) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 * feat: 삭제 아이콘을 위한 IconButton component 수정 (#209) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 * feat: 멤버 액션 삭제 기능 구현 + 바뀐 디자인시스템 적용 (#214) * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA Co-authored-by: Arachne * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe Co-authored-by: JUHA Co-authored-by: Arachne Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * fix: FixedButton의 delete button type "button"으로 변경 (#234) * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 * feat: 행사생성 flow에서 admin 접근을 위한 비밀번호를 입력받는 기능 추가 (#226) * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 * feat: 지출 액션 수정, 삭제 기능 구현 (#230) * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 * feat: 전체 참여자 BottomSheet 내부 디자인 퍼블리싱 (#228) * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 * feat: api에러 등의 에러를 잡아 핸들링 (#232) * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 * chore: 빌드 환경 prod와 dev로 구분 (#217) * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 * fix: merge를 통해 발생한 에러 해결 (#246) * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 * fix: input value 수정이 되지 않는 문제 (#253) * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 * fix: useToast 에러바운더리 문제 해결 (#264) * fix: 디자인시스템 Text 컴포넌트 color prop 받도록 변경 (#257) * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 * fix: 디자인시스템 Input value 동기화 오류 수정 (#266) * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish * fix: 행동디자인 Search 컴포넌트 기능 제거 (#260) * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 * feat: 행사 생성 완료 페이지 유저 친화적으로 변경 (#271) * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 * feat: 인원 탈주 시 인원 검색 기능 구현 (#270) * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 데이터 요청하고 출력하기 (#250) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 이름 수정 및 삭제 (#276) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 * feat: sentry 적용 (#262) * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 3차 데모데이 merge 중 발생한 문제 수정 (#280) * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 * feat: requestPost에 대해 response가 있는 post와 없는 post로 분기해 사용하도록함 (#281) * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 * feat: 홈에서 액션 수정 삭제 바텀시트 활성화 버그 (#285) * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 * feat: cookie가 없는 경우 비밀번호 입력 페이지로 이동 (#286) * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 * feat: 데모데이를 위해 페이지 약간 수정 (#289) * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 * fix: import 가 안되어있는 부분 수정 (#293) * fix: 인원 탈주 검색 인풋 오류 (#299) * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 * chore: hooks폴더 구조 정리 (#312) * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 * feat: 전체 참여자 수정 및 삭제 수정 (#315) * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 * feat: 차수 멤버 확인, useFetch 확장, BottomSheet 활성화 수정 (#311) * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 * feat: 참여 인원 확인 임시 버튼 삭제 (#318) * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 * feat: bottomSheet maxWidth 768px 되도록 변경 (#321) * feat: 메인, 관리 페이지 설명 글 수정 (#324) * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 * fix: useDynamicInput 버그 수정 (#327) * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 * feat: 홈 및 관리 페이지에서 링크 복사 기능 추가 (#329) * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: pr issue close workflow 생성 (#328) * test: cypress 적용 및 행사 생성 flow e2e 테스트 작성 (#331) * chore: cypress 설정 Co-authored-by: JinHo Kim * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim * fix: 토큰이 없을 때, 관리페이지로 이동하면 오류가 발생하는 부분 수정 (#338) * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 * fix: 인원 탈주 추가 시 disable 버그 (#339) * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 * feat: Sentry prod 환경에서만 돌아가도록 fetcher 설정 (#343) * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 * feat: 환경 변수 타입 선언 (#345) * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * feat: useDeleteMemberAction 토스트 함수 결합도 제거 (#347) * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 * feat: 사용성 개선 - Title component 변경 및 UX writing 수정 (#352) * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 * feat: 비밀번호 입력 페이지 커스텀 훅으로 분리 (#354) * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 * fix: 탭 클릭 시 전체가 클릭되는 것처럼 보이는 현상 해결 (#356) * feat: 사용성 개선 - 지출 내역 입력 아이템 구현 (#357) * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * refactor: 행사 생성 완료 페이지에서 불필요한 상태 제거 (#350) * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 * fix: 인원 탈주 시 검색이 되지 않는 버그 해결 (#368) * fix: 머지하면서 신경쓰지 못한 코드오류 해결 (#381) * feat: Input 검증 에러 메시지 타입 구조 변경 (#376) * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 * feat: 공통 input 코드를 useInput hook으로 분리 (#379) * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 * test: 훅에 필요한 테스트 추가 (#358) * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 * refactor: 멤버 액션 삭제 훅 리팩토링 (#383) * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. * refactor: 이벤트 생성 페이지 리팩토링 (#385) * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 * test: useError, useToast 테스트코드 작성 (#387) * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 * feat: Zustand, react-query 도입 및 적용 (#388) * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 Co-authored-by: Soyeon Choe * fix: valideMemberName의 조건문 name은 1 이하일 수 없다를 제거 (#396) Co-authored-by: Soyeon Choe * feat: 총액 업데이트 로직을 store안으로 이동 (#401) * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 * fix: action log가 길어질 때 heigth 잘리는 버그 수정 (#408) * feat: 전체 인원 수정 '삭제' api 로직 롤백 수정 (#409) * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 * feat: EditableItem.Input이 동적인 width를 갖도록 수정 (#411) * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 * feat: 차등 정산 기능 구현 및 테스트 작성 (#406) * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 * feat: 차등 적용 적용 중 지원되지 않는 기능 수정 (#423) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: 차등 적용 can submit이 valid 하지만 false되는 버그 (#428) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 * feat: 지출 내역 추가 변경사항 적용 (#414) * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 * feat: 지출 내역 아이템 클릭시 뜨는 차등 정산 모달 퍼블리싱 (#431) * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 * feat: BottomSheet 지출 부분 삭제 & input autoFocus (#433) * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim Co-authored-by: Pakxe * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe , soi-ha , jinhokim98 * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: … * fix: number타입의 비밀번호를 4자리의 문자열로 받도록 수정 * fix: 지출 내역 이름 길이가 20자가 넘지 않도록 수정 * refactor: 디자인 시스템 폐지에 따른 폴더 구조 변경 (#543) * refactor: 디자인 시스템 폐지로 인한 폴더구조 변경 Co-authored-by: TaehunLee Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * chore: 파일 구조 변경에 따른 workflow 수정 * remove: server directory 삭제 * chore: workflow에서 cache 설정 제거 * fix: lint 적용 * fix: lint 설정 HDesign 추가로 인한 lint 수정 Co-authored-by: Soyeon Choe Co-authored-by: Pakxe * chore: workflow에 defaults 추가 * chore: alias jest에 추가 * chore: 의존성 정리 * refactor: hdesign svg를 assets로 이동 * fix: hdesign assets를 옮기면서 생긴 test 오류수정 * chore: chromatic log 추가 * chore: chromatic working-directory 추가 * chore: chromatic working-directory 위치 변경 * chore: chromatic cache dependencies 설정 추가 * chore: chromatic working-directory 제거 * chore: chromatic working directory 설정 다시 추가 * chore: chromatic 설정 변경 * fix: 스토리북 절대경로 제대로 설정 * chore: chromatic 배포 다시 설정 * chore: chromatic 배포 다시 설정 * fix: chromatic snapshot 변경 사항을 무시하고 CI 통과하도록 설정 * fix: working directory 다시 설정 --------- Co-authored-by: TaehunLee Co-authored-by: Pakxe Co-authored-by: Soyeon Choe * feat: 변경된 API 적용 및 사용하지 않는 코드 제거, 지출내역 추가 flow 및 UI 변경 (#574) * feat: NumberKeyboard 구현 * feature: Top Top.Line component 구현 및 행사 생성 플로우 UX 개선 * fix: 공백을 포함하지 않던 문제 수정 * refactor: useNumberKeyboard로 기능 관련 역할 분리 * feat: keyboard type에 string 추가 * style: lint 적용 * feature: CompleteCreateEventPage 변경 * refactor: api 변경에 따라, USER_API_PREFIX, ADMIN_API_PREFIX로 구분 * chore: MSW 설정 변경 중 TODO: intercept 되지 않는 오류 수정 중 * fix: 사용하지 않는 Button component의 isFull 속성 제거 * fix: mockEndpointPrefix 경로 수정 * feat: Amount Component 구현 * fix: meatball Icon 추가 * fix: 잘못 적용된 endpoint 적용 * fix: Title component 수정 * test: Top component storybook 추가 * feat: ListItem Component 추가 * feat: Chip Component 추가 * feat: ChipGroup Component 생성 * design: ChipGroup style 수정 * fix: FixedButton에 onBackClick prop 추가 * refactor: 변경된 api 구조에 맞게 수정 및 type 생성에 대한 통일화 * fix: 변경된 api에 맞게 MSW 코드 변경 * feature: ChipButton component 구현 * feature: AmountInput Component 구현 * design: Button disabled color 변경 * move: NumberKeyboard 위치 변경 * feature: AddBillFunnel page 구현 * fix: API 및 UX 변경사항으로 인해 함꼐 변경이 필요한 사항들 적용 * refactor: api 변경사항에 따른 request 함수들 및 react-query hook 변경 1. request 함수 내에서 Request type 선언하도록 변경 2. react-query에서 data를 정제 및 이름을 변경하여 return 하도록 변경 3. react-query hook들을 domain 별로 그룹화 4. react-qeury hook 및 request 함수 backEnd에서 사용하는 이름 및 model과 통일되도록 변경 Co-authored-by: Soyeon Choe Co-authored-by: JinHo Kim * move: NumberKeyboard component 위치 변경 * remove: 개선 과정에서 사용하지 않는 레거시 파일 삭제 Co-authored-by: Soyeon Choe Co-authored-by: JinHo Kim * fix: 현재 사용하지 않지만, 추후 사용 가능성이 있는 코드 이름 변경 및 주석 처리 Co-authored-by: Soyeon Choe Co-authored-by: JinHo Kim * refactor: API 변경 사항 및 전체 구조 변경에 따른 코드 반영 및 경로 수정, 이름 변경 Co-authored-by: Soyeon Choe Co-authored-by: JinHo Kim * fix: MSW mocking 해제 * style: lint 적용 * style: 사용하지 않는 코드 제거 * fix: NumberKeyboard import 잘못 지정된 오류 수정 * style: lint 적용 * fix: 사용하지 않는 테스트 코드 제거 --------- Co-authored-by: Soyeon Choe Co-authored-by: JinHo Kim * feat: 초대하기 OS 공유 기능 추가 (#548) * feat: 카카오 공유를 사용하기 위한 초기 설정 * feat: 모바일 디바이스를 감지할 수 있는 메서드 추가 * feat: 모바일 기기에서는 카카오톡 공유, 데스크탑에서는 텍스트 복사 유지 * style: 공유 텍스트 객체를 재사용 * fix: kakao api test 환경에선 돌아가지 않도록 설정 * chore: cypress-run node-env 추가 * fix: cypress에서 kakao init을 호출하지 않도록 mocking * fix: Cypress.on을 이용한 에러처리 무시; * fix: intercept 메서드 수정 * fix: test 환경이 아닌 경우 initialized도 읽지 않도록 변경 * fix: test 환경에선 돌아가지 않도록 부등호수정 * fix: window.kakao가 undefined일 경우 돌아가지 않도록 방어 * fix: 다시 blockKakao 복구 * style: member invite => share event로 컴포넌트 이름 변경 * refactor: event layout hook에서 share 책임 분리 * style: 카카오톡 공유 실행 함수 이름 변경 * style: useEventPageLayout hook 파일 이름 변경 * style: invite -> share로 용어 통일성 * refactor: isMobile 한 번만 호출되도록 변경 * fix: 변경된 구조로 인한 오류 수정 * feat: 참여자 별 내역에서 토스로 송금 유도하는 기능 (중간) (#556) * chore: png 확장자 추가로 인한 file-loader설치 및 png 확장자 선언 * feat: icon에 toss 타입 추가 * feat: 은행 선택 디자인 구현 * design: 은행선택 grid 반응형적용 * feat: 계좌번호 입력 플로우 생성 * fix: 콘솔 창 오류 제거 * fix: 은행 이름 변경 * design: 지출 리스트 갭 변경 * feat: 참여자 별 내역에서 은행아이콘(토스) 보이도록 설정 * feat: cansubmit 추가 * fix: 스토리북 prop 누락 추가 * chore: png도 jest mock되도록 설정 * fix: 테스트 환경에선 상대경로 api, 브라우저 환경에선 절대경로 api를 호출하도록 설정 * feat: 은행 송금 버튼 생성 * feat: 버튼 클릭 시 모바일 환경에서 토스로 넘기는 기능 * feat: 모바일 기기 감지 기능 구현 * refactor: 디자인 컴포넌트에 맞게 디자인 외 기능 외부로 분리 * style: Bank send Flex 컴포넌트 이용 * style: bank select Flex 컴포넌트 이용 * style: expense list flex 컴포넌트로 이용 * style: 사용하지 않는 import 제거 * style: fileMock -> imageFileMock으로 파일 이름 변경 * style: 사용하지 않는 코드 제거 * style: 사용 방식이 바뀐 코드 임시로 주석처리 * feat: 네트워크 상태가 오프라인일 경우 토스트로 안내하는 기능 (#568) * feat: 네트워크가 오프라인 상태가 되었을 때 토스트로 오프라인 상태임을 알리는 컴포넌트 구현 * feat: 외부에서 토스트를 닫기 위한 함수를 ToastProvider에서 return에 추가 * rename: NetworkCatcher -> NetworkStateCatcher로 직관적인 이름으로 변경 * feat: 네트워크 상태를 감지하기 위한 컴포넌트를 App에서 호출 * feat: 입금 상태를 관리하는 컴포넌트 DepositToggle 기능 구현 (#555) * design: DepositToggle 퍼블리싱 * feat: isDeposit에 따라 toggle 스타일 변경하기 * design: DepositToggle의 storybook 추가 * design: DepositToggle의 세로 중앙 정렬이 안되는 문제 해결 * design: toggle 흰 배경색상 transition 주기 * fix: DepositToggle animation 추가 * refactor: 사용하지 않은 코드 삭제 및 styleProps 구조 변경 * refactor: Text 컴포넌트의 class를 deposit-text로 통일시켜, p 태그에 스타일 사용으로 인한 부작용 방지 * refactor: WithTheme을 사용하여 스토리북 에러 해결을 간편하게 변경 * refactor: 스토리북에서 DepositToggle을 클릭시 focus가 변경되도록 수정 --------- Co-authored-by: 이태훈 * feat: 참여자 입금 상태, 참여자 이름 Chip 컴포넌트 구현 (#570) * feat: Icon 컴포넌트에 check, x 추가 * feat: 참여자의 입금 상태를 관리하는 DepositCheck 컴포넌트 기능 구현 * test: DepositCheck 스토리북 생성 * refactor: isCheck props를 isDeposited로 api 이름과 동일하게 변경 * fix: icon defalut color 누락된 부분 추가 --------- Co-authored-by: jinho_kim98 * feat: 에러 발생 시 지역적인 error boundary를 사용할 수 있도록 에러 처리 방식 개선 (#567) * rename: FetchError -> RequestError로 이름 변경 * feat: 에러의 타입이 RequestError 인지 확인하는 유틸 함수 구현 * refactor: 에러 객체를 불필요하게 object로 변환하는 과정 제거 * feat: 에러 처리 전략이 에러 바운더리일 경우 updateAppError로직을 수행하지 않도록 하고, throwOnError 옵션을 킴 * feat: GET 메서드에서 발생한 에러와 에러 처리 전략 정보 전달을 위한 RequestGetError 클래스 구현 * refactor: errorInfo라는 에러를 객체로 바꾼 자료형을 사용하지 않도록 개선 * feat: 기본 제공되는 RequestInit을 최대한 활용하도록 타입 수정과 직관적인 이름으로 개선 * feat: GET request인 경우 에러 처리 전략을 넘겨받도록 함 * refactor: 내부에 있는 로직과 맞지 않는 함수명에서 로직과 함수명이 모두 직관적으로 일치하도록 수정 * feat: 메서드 타입에 따라 해당하는 에러 인스턴스를 반환하는 로직 구현 * feat: GET 메서드를 사용하는 api 호출 함수들에 에러 처리 전략을 인자로 받을 수 있도록 수정 * fix: 로직이 반대의 값을 반환하는 것을 수정 * test: 에러 이름 수정과 에러 코드가 어떤 코드인지 의미를 담은 변수명으로 수정 * rename: 의미를 직관적으로 알 수 있도록 UnHandledErrorBoundary -> UnPredictableErrorBoundary로 이름 수정 * rename: 규칙에 맞도록 쿼리 hook이름 수정 * refactor: errorInfo를 제거하고 불필요한 분기문 제거 * chore: 충돌 해결 * docs: 서비스 소개글 작성 (#295) * docs: 서비스 소개글 작성 * docs: 서비스 소개 이미지로 대체 --------- Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> * feat: 참여자 별 내역에서 토스로 송금 유도하는 기능 (마무리) (#577) * chore: png 확장자 추가로 인한 file-loader설치 및 png 확장자 선언 * feat: icon에 toss 타입 추가 * feat: 은행 선택 디자인 구현 * design: 은행선택 grid 반응형적용 * feat: 계좌번호 입력 플로우 생성 * fix: 콘솔 창 오류 제거 * fix: 은행 이름 변경 * design: 지출 리스트 갭 변경 * feat: 참여자 별 내역에서 은행아이콘(토스) 보이도록 설정 * feat: cansubmit 추가 * fix: 스토리북 prop 누락 추가 * chore: png도 jest mock되도록 설정 * fix: 테스트 환경에선 상대경로 api, 브라우저 환경에선 절대경로 api를 호출하도록 설정 * feat: 은행 송금 버튼 생성 * feat: 버튼 클릭 시 모바일 환경에서 토스로 넘기는 기능 * feat: 모바일 기기 감지 기능 구현 * refactor: 디자인 컴포넌트에 맞게 디자인 외 기능 외부로 분리 * style: Bank send Flex 컴포넌트 이용 * style: bank select Flex 컴포넌트 이용 * style: expense list flex 컴포넌트로 이용 * style: 사용하지 않는 import 제거 * style: fileMock -> imageFileMock으로 파일 이름 변경 * feat: 이벤트 정보를 불러오고 정보를 수정하는 api 구현 * feat: eventName -> eventOutline으로 이름 변경 * feat: 계좌를 입력받는 기능 구현 * feat: 계좌번호 라우트 이벤트 id를 받도록 변경 * fix: 서버상태와 클라이언트 상태 분리 * test: event outline 수정 핸들러 등록 * fix: input 초기값 undefined 주지 않도록 설정 * fix: 변경된 상태를 보내도록 수정 * test: 초기 은행이름 맞춰줌 * feat: input에 항상 테두리가 보이도록 설정하는 옵션 추가 * feat: label input 라벨이 항상 보이도록 하는 옵션 추가 * fix: Line 컴포넌트 key prop 추가 * feat: index에 Line, FunnelLayout 추가 * feat: FunnelLayout 추가 * fix: 변경된 파일구조 반영 * style: eventName => event로 포괄적인 의미로 수정 * style: account => update로 라우팅 변경 * style: 퍼널 구조 형식으로 페이지 레이아웃 수정 * style: get event return을 묶어서 return * fix: mocking base url 수정 * style: 디렉토리 이름 변경 * style: 사용하지 않게 된 핸들러 제거 * refactor: Event type 확장으로 기존에 선언했던 EventOutline 타입 제거 및 반영 * fix: 변경된 api 반영 * refactor: mutateAsync로 변경하여 비동기함수로 변경 * feat: 계좌번호 등록하고 관리페이지로 돌아가는 기능 구현 * feat: 계좌정보가 등록되지 않았을 때 공유 버튼을 누르면 계좌번호 입력을 유도하는 기능 구현 * refactor: 마지막 path를 바꿔주는 함수를 사용해서 route 하는 방식으로 변경 * feat: 마지막 변경이 아니라 마지막 path를 빼는 기능으로 변경 * feat: 바뀐 url path 정책 반영 * feat: 송금액이 0원일 때의 대체 버튼 추가 * design: 토스 아이콘 크기 수정 * feat: 계좌번호 정보를 복사 후 토스를 여는 기능 구현 * feat: 계좌번호가 입력되지 않았을 때 토스 송금 버튼을 눌렀을 때 토스트가 나오도록 설정 * Merge branch 'fe-dev' of https://github.com/woowacourse-teams/2024-haeng-dong into feature/#569 * fix: 지우지 않은 코드 삭제 * fix: 홈에서 버튼 누를 때 navigate 오류나는 버그 수정 * style: isFinish -> isDeposited로 prop 명 변경 * design: 불필요한 gap 제거 * refactor: mutation rest return하도록 설정 * feat: 토스트 사용성 개선 (#579) * chore: 컨벤션에 맞도록 공백 추가 * feat: 토스트 컴포넌트와 훅에서 공용으로 사용하는 타입을 분리 * feat: 전역 상태로 관리할 필요가 없어졌으므로 ToastProvider -> useToast로 내용물 이전 * fix: 토스트 컴포넌트에 isAutoClosed 가 false면 계속 떠있도록 수정 * refactor: 공용 토스트 타입을 재사용하도록 수정 * feat: 콜백을 등록해두고, 토스트 이벤트 발생 시 등록되어있는 콜백 함수르 실행하는 객체 구현 * feat: 토스트를 간편하게 사용할 수 있도록 인터페이스 역할을 하는 toast 함수 구현 * feat: 토스트를 띄우기 위한 컨테이너 구현 * feat: 토스트 콜백 함수를 다루는 객체에서 사용하는 타입 분리 * test: 변경된 토스트에 맞게 테스트 코드 수정 * feat: 토스트를 띄우기 위해 App에 ToastContainer 호출 * test: ToastProvider -> ToastContainer로 수정 * feat: 토스트를 호출하는 곳을 바뀐 토스트 호출 형식으로 수정 * style: 이벤트의 콜백 목록을 저장한다는 의미가 드러나도록 eventList -> eventCallbackList로 변수명 수정 * chore: 테스트를 위해 작성한 코드 제거 * feat: 기존 토스트 방식에서 개선된 토스트방식으로 수정 * feat: 이벤트 홈 화면 새로운 플로우로 교체 (참여자 별 정산, 전체 지출 내역), Dropdown 컴포넌트 구현 (#582) * feat: z index theme에 추가 * feat: 탭 컴포넌트 스타일 바뀐대로 설정 * design: gap 만큼 더 움직이도록 설정 * feat: ExpenseList안에 검색input 추가 * feat: Flex 컴포넌트에 다른 style 넣을 수 있도록 확장 * feat: inputType search일 때 검색 아이콘 보이도록 설정 * feat: 바뀐 이벤트 홈 디자인 반영 * remove: 사용하지 않는 Search 컴포넌트 삭제 * fix: Flex컴포넌트 다른 스타일 확장으로 인한 ts 오류 수정 * feat: ExpenseList isDeposited 내용 추가 * style: 사용하지 않는 import제거 * design: 버튼 색상 변경 * feat: 지출내역이 없을 때 fallback 추가 * feat: 지출 내역이 없을 때 fallback 적용 * feat: Dropdown 컴포넌트 구현 * fix: createPortal 제거 -> position absolute를 이용해 대체 * feat: AdminPage에 dropdown 컴포넌트 적용 * design: 모바일에서 클릭 시 파란색 강조되는 색 제거 * feat: 계좌번호 입력 드랍다운 눌렀을 때 페이지 이동 (머지되면 붙일 예정) * design: 탭 컴포넌트 애니메이션 cubic-bezier를 이용해서 변경 * design: 드랍다운 버튼 hover 강조 * fix: ResizeObserver를 이용해서 tab width의 값을 정확히 가져오도록 설정 * design: tab width가 0일 때 indicator가 랜더링 되지 않도록 설정 * chore: 충돌 병합 * feat: 지출 내역 생성하기 기능 추가 (#587) * feat: 지출 내역 생성 api 연결 및 유효성 검사 * feat: Funnel 파일 분리 및 member 생성 api 로직 변경 * fix: AddBillFunnel route 수정 * style: lint 적용 * refactor: BillStep hook 분리 * style: lint 적용 * fix: postMember api 요청 변경 * fix: addBill route 수정 * fix: TitleStep에서 PriceStep으로 이동했을 때, billInfo.price 초기화되던 오류 수정 * fix: MSW mocking 해제 * rename: AddBillFunnel 경로 수정 * fix: mutateAsync를 이용하여 postMembers 이후 postBills 요청을 보내도록 수정 * fix: API 변경에 맞추어 수정 * style: lint 적용 * feat: 행사 생성 페이지에 퍼널 방식 적용 (#591) * feat: 행사 생성 페이지의 path 수정 * fix: 컴포넌트 구현이 바뀜에 따라 다른 컴포넌트를 사용해 제목을 그리도록 수정 * feat: 행사 생성 페이지를 퍼널 방식을 이용해 렌더링 하도록 수정 * feat: 퍼널 구조에서 사용되는 공통적인 로직과 컴포넌트를 위한 useFunnel 훅 구현 * rename: 퍼널 방식으로 변경됨에 따른 Page -> Step 으로의 이름 변경 * feat: 행사 생성 퍼널에서 여러 step에 걸쳐 사용되는 상태를 선언해 내려주는 useCreateEventData 훅 구현 * feat: 행사 생성 퍼널을 router에서 호출 * feat: 뒤로가기 버튼인 Back에 onClick인자가 주어지면 그 함수를 사용하고 주어지지 않으면 -1로 뒤로가도록 함 * feat: Funnel 컴포넌트에서 현재의 step을 위한 Step 컴포넌트를 찾지 못했다면 에러를 던지도록 함 * feat: 응답이 성공해야만 다음 로직을 실행할 수 있도록 mutateAsync 사용해 순서 보장 * feat: 퍼널 구조에서 사용되는 공통적인 로직과 컴포넌트를 위한 useFunnel 훅 구현 * style: return 위 개행 추가 * style: 가독성을 위해 Step간 개행을 넣음 * test: 퍼널이 도입되어 행사 생성 과정에서 url이 변경되지 않기 때문에 url이 올바르게 변경되었는지 판단하는 라인을 제거 * test: 행사 생성 url이 바뀐 것을 cypress에도 적용 * feat: 불필요해진 행사 생성 완료 path 제거 * test: url을 수정된 값으로 변경 * test: 테스트 임시 비활성화 * feat: 조건부로 기본 이벤트 동작을 막던 것에서 조건 제거 * feat: 불필요한 함수 제거 * feat: 키다운 핸들러를 없애 onSubmit으로 통합 * test: 주석처리했던 테스트 복구 * feat: 지출 내역 수정하기 기능 추가 (#594) * test: MSW 코드 수정 * feat: BillDetails component 구현 * fix: useRequestGetBillDatails hook return 수정 * fix: ListItem에 OnClick prop을 받을 수 있도록 수정 * fix: FixedButton component 수정 * feat: EditableLine component 구현 * feat: EditBillPage 구현 * test: MSW mock data 수정 * fix: 잘못 적용되어 있던 API 수정 * fix: AmountInput Component prop 및 작동방식 변경 * fix: Amount, EditableAmount css 수정 * fix: NumberKeyboard component 수정 * feat: NumberKeyboardBottomSheet component 구현 * fix: EditableLine component 수정 * fix: BillDetails component 수정 * feat: EditBillPage component 수정 및 계산 로직 추가 * fix: NumberKeyboardBottomSheet component 수정 * fix: useRequestPutBill 수정 * feat: BillDetails 클릭 시 focus 이동 스크롤 및 API 연결 * feat: Button Loading 상태 추가 * remove: 사용하지 않는 코드 삭제 * design: BillDetails 디자인 잘못된 오류 수정 * fix: Bill.price가 0인 경우 수정하지 못하도록 변경 * fix: BillDetail이 최대 금액을 넘어가는 오류 수정 * fix: 사용하지 않는 코드 제거 * fix: useNumberKeyboard Component 오류 수정 * style: lint 적용 * refactor: EditBillPage 로직 hook으로 분리 * fix: export 잘못된 오류 수정 * fix: MSW mocking 해제 * test: Top component storybook 오류 해결 * test: Step.stories.tsx 수정 * style: lint 적용 * style: lint 적용 * feat: 전체 참여자 관리 페이지 구현 (#595) * design: 변경된 DepositToggle로 수정 * fix: toggle의 넓이가 맞지 않는 문제 해결 (원인: Text의 사이즈가 tiny로 되어있지 않아서) * chore: Design Components를 index.tsx에 추가 및 이에 따른 export/import 수정 * design: Icon 컴포넌트에 pencilMini와 trashMini 타입 추가 * design: DepositToggle height 고정 * design: 전체 참여자 관리 페이지 디자인 구현 * chore: 변경된 api 응답 요청에 맞게 name을 memberName으로 수정 * feat: member의 이름을 변경하는 기능 추가 * feat: member 삭제 기능 추가 * feat: isDeposited 변경 기능 구현 및 PUT 요청 형태에 맞게 changedMembers 상태 추가 * feat: 변경된 값(changedMembers)이 초기 상태와 동일할 경우, Put 요청에서 제외하도록 기능 추가 * feat: memberName의 최대 길이 유효성 검사 및 변경된 값만 저장하는 filteredChangedMembers 상태 추가 * feat: 중복된 이름이 존재할 경우 수정완료 버튼 비활성화 기능 추가 * chore: 불필요한 console.log 삭제 * feat: EventMemberManage 라우터 추가 * feat: memberName이 0일 경우 FixedButton 비활성화 기능 추가 * design: memberName input의 width를 98px로 고정 * design: input에 focus가 되었을 경우 borderBottom의 에 primary 색상으로 변경하기 * design: reports의 데이터가 존재하지 않을 때, 문구 추가 * design: reports의 값이 많아 뷰포트 높이를 넘어갈 경우 overflow 적용을 위해 css 수정 (FixedButton: z-index 추가, DepositToggle: position 변경) * remove: 사용하지 않는 useSetAllMemberList 훅 제거 * style: lint적용 * fix: 충돌 해결 * design: MainLayout 중복으로 padding이 이중으로 생기는 문제 해결 * fix: 변경된 api 구조에 따라 api 관련 코드 수정 * fix: 잘못된 navigate 경로 수정 * style: 사용하지 않는 코드 제거 * feat: dropdown route 적용 --------- Co-authored-by: 이태훈 * fix: 계좌번호 입력 확인 버튼 활성화가 되지 않는 버그, 빈 값일 때 새로운 값이 반영되지 않는 버그 (#602) * fix: can submit 조건이 잘못됐던 버그 수정 * fix: 새로운 데이터가 빈 값인지를 체크하는 것으로 변경 * fix: 홈에서는 지출 상세로 들어가지 않도록 설정 (#604) * fix: 입금 상태를 변경하고 '수정완료' 버튼 클릭 시, 중복 이름 버그 발생 (#611) * fix: 전체 참여자 delete,put 요청 mutate대신 mutateAsync를 사용하여 요청 순서 보장하기 * chore: mutateAsync를 사용한 곳 이름에 Async 추가하기 * refactor: useEventMember 불필요한 상태 제거 및 렌더링 성능 개선 (#613) * refactor: 불필요한 상태(changedMembers) 제거 및 렌더링 성능 개선 * refactor: isCanRequest의 이름을 isCanSubmit으로 변경 * rename: EventMemberManage의 파일 이름을 EventMember로 변경 * refactor: delete와 put 요청에 await 추가 * refactor: 중복 이름 확인 로직을 set.length를 활용하여 간단하게 수정 * refactor: useCallback에 의존성 추가 * fix: FixedButton loading button layout 깨지는 오류 수정 (#624) * refactor: 홈 관리 네비게이션에 랜딩페이지로 이동하는 기능 추가 및 TopNav 구조 개선 (#627) * style: 불필요한 directory 구조 한 단계 제거 (Common) * style: 행동디자인에서 Switch 바깥으로 분리 * refactor: TopNav 자유롭게 사용할 수 있도록 변경 * style: 디렉토리 구조 변하면서 생긴 import 수정 * style: 사용하지 않는 import 문 제거 * design: TextButton color onTertiary 추가 * remove: 사용하지 않게된 Switch 제거 * remove: 사용하지 않는 Back 컴포넌트 제거 * feat: 흔듯콘 아이콘 추가 * refactor: TopNav, NavElement를 사용해 navigate 책임 이동 * refactor: 변경된 TopNav 적용 * style: 콘솔 경고창 에러를 방지하기 위해 변경 * feat: noEmphasis prop 추가 (true일 때 강조되지 않음) * design: 마진 맞춰줌 * remove: navigate 기능이 들어오면서 스토리북에서 변경되는 것을 보여줄 수 없어서 스토리북에서 제거 * style: emotion css를 위한 추가 * style: NavElement -> NavItem으로 이름 변경 * Merge branch 'fe-dev' into feature/#614 --------- Co-authored-by: Soyeon Choe * fix: 참여인원이 많을 때, 지출 내역 카드에서 멤버 칩의 레이아웃이 깨지는 문제 (#628) * fix: 참여인원 많은 경우 멤버 칩 레이아웃 깨지는 문제 수정 * fix: step의 멤버 수가 많을 때 member ChipGroup 레이아웃 깨지던 문제 해결 * style: lint 적용 * fix: 지출 내역 추가 단계에서 값이 0일 경우 레이아웃이 깨지는 문제 수정 (#631) * fix: NumberKeyboardBottomSheet 영역을 드래그 했을 때, 뒷 영역이 스크롤되던 오류 수정 (#633) * feat: 계좌번호 입력 제한 추가 (#634) * feat: 계좌번호 입력 유효성 기능 추가 * feat: 계좌번호 유효성을 검증하고 input을 컨트롤하는 기능 추가 * style: console.log 제거 * feat: 계좌번호 정규표현식 수정 --------- Co-authored-by: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> * refactor: 전체 참여자 관리: '수정 완료'시, Toast 띄우기 (#636) * refactor: 불필요한 상태(changedMembers) 제거 및 렌더링 성능 개선 * refactor: isCanRequest의 이름을 isCanSubmit으로 변경 * rename: EventMemberManage의 파일 이름을 EventMember로 변경 * refactor: delete와 put 요청에 await 추가 * refactor: 중복 이름 확인 로직을 set.length를 활용하여 간단하게 수정 * feat: 수정이 완료되었을 경우 수정 완료 toast 띄우기 * fix: 백엔드 api 변경으로 put 요청 변경 * refactor: isCanSubmit 이름을 canSubmit으로 변경 * style: lint 적용 * fix: 행사에 나갔던 멤버 추가할 수 없던 오류 수정 (#637) * fix: 모바일 환경에서 font 적용되지 않는 문제 해결 (#638) * fix: 모바일에서 멤버 추가가 제대로 되지 않는 문제 해결 (#639) * fix: 지출에 멤버가 1명일 때, 금액이 수정되는 오류 (#641) * fix: 고정되지 않은 멤버가 한명일 때, 수정되던 오류 수정 * fix: 잘못 삭제된 코드 복구 * fix 행사 이름 한글이 두 자 씩 입력되는 버그 (#640) * refactor: handleEventNameChange 유효하지 않은 값이 들어올 경우 로직 수정 * fix: input에 value가 변경될 때마다 컴포넌트가 리렌더링되는 문제 해결 * chore: 사용하지 않는 import 삭제 * refactor: z-index를 상수화 (#635) * feat: z-index 토큰 생성 * chore: 생성된 z-index 토큰에 맞춰 변경 * feat: Toast z-index 추가 * refactor: 최신의 서버 에러 코드를 프론트에 업데이트하고, 사용자에게 보여지는 에러 메세지를 이해하기 쉽도록 수정 (#632) * feat: 서버 에러 코드와 메세지 업데이트, 그리고 상수를 사용하지 않는 부분을 사용하도록 변경 * feat: 지출 내역 이름의 최대 길이 상수를 추가 * fix: 서버 에러 코드가 잘못 입력된 것을 수정 * feat: 로그인 만료 안내에 다시 로그인해달라는 문장 추가 * feat: 상수를 사용하도록 적용 * fix: GlobalStyle tnum 삭제 (#648) * feat: IOS 환경에서도 토스 송금 기능을 똑같이 이용할 수 있도록 설정 (#651) * feat: 안드로이드, ios 판별하는 기능 추가 * style: import 방식 변경 반영 * feat: 안드로이드는 그대로, ios는 송금하기로 이동 * fix: merge 진행하면서 put, delete 요청 순서 보장 사라짐 + 수정 완료 Toast 없어짐 추가 (#652) * fix: put, delete 요청 순서 보장 * fix: 정상적으로 수정되었을 경우 '수정완료' 토스트 띄우기 * fix: 랜딩페이지와 메인페이지의 header 디자인이 맞지 않는 에러 해결 * fix: z-index 상수화 미적용 코드 적용 및 불필요한 z-index 삭제 * fix: TopNav를 사용하는 곳에서 기본적으로 margin: 0 1rem이 적용되도록 수정 * fix: cypress에서 header 태그로 '정산시작하기' 버튼을 찾는 코드로 인해 Nav 컴포넌트에서는 Flex 컴포넌트를 사용하지 않고 header 태그 사용으로 변경 * test: 정산 시작하기 버튼에 관한 e2e 테스트 코드 변경 * fix: 멤버 추가 시 제대로 작동하지 않는 문제 수정 (#653) * fix: 지출 생성 시 멤버 추가가 제대로 되지 않던 오류 해결 * style: console.log 제거 * fix: login 페이지 레이아웃 오류 (#655) * fix: login 페이지 레이아웃 수정 * style: lint 적용 * fix: 멤버 추가 제대로 작동하지 않는 문제 수정 (#661) --------- Co-authored-by: 김진호 Co-authored-by: pakxe Co-authored-by: kunsanglee Co-authored-by: Soyeon Choe Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Soyeon Choe Co-authored-by: juha Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> Co-authored-by: JUHA <84626225+khabh@users.noreply.github.com> Co-authored-by: JinHo Kim Co-authored-by: Pakxe Co-authored-by: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: 이태훈 Co-authored-by: JUHA Co-authored-by: Arachne Co-authored-by: TaehunLee --- .github/workflows/design-pull-request.yml | 54 - .github/workflows/frontend-pull-request.yml | 52 +- HDesign/.gitignore | 12 - HDesign/.npmignore | 7 - HDesign/.npmrc | 2 - HDesign/.prettierrc | 12 - HDesign/.storybook/main.ts | 47 - HDesign/eslint.config.mjs | 153 - HDesign/package-lock.json | 13707 ---------------- HDesign/package.json | 72 - HDesign/src/assets/index.ts | 7 - HDesign/src/assets/svg.d.ts | 6 - .../ExpenseList/ExpenseList.stories.tsx | 29 - .../ExpenseList/ExpenseList.style.ts | 29 - .../components/ExpenseList/ExpenseList.tsx | 37 - .../ExpenseList/ExpenseList.type.ts | 10 - HDesign/src/components/Icon/Icon.tsx | 29 - .../src/components/Search/Search.stories.tsx | 32 - HDesign/src/components/Search/Search.style.ts | 42 - HDesign/src/components/Search/Search.tsx | 37 - .../src/components/Switch/Switch.stories.tsx | 35 - HDesign/src/components/Switch/Switch.style.ts | 6 - HDesign/src/components/Switch/Switch.tsx | 24 - HDesign/src/components/Switch/Switch.type.ts | 5 - HDesign/src/components/Tabs/Tabs.style.ts | 53 - HDesign/src/components/Tabs/Tabs.tsx | 53 - HDesign/src/components/Title/Title.tsx | 34 - .../src/components/Toast/Toast.stories.tsx | 71 - HDesign/src/components/Toast/Toast.style.ts | 44 - HDesign/src/components/Toast/Toast.tsx | 73 - HDesign/src/components/Toast/Toast.type.ts | 21 - .../Toast/ToastProvider.stories.tsx | 46 - .../src/components/Toast/ToastProvider.tsx | 59 - HDesign/src/components/TopNav/Back.tsx | 17 - .../src/components/TopNav/TopNav.stories.tsx | 50 - HDesign/src/components/TopNav/TopNav.style.ts | 18 - HDesign/src/components/TopNav/TopNav.tsx | 20 - HDesign/src/index.tsx | 62 - HDesign/tsconfig.json | 34 - README.md | 4 +- client/.gitignore | 3 + client/.storybook/main.ts | 59 + {HDesign => client}/.storybook/preview.tsx | 2 +- client/cypress/e2e/createEvent.cy.ts | 24 +- client/cypress/support/commands.ts | 12 +- client/eslint.config.mjs | 5 + client/index.html | 5 + client/jest.config.ts | 11 +- client/package-lock.json | 7113 ++++++-- client/package.json | 20 +- client/src/App.tsx | 30 +- client/src/GlobalStyle.ts | 252 +- client/src/UnPredictableErrorBoundary.tsx | 10 + client/src/UnhandledErrorBoundary.tsx | 10 - .../apis/{tempPrefix.ts => endpointPrefix.ts} | 3 +- client/src/apis/fetcher.ts | 149 +- client/src/apis/request/auth.ts | 18 +- client/src/apis/request/bill.ts | 85 +- client/src/apis/request/event.ts | 49 +- client/src/apis/request/member.ts | 94 +- client/src/apis/request/report.ts | 21 +- client/src/apis/request/step.ts | 17 + client/src/apis/request/stepList.ts | 17 - .../{withEventId.type.ts => withId.type.ts} | 4 + .../src/assets/image/Toss_Symbol_Primary.png | Bin 0 -> 925412 bytes client/src/assets/image/banksprite.png | Bin 0 -> 48163 bytes .../src/assets/image}/buljusa.svg | 0 client/src/assets/image/check.svg | 3 + .../src/assets/image}/confirm.svg | 0 client/src/assets/image/editPencil.svg | 3 + .../src/assets/image}/error.svg | 0 .../src/assets/image}/inputDelete.svg | 0 .../src/assets/image}/loadingAnimation.json | 0 client/src/assets/image/meatballs.svg | 3 + client/src/assets/image/pencil_mini.svg | 3 + .../src/assets/image}/rightChevron.svg | 0 .../src/assets/image}/search.svg | 0 .../src/assets/image}/trash.svg | 0 client/src/assets/image/trash_mini.svg | 3 + client/src/assets/image/x.svg | 3 + .../AmountInput/AmountInput.stories.tsx | 23 + .../components/AmountInput/AmountInput.tsx | 47 + .../AppErrorBoundary/ErrorCatcher.test.tsx | 46 +- .../AppErrorBoundary/ErrorCatcher.tsx | 62 +- .../components/BillDetails/BillDetails.tsx | 52 + .../components/Amount/Amount.stories.tsx | 28 + .../Design/components/Amount/Amount.tsx | 28 + .../components/Amount/EditableAmount.tsx | 107 + .../BankSelect/BankSelect.stories.tsx | 23 + .../components/BankSelect/BankSelect.style.ts | 31 + .../components/BankSelect/BankSelect.tsx | 30 + .../BankSendButton/BankSelect.stories.tsx | 29 + .../BankSendButton/BankSendButton.style.ts | 23 + .../BankSendButton/BankSendButton.tsx | 48 + .../BottomSheet/BottomSheet.stories.tsx | 4 +- .../BottomSheet/BottomSheet.style.ts | 4 +- .../components/BottomSheet/BottomSheet.tsx | 3 +- .../BottomSheet/BottomSheet.type.ts | 0 .../components/BottomSheet/useBottomSheet.ts | 2 + .../components/Button/Button.stories.tsx | 0 .../Design}/components/Button/Button.style.ts | 7 +- .../Design}/components/Button/Button.tsx | 9 +- .../Design}/components/Button/Button.type.ts | 0 .../Design/components/Chip/Chip.stories.tsx | 36 + .../Design/components/Chip/Chip.style.ts | 20 + .../Design/components/Chip/Chip.tsx | 26 + .../ChipButton/ChipButton.stories.tsx | 34 + .../components/ChipButton/ChipButton.style.ts | 21 + .../components/ChipButton/ChipButton.tsx | 27 + .../ChipGroup/ChipGroup.stories.tsx | 29 + .../components/ChipGroup/ChipGroup.style.ts | 8 + .../Design/components/ChipGroup/ChipGroup.tsx | 27 + .../DepositCheck/DepositCheck.stories.tsx | 27 + .../DepositCheck/DepositCheck.style.ts | 21 + .../components/DepositCheck/DepositCheck.tsx | 21 + .../DepositCheck/DepositCheck.type.ts | 11 + .../DepositToggle/DepositToggle.stories.tsx | 51 + .../DepositToggle/DepositToggle.style.ts | 43 + .../DepositToggle/DepositToggle.tsx | 26 + .../DepositToggle/DepositToggle.type.ts | 12 + .../DragHandleItem/DragHandleItem.stories.tsx | 2 +- .../DragHandleItem/DragHandleItem.style.ts | 1 - .../DragHandleItem/DragHandleItem.tsx | 9 +- .../DragHandleItem/DragHandleItem.type.ts | 1 - .../DragHandleItemContainer.stories.tsx | 4 +- .../DragHandleItemContainer.style.ts | 1 - .../DragHandleItemContainer.tsx | 0 .../DragHandleItemContainer.type.ts | 0 .../components/Dropdown/Dropdown.stories.tsx | 34 + .../components/Dropdown/Dropdown.style.ts | 33 + .../Design/components/Dropdown/Dropdown.tsx | 36 + .../components/Dropdown/Dropdown.type.ts | 7 + .../components/Dropdown/DropdownButton.tsx | 21 + .../Design/components/Dropdown/useDropdown.ts | 39 + .../EditableItem/EditableItem.Input.style.ts | 3 +- .../EditableItem/EditableItem.Input.tsx | 10 +- .../EditableItem/EditableItem.Input.type.ts | 3 +- .../EditableItem/EditableItem.context.tsx | 0 .../EditableItem.input.stories.tsx | 2 +- .../EditableItem/EditableItem.stories.tsx | 6 +- .../EditableItem/EditableItem.style.ts | 1 - .../components/EditableItem/EditableItem.tsx | 5 +- .../EditableItem/EditableItem.type.ts | 1 - .../EditableItem/useEditableItem.ts | 0 .../EditableItem/useEditableItemInput.ts | 2 + .../ExpenseList/ExpenseList.stories.tsx | 61 + .../components/ExpenseList/ExpenseList.tsx | 75 + .../ExpenseList/ExpenseList.type.ts | 15 + .../FixedButton/FixedButton.stories.tsx | 2 +- .../FixedButton/FixedButton.style.ts | 61 +- .../components/FixedButton/FixedButton.tsx | 29 +- .../FixedButton/FixedButton.type.ts | 4 +- .../Design}/components/Flex/Flex.style.ts | 4 +- .../Design}/components/Flex/Flex.tsx | 12 +- .../Design}/components/Flex/Flex.type.ts | 4 +- .../Design}/components/Icon/Icon.stories.tsx | 16 +- .../Design}/components/Icon/Icon.style.ts | 10 +- .../Design/components/Icon/Icon.tsx | 50 + .../Design}/components/Icon/Icon.type.ts | 19 +- .../IconButton/IconButton.stories.tsx | 4 +- .../components/IconButton/IconButton.style.ts | 3 +- .../components/IconButton/IconButton.tsx | 3 +- .../components/IconButton/IconButton.type.ts | 0 .../components/Input/Input.stories.tsx | 6 +- .../Design}/components/Input/Input.style.ts | 45 +- .../Design}/components/Input/Input.tsx | 33 +- .../Design}/components/Input/Input.type.ts | 1 + .../Design}/components/Input/useInput.ts | 0 .../IsFixedIcon/IsFixedIcon.style.ts | 0 .../components/IsFixedIcon/IsFixedIcon.tsx | 0 .../components/LabelGroupInput/Element.tsx | 0 .../LabelGroupInput/Element.type.ts | 0 .../LabelGroupInput/GroupInputContext.tsx | 0 .../LabelGroupInput.stories.tsx | 2 +- .../LabelGroupInput/LabelGroupInput.style.ts | 0 .../LabelGroupInput/LabelGroupInput.tsx | 3 +- .../LabelGroupInput/LabelGroupInput.type.ts | 0 .../components/LabelGroupInput/index.ts | 0 .../LabelInput/LabelInput.stories.tsx | 2 +- .../components/LabelInput/LabelInput.style.ts | 16 +- .../components/LabelInput/LabelInput.tsx | 22 +- .../components/LabelInput/LabelInput.type.ts | 7 +- .../components/LabelInput/useLabelInput.ts | 0 .../ListButton/ListButton.stories.tsx | 2 +- .../components/ListButton/ListButton.style.ts | 0 .../components/ListButton/ListButton.tsx | 9 +- .../components/ListButton/ListButton.type.ts | 0 .../components/ListItem/ListItem.stories.tsx | 37 + .../components/ListItem/ListItem.style.ts | 21 + .../Design/components/ListItem/ListItem.tsx | 18 + .../Design/components/ListItem/Row.tsx | 15 + .../components/NumberKeyboard/Keypad.tsx | 42 + .../NumberKeyboard/NumberKeyboard.stories.tsx | 44 + .../NumberKeyboard/NumberKeyboard.tsx | 76 + .../NumberKeyboardBottomSheet.tsx | 50 + .../NumberKeyboard/useNumberKeyboard.tsx | 61 + .../useNumberKeyboardBottomSheet.ts | 32 + .../Design}/components/Tabs/Tab.tsx | 0 .../Design}/components/Tabs/Tab.type.ts | 0 .../Design}/components/Tabs/Tabs.stories.tsx | 2 +- .../Design/components/Tabs/Tabs.style.ts | 63 + .../Design/components/Tabs/Tabs.tsx | 85 + .../Design}/components/Text/Text.stories.tsx | 2 +- .../Design}/components/Text/Text.style.ts | 2 + .../Design}/components/Text/Text.tsx | 2 +- .../Design}/components/Text/Text.type.ts | 1 - .../TextButton/TextButton.stories.tsx | 2 +- .../components/TextButton/TextButton.style.ts | 1 - .../components/TextButton/TextButton.tsx | 4 - .../components/TextButton/TextButton.type.ts | 2 +- .../components/Title/Title.stories.tsx | 14 +- .../Design}/components/Title/Title.style.ts | 14 +- .../Design/components/Title/Title.tsx | 27 + .../Design}/components/Title/Title.type.ts | 4 +- .../Design/components/Top/EditableLine.tsx | 78 + .../components/Design/components/Top/Line.tsx | 41 + .../Design/components/Top/Top.stories.tsx | 30 + .../components/Design/components/Top/Top.tsx | 21 + .../Design/components/TopNav/NavItem.style.ts | 9 + .../Design/components/TopNav/NavItem.tsx | 55 + .../Design/components/TopNav/NavItem.type.ts | 14 + .../Design/components/TopNav/TopNav.style.ts | 8 + .../Design/components/TopNav/TopNav.tsx | 19 + client/src/components/Design/index.tsx | 66 + .../Design}/layouts/ContentLayout.tsx | 0 .../Design/layouts/FunnelLayout.tsx | 19 + .../components/Design}/layouts/MainLayout.tsx | 2 +- .../components/Design}/theme/GlobalStyle.ts | 25 + .../Design}/theme/HDesignProvider.tsx | 3 +- .../components/Design}/theme/theme.type.ts | 2 + .../src/components/Design}/token/colors.ts | 0 .../components/Design}/token/typography.ts | 0 client/src/components/Design/token/zIndex.ts | 39 + .../Design}/type/strictPropsWithChildren.ts | 0 .../src/components/Design}/type/withTheme.ts | 0 .../utils/changeCamelCaseToKebabCase.ts | 0 .../src/components/Design}/utils/colors.ts | 0 .../ExpenseDetailModal/ExpenseDetailModal.tsx | 130 + .../KakaoInitializer/KakaoInitializer.tsx | 15 + .../{Common => }/Logo/Logo.style.ts | 0 .../{Common => }/Logo/RunningDogLogo.tsx | 0 .../{Common => }/Logo/StandingDogLogo.tsx | 0 .../src/components/{Common => }/Logo/index.ts | 0 .../MemberReportList/MemberReportList.tsx | 22 - .../BankSelectModal.style.ts} | 2 +- .../Modal/BankSelectModal/BankSelectModal.tsx | 31 + .../ExpenseDetailModal/ExpenseDetailModal.tsx | 142 - .../MemberListInBillStep.style.ts | 10 - .../MemberListInBillStep.tsx | 53 - .../Modal/MemberListInBillStep/index.ts | 1 - .../ModalBasedOnMemberCount.tsx | 39 - .../AddMemberActionListModalContent.style.ts | 23 - .../AddMemberActionListModalContent.tsx | 50 - .../InMember.tsx | 35 - .../OutMember.tsx | 52 - .../AddMemberActionListModalContent/index.ts | 1 - .../DeleteMemberActionModal.style.ts | 27 - .../DeleteMemberActionModal.tsx | 88 - .../DeleteMemberActionModal/index.ts | 1 - .../PutAndDeleteBillActionModal.tsx | 149 - .../PutAndDeleteBillActionModal/index.ts | 1 - .../SetActionListModal.style.ts | 20 - .../SetActionModal/SetActionListModal.tsx | 42 - .../components/Modal/SetActionModal/index.ts | 1 - .../SetAllMemberListModal.style.ts | 36 - .../SetAllMemberListModal.tsx | 80 - .../SetInitialMemberListModal.style.ts | 20 - .../SetInitialMemberListModal.tsx | 66 - .../Modal/SetInitialMemberListModal/index.ts | 1 - client/src/components/Modal/index.ts | 4 - .../QueryClientBoundary.tsx | 11 + client/src/components/Reports/Reports.tsx | 26 + .../ShareEventButton/ShareEventButton.tsx | 62 + .../src/components/ShareEventButton/index.ts | 1 + .../src/components/StepList/BillStepItem.tsx | 138 - .../components/StepList/MemberStepItem.tsx | 38 - .../src/components/StepList/Step.stories.tsx | 69 + client/src/components/StepList/Step.tsx | 91 +- client/src/components/StepList/StepList.tsx | 76 - client/src/components/StepList/Steps.tsx | 27 + client/src/components/Toast/Toast.style.ts | 11 +- client/src/components/Toast/Toast.tsx | 36 +- client/src/components/Toast/Toast.type.ts | 25 +- .../src/components/Toast/ToastContainer.tsx | 11 + client/src/constants/bank.ts | 32 + client/src/constants/errorMessage.ts | 88 +- client/src/constants/message.ts | 5 + client/src/constants/queryKeys.ts | 12 +- client/src/constants/regExp.ts | 5 +- client/src/constants/routerUrls.ts | 10 +- client/src/constants/rule.ts | 7 +- client/src/errors/FetchError.ts | 23 - client/src/errors/RequestError.ts | 24 + client/src/errors/RequestGetError.ts | 21 + client/src/errors/requestErrorType.ts | 10 + client/src/global.d.ts | 2 + .../useRequestPostAuthentication.ts | 11 +- .../queries/{ => auth}/useRequestPostLogin.ts | 12 +- .../queries/bill/useRequestDeleteBill.ts | 29 + .../queries/bill/useRequestGetBillDetails.ts | 28 + .../hooks/queries/bill/useRequestPostBill.ts | 27 + .../hooks/queries/bill/useRequestPutBill.ts | 26 + .../queries/bill/useRequestPutBillDetails.ts | 48 + .../hooks/queries/event/useRequestGetEvent.ts | 26 + .../queries/event/useRequestPatchEvent.ts | 31 + .../queries/event/useRequestPostEvent.ts | 18 + .../queries/member/useRequestDeleteMember.ts | 26 + .../queries/member/useRequestGetAllMembers.ts | 21 + .../member/useRequestGetCurrentMembers.ts | 21 + .../queries/member/useRequestPostMembers.ts | 26 + .../queries/member/useRequestPutMembers.ts | 26 + .../queries/report/useRequestGetReports.ts | 23 + .../useRequestGetSteps.ts} | 16 +- .../queries/useRequestDeleteAllMemberList.ts | 28 - .../queries/useRequestDeleteBillAction.ts | 26 - .../queries/useRequestDeleteMemberAction.ts | 28 - .../queries/useRequestGetAllMemberList.ts | 18 - .../useRequestGetCurrentInMemberList.ts | 18 - .../hooks/queries/useRequestGetEventName.ts | 18 - .../queries/useRequestGetMemberReportList.ts | 17 - .../useRequestGetMemberReportListInAction.ts | 24 - .../hooks/queries/useRequestPostBillList.ts | 27 - .../src/hooks/queries/useRequestPostEvent.ts | 16 - .../hooks/queries/useRequestPostMemberList.ts | 37 - .../queries/useRequestPutAllMemberList.ts | 28 - .../hooks/queries/useRequestPutBillAction.ts | 29 - .../useRequestPutMemberReportListInAction.ts | 49 - client/src/hooks/useAccount.ts | 97 + client/src/hooks/useAddBillFunnel.ts | 33 + client/src/hooks/useCreateEventData.tsx | 17 + .../useDeleteMemberAction.test.tsx | 139 - .../useDeleteMemberAction.tsx | 86 - client/src/hooks/useDynamicInput.tsx | 142 - client/src/hooks/useEditBillActions.ts | 78 + client/src/hooks/useEditBillKeyboardAction.ts | 45 + client/src/hooks/useEditBillPage.ts | 53 + client/src/hooks/useEditBillPageScroll.ts | 35 + client/src/hooks/useEditBillState.ts | 95 + client/src/hooks/useEventLogin.ts | 8 +- client/src/hooks/useEventMember.ts | 121 + client/src/hooks/useEventPageLayout.ts | 30 + client/src/hooks/useFunnel.tsx | 61 + .../useMemberReportInput.tsx | 89 - .../useMemberReportListInAction.test.tsx | 327 - .../useMemberReportListInAction.ts | 156 - client/src/hooks/useMembersStep.ts | 126 + client/src/hooks/useNavSwitch.tsx | 42 - client/src/hooks/usePriceStep.ts | 27 + client/src/hooks/usePutAndDeleteBill.ts | 115 + client/src/hooks/usePutAndDeleteBillAction.ts | 113 - client/src/hooks/useReportsPage.ts | 60 + client/src/hooks/useSearchInMemberList.ts | 54 - .../useSearchMemberReportList.test.tsx | 41 - .../useSearchMemberReportList.tsx | 16 - client/src/hooks/useSearchReports/index.ts | 1 + .../useSearchReports/useSearchReports.tsx | 16 + client/src/hooks/useSetAllMemberList.tsx | 100 - client/src/hooks/useSetBillInput.ts | 67 - ...ventNamePage.ts => useSetEventNameStep.ts} | 17 +- client/src/hooks/useSetEventPasswordPage.ts | 60 - client/src/hooks/useSetEventPasswordStep.ts | 72 + client/src/hooks/useShareEvent.ts | 47 + client/src/hooks/useTitleStep.ts | 64 + client/src/hooks/useToast/ToastProvider.tsx | 47 - client/src/hooks/useToast/toast.ts | 19 + .../src/hooks/useToast/toastEventManager.ts | 24 + .../hooks/useToast/toastEventManager.type.ts | 21 + client/src/hooks/useToast/useToast.test.tsx | 36 +- client/src/hooks/useToast/useToast.tsx | 51 +- client/src/index.tsx | 10 +- client/src/mocks/handlers.ts | 8 +- client/src/mocks/handlers/authHandlers.ts | 108 +- client/src/mocks/handlers/billHandler.ts | 115 + client/src/mocks/handlers/eventHandlers.ts | 99 +- client/src/mocks/handlers/memberHandler.ts | 62 + .../handlers/memberReportInActionHandlers.ts | 49 - client/src/mocks/handlers/reportHandlers.ts | 14 +- client/src/mocks/handlers/stepListHandler.ts | 113 - client/src/mocks/imageFileMock.ts | 7 + client/src/mocks/invalidMemberStepList.json | 100 - client/src/mocks/memberActionStepList.json | 23 - .../src/mocks/memberReportListInAction.json | 6 - client/src/mocks/memberReportSearchList.json | 10 - client/src/mocks/mockEndpointPrefix.ts | 3 + client/src/mocks/reportList.json | 18 - client/src/mocks/sharedState.ts | 143 + client/src/mocks/stepList.json | 100 - client/src/pages/AccountPage/Account.tsx | 82 + .../src/pages/AddBillFunnel/AddBillFunnel.tsx | 34 + .../pages/AddBillFunnel/steps/MembersStep.tsx | 104 + .../pages/AddBillFunnel/steps/PriceStep.tsx | 64 + .../pages/AddBillFunnel/steps/TitleStep.tsx | 63 + .../CompleteCreateEventPage.tsx | 29 - .../CompleteCreateEventStep.tsx | 38 + .../CreateEventPage/CreateEventFunnel.tsx | 60 + .../CreateEventPage/SetEventNamePage.tsx | 42 - .../CreateEventPage/SetEventNameStep.tsx | 56 + .../CreateEventPage/SetEventPasswordPage.tsx | 41 - .../CreateEventPage/SetEventPasswordStep.tsx | 64 + client/src/pages/CreateEventPage/index.ts | 6 +- .../src/pages/EditBillPage/EditBillPage.tsx | 96 + client/src/pages/ErrorPage/ErrorPage.tsx | 11 +- .../EventPage/AdminPage/AdminPage.style.ts | 3 +- .../pages/EventPage/AdminPage/AdminPage.tsx | 104 +- .../EventPage/AdminPage/EventLoginPage.tsx | 31 +- .../EventPage/AdminPage/EventMember.style.ts | 56 + .../pages/EventPage/AdminPage/EventMember.tsx | 94 + .../BillEmptyFallback/index.tsx | 16 + .../EventPageFallback/fallbackText.ts | 7 + .../src/pages/EventPage/EventPageLayout.tsx | 63 +- .../EventPage/HomePage/HomePage.style.ts | 9 + .../src/pages/EventPage/HomePage/HomePage.tsx | 25 +- client/src/pages/MainPage/MainPage.tsx | 6 +- client/src/pages/MainPage/Nav/Nav.style.ts | 29 +- client/src/pages/MainPage/Nav/Nav.tsx | 31 +- .../pages/MainPage/Section/AddBillSection.tsx | 3 +- .../MainPage/Section/AddMemberSection.tsx | 5 +- .../MainPage/Section/DescriptionSection.tsx | 4 +- .../pages/MainPage/Section/MainSection.tsx | 9 +- ...berReportSection.tsx => ReportSection.tsx} | 7 +- client/src/router.tsx | 35 +- client/src/store/stepListStore.ts | 16 - client/src/store/stepsStore.ts | 16 + client/src/store/totalExpenseAmountStore.ts | 6 +- client/src/types/fetchErrorType.ts | 11 - client/src/types/kakao.d.ts | 38 + client/src/types/serviceType.ts | 123 +- client/src/types/toastType.ts | 20 + client/src/utils/NetworkStateCatcher.tsx | 39 + client/src/utils/caculateExpense.ts | 16 +- client/src/utils/captureError.ts | 62 +- client/src/utils/detectDevice.ts | 20 + client/src/utils/getDeletedLastPath.ts | 7 + client/src/utils/groupActions.ts | 27 - client/src/utils/isRequestError.ts | 7 + client/src/utils/sendLogToSentry.ts | 38 +- client/src/utils/stepListToActions.ts | 23 - .../utils/validate/validateAccountNumber.ts | 23 + ...portInAction.ts => validateBillDetails.ts} | 4 +- .../src/utils/validate/validateEventName.ts | 1 + .../src/utils/validate/validateMemberName.ts | 10 +- client/src/utils/validate/validatePurchase.ts | 47 - client/tsconfig.json | 10 +- client/webpack.common.mjs | 11 + server/.gitignore | 244 - server/Dockerfile | 9 - server/build.gradle | 86 - server/docs/24-08-04-erd.sql | 65 - server/docs/24-08-04-erd.svg | 4 - server/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - server/gradlew | 249 - server/gradlew.bat | 92 - server/settings.gradle | 1 - server/src/docs/asciidoc/billAction.adoc | 121 - .../src/docs/asciidoc/billActionDetail.adoc | 93 - server/src/docs/asciidoc/event.adoc | 205 - server/src/docs/asciidoc/index.adoc | 15 - server/src/docs/asciidoc/memberAction.adoc | 100 - .../src/docs/asciidoc/memberBillReport.adoc | 17 - .../haengdong/HaengdongApplication.java | 15 - .../haengdong/application/ActionService.java | 39 - .../haengdong/application/AuthService.java | 41 - .../application/BillActionDetailService.java | 76 - .../application/BillActionService.java | 80 - .../haengdong/application/EventService.java | 170 - .../application/MemberActionFactory.java | 62 - .../application/MemberActionService.java | 100 - .../request/BillActionAppRequest.java | 15 - .../BillActionDetailUpdateAppRequest.java | 8 - .../BillActionDetailsUpdateAppRequest.java | 8 - .../request/BillActionUpdateAppRequest.java | 7 - .../application/request/EventAppRequest.java | 10 - .../request/EventLoginAppRequest.java | 4 - .../request/MemberActionSaveAppRequest.java | 12 - .../request/MemberActionsSaveAppRequest.java | 6 - .../request/MemberNameUpdateAppRequest.java | 7 - .../request/MemberNamesUpdateAppRequest.java | 8 - .../response/ActionAppResponse.java | 61 - .../response/BillActionDetailAppResponse.java | 18 - .../BillActionDetailsAppResponse.java | 14 - .../response/CurrentMemberAppResponse.java | 10 - .../response/EventAppResponse.java | 10 - .../response/EventDetailAppResponse.java | 10 - .../response/MemberBillReportAppResponse.java | 4 - .../response/MembersAppResponse.java | 8 - .../haengdong/config/AdminInterceptor.java | 51 - .../config/RequestServletFilter.java | 23 - .../server/haengdong/config/WebMvcConfig.java | 66 - .../haengdong/domain/TokenProvider.java | 12 - .../haengdong/domain/action/Action.java | 42 - .../domain/action/ActionRepository.java | 23 - .../haengdong/domain/action/BillAction.java | 156 - .../domain/action/BillActionDetail.java | 61 - .../action/BillActionDetailRepository.java | 20 - .../domain/action/BillActionRepository.java | 27 - .../domain/action/CurrentMembers.java | 81 - .../haengdong/domain/action/MemberAction.java | 76 - .../domain/action/MemberActionRepository.java | 53 - .../domain/action/MemberActionStatus.java | 19 - .../domain/action/MemberBillReport.java | 75 - .../domain/action/MemberGroupIdProvider.java | 11 - .../server/haengdong/domain/event/Event.java | 70 - .../domain/event/EventRepository.java | 11 - .../haengdong/domain/event/EventStep.java | 28 - .../domain/event/EventTokenProvider.java | 12 - .../haengdong/domain/event/Password.java | 52 - .../exception/AuthenticationException.java | 19 - .../haengdong/exception/ErrorResponse.java | 15 - .../exception/GlobalExceptionHandler.java | 90 - .../exception/HaengdongErrorCode.java | 69 - .../exception/HaengdongException.java | 19 - .../auth/AuthenticationExtractor.java | 23 - .../infrastructure/auth/CookieProperties.java | 15 - .../infrastructure/auth/JwtTokenProvider.java | 54 - .../infrastructure/auth/TokenProperties.java | 7 - .../presentation/ActionController.java | 26 - .../presentation/BillActionController.java | 55 - .../BillActionDetailController.java | 42 - .../presentation/EventController.java | 120 - .../presentation/MemberActionController.java | 60 - .../BillActionDetailUpdateRequest.java | 21 - .../BillActionDetailsUpdateRequest.java | 16 - .../request/BillActionSaveRequest.java | 19 - .../request/BillActionUpdateRequest.java | 18 - .../request/BillActionsSaveRequest.java | 18 - .../request/EventLoginRequest.java | 14 - .../request/EventSaveRequest.java | 18 - .../request/MemberActionsSaveRequest.java | 25 - .../request/MemberNameUpdateRequest.java | 18 - .../request/MemberNamesUpdateRequest.java | 17 - .../presentation/response/ActionResponse.java | 26 - .../response/ActionResponse2.java | 22 - .../response/ActionsResponse.java | 14 - .../response/BillActionDetailResponse.java | 18 - .../response/BillActionDetailsResponse.java | 16 - .../response/CurrentMembersResponse.java | 15 - .../response/EventDetailResponse.java | 10 - .../presentation/response/EventResponse.java | 10 - .../response/MemberBillReportResponse.java | 10 - .../response/MemberBillReportsResponse.java | 15 - .../response/MembersResponse.java | 13 - .../presentation/response/StepResponse.java | 27 - .../presentation/response/StepsResponse.java | 56 - server/src/main/resources/application.yml | 66 - server/src/main/resources/config | 1 - server/src/main/resources/logback-spring.xml | 97 - .../application/ActionServiceTest.java | 91 - .../BillActionDetailServiceTest.java | 111 - .../application/BillActionServiceTest.java | 229 - .../application/EventServiceTest.java | 231 - .../application/MemberActionFactoryTest.java | 223 - .../application/MemberActionServiceTest.java | 251 - .../application/ServiceTestSupport.java | 11 - .../docs/ActionControllerDocsTest.java | 70 - .../docs/BillActionControllerDocsTest.java | 128 - .../BillActionDetailControllerDocsTest.java | 127 - .../docs/EventControllerDocsTest.java | 381 - .../docs/MemberActionControllerDocsTest.java | 157 - .../haengdong/docs/RestDocsSupport.java | 28 - .../haengdong/domain/action/ActionTest.java | 31 - .../domain/action/BillActionTest.java | 89 - .../domain/action/CurrentMembersTest.java | 97 - .../domain/action/MemberBillReportTest.java | 56 - .../haengdong/domain/event/EventTest.java | 65 - .../haengdong/domain/event/PasswordTest.java | 19 - .../presentation/ActionControllerTest.java | 36 - .../BillActionControllerTest.java | 97 - .../BillActionDetailControllerTest.java | 56 - .../presentation/ControllerTestSupport.java | 53 - .../presentation/EventControllerTest.java | 111 - .../MemberActionControllerTest.java | 74 - .../response/StepsResponseTest.java | 63 - .../support/extension/DatabaseCleaner.java | 52 - .../extension/DatabaseCleanerExtension.java | 19 - .../haengdong/support/fixture/Fixture.java | 15 - 576 files changed, 13163 insertions(+), 28596 deletions(-) delete mode 100644 .github/workflows/design-pull-request.yml delete mode 100644 HDesign/.gitignore delete mode 100644 HDesign/.npmignore delete mode 100644 HDesign/.npmrc delete mode 100644 HDesign/.prettierrc delete mode 100644 HDesign/.storybook/main.ts delete mode 100644 HDesign/eslint.config.mjs delete mode 100644 HDesign/package-lock.json delete mode 100644 HDesign/package.json delete mode 100644 HDesign/src/assets/index.ts delete mode 100644 HDesign/src/assets/svg.d.ts delete mode 100644 HDesign/src/components/ExpenseList/ExpenseList.stories.tsx delete mode 100644 HDesign/src/components/ExpenseList/ExpenseList.style.ts delete mode 100644 HDesign/src/components/ExpenseList/ExpenseList.tsx delete mode 100644 HDesign/src/components/ExpenseList/ExpenseList.type.ts delete mode 100644 HDesign/src/components/Icon/Icon.tsx delete mode 100644 HDesign/src/components/Search/Search.stories.tsx delete mode 100644 HDesign/src/components/Search/Search.style.ts delete mode 100644 HDesign/src/components/Search/Search.tsx delete mode 100644 HDesign/src/components/Switch/Switch.stories.tsx delete mode 100644 HDesign/src/components/Switch/Switch.style.ts delete mode 100644 HDesign/src/components/Switch/Switch.tsx delete mode 100644 HDesign/src/components/Switch/Switch.type.ts delete mode 100644 HDesign/src/components/Tabs/Tabs.style.ts delete mode 100644 HDesign/src/components/Tabs/Tabs.tsx delete mode 100644 HDesign/src/components/Title/Title.tsx delete mode 100644 HDesign/src/components/Toast/Toast.stories.tsx delete mode 100644 HDesign/src/components/Toast/Toast.style.ts delete mode 100644 HDesign/src/components/Toast/Toast.tsx delete mode 100644 HDesign/src/components/Toast/Toast.type.ts delete mode 100644 HDesign/src/components/Toast/ToastProvider.stories.tsx delete mode 100644 HDesign/src/components/Toast/ToastProvider.tsx delete mode 100644 HDesign/src/components/TopNav/Back.tsx delete mode 100644 HDesign/src/components/TopNav/TopNav.stories.tsx delete mode 100644 HDesign/src/components/TopNav/TopNav.style.ts delete mode 100644 HDesign/src/components/TopNav/TopNav.tsx delete mode 100644 HDesign/src/index.tsx delete mode 100644 HDesign/tsconfig.json create mode 100644 client/.storybook/main.ts rename {HDesign => client}/.storybook/preview.tsx (91%) create mode 100644 client/src/UnPredictableErrorBoundary.tsx delete mode 100644 client/src/UnhandledErrorBoundary.tsx rename client/src/apis/{tempPrefix.ts => endpointPrefix.ts} (63%) create mode 100644 client/src/apis/request/step.ts delete mode 100644 client/src/apis/request/stepList.ts rename client/src/apis/{withEventId.type.ts => withId.type.ts} (50%) create mode 100644 client/src/assets/image/Toss_Symbol_Primary.png create mode 100644 client/src/assets/image/banksprite.png rename {HDesign/src/assets => client/src/assets/image}/buljusa.svg (100%) create mode 100644 client/src/assets/image/check.svg rename {HDesign/src/assets => client/src/assets/image}/confirm.svg (100%) create mode 100644 client/src/assets/image/editPencil.svg rename {HDesign/src/assets => client/src/assets/image}/error.svg (100%) rename {HDesign/src/assets => client/src/assets/image}/inputDelete.svg (100%) rename {HDesign/src/assets => client/src/assets/image}/loadingAnimation.json (100%) create mode 100644 client/src/assets/image/meatballs.svg create mode 100644 client/src/assets/image/pencil_mini.svg rename {HDesign/src/assets => client/src/assets/image}/rightChevron.svg (100%) rename {HDesign/src/assets => client/src/assets/image}/search.svg (100%) rename {HDesign/src/assets => client/src/assets/image}/trash.svg (100%) create mode 100644 client/src/assets/image/trash_mini.svg create mode 100644 client/src/assets/image/x.svg create mode 100644 client/src/components/AmountInput/AmountInput.stories.tsx create mode 100644 client/src/components/AmountInput/AmountInput.tsx create mode 100644 client/src/components/BillDetails/BillDetails.tsx create mode 100644 client/src/components/Design/components/Amount/Amount.stories.tsx create mode 100644 client/src/components/Design/components/Amount/Amount.tsx create mode 100644 client/src/components/Design/components/Amount/EditableAmount.tsx create mode 100644 client/src/components/Design/components/BankSelect/BankSelect.stories.tsx create mode 100644 client/src/components/Design/components/BankSelect/BankSelect.style.ts create mode 100644 client/src/components/Design/components/BankSelect/BankSelect.tsx create mode 100644 client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx create mode 100644 client/src/components/Design/components/BankSendButton/BankSendButton.style.ts create mode 100644 client/src/components/Design/components/BankSendButton/BankSendButton.tsx rename {HDesign/src => client/src/components/Design}/components/BottomSheet/BottomSheet.stories.tsx (86%) rename {HDesign/src => client/src/components/Design}/components/BottomSheet/BottomSheet.style.ts (94%) rename {HDesign/src => client/src/components/Design}/components/BottomSheet/BottomSheet.tsx (94%) rename {HDesign/src => client/src/components/Design}/components/BottomSheet/BottomSheet.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/BottomSheet/useBottomSheet.ts (99%) rename {HDesign/src => client/src/components/Design}/components/Button/Button.stories.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/Button/Button.style.ts (94%) rename {HDesign/src => client/src/components/Design}/components/Button/Button.tsx (83%) rename {HDesign/src => client/src/components/Design}/components/Button/Button.type.ts (100%) create mode 100644 client/src/components/Design/components/Chip/Chip.stories.tsx create mode 100644 client/src/components/Design/components/Chip/Chip.style.ts create mode 100644 client/src/components/Design/components/Chip/Chip.tsx create mode 100644 client/src/components/Design/components/ChipButton/ChipButton.stories.tsx create mode 100644 client/src/components/Design/components/ChipButton/ChipButton.style.ts create mode 100644 client/src/components/Design/components/ChipButton/ChipButton.tsx create mode 100644 client/src/components/Design/components/ChipGroup/ChipGroup.stories.tsx create mode 100644 client/src/components/Design/components/ChipGroup/ChipGroup.style.ts create mode 100644 client/src/components/Design/components/ChipGroup/ChipGroup.tsx create mode 100644 client/src/components/Design/components/DepositCheck/DepositCheck.stories.tsx create mode 100644 client/src/components/Design/components/DepositCheck/DepositCheck.style.ts create mode 100644 client/src/components/Design/components/DepositCheck/DepositCheck.tsx create mode 100644 client/src/components/Design/components/DepositCheck/DepositCheck.type.ts create mode 100644 client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx create mode 100644 client/src/components/Design/components/DepositToggle/DepositToggle.style.ts create mode 100644 client/src/components/Design/components/DepositToggle/DepositToggle.tsx create mode 100644 client/src/components/Design/components/DepositToggle/DepositToggle.type.ts rename {HDesign/src => client/src/components/Design}/components/DragHandleItem/DragHandleItem.stories.tsx (94%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItem/DragHandleItem.style.ts (99%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItem/DragHandleItem.tsx (85%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItem/DragHandleItem.type.ts (99%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx (92%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItemContainer/DragHandleItemContainer.style.ts (99%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItemContainer/DragHandleItemContainer.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItemContainer/DragHandleItemContainer.type.ts (100%) create mode 100644 client/src/components/Design/components/Dropdown/Dropdown.stories.tsx create mode 100644 client/src/components/Design/components/Dropdown/Dropdown.style.ts create mode 100644 client/src/components/Design/components/Dropdown/Dropdown.tsx create mode 100644 client/src/components/Design/components/Dropdown/Dropdown.type.ts create mode 100644 client/src/components/Design/components/Dropdown/DropdownButton.tsx create mode 100644 client/src/components/Design/components/Dropdown/useDropdown.ts rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.Input.style.ts (97%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.Input.tsx (90%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.Input.type.ts (89%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.context.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.input.stories.tsx (92%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.stories.tsx (98%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.style.ts (99%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.tsx (93%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.type.ts (99%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/useEditableItem.ts (100%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/useEditableItemInput.ts (98%) create mode 100644 client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx create mode 100644 client/src/components/Design/components/ExpenseList/ExpenseList.tsx create mode 100644 client/src/components/Design/components/ExpenseList/ExpenseList.type.ts rename {HDesign/src => client/src/components/Design}/components/FixedButton/FixedButton.stories.tsx (93%) rename {HDesign/src => client/src/components/Design}/components/FixedButton/FixedButton.style.ts (68%) rename {HDesign/src => client/src/components/Design}/components/FixedButton/FixedButton.tsx (55%) rename {HDesign/src => client/src/components/Design}/components/FixedButton/FixedButton.type.ts (80%) rename {HDesign/src => client/src/components/Design}/components/Flex/Flex.style.ts (93%) rename {HDesign/src => client/src/components/Design}/components/Flex/Flex.tsx (59%) rename {HDesign/src => client/src/components/Design}/components/Flex/Flex.type.ts (89%) rename {HDesign/src => client/src/components/Design}/components/Icon/Icon.stories.tsx (61%) rename {HDesign/src => client/src/components/Design}/components/Icon/Icon.style.ts (84%) create mode 100644 client/src/components/Design/components/Icon/Icon.tsx rename {HDesign/src => client/src/components/Design}/components/Icon/Icon.type.ts (66%) rename {HDesign/src => client/src/components/Design}/components/IconButton/IconButton.stories.tsx (92%) rename {HDesign/src => client/src/components/Design}/components/IconButton/IconButton.style.ts (97%) rename {HDesign/src => client/src/components/Design}/components/IconButton/IconButton.tsx (88%) rename {HDesign/src => client/src/components/Design}/components/IconButton/IconButton.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Input/Input.stories.tsx (90%) rename {HDesign/src => client/src/components/Design}/components/Input/Input.style.ts (53%) rename {HDesign/src => client/src/components/Design}/components/Input/Input.tsx (59%) rename {HDesign/src => client/src/components/Design}/components/Input/Input.type.ts (92%) rename {HDesign/src => client/src/components/Design}/components/Input/useInput.ts (100%) rename {HDesign/src => client/src/components/Design}/components/IsFixedIcon/IsFixedIcon.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/IsFixedIcon/IsFixedIcon.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/Element.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/Element.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/GroupInputContext.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/LabelGroupInput.stories.tsx (96%) rename HDesign/src/components/LabelInput/LabelInput.style.ts => client/src/components/Design/components/LabelGroupInput/LabelGroupInput.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/LabelGroupInput.tsx (97%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/LabelGroupInput.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/index.ts (100%) rename {HDesign/src => client/src/components/Design}/components/LabelInput/LabelInput.stories.tsx (95%) rename HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts => client/src/components/Design/components/LabelInput/LabelInput.style.ts (62%) rename {HDesign/src => client/src/components/Design}/components/LabelInput/LabelInput.tsx (74%) rename {HDesign/src => client/src/components/Design}/components/LabelInput/LabelInput.type.ts (69%) rename {HDesign/src => client/src/components/Design}/components/LabelInput/useLabelInput.ts (100%) rename {HDesign/src => client/src/components/Design}/components/ListButton/ListButton.stories.tsx (90%) rename {HDesign/src => client/src/components/Design}/components/ListButton/ListButton.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/ListButton/ListButton.tsx (82%) rename {HDesign/src => client/src/components/Design}/components/ListButton/ListButton.type.ts (100%) create mode 100644 client/src/components/Design/components/ListItem/ListItem.stories.tsx create mode 100644 client/src/components/Design/components/ListItem/ListItem.style.ts create mode 100644 client/src/components/Design/components/ListItem/ListItem.tsx create mode 100644 client/src/components/Design/components/ListItem/Row.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/Keypad.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/useNumberKeyboardBottomSheet.ts rename {HDesign/src => client/src/components/Design}/components/Tabs/Tab.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/Tabs/Tab.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Tabs/Tabs.stories.tsx (93%) create mode 100644 client/src/components/Design/components/Tabs/Tabs.style.ts create mode 100644 client/src/components/Design/components/Tabs/Tabs.tsx rename {HDesign/src => client/src/components/Design}/components/Text/Text.stories.tsx (93%) rename {HDesign/src => client/src/components/Design}/components/Text/Text.style.ts (90%) rename {HDesign/src => client/src/components/Design}/components/Text/Text.tsx (87%) rename {HDesign/src => client/src/components/Design}/components/Text/Text.type.ts (99%) rename {HDesign/src => client/src/components/Design}/components/TextButton/TextButton.stories.tsx (93%) rename {HDesign/src => client/src/components/Design}/components/TextButton/TextButton.style.ts (99%) rename {HDesign/src => client/src/components/Design}/components/TextButton/TextButton.tsx (86%) rename {HDesign/src => client/src/components/Design}/components/TextButton/TextButton.type.ts (85%) rename {HDesign/src => client/src/components/Design}/components/Title/Title.stories.tsx (59%) rename {HDesign/src => client/src/components/Design}/components/Title/Title.style.ts (51%) create mode 100644 client/src/components/Design/components/Title/Title.tsx rename {HDesign/src => client/src/components/Design}/components/Title/Title.type.ts (82%) create mode 100644 client/src/components/Design/components/Top/EditableLine.tsx create mode 100644 client/src/components/Design/components/Top/Line.tsx create mode 100644 client/src/components/Design/components/Top/Top.stories.tsx create mode 100644 client/src/components/Design/components/Top/Top.tsx create mode 100644 client/src/components/Design/components/TopNav/NavItem.style.ts create mode 100644 client/src/components/Design/components/TopNav/NavItem.tsx create mode 100644 client/src/components/Design/components/TopNav/NavItem.type.ts create mode 100644 client/src/components/Design/components/TopNav/TopNav.style.ts create mode 100644 client/src/components/Design/components/TopNav/TopNav.tsx create mode 100644 client/src/components/Design/index.tsx rename {HDesign/src => client/src/components/Design}/layouts/ContentLayout.tsx (100%) create mode 100644 client/src/components/Design/layouts/FunnelLayout.tsx rename {HDesign/src => client/src/components/Design}/layouts/MainLayout.tsx (96%) rename {HDesign/src => client/src/components/Design}/theme/GlobalStyle.ts (81%) rename {HDesign/src => client/src/components/Design}/theme/HDesignProvider.tsx (94%) rename {HDesign/src => client/src/components/Design}/theme/theme.type.ts (72%) rename {HDesign/src => client/src/components/Design}/token/colors.ts (100%) rename {HDesign/src => client/src/components/Design}/token/typography.ts (100%) create mode 100644 client/src/components/Design/token/zIndex.ts rename {HDesign/src => client/src/components/Design}/type/strictPropsWithChildren.ts (100%) rename {HDesign/src => client/src/components/Design}/type/withTheme.ts (100%) rename {HDesign/src => client/src/components/Design}/utils/changeCamelCaseToKebabCase.ts (100%) rename {HDesign/src => client/src/components/Design}/utils/colors.ts (100%) create mode 100644 client/src/components/ExpenseDetailModal/ExpenseDetailModal.tsx create mode 100644 client/src/components/KakaoInitializer/KakaoInitializer.tsx rename client/src/components/{Common => }/Logo/Logo.style.ts (100%) rename client/src/components/{Common => }/Logo/RunningDogLogo.tsx (100%) rename client/src/components/{Common => }/Logo/StandingDogLogo.tsx (100%) rename client/src/components/{Common => }/Logo/index.ts (100%) delete mode 100644 client/src/components/MemberReportList/MemberReportList.tsx rename client/src/components/Modal/{SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts => BankSelectModal/BankSelectModal.style.ts} (95%) create mode 100644 client/src/components/Modal/BankSelectModal/BankSelectModal.tsx delete mode 100644 client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx delete mode 100644 client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts delete mode 100644 client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx delete mode 100644 client/src/components/Modal/MemberListInBillStep/index.ts delete mode 100644 client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx delete mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts delete mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx delete mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx delete mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx delete mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts delete mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts delete mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx delete mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts delete mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx delete mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts delete mode 100644 client/src/components/Modal/SetActionModal/SetActionListModal.style.ts delete mode 100644 client/src/components/Modal/SetActionModal/SetActionListModal.tsx delete mode 100644 client/src/components/Modal/SetActionModal/index.ts delete mode 100644 client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts delete mode 100644 client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx delete mode 100644 client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts delete mode 100644 client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx delete mode 100644 client/src/components/Modal/SetInitialMemberListModal/index.ts delete mode 100644 client/src/components/Modal/index.ts create mode 100644 client/src/components/Reports/Reports.tsx create mode 100644 client/src/components/ShareEventButton/ShareEventButton.tsx create mode 100644 client/src/components/ShareEventButton/index.ts delete mode 100644 client/src/components/StepList/BillStepItem.tsx delete mode 100644 client/src/components/StepList/MemberStepItem.tsx create mode 100644 client/src/components/StepList/Step.stories.tsx delete mode 100644 client/src/components/StepList/StepList.tsx create mode 100644 client/src/components/StepList/Steps.tsx create mode 100644 client/src/components/Toast/ToastContainer.tsx create mode 100644 client/src/constants/bank.ts create mode 100644 client/src/constants/message.ts delete mode 100644 client/src/errors/FetchError.ts create mode 100644 client/src/errors/RequestError.ts create mode 100644 client/src/errors/RequestGetError.ts create mode 100644 client/src/errors/requestErrorType.ts rename client/src/hooks/queries/{ => auth}/useRequestPostAuthentication.ts (74%) rename client/src/hooks/queries/{ => auth}/useRequestPostLogin.ts (65%) create mode 100644 client/src/hooks/queries/bill/useRequestDeleteBill.ts create mode 100644 client/src/hooks/queries/bill/useRequestGetBillDetails.ts create mode 100644 client/src/hooks/queries/bill/useRequestPostBill.ts create mode 100644 client/src/hooks/queries/bill/useRequestPutBill.ts create mode 100644 client/src/hooks/queries/bill/useRequestPutBillDetails.ts create mode 100644 client/src/hooks/queries/event/useRequestGetEvent.ts create mode 100644 client/src/hooks/queries/event/useRequestPatchEvent.ts create mode 100644 client/src/hooks/queries/event/useRequestPostEvent.ts create mode 100644 client/src/hooks/queries/member/useRequestDeleteMember.ts create mode 100644 client/src/hooks/queries/member/useRequestGetAllMembers.ts create mode 100644 client/src/hooks/queries/member/useRequestGetCurrentMembers.ts create mode 100644 client/src/hooks/queries/member/useRequestPostMembers.ts create mode 100644 client/src/hooks/queries/member/useRequestPutMembers.ts create mode 100644 client/src/hooks/queries/report/useRequestGetReports.ts rename client/src/hooks/queries/{useRequestGetStepList.ts => step/useRequestGetSteps.ts} (60%) delete mode 100644 client/src/hooks/queries/useRequestDeleteAllMemberList.ts delete mode 100644 client/src/hooks/queries/useRequestDeleteBillAction.ts delete mode 100644 client/src/hooks/queries/useRequestDeleteMemberAction.ts delete mode 100644 client/src/hooks/queries/useRequestGetAllMemberList.ts delete mode 100644 client/src/hooks/queries/useRequestGetCurrentInMemberList.ts delete mode 100644 client/src/hooks/queries/useRequestGetEventName.ts delete mode 100644 client/src/hooks/queries/useRequestGetMemberReportList.ts delete mode 100644 client/src/hooks/queries/useRequestGetMemberReportListInAction.ts delete mode 100644 client/src/hooks/queries/useRequestPostBillList.ts delete mode 100644 client/src/hooks/queries/useRequestPostEvent.ts delete mode 100644 client/src/hooks/queries/useRequestPostMemberList.ts delete mode 100644 client/src/hooks/queries/useRequestPutAllMemberList.ts delete mode 100644 client/src/hooks/queries/useRequestPutBillAction.ts delete mode 100644 client/src/hooks/queries/useRequestPutMemberReportListInAction.ts create mode 100644 client/src/hooks/useAccount.ts create mode 100644 client/src/hooks/useAddBillFunnel.ts create mode 100644 client/src/hooks/useCreateEventData.tsx delete mode 100644 client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx delete mode 100644 client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx delete mode 100644 client/src/hooks/useDynamicInput.tsx create mode 100644 client/src/hooks/useEditBillActions.ts create mode 100644 client/src/hooks/useEditBillKeyboardAction.ts create mode 100644 client/src/hooks/useEditBillPage.ts create mode 100644 client/src/hooks/useEditBillPageScroll.ts create mode 100644 client/src/hooks/useEditBillState.ts create mode 100644 client/src/hooks/useEventMember.ts create mode 100644 client/src/hooks/useEventPageLayout.ts create mode 100644 client/src/hooks/useFunnel.tsx delete mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx delete mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx delete mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts create mode 100644 client/src/hooks/useMembersStep.ts delete mode 100644 client/src/hooks/useNavSwitch.tsx create mode 100644 client/src/hooks/usePriceStep.ts create mode 100644 client/src/hooks/usePutAndDeleteBill.ts delete mode 100644 client/src/hooks/usePutAndDeleteBillAction.ts create mode 100644 client/src/hooks/useReportsPage.ts delete mode 100644 client/src/hooks/useSearchInMemberList.ts delete mode 100644 client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx delete mode 100644 client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx create mode 100644 client/src/hooks/useSearchReports/index.ts create mode 100644 client/src/hooks/useSearchReports/useSearchReports.tsx delete mode 100644 client/src/hooks/useSetAllMemberList.tsx delete mode 100644 client/src/hooks/useSetBillInput.ts rename client/src/hooks/{useSetEventNamePage.ts => useSetEventNameStep.ts} (71%) delete mode 100644 client/src/hooks/useSetEventPasswordPage.ts create mode 100644 client/src/hooks/useSetEventPasswordStep.ts create mode 100644 client/src/hooks/useShareEvent.ts create mode 100644 client/src/hooks/useTitleStep.ts delete mode 100644 client/src/hooks/useToast/ToastProvider.tsx create mode 100644 client/src/hooks/useToast/toast.ts create mode 100644 client/src/hooks/useToast/toastEventManager.ts create mode 100644 client/src/hooks/useToast/toastEventManager.type.ts create mode 100644 client/src/mocks/handlers/billHandler.ts create mode 100644 client/src/mocks/handlers/memberHandler.ts delete mode 100644 client/src/mocks/handlers/memberReportInActionHandlers.ts delete mode 100644 client/src/mocks/handlers/stepListHandler.ts create mode 100644 client/src/mocks/imageFileMock.ts delete mode 100644 client/src/mocks/invalidMemberStepList.json delete mode 100644 client/src/mocks/memberActionStepList.json delete mode 100644 client/src/mocks/memberReportListInAction.json delete mode 100644 client/src/mocks/memberReportSearchList.json create mode 100644 client/src/mocks/mockEndpointPrefix.ts delete mode 100644 client/src/mocks/reportList.json create mode 100644 client/src/mocks/sharedState.ts delete mode 100644 client/src/mocks/stepList.json create mode 100644 client/src/pages/AccountPage/Account.tsx create mode 100644 client/src/pages/AddBillFunnel/AddBillFunnel.tsx create mode 100644 client/src/pages/AddBillFunnel/steps/MembersStep.tsx create mode 100644 client/src/pages/AddBillFunnel/steps/PriceStep.tsx create mode 100644 client/src/pages/AddBillFunnel/steps/TitleStep.tsx delete mode 100644 client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx create mode 100644 client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx create mode 100644 client/src/pages/CreateEventPage/CreateEventFunnel.tsx delete mode 100644 client/src/pages/CreateEventPage/SetEventNamePage.tsx create mode 100644 client/src/pages/CreateEventPage/SetEventNameStep.tsx delete mode 100644 client/src/pages/CreateEventPage/SetEventPasswordPage.tsx create mode 100644 client/src/pages/CreateEventPage/SetEventPasswordStep.tsx create mode 100644 client/src/pages/EditBillPage/EditBillPage.tsx create mode 100644 client/src/pages/EventPage/AdminPage/EventMember.style.ts create mode 100644 client/src/pages/EventPage/AdminPage/EventMember.tsx create mode 100644 client/src/pages/EventPage/EventPageFallback/BillEmptyFallback/index.tsx create mode 100644 client/src/pages/EventPage/EventPageFallback/fallbackText.ts create mode 100644 client/src/pages/EventPage/HomePage/HomePage.style.ts rename client/src/pages/MainPage/Section/{MemberReportSection.tsx => ReportSection.tsx} (86%) delete mode 100644 client/src/store/stepListStore.ts create mode 100644 client/src/store/stepsStore.ts delete mode 100644 client/src/types/fetchErrorType.ts create mode 100644 client/src/types/kakao.d.ts create mode 100644 client/src/types/toastType.ts create mode 100644 client/src/utils/NetworkStateCatcher.tsx create mode 100644 client/src/utils/detectDevice.ts create mode 100644 client/src/utils/getDeletedLastPath.ts delete mode 100644 client/src/utils/groupActions.ts create mode 100644 client/src/utils/isRequestError.ts delete mode 100644 client/src/utils/stepListToActions.ts create mode 100644 client/src/utils/validate/validateAccountNumber.ts rename client/src/utils/validate/{validateMemberReportInAction.ts => validateBillDetails.ts} (85%) delete mode 100644 client/src/utils/validate/validatePurchase.ts delete mode 100644 server/.gitignore delete mode 100644 server/Dockerfile delete mode 100644 server/build.gradle delete mode 100644 server/docs/24-08-04-erd.sql delete mode 100644 server/docs/24-08-04-erd.svg delete mode 100644 server/gradle/wrapper/gradle-wrapper.jar delete mode 100644 server/gradle/wrapper/gradle-wrapper.properties delete mode 100644 server/gradlew delete mode 100644 server/gradlew.bat delete mode 100644 server/settings.gradle delete mode 100644 server/src/docs/asciidoc/billAction.adoc delete mode 100644 server/src/docs/asciidoc/billActionDetail.adoc delete mode 100644 server/src/docs/asciidoc/event.adoc delete mode 100644 server/src/docs/asciidoc/index.adoc delete mode 100644 server/src/docs/asciidoc/memberAction.adoc delete mode 100644 server/src/docs/asciidoc/memberBillReport.adoc delete mode 100644 server/src/main/java/server/haengdong/HaengdongApplication.java delete mode 100644 server/src/main/java/server/haengdong/application/ActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/AuthService.java delete mode 100644 server/src/main/java/server/haengdong/application/BillActionDetailService.java delete mode 100644 server/src/main/java/server/haengdong/application/BillActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/EventService.java delete mode 100644 server/src/main/java/server/haengdong/application/MemberActionFactory.java delete mode 100644 server/src/main/java/server/haengdong/application/MemberActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/EventAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/response/ActionAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/EventAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/MembersAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/config/AdminInterceptor.java delete mode 100644 server/src/main/java/server/haengdong/config/RequestServletFilter.java delete mode 100644 server/src/main/java/server/haengdong/config/WebMvcConfig.java delete mode 100644 server/src/main/java/server/haengdong/domain/TokenProvider.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/Action.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/ActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillAction.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionDetail.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/CurrentMembers.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberAction.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberBillReport.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/Event.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventStep.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/Password.java delete mode 100644 server/src/main/java/server/haengdong/exception/AuthenticationException.java delete mode 100644 server/src/main/java/server/haengdong/exception/ErrorResponse.java delete mode 100644 server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java delete mode 100644 server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java delete mode 100644 server/src/main/java/server/haengdong/exception/HaengdongException.java delete mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java delete mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java delete mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java delete mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java delete mode 100644 server/src/main/java/server/haengdong/presentation/ActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/BillActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/BillActionDetailController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/EventController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/MemberActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/EventResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/MembersResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/StepResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/StepsResponse.java delete mode 100644 server/src/main/resources/application.yml delete mode 160000 server/src/main/resources/config delete mode 100644 server/src/main/resources/logback-spring.xml delete mode 100644 server/src/test/java/server/haengdong/application/ActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/BillActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/EventServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java delete mode 100644 server/src/test/java/server/haengdong/application/MemberActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/ServiceTestSupport.java delete mode 100644 server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java delete mode 100644 server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java delete mode 100644 server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java delete mode 100644 server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java delete mode 100644 server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java delete mode 100644 server/src/test/java/server/haengdong/docs/RestDocsSupport.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/ActionTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/BillActionTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/event/EventTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/event/PasswordTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/ActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java delete mode 100644 server/src/test/java/server/haengdong/presentation/EventControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java delete mode 100644 server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java delete mode 100644 server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java delete mode 100644 server/src/test/java/server/haengdong/support/fixture/Fixture.java diff --git a/.github/workflows/design-pull-request.yml b/.github/workflows/design-pull-request.yml deleted file mode 100644 index af168a976..000000000 --- a/.github/workflows/design-pull-request.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Storybook Deployment - -on: - pull_request: - branches: - - fe-dev - paths: - - 'HDesign/**' - -jobs: - chromatic: - name: Run Chromatic - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '20.15.1' - - - name: Cache dependencies - id: cache - uses: actions/cache@v3 - with: - path: '**/node_modules' - key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-npm- - - - name: Install dependencies - if: steps.cache.outputs.cache-hit != 'true' - run: | - cd HDesign - npm install - - - name: Run lint - run: npm run lint - working-directory: ./HDesign - - - name: Run Chromatic - uses: chromaui/action@latest - id: publish_chromatic - with: - workingDir: HDesign - projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} - - - name: Comment on PR - uses: thollander/actions-comment-pull-request@v2 - with: - message: '🚀 **storybook**: ${{ steps.publish_chromatic.outputs.storybookUrl }}' diff --git a/.github/workflows/frontend-pull-request.yml b/.github/workflows/frontend-pull-request.yml index c2749939b..913ba783d 100644 --- a/.github/workflows/frontend-pull-request.yml +++ b/.github/workflows/frontend-pull-request.yml @@ -5,7 +5,7 @@ on: types: [opened, synchronize] branches: [main, fe-dev] paths: - - 'client/**' + - "client/**" jobs: test: @@ -23,18 +23,15 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '20.15.1' + node-version: "20.15.1" - name: Install dependencies - working-directory: ./client run: npm install - name: Run lint - working-directory: ./client run: npm run lint - name: Run test - working-directory: ./client run: npm run test - name: Cypress test @@ -47,3 +44,48 @@ jobs: - name: Run Cypress tests run: npm run cypress-run + + chromatic: + name: Run Chromatic + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + working-directory: ./client + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20.15.1" + + - name: Cache dependencies + id: cache + uses: actions/cache@v3 + with: + path: "**/node_modules" + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}-v1 + restore-keys: | + ${{ runner.os }}-npm- + + - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: npm install + + - name: Run Chromatic + uses: chromaui/action@latest + id: publish_chromatic + with: + workingDir: client + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + + - name: Comment on PR + uses: thollander/actions-comment-pull-request@v2 + with: + message: "🚀 **storybook**: ${{ steps.publish_chromatic.outputs.storybookUrl }}" diff --git a/HDesign/.gitignore b/HDesign/.gitignore deleted file mode 100644 index b98928456..000000000 --- a/HDesign/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -logs -*.log -npm-debug.log* - -node_modules -dist - -.env - -storybook-static -*storybook.log -.DS_Store diff --git a/HDesign/.npmignore b/HDesign/.npmignore deleted file mode 100644 index 363c89306..000000000 --- a/HDesign/.npmignore +++ /dev/null @@ -1,7 +0,0 @@ -node_modules/ -src/ -tsconfig.json -.storybook/ -.eslintrc.json -.prettierrc -webpack.config.js \ No newline at end of file diff --git a/HDesign/.npmrc b/HDesign/.npmrc deleted file mode 100644 index ece05f588..000000000 --- a/HDesign/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -engine-strict = true -legacy-peer-deps = true diff --git a/HDesign/.prettierrc b/HDesign/.prettierrc deleted file mode 100644 index c025201f4..000000000 --- a/HDesign/.prettierrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "all", - "printWidth": 120, - "tabWidth": 2, - "semi": true, - "arrowParens": "avoid", - "endOfLine": "auto", - "jsxSingleQuote": false, - "bracketSpacing": false, - "proseWrap": "preserve" -} diff --git a/HDesign/.storybook/main.ts b/HDesign/.storybook/main.ts deleted file mode 100644 index a1fa61591..000000000 --- a/HDesign/.storybook/main.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** @type { import('@storybook/react-webpack5').StorybookConfig } */ -import type {StorybookConfig} from '@storybook/react-webpack5'; -import path from 'path'; - -const config: StorybookConfig = { - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], - addons: [ - '@storybook/addon-webpack5-compiler-swc', - '@storybook/addon-onboarding', - '@storybook/addon-links', - '@storybook/addon-essentials', - '@chromatic-com/storybook', - '@storybook/addon-interactions', - ], - framework: { - name: '@storybook/react-webpack5', - options: {}, - }, - webpackFinal: async config => { - if (config.resolve) { - config.resolve.alias = { - ...config.resolve.alias, - '@components': path.resolve(__dirname, '../src/components'), - '@token': path.resolve(__dirname, '../src/token'), - '@type': path.resolve(__dirname, '../src/type'), - '@theme': path.resolve(__dirname, '../src/theme'), - '@assets': path.resolve(__dirname, '../src/assets'), - '@utils': path.resolve(__dirname, '../src/utils'), - }; - } - - config.module = config.module || {}; - config.module.rules = config.module.rules || []; - - const imageRule = config.module.rules.find(rule => rule?.['test']?.test('.svg')); - if (imageRule) { - imageRule['exclude'] = /\.svg$/; - } - - config.module.rules.push({ - test: /\.svg$/, - use: ['@svgr/webpack'], - }); - return config; - }, -}; -export default config; diff --git a/HDesign/eslint.config.mjs b/HDesign/eslint.config.mjs deleted file mode 100644 index e025936a4..000000000 --- a/HDesign/eslint.config.mjs +++ /dev/null @@ -1,153 +0,0 @@ -import path from 'node:path'; -import {fileURLToPath} from 'node:url'; - -import {fixupConfigRules, fixupPluginRules} from '@eslint/compat'; -import react from 'eslint-plugin-react'; -import typescriptEslint from '@typescript-eslint/eslint-plugin'; -import _import from 'eslint-plugin-import'; -import prettier from 'eslint-plugin-prettier'; -import tsParser from '@typescript-eslint/parser'; -import js from '@eslint/js'; -import {FlatCompat} from '@eslint/eslintrc'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all, -}); - -export default [ - ...fixupConfigRules( - compat.extends( - 'eslint:recommended', - 'plugin:react/recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', - 'plugin:import/typescript', - 'plugin:import/recommended', - 'plugin:import/errors', - 'plugin:import/warnings', - 'prettier', - 'plugin:prettier/recommended', - ), - ), - { - plugins: { - react: fixupPluginRules(react), - '@typescript-eslint': fixupPluginRules(typescriptEslint), - import: fixupPluginRules(_import), - prettier: fixupPluginRules(prettier), - }, - - languageOptions: { - parser: tsParser, - }, - - settings: { - 'import/resolver': { - node: { - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }, - - typescript: { - directory: './lib', - }, - }, - - 'import/parsers': { - '@typescript-eslint/parser': ['.ts', '.tsx'], - }, - - 'import/ignore': ['lottie-react'], - }, - - rules: { - 'no-use-before-define': 0, - 'prettier/prettier': 'error', - 'react/react-in-jsx-scope': 'off', - 'react/prop-types': 'off', - 'import/prefer-default-export': 0, - 'import/no-named-as-default': 0, - 'import/namespace': 0, - 'import/extensions': 0, - 'import/no-cycle': 0, - 'react/no-unknown-property': 0, - 'react/jsx-filename-extension': [1, {extensions: ['.ts', '.tsx']}], - 'react/function-component-definition': 0, - 'react/jsx-props-no-spreading': 0, - 'react/jsx-key': 0, - 'react/button-has-type': 'off', - 'no-shadow': 0, - 'no-console': 0, - 'no-alert': 0, - 'react/no-children-prop': 'off', - 'react/no-array-index-key': 'off', - 'react-hooks/exhaustive-deps': 'off', - 'react-hooks/rules-of-hooks': 'off', - 'react/jsx-no-useless-fragment': 'off', - 'react/jsx-no-constructed-context-values': 'off', - 'jsx-a11y/click-events-have-key-events': 'off', - 'jsx-a11y/no-static-element-interactions': 'off', - - '@typescript-eslint/no-unused-vars': 0, - - // 'react/jsx-uses-vars': 'error', - // '@typescript-eslint/no-use-before-define': ['error'], - // '@typescript-eslint/explicit-module-boundary-types': 'error', - - 'import/order': [ - 'error', - { - 'newlines-between': 'always', - - groups: ['type', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'unknown'], - - pathGroups: [ - { - pattern: 'react*', - group: 'external', - position: 'before', - }, - { - pattern: '@components/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@layouts/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@assets/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@theme/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@token/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@types/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@utils/*', - group: 'internal', - position: 'after', - }, - ], - }, - ], - }, - }, -]; diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json deleted file mode 100644 index fb92d2ae1..000000000 --- a/HDesign/package-lock.json +++ /dev/null @@ -1,13707 +0,0 @@ -{ - "name": "haengdong-design", - "version": "0.1.81", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "haengdong-design", - "version": "0.1.81", - "license": "ISC", - "dependencies": { - "@emotion/react": "^11.11.4", - "@storybook/addon-webpack5-compiler-swc": "^1.0.5", - "@svgr/webpack": "^8.1.0", - "lottie-react": "^2.4.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-router-dom": "^6.24.1" - }, - "devDependencies": { - "@chromatic-com/storybook": "^1.6.1", - "@eslint/compat": "^1.1.0", - "@eslint/js": "^9.6.0", - "@storybook/addon-essentials": "^8.2.2", - "@storybook/addon-interactions": "^8.2.2", - "@storybook/addon-links": "^8.2.2", - "@storybook/addon-onboarding": "^8.2.2", - "@storybook/blocks": "^8.2.2", - "@storybook/react": "^8.2.2", - "@storybook/react-webpack5": "^8.2.3", - "@storybook/test": "^8.2.2", - "@swc/core": "^1.7.6", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.16.0", - "@typescript-eslint/parser": "^7.16.0", - "esbuild": "^0.23.0", - "eslint": "^9.8.0", - "eslint-config-prettier": "^9.1.0", - "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.9.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.4", - "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-storybook": "^0.8.0", - "file-loader": "^6.2.0", - "globals": "^15.8.0", - "prettier": "3.3.2", - "storybook": "^8.2.2", - "storybook-addon-react-router-v6": "^2.0.15", - "ts-loader": "^9.5.1", - "tsc-alias": "^1.8.10", - "typescript": "^5.5.3", - "typescript-eslint": "^7.16.0" - }, - "engines": { - "node": ">=20.15.1", - "npm": ">=10.7.0" - } - }, - "node_modules/@adobe/css-tools": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", - "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", - "dev": true - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", - "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", - "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.9", - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-module-transforms": "^7.24.9", - "@babel/helpers": "^7.24.8", - "@babel/parser": "^7.24.8", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.9", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" - }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.9.tgz", - "integrity": "sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==", - "dependencies": { - "@babel/types": "^7.24.9", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", - "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", - "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", - "dependencies": { - "@babel/compat-data": "^7.24.8", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", - "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", - "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", - "dependencies": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", - "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", - "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-wrap-function": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", - "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", - "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", - "dependencies": { - "@babel/helper-function-name": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", - "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", - "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", - "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", - "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", - "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-flow": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", - "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", - "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", - "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", - "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", - "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", - "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", - "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", - "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", - "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", - "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", - "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", - "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", - "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/template": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", - "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", - "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", - "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", - "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", - "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", - "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.7.tgz", - "integrity": "sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-flow": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", - "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", - "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", - "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", - "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", - "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", - "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", - "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", - "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", - "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", - "dependencies": { - "@babel/helper-module-transforms": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-simple-access": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", - "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", - "dependencies": { - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", - "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", - "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", - "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", - "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", - "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", - "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", - "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", - "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", - "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", - "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", - "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", - "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", - "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", - "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz", - "integrity": "sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", - "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", - "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", - "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", - "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", - "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", - "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", - "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", - "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", - "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", - "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", - "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", - "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", - "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/plugin-syntax-typescript": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", - "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", - "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", - "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", - "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", - "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", - "dependencies": { - "@babel/compat-data": "^7.24.8", - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-option": "^7.24.8", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.7", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.24.7", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoped-functions": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.24.7", - "@babel/plugin-transform-class-properties": "^7.24.7", - "@babel/plugin-transform-class-static-block": "^7.24.7", - "@babel/plugin-transform-classes": "^7.24.8", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-dotall-regex": "^7.24.7", - "@babel/plugin-transform-duplicate-keys": "^7.24.7", - "@babel/plugin-transform-dynamic-import": "^7.24.7", - "@babel/plugin-transform-exponentiation-operator": "^7.24.7", - "@babel/plugin-transform-export-namespace-from": "^7.24.7", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.24.7", - "@babel/plugin-transform-json-strings": "^7.24.7", - "@babel/plugin-transform-literals": "^7.24.7", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-member-expression-literals": "^7.24.7", - "@babel/plugin-transform-modules-amd": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-modules-systemjs": "^7.24.7", - "@babel/plugin-transform-modules-umd": "^7.24.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-new-target": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-object-super": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-property-literals": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-reserved-words": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-template-literals": "^7.24.7", - "@babel/plugin-transform-typeof-symbol": "^7.24.8", - "@babel/plugin-transform-unicode-escapes": "^7.24.7", - "@babel/plugin-transform-unicode-property-regex": "^7.24.7", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.37.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/preset-flow": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz", - "integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "@babel/plugin-transform-flow-strip-types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-react": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", - "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "@babel/plugin-transform-react-display-name": "^7.24.7", - "@babel/plugin-transform-react-jsx": "^7.24.7", - "@babel/plugin-transform-react-jsx-development": "^7.24.7", - "@babel/plugin-transform-react-pure-annotations": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", - "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.7", - "@babel/plugin-transform-typescript": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/register": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", - "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.6", - "source-map-support": "^0.5.16" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/register/node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/register/node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" - }, - "node_modules/@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", - "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.8", - "@babel/types": "^7.24.8", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/traverse/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@babel/types": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", - "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", - "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@base2/pretty-print-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", - "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", - "dev": true - }, - "node_modules/@chromatic-com/storybook": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-1.6.1.tgz", - "integrity": "sha512-x1x1NB3j4xpfeSWKr96emc+7ZvfsvH+/WVb3XCjkB24PPbT8VZXb3mJSAQMrSzuQ8+eQE9kDogYHH9Fj3tb/Cw==", - "dev": true, - "dependencies": { - "chromatic": "^11.4.0", - "filesize": "^10.0.12", - "jsonfile": "^6.1.0", - "react-confetti": "^6.1.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=16.0.0", - "yarn": ">=1.22.18" - } - }, - "node_modules/@chromatic-com/storybook/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@chromatic-com/storybook/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@emotion/cache": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", - "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", - "dependencies": { - "@emotion/memoize": "^0.8.1", - "@emotion/sheet": "^1.2.2", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" - }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" - }, - "node_modules/@emotion/react": { - "version": "11.11.4", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", - "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "hoist-non-react-statics": "^3.3.1" - }, - "peerDependencies": { - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@emotion/serialize": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", - "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", - "dependencies": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", - "csstype": "^3.0.2" - } - }, - "node_modules/@emotion/sheet": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", - "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" - }, - "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" - }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "node_modules/@emotion/utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", - "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" - }, - "node_modules/@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/compat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", - "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", - "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", - "dev": true, - "dependencies": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/js": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", - "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", - "dev": true, - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@mdx-js/react": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", - "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", - "dev": true, - "dependencies": { - "@types/mdx": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@remix-run/router": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", - "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/addon-actions": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.2.2.tgz", - "integrity": "sha512-SN4cSRt3f0qXi5te+yhMseSdQuZntA8lGlASbRmN77YQTpIaGsNiH88xFoky0s9qz531hiRfU1R0ZSMylBwSKw==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "@types/uuid": "^9.0.1", - "dequal": "^2.0.2", - "polished": "^4.2.2", - "uuid": "^9.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-actions/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@storybook/addon-backgrounds": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.2.2.tgz", - "integrity": "sha512-m/xJe7uKL+kfJx7pQcHwAeIvJ3tdLIpDGrMAVDNDJHcAxfe44cFjIInaV/1HKf3y5Awap+DZFW66ekkxuI9zzA==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "memoizerific": "^1.11.3", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-controls": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.2.2.tgz", - "integrity": "sha512-y241aOANGzT5XBADUIvALwG/xF5eC6UItzmWJaFvOzSBCq74GIA0+Hu9atyFdvFQbXOrdvPWC4jR+9iuBFRxAA==", - "dev": true, - "dependencies": { - "dequal": "^2.0.2", - "lodash": "^4.17.21", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-docs": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.2.2.tgz", - "integrity": "sha512-qk/yjAR9RpsSrKLLbeCgb6u58c8TmYqyJSnXgbAozZZNKHBWlIpvZ/hTNYud8qo0coPlxnLdjnZf32TykWGlAg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.4", - "@mdx-js/react": "^3.0.0", - "@storybook/blocks": "8.2.2", - "@storybook/csf-plugin": "8.2.2", - "@storybook/global": "^5.0.0", - "@storybook/react-dom-shim": "8.2.2", - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "fs-extra": "^11.1.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "rehype-external-links": "^3.0.0", - "rehype-slug": "^6.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-docs/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@storybook/addon-essentials": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.2.2.tgz", - "integrity": "sha512-yN//BFMbSvNV0+Sll2hcKmgJX06TUKQDm6pZimUjkXczFtOmK7K/UdDmKjWS+qjhfJdWpxdRoEpxoHvvRmNfsA==", - "dev": true, - "dependencies": { - "@storybook/addon-actions": "8.2.2", - "@storybook/addon-backgrounds": "8.2.2", - "@storybook/addon-controls": "8.2.2", - "@storybook/addon-docs": "8.2.2", - "@storybook/addon-highlight": "8.2.2", - "@storybook/addon-measure": "8.2.2", - "@storybook/addon-outline": "8.2.2", - "@storybook/addon-toolbars": "8.2.2", - "@storybook/addon-viewport": "8.2.2", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-highlight": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.2.2.tgz", - "integrity": "sha512-yDTRzzL+IJAymgY32xoZl09BGBVmPOUV2wVNGYcZkkBLvz2GSQMTfUe1/7F4jAx//+rFBu48/MQzsTC7Bk8kPw==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-interactions": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.2.2.tgz", - "integrity": "sha512-zRRuUwm/l41JtTUgjIoQTUgLT99Hsdz9cqKca/8NYo1MGBdEcKE41DH4aBIzKaOKFu7p9q00/o/X1EqYX4LMUA==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "@storybook/instrumenter": "8.2.2", - "@storybook/test": "8.2.2", - "polished": "^4.2.2", - "ts-dedent": "^2.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-links": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.2.2.tgz", - "integrity": "sha512-eGh7O7SgTJMtnuXC0HlRPOegu1njcJS2cnVqjbzjvjxsPSBhbHpdYMi9Q9E7al/FKuqMUOjIR9YLIlmK1AJaqA==", - "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@storybook/global": "^5.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-measure": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.2.2.tgz", - "integrity": "sha512-3rCo/aMltt5FrBVdr2dYlD8HlE2q9TLKGJZnwh9on4QyL6ArHbdYw0LmyHe/LrFahJ49w1XQZBMSJcAdRkkS7w==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "tiny-invariant": "^1.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-onboarding": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.2.2.tgz", - "integrity": "sha512-dCdE8Mt/JW6cq6dY7co35Sul/bAkUT3ixaxBrUagFUYUQ/PTYM6p4/B+45RURD5S9z8LVHH1rVgmEeScm3U78w==", - "dev": true, - "dependencies": { - "react-confetti": "^6.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-outline": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.2.2.tgz", - "integrity": "sha512-Y+PQtfTNO8GLX5nz+3x5AMfHNvdGvBXazJ29+Rl1ygYN1+Q9ZhRJDE1kAK0wLxb7CG14peAgdYEaQb3Rduv7HQ==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-toolbars": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.2.2.tgz", - "integrity": "sha512-JGOueOc3EPljlCl9dVSQee0aMYoqGNvN0UH+R6wYJ3bDZ+tUG/iYpsZVPUOvS8vzp3Imk5Is1kzQbQYJtzdGLg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-viewport": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.2.2.tgz", - "integrity": "sha512-gkZ8bsjGGP0NuevkT2iKC+szezSy+w4BrBDknf490mRU2K/B2e7TGojf/j/AtxzILMzD4IKzKUXbE/zwcqjZvA==", - "dev": true, - "dependencies": { - "memoizerific": "^1.11.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-webpack5-compiler-swc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", - "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", - "dependencies": { - "@swc/core": "^1.7.3", - "swc-loader": "^0.2.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@storybook/blocks": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.2.2.tgz", - "integrity": "sha512-av0Tryg4toDl2L/d1ABErtsAk9wvM1su6+M4wq5/Go50sk5IjGTldhbZFa9zNOohxLkZwaj0Q5xAgJ1Y+m5KrQ==", - "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@storybook/global": "^5.0.0", - "@storybook/icons": "^1.2.5", - "@types/lodash": "^4.14.167", - "color-convert": "^2.0.1", - "dequal": "^2.0.2", - "lodash": "^4.17.21", - "markdown-to-jsx": "^7.4.5", - "memoizerific": "^1.11.3", - "polished": "^4.2.2", - "react-colorful": "^5.1.2", - "telejson": "^7.2.0", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack5": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.3.tgz", - "integrity": "sha512-yU9rtcVpo12vD8m/nbdepyJ09K937ZnSsrvIM9XfzbxXA/+p4Cov9Rjg1VfoWyRd1ApxaztSktQlawBlb6bKEA==", - "dev": true, - "dependencies": { - "@storybook/core-webpack": "8.2.3", - "@types/node": "^18.0.0", - "@types/semver": "^7.3.4", - "browser-assert": "^1.2.1", - "case-sensitive-paths-webpack-plugin": "^2.4.0", - "cjs-module-lexer": "^1.2.3", - "constants-browserify": "^1.0.0", - "css-loader": "^6.7.1", - "es-module-lexer": "^1.5.0", - "express": "^4.19.2", - "fork-ts-checker-webpack-plugin": "^8.0.0", - "fs-extra": "^11.1.0", - "html-webpack-plugin": "^5.5.0", - "magic-string": "^0.30.5", - "path-browserify": "^1.0.1", - "process": "^0.11.10", - "semver": "^7.3.7", - "style-loader": "^3.3.1", - "terser-webpack-plugin": "^5.3.1", - "ts-dedent": "^2.0.0", - "url": "^0.11.0", - "util": "^0.12.4", - "util-deprecate": "^1.0.2", - "webpack": "5", - "webpack-dev-middleware": "^6.1.2", - "webpack-hot-middleware": "^2.25.1", - "webpack-virtual-modules": "^0.6.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.3" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", - "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^7.0.1", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "node-abort-controller": "^3.0.1", - "schema-utils": "^3.1.1", - "semver": "^7.3.5", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">=12.13.0", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "typescript": ">3.6.0", - "webpack": "^5.11.0" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/@storybook/builder-webpack5/node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", - "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.12", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/@storybook/codemod": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.2.2.tgz", - "integrity": "sha512-wRUVKLHVUhbLJYKW3QOufUxJGwaUT4jTCD8+HOGpHPdJO3NrwXu186xt4tuPZO2Y/NnacPeCQPsaK5ok4O8o7A==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/preset-env": "^7.24.4", - "@babel/types": "^7.24.0", - "@storybook/core": "8.2.2", - "@storybook/csf": "0.1.11", - "@types/cross-spawn": "^6.0.2", - "cross-spawn": "^7.0.3", - "globby": "^14.0.1", - "jscodeshift": "^0.15.1", - "lodash": "^4.17.21", - "prettier": "^3.1.1", - "recast": "^0.23.5", - "tiny-invariant": "^1.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/codemod/node_modules/globby": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", - "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/codemod/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/codemod/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/core": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.2.2.tgz", - "integrity": "sha512-L4ojYI+Os/i5bCReDIlFgEDQSS94mbJlNU9WRzEGZpqNC5/hbFEC9Tip7P1MiRx9NrewkzU7b+UCP7mi3e4drQ==", - "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@types/express": "^4.17.21", - "@types/node": "^18.0.0", - "browser-assert": "^1.2.1", - "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0", - "esbuild-register": "^3.5.0", - "express": "^4.19.2", - "process": "^0.11.10", - "recast": "^0.23.5", - "util": "^0.12.4", - "ws": "^8.2.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/core-webpack": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.3.tgz", - "integrity": "sha512-0M4mJM6i4Oqp1javRMg/8wJW7VJ6p6Z8GKp6evfHLEWZAzdnexQIkPd5FFaDlFXbQNH1H0oJ+6ei4nIBtEegKg==", - "dev": true, - "dependencies": { - "@types/node": "^18.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.3" - } - }, - "node_modules/@storybook/core-webpack/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/core/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/@storybook/csf": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.11.tgz", - "integrity": "sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==", - "dev": true, - "dependencies": { - "type-fest": "^2.19.0" - } - }, - "node_modules/@storybook/csf-plugin": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.2.2.tgz", - "integrity": "sha512-3K2RUpDDvq3DT46qAIj2VBC+fzTTebRUcZUsRfS6G1AzaX9p25iClEHiwcJacFkgQKhkci8A/Ly3Z4JJ3b4Pgw==", - "dev": true, - "dependencies": { - "unplugin": "^1.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/global": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", - "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", - "dev": true - }, - "node_modules/@storybook/icons": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.9.tgz", - "integrity": "sha512-cOmylsz25SYXaJL/gvTk/dl3pyk7yBFRfeXTsHvTA3dfhoU/LWSq0NKL9nM7WBasJyn6XPSGnLS4RtKXLw5EUg==", - "dev": true, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/instrumenter": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.2.2.tgz", - "integrity": "sha512-refwnHqKHhya45MgqakhMG0jKhTiEIAl0aOwAaQy9+zf9ncMIYQAXRQsSZ2Z188lFWE24wbeHKteb62a5ZfWwQ==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "@vitest/utils": "^1.3.1", - "util": "^0.12.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/preset-react-webpack": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.2.3.tgz", - "integrity": "sha512-i886+vCMGlpFgOAOIg6BxSHgt38MXS6gqNX8Z65KVVIlI6i/9WqEQeHYfukbdGvVZ96cYWmdrnqUieIIkdCdBw==", - "dev": true, - "dependencies": { - "@storybook/core-webpack": "8.2.3", - "@storybook/react": "8.2.3", - "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", - "@types/node": "^18.0.0", - "@types/semver": "^7.3.4", - "find-up": "^5.0.0", - "fs-extra": "^11.1.0", - "magic-string": "^0.30.5", - "react-docgen": "^7.0.0", - "resolve": "^1.22.8", - "semver": "^7.3.7", - "tsconfig-paths": "^4.2.0", - "webpack": "5" - }, - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.3" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/react": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.2.3.tgz", - "integrity": "sha512-818F6pJWFBiwG0r6DiUVrV+qndwbIso2gtgJoituBgIJO2eIzNmkPNSsckbaR7u+FpE4dWiIIhmDVZSnRwvDlA==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "@storybook/react-dom-shim": "8.2.3", - "@types/escodegen": "^0.0.6", - "@types/estree": "^0.0.51", - "@types/node": "^18.0.0", - "acorn": "^7.4.1", - "acorn-jsx": "^5.3.1", - "acorn-walk": "^7.2.0", - "escodegen": "^2.1.0", - "html-tags": "^3.1.0", - "lodash": "^4.17.21", - "prop-types": "^15.7.2", - "react-element-to-jsx-string": "^15.0.0", - "semver": "^7.3.7", - "ts-dedent": "^2.0.0", - "type-fest": "~2.19", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.3", - "typescript": ">= 4.2.x" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/react-docgen-typescript-plugin": { - "version": "1.0.6--canary.9.0c3f3b7.0", - "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", - "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "endent": "^2.0.1", - "find-cache-dir": "^3.3.1", - "flat-cache": "^3.0.4", - "micromatch": "^4.0.2", - "react-docgen-typescript": "^2.2.2", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "typescript": ">= 4.x", - "webpack": ">= 4" - } - }, - "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@storybook/react-dom-shim": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.2.tgz", - "integrity": "sha512-4fb1/yT9WXHzHjs0In6orIEZxga5eXd9UaXEFGudBgowCjDUVP9LabDdKTbGusz20lfaAkATsRG/W+EcSLoh8w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/react-webpack5": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.2.3.tgz", - "integrity": "sha512-lcm73r8S5Uy2ENuFDSR07fW+KRSYGNcrF53VItP+rgFZHrOm7gaeebrjSIA6r4tQwdd9218VaqpQGFrKAURS2w==", - "dev": true, - "dependencies": { - "@storybook/builder-webpack5": "8.2.3", - "@storybook/preset-react-webpack": "8.2.3", - "@storybook/react": "8.2.3", - "@types/node": "^18.0.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.3", - "typescript": ">= 4.2.x" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/react-webpack5/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/react/node_modules/@storybook/react-dom-shim": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.3.tgz", - "integrity": "sha512-N8AsM6N1S867GGWt2J2q5oY5ryqxohh3y1HqNtjg+wXf5+RkTD6M2Cgqe6p+JHz81nDKyvvVzP60MvvDhY5VOA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.3" - } - }, - "node_modules/@storybook/react/node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "node_modules/@storybook/react/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/react/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/@storybook/test": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.2.2.tgz", - "integrity": "sha512-X2qAKErjTh1X7XLAZqCMtU0ZK8JuwdKmgiqU0oXWxIDmCX6/Dm9ZIcdMZHs/S+K/UnIByjNlQpTShLVfRUeN1w==", - "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@storybook/instrumenter": "8.2.2", - "@testing-library/dom": "10.1.0", - "@testing-library/jest-dom": "6.4.5", - "@testing-library/user-event": "14.5.2", - "@vitest/expect": "1.6.0", - "@vitest/spy": "1.6.0", - "util": "^0.12.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", - "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", - "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", - "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", - "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", - "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", - "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-preset": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", - "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", - "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", - "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", - "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", - "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", - "@svgr/babel-plugin-transform-svg-component": "8.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", - "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", - "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^8.1.3", - "snake-case": "^3.0.4" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", - "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", - "dependencies": { - "@babel/types": "^7.21.3", - "entities": "^4.4.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/@svgr/plugin-jsx": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", - "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", - "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "@svgr/hast-util-to-babel-ast": "8.0.0", - "svg-parser": "^2.0.4" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "*" - } - }, - "node_modules/@svgr/plugin-svgo": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", - "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", - "dependencies": { - "cosmiconfig": "^8.1.3", - "deepmerge": "^4.3.1", - "svgo": "^3.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "*" - } - }, - "node_modules/@svgr/webpack": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", - "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", - "dependencies": { - "@babel/core": "^7.21.3", - "@babel/plugin-transform-react-constant-elements": "^7.21.3", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.0", - "@svgr/core": "8.1.0", - "@svgr/plugin-jsx": "8.1.0", - "@svgr/plugin-svgo": "8.1.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@swc/core": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.6.tgz", - "integrity": "sha512-FZxyao9eQks1MRmUshgsZTmlg/HB2oXK5fghkoWJm/1CU2q2kaJlVDll2as5j+rmWiwkp0Gidlq8wlXcEEAO+g==", - "hasInstallScript": true, - "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.12" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.6", - "@swc/core-darwin-x64": "1.7.6", - "@swc/core-linux-arm-gnueabihf": "1.7.6", - "@swc/core-linux-arm64-gnu": "1.7.6", - "@swc/core-linux-arm64-musl": "1.7.6", - "@swc/core-linux-x64-gnu": "1.7.6", - "@swc/core-linux-x64-musl": "1.7.6", - "@swc/core-win32-arm64-msvc": "1.7.6", - "@swc/core-win32-ia32-msvc": "1.7.6", - "@swc/core-win32-x64-msvc": "1.7.6" - }, - "peerDependencies": { - "@swc/helpers": "*" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.6.tgz", - "integrity": "sha512-6lYHey84ZzsdtC7UuPheM4Rm0Inzxm6Sb8U6dmKc4eCx8JL0LfWG4LC5RsdsrTxnjTsbriWlnhZBffh8ijUHIQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" - }, - "node_modules/@swc/types": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", - "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", - "dependencies": { - "@swc/counter": "^0.1.3" - } - }, - "node_modules/@testing-library/dom": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", - "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/@testing-library/jest-dom": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz", - "integrity": "sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==", - "dev": true, - "dependencies": { - "@adobe/css-tools": "^4.3.2", - "@babel/runtime": "^7.9.2", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "lodash": "^4.17.21", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" - }, - "peerDependencies": { - "@jest/globals": ">= 28", - "@types/bun": "latest", - "@types/jest": ">= 28", - "jest": ">= 28", - "vitest": ">= 0.32" - }, - "peerDependenciesMeta": { - "@jest/globals": { - "optional": true - }, - "@types/bun": { - "optional": true - }, - "@types/jest": { - "optional": true - }, - "jest": { - "optional": true - }, - "vitest": { - "optional": true - } - } - }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", - "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", - "dev": true - }, - "node_modules/@testing-library/jest-dom/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@testing-library/user-event": { - "version": "14.5.2", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", - "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", - "dev": true, - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/doctrine": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", - "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", - "dev": true - }, - "node_modules/@types/emscripten": { - "version": "1.39.13", - "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.13.tgz", - "integrity": "sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw==", - "dev": true - }, - "node_modules/@types/escodegen": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.6.tgz", - "integrity": "sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==", - "dev": true - }, - "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/lodash": { - "version": "4.17.6", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", - "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==", - "dev": true - }, - "node_modules/@types/mdx": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", - "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/resolve": { - "version": "1.20.6", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", - "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, - "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@vitest/expect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", - "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", - "dev": true, - "dependencies": { - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", - "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", - "dev": true, - "dependencies": { - "tinyspy": "^2.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", - "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", - "dev": true, - "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@vitest/utils/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@vitest/utils/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/@yarnpkg/fslib": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", - "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", - "dev": true, - "dependencies": { - "@yarnpkg/libzip": "^2.3.0", - "tslib": "^1.13.0" - }, - "engines": { - "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" - } - }, - "node_modules/@yarnpkg/fslib/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@yarnpkg/libzip": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", - "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", - "dev": true, - "dependencies": { - "@types/emscripten": "^1.39.6", - "tslib": "^1.13.0" - }, - "engines": { - "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" - } - }, - "node_modules/@yarnpkg/libzip/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ast-types": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", - "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", - "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/babel-core": { - "version": "7.0.0-bridge.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", - "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "dev": true, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - } - }, - "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", - "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1", - "core-js-compat": "^3.36.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-assert": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", - "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", - "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001642", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", - "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chromatic": { - "version": "11.5.5", - "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.5.5.tgz", - "integrity": "sha512-YS0GJwegF0vpMbwZE68/xJlI4SlUGMqI78V2ATAF19YwTHaq8jGP1CPQGKUSlgWUhzPtyu3ELy6Dvv/owYljAg==", - "dev": true, - "bin": { - "chroma": "dist/bin.js", - "chromatic": "dist/bin.js", - "chromatic-cli": "dist/bin.js" - }, - "peerDependencies": { - "@chromatic-com/cypress": "^0.*.* || ^1.0.0", - "@chromatic-com/playwright": "^0.*.* || ^1.0.0" - }, - "peerDependenciesMeta": { - "@chromatic-com/cypress": { - "optional": true - }, - "@chromatic-com/playwright": { - "optional": true - } - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/citty": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", - "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "dev": true, - "dependencies": { - "consola": "^3.2.3" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", - "dev": true - }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/compare-versions": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", - "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/confbox": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", - "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", - "dev": true - }, - "node_modules/consola": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", - "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", - "dev": true, - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", - "dependencies": { - "browserslist": "^4.23.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", - "dev": true, - "dependencies": { - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/crypto-random-string/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dependencies": { - "css-tree": "~2.2.0" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "dev": true - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.827", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", - "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/endent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", - "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", - "dev": true, - "dependencies": { - "dedent": "^0.7.0", - "fast-json-parse": "^1.0.3", - "objectorarray": "^1.0.5" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/envinfo": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", - "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" - } - }, - "node_modules/esbuild-register": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.5.0.tgz", - "integrity": "sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "peerDependencies": { - "esbuild": ">=0.12 <1" - } - }, - "node_modules/esbuild-register/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/esbuild-register/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", - "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.17.1", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.8.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", - "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", - "dev": true, - "dependencies": { - "aria-query": "~5.1.3", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.9.1", - "axobject-query": "~3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.19", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.34.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.4.tgz", - "integrity": "sha512-Np+jo9bUwJNxCsT12pXtrGhJgT3T44T1sHhn1Ssr42XFn8TES0267wPGo5nNrMHi8qkyimDAX2BUmkf9pSaVzA==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.8", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-react/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-storybook": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.8.0.tgz", - "integrity": "sha512-CZeVO5EzmPY7qghO2t64oaFM+8FTaD4uzOEjHKp516exyTKo+skKAL9GI3QALS2BXhyALJjNtwbmr1XinGE8bA==", - "dev": true, - "dependencies": { - "@storybook/csf": "^0.0.1", - "@typescript-eslint/utils": "^5.62.0", - "requireindex": "^1.2.0", - "ts-dedent": "^2.2.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "eslint": ">=6" - } - }, - "node_modules/eslint-plugin-storybook/node_modules/@storybook/csf": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", - "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", - "dev": true, - "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-parse": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", - "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-package-json": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-1.2.0.tgz", - "integrity": "sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==", - "dev": true, - "dependencies": { - "walk-up-path": "^3.0.1" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/file-entry-cache/node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/filesize": { - "version": "10.1.4", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.4.tgz", - "integrity": "sha512-ryBwPIIeErmxgPnm6cbESAzXjuEFubs+yKYLBZvg3CaiNcmkJChoOGcBSrZ6IwkMwPABwPpVXE6IlNdGJJrvEg==", - "dev": true, - "engines": { - "node": ">= 10.4.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/flat-cache/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flat-cache/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/flow-parser": { - "version": "0.239.1", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.239.1.tgz", - "integrity": "sha512-topOrETNxJ6T2gAnQiWqAlzGPj8uI2wtmNOlDIMNB+qyvGJZ6R++STbUOTAYmvPhOMz2gXnXPH0hOvURYmrBow==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/fs-monkey": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", - "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", - "dev": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/giget": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", - "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", - "dev": true, - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.2.3", - "defu": "^6.1.4", - "node-fetch-native": "^1.6.3", - "nypm": "^0.3.8", - "ohash": "^1.1.3", - "pathe": "^1.1.2", - "tar": "^6.2.0" - }, - "bin": { - "giget": "dist/cli.mjs" - } - }, - "node_modules/github-slugger": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", - "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", - "dev": true - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/globals": { - "version": "15.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", - "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hast-util-heading-rank": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", - "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-is-element": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", - "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", - "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ] - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", - "dev": true, - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.20.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-absolute-url": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", - "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dev": true, - "dependencies": { - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jscodeshift": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", - "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.0", - "@babel/parser": "^7.23.0", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-modules-commonjs": "^7.23.0", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", - "@babel/plugin-transform-optional-chaining": "^7.23.0", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/preset-flow": "^7.22.15", - "@babel/preset-typescript": "^7.23.0", - "@babel/register": "^7.22.15", - "babel-core": "^7.0.0-bridge.0", - "chalk": "^4.1.2", - "flow-parser": "0.*", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.4", - "neo-async": "^2.5.0", - "node-dir": "^0.1.17", - "recast": "^0.23.3", - "temp": "^0.8.4", - "write-file-atomic": "^2.3.0" - }, - "bin": { - "jscodeshift": "bin/jscodeshift.js" - }, - "peerDependencies": { - "@babel/preset-env": "^7.1.6" - }, - "peerDependenciesMeta": { - "@babel/preset-env": { - "optional": true - } - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lottie-react": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", - "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", - "dependencies": { - "lottie-web": "^5.10.2" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/lottie-web": { - "version": "5.12.2", - "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", - "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" - }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "dev": true, - "bin": { - "lz-string": "bin/bin.js" - } - }, - "node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/map-or-similar": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", - "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", - "dev": true - }, - "node_modules/markdown-to-jsx": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.7.tgz", - "integrity": "sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==", - "dev": true, - "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "react": ">= 0.14.0" - } - }, - "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memoizerific": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", - "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", - "dev": true, - "dependencies": { - "map-or-similar": "^1.5.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mlly": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", - "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", - "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "pathe": "^1.1.2", - "pkg-types": "^1.1.1", - "ufo": "^1.5.3" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/mylas": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", - "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", - "dev": true, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/raouldeheer" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", - "dev": true - }, - "node_modules/node-dir": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", - "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", - "dev": true, - "dependencies": { - "minimatch": "^3.0.2" - }, - "engines": { - "node": ">= 0.10.5" - } - }, - "node_modules/node-dir/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/node-dir/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/node-fetch-native": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", - "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/nypm": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.9.tgz", - "integrity": "sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==", - "dev": true, - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.2.3", - "execa": "^8.0.1", - "pathe": "^1.1.2", - "pkg-types": "^1.1.1", - "ufo": "^1.5.3" - }, - "bin": { - "nypm": "dist/cli.mjs" - }, - "engines": { - "node": "^14.16.0 || >=16.10.0" - } - }, - "node_modules/nypm/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/nypm/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/nypm/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/nypm/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/objectorarray": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", - "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", - "dev": true - }, - "node_modules/ohash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", - "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-types": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.3.tgz", - "integrity": "sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==", - "dev": true, - "dependencies": { - "confbox": "^0.1.7", - "mlly": "^1.7.1", - "pathe": "^1.1.2" - } - }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", - "dev": true, - "dependencies": { - "queue-lit": "^1.5.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/polished": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", - "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.17.8" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", - "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pretty-format/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-lit": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", - "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-colorful": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", - "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", - "dev": true, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/react-confetti": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", - "integrity": "sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==", - "dev": true, - "dependencies": { - "tween-functions": "^1.2.0" - }, - "engines": { - "node": ">=10.18" - }, - "peerDependencies": { - "react": "^16.3.0 || ^17.0.1 || ^18.0.0" - } - }, - "node_modules/react-docgen": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-7.0.3.tgz", - "integrity": "sha512-i8aF1nyKInZnANZ4uZrH49qn1paRgBZ7wZiCNBMnenlPzEv0mRl+ShpTVEI6wZNl8sSc79xZkivtgLKQArcanQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.18.9", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9", - "@types/babel__core": "^7.18.0", - "@types/babel__traverse": "^7.18.0", - "@types/doctrine": "^0.0.9", - "@types/resolve": "^1.20.2", - "doctrine": "^3.0.0", - "resolve": "^1.22.1", - "strip-indent": "^4.0.0" - }, - "engines": { - "node": ">=16.14.0" - } - }, - "node_modules/react-docgen-typescript": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", - "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", - "dev": true, - "peerDependencies": { - "typescript": ">= 4.3.x" - } - }, - "node_modules/react-docgen/node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-element-to-jsx-string": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz", - "integrity": "sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==", - "dev": true, - "dependencies": { - "@base2/pretty-print-object": "1.0.1", - "is-plain-object": "5.0.0", - "react-is": "18.1.0" - }, - "peerDependencies": { - "react": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0", - "react-dom": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0" - } - }, - "node_modules/react-element-to-jsx-string/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-element-to-jsx-string/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", - "dev": true - }, - "node_modules/react-inspector": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.2.tgz", - "integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==", - "dev": true, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-router": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.1.tgz", - "integrity": "sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==", - "dependencies": { - "@remix-run/router": "1.17.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.24.1.tgz", - "integrity": "sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==", - "dependencies": { - "@remix-run/router": "1.17.1", - "react-router": "6.24.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/recast": { - "version": "0.23.9", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", - "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", - "dev": true, - "dependencies": { - "ast-types": "^0.16.1", - "esprima": "~4.0.0", - "source-map": "~0.6.1", - "tiny-invariant": "^1.3.3", - "tslib": "^2.0.1" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/redent/node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/rehype-external-links": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rehype-external-links/-/rehype-external-links-3.0.0.tgz", - "integrity": "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-is-element": "^3.0.0", - "is-absolute-url": "^4.0.0", - "space-separated-tokens": "^2.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-slug": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz", - "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0", - "github-slugger": "^2.0.0", - "hast-util-heading-rank": "^3.0.0", - "hast-util-to-string": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requireindex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", - "dev": true, - "engines": { - "node": ">=0.10.5" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/storybook": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.2.2.tgz", - "integrity": "sha512-xDT9gyzAEFQNeK7P+Mj/8bNzN+fbm6/4D6ihdSzmczayjydpNjMs74HDHMY6S4Bfu6tRVyEK2ALPGnr6ZVofBA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/types": "^7.24.0", - "@storybook/codemod": "8.2.2", - "@storybook/core": "8.2.2", - "@types/semver": "^7.3.4", - "@yarnpkg/fslib": "2.10.3", - "@yarnpkg/libzip": "2.3.0", - "chalk": "^4.1.0", - "commander": "^6.2.1", - "cross-spawn": "^7.0.3", - "detect-indent": "^6.1.0", - "envinfo": "^7.7.3", - "execa": "^5.0.0", - "fd-package-json": "^1.2.0", - "find-up": "^5.0.0", - "fs-extra": "^11.1.0", - "giget": "^1.0.0", - "globby": "^14.0.1", - "jscodeshift": "^0.15.1", - "leven": "^3.1.0", - "ora": "^5.4.1", - "prettier": "^3.1.1", - "prompts": "^2.4.0", - "semver": "^7.3.7", - "strip-json-comments": "^3.0.1", - "tempy": "^3.1.0", - "tiny-invariant": "^1.3.1", - "ts-dedent": "^2.0.0" - }, - "bin": { - "getstorybook": "bin/index.cjs", - "sb": "bin/index.cjs", - "storybook": "bin/index.cjs" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/storybook-addon-react-router-v6": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/storybook-addon-react-router-v6/-/storybook-addon-react-router-v6-2.0.15.tgz", - "integrity": "sha512-4vOYIQwehlQLyXaCT9K0Iu0po2Z+pANGsqkfm/BQuAEjE9MoN7vrsrQLHINhKbmQVtNMmuS/oBR3GGNbqQ1gew==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "compare-versions": "^6.0.0", - "react-inspector": "6.0.2" - }, - "peerDependencies": { - "@storybook/blocks": "^7.0.0", - "@storybook/channels": "^7.0.0", - "@storybook/components": "^7.0.0", - "@storybook/core-events": "^7.0.0", - "@storybook/manager-api": "^7.0.0", - "@storybook/preview-api": "^7.0.0", - "@storybook/theming": "^7.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-router-dom": "^6.4.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/storybook/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/storybook/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/storybook/node_modules/globby": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", - "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string.prototype.includes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", - "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", - "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-loader": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", - "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", - "dev": true, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" - }, - "node_modules/svgo": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", - "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^5.1.0", - "css-tree": "^2.3.1", - "css-what": "^6.1.0", - "csso": "^5.0.5", - "picocolors": "^1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/svgo" - } - }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/svgo/node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/svgo/node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/svgo/node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/svgo/node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/svgo/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/swc-loader": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", - "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", - "dependencies": { - "@swc/counter": "^0.1.3" - }, - "peerDependencies": { - "@swc/core": "^1.2.147", - "webpack": ">=2" - } - }, - "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "dev": true, - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/telejson": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", - "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", - "dev": true, - "dependencies": { - "memoizerific": "^1.11.3" - } - }, - "node_modules/temp": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", - "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", - "dev": true, - "dependencies": { - "rimraf": "~2.6.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/temp-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", - "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", - "dev": true, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/temp/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/temp/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/temp/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/temp/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/tempy": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", - "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", - "dev": true, - "dependencies": { - "is-stream": "^3.0.0", - "temp-dir": "^3.0.0", - "type-fest": "^2.12.2", - "unique-string": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terser": { - "version": "5.31.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", - "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", - "dev": true - }, - "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", - "dev": true, - "engines": { - "node": ">=6.10" - } - }, - "node_modules/ts-loader": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", - "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4", - "source-map": "^0.7.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" - } - }, - "node_modules/ts-loader/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tsc-alias": { - "version": "1.8.10", - "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", - "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.3", - "commander": "^9.0.0", - "globby": "^11.0.4", - "mylas": "^2.1.9", - "normalize-path": "^3.0.0", - "plimit-lit": "^1.2.6" - }, - "bin": { - "tsc-alias": "dist/bin/index.js" - } - }, - "node_modules/tsc-alias/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tween-functions": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", - "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", - "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", - "dev": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "7.16.0", - "@typescript-eslint/parser": "7.16.0", - "@typescript-eslint/utils": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/ufo": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", - "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "dev": true, - "dependencies": { - "crypto-random-string": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/unplugin": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.11.0.tgz", - "integrity": "sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==", - "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "chokidar": "^3.6.0", - "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.6.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", - "dev": true, - "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.11.2" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "node_modules/url/node_modules/qs": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", - "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/walk-up-path": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", - "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", - "dev": true - }, - "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webpack": { - "version": "5.93.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", - "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-hot-middleware": { - "version": "2.26.1", - "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", - "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", - "dev": true, - "dependencies": { - "ansi-html-community": "0.0.8", - "html-entities": "^2.1.0", - "strip-ansi": "^6.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-virtual-modules": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", - "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", - "dev": true - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/HDesign/package.json b/HDesign/package.json deleted file mode 100644 index 062987bf1..000000000 --- a/HDesign/package.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "name": "haengdong-design", - "version": "0.1.81", - "description": "", - "main": "./dist/index.js", - "module": "./dist/index.js", - "types": "./dist/index.d.ts", - "files": [ - "dist" - ], - "scripts": { - "start": "webpack serve ", - "build": "rm -rf dist && mkdir dist && tsc && cp -r ./src/assets ./dist && tsc-alias", - "storybook": "storybook dev -p 6006", - "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", - "format": "prettier --write {src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", - "build-storybook": "storybook build" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "@chromatic-com/storybook": "^1.6.1", - "@eslint/compat": "^1.1.0", - "@eslint/js": "^9.6.0", - "@storybook/addon-essentials": "^8.2.2", - "@storybook/addon-interactions": "^8.2.2", - "@storybook/addon-links": "^8.2.2", - "@storybook/addon-onboarding": "^8.2.2", - "@storybook/blocks": "^8.2.2", - "@storybook/react": "^8.2.2", - "@storybook/react-webpack5": "^8.2.3", - "@storybook/test": "^8.2.2", - "@swc/core": "^1.7.6", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.16.0", - "@typescript-eslint/parser": "^7.16.0", - "esbuild": "^0.23.0", - "eslint": "^9.8.0", - "eslint-config-prettier": "^9.1.0", - "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.9.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.4", - "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-storybook": "^0.8.0", - "file-loader": "^6.2.0", - "globals": "^15.8.0", - "prettier": "3.3.2", - "storybook": "^8.2.2", - "storybook-addon-react-router-v6": "^2.0.15", - "ts-loader": "^9.5.1", - "tsc-alias": "^1.8.10", - "typescript": "^5.5.3", - "typescript-eslint": "^7.16.0" - }, - "dependencies": { - "@emotion/react": "^11.11.4", - "@storybook/addon-webpack5-compiler-swc": "^1.0.5", - "@svgr/webpack": "^8.1.0", - "lottie-react": "^2.4.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-router-dom": "^6.24.1" - }, - "engines": { - "npm": ">=10.7.0", - "node": ">=20.15.1" - } -} diff --git a/HDesign/src/assets/index.ts b/HDesign/src/assets/index.ts deleted file mode 100644 index a9c277581..000000000 --- a/HDesign/src/assets/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export {default as InputDelete} from '@assets/inputDelete.svg'; -export {default as Buljusa} from '@assets/buljusa.svg'; -export {default as Error} from '@assets/error.svg'; -export {default as Confirm} from '@assets/confirm.svg'; -export {default as Trash} from '@assets/trash.svg'; -export {default as Search} from '@assets/search.svg'; -export {default as RightChevron} from '@assets/rightChevron.svg'; diff --git a/HDesign/src/assets/svg.d.ts b/HDesign/src/assets/svg.d.ts deleted file mode 100644 index 2db81e756..000000000 --- a/HDesign/src/assets/svg.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module '*.svg' { - import type React from 'react'; - - const SVG: React.FC>; - export default SVG; -} diff --git a/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx b/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx deleted file mode 100644 index ccf8e28de..000000000 --- a/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import type {Meta, StoryObj} from '@storybook/react'; - -import ExpenseList from '@components/ExpenseList/ExpenseList'; - -const meta = { - title: 'Components/ExpenseList', - component: ExpenseList, - tags: ['autodocs'], - argTypes: { - expenseList: { - description: '', - }, - }, - args: { - expenseList: [ - {name: '소하', price: 2000}, - {name: '토다리', price: 2000}, - {name: '웨디', price: 1080}, - {name: '쿠키', price: 3020}, - ], - }, -} satisfies Meta; - -export default meta; - -type Story = StoryObj; - -export const Playground: Story = {}; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.style.ts b/HDesign/src/components/ExpenseList/ExpenseList.style.ts deleted file mode 100644 index 8dbd227aa..000000000 --- a/HDesign/src/components/ExpenseList/ExpenseList.style.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -export const expenseItemStyle = () => - css({ - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - width: '100%', - height: '2.5rem', - padding: '0.5rem 1rem', - }); - -export const expenseItemLeftStyle = () => - css({ - display: 'flex', - alignItems: 'center', - gap: '1rem', - }); - -export const expenseListStyle = (theme: Theme) => - css({ - width: '100%', - backgroundColor: theme.colors.white, - padding: '0.5rem 0', - borderRadius: '1rem', - height: '100%', - }); diff --git a/HDesign/src/components/ExpenseList/ExpenseList.tsx b/HDesign/src/components/ExpenseList/ExpenseList.tsx deleted file mode 100644 index 1f57810e5..000000000 --- a/HDesign/src/components/ExpenseList/ExpenseList.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/** @jsxImportSource @emotion/react */ - -import Text from '@components/Text/Text'; -import Icon from '@components/Icon/Icon'; - -import {useTheme} from '@theme/HDesignProvider'; - -import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; -import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle} from './ExpenseList.style'; - -// TODO: (@soha) 따로 파일 분리할까 고민중.. 여기서만 사용할 것 같긴 한데.. 흠 -// TODO: (@todari) : 추후 클릭 시 상호작용이 생기면 iconButton으로 변경할 수 있음 -function ExpenseItem({name, price, ...buttonProps}: ExpenseItemProps) { - const {theme} = useTheme(); - return ( - - ); -} - -function ExpenseList({expenseList = []}: ExpenseListProps) { - const {theme} = useTheme(); - return ( -
- {expenseList.map(({name, price}, index: number) => ( - - ))} -
- ); -} - -export default ExpenseList; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.type.ts b/HDesign/src/components/ExpenseList/ExpenseList.type.ts deleted file mode 100644 index 939cd2f68..000000000 --- a/HDesign/src/components/ExpenseList/ExpenseList.type.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface ExpenseItemCustomProps { - name: string; - price: number; -} - -export type ExpenseItemProps = React.ComponentProps<'button'> & ExpenseItemCustomProps; - -export type ExpenseListProps = { - expenseList: ExpenseItemProps[]; -}; diff --git a/HDesign/src/components/Icon/Icon.tsx b/HDesign/src/components/Icon/Icon.tsx deleted file mode 100644 index 13d8e7835..000000000 --- a/HDesign/src/components/Icon/Icon.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/** @jsxImportSource @emotion/react */ - -import {IconProps} from '@components/Icon/Icon.type'; -import {InputDelete, Buljusa, RightChevron, Search, Trash, Confirm, Error} from '@assets'; - -import {useTheme} from '@theme/HDesignProvider'; - -import {iconStyle} from './Icon.style'; - -const ICON = { - inputDelete: , - buljusa: , - rightChevron: , - search: , - error: , - confirm: , - trash: , -}; - -export const Icon: React.FC = ({iconColor, iconType, ...htmlProps}: IconProps) => { - const {theme} = useTheme(); - return ( -
- {ICON[iconType]} -
- ); -}; - -export default Icon; diff --git a/HDesign/src/components/Search/Search.stories.tsx b/HDesign/src/components/Search/Search.stories.tsx deleted file mode 100644 index 6b5d821cd..000000000 --- a/HDesign/src/components/Search/Search.stories.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import type {Meta, StoryObj} from '@storybook/react'; - -import React from 'react'; - -import Search from '@components/Search/Search'; - -const meta = { - title: 'Components/Search', - component: Search, - tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, - decorators: [ - Story => ( -
- -
- ), - ], - args: { - isShowTargetInput: true, - matchItems: ['todari', 'cookie'], - onMatchItemClick: keyword => alert(keyword), - }, -} satisfies Meta; - -export default meta; - -type Story = StoryObj; - -export const Playground: Story = {}; diff --git a/HDesign/src/components/Search/Search.style.ts b/HDesign/src/components/Search/Search.style.ts deleted file mode 100644 index d75e8fe25..000000000 --- a/HDesign/src/components/Search/Search.style.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -export const searchStyle = css({ - position: 'relative', - - width: '100%', -}); - -export const searchTermsStyle = (theme: Theme) => - css({ - position: 'absolute', - top: '3.5rem', - zIndex: 1, - - width: '100%', - padding: '0.5rem 1rem', - - borderRadius: '1rem', - - backgroundColor: theme.colors.white, - - boxShadow: '0 0.25rem 0.5rem 0 rgba(0, 0, 0, 0.12)', - }); - -export const searchTermStyle = (theme: Theme) => - css( - { - width: '100%', - padding: '0.5rem', - - color: theme.colors.onTertiary, - - '&:hover': { - borderRadius: '0.5rem', - - backgroundColor: theme.colors.lightGrayContainer, - }, - }, - theme.typography.body, - ); diff --git a/HDesign/src/components/Search/Search.tsx b/HDesign/src/components/Search/Search.tsx deleted file mode 100644 index 58c292cc4..000000000 --- a/HDesign/src/components/Search/Search.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import Flex from '@components/Flex/Flex'; - -import {useTheme} from '@theme/HDesignProvider'; - -import {searchStyle, searchTermsStyle, searchTermStyle} from './Search.style'; - -export interface SearchProps { - isShowTargetInput: boolean; - matchItems: string[]; - onMatchItemClick: (term: string) => void; -} - -const Search = ({isShowTargetInput, matchItems, onMatchItemClick, children}: React.PropsWithChildren) => { - const {theme} = useTheme(); - - return ( -
- {children} - {matchItems.length > 0 && isShowTargetInput && ( -
    - - {matchItems.map((matchItem, index) => ( -
  • - -
  • - ))} -
    -
- )} -
- ); -}; - -export default Search; diff --git a/HDesign/src/components/Switch/Switch.stories.tsx b/HDesign/src/components/Switch/Switch.stories.tsx deleted file mode 100644 index a3558754a..000000000 --- a/HDesign/src/components/Switch/Switch.stories.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import type {Meta, StoryObj} from '@storybook/react'; - -import Switch from '@components/Switch/Switch'; - -const meta = { - title: 'Components/Switch', - component: Switch, - tags: ['autodocs'], - parameters: { - layout: 'centered', - }, - argTypes: { - value: { - description: '', - control: {type: 'select', options: ['홈', '관리']}, - }, - values: { - description: '', - }, - onChange: { - description: '', - }, - }, - args: { - value: '홈', - values: ['홈', '관리'], - onChange: value => alert(`${value} 선택됨`), - }, -} satisfies Meta; - -export default meta; - -type Story = StoryObj; - -export const Playground: Story = {}; diff --git a/HDesign/src/components/Switch/Switch.style.ts b/HDesign/src/components/Switch/Switch.style.ts deleted file mode 100644 index d88c18748..000000000 --- a/HDesign/src/components/Switch/Switch.style.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {css} from '@emotion/react'; - -export const switchContainerStyle = css({ - display: 'flex', - gap: '0.75rem', -}); diff --git a/HDesign/src/components/Switch/Switch.tsx b/HDesign/src/components/Switch/Switch.tsx deleted file mode 100644 index 4a1275185..000000000 --- a/HDesign/src/components/Switch/Switch.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import TextButton from '../TextButton/TextButton'; - -import {switchContainerStyle} from './Switch.style'; -import {SwitchProps} from './Switch.type'; - -function Switch({value, values, onChange}: SwitchProps) { - return ( -
- {values.map((item, index) => ( - onChange(values[index])} - > - {item} - - ))} -
- ); -} - -export default Switch; diff --git a/HDesign/src/components/Switch/Switch.type.ts b/HDesign/src/components/Switch/Switch.type.ts deleted file mode 100644 index 7e0d31d0f..000000000 --- a/HDesign/src/components/Switch/Switch.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface SwitchProps { - value: string; - values: string[]; - onChange: (value: string) => void; -} diff --git a/HDesign/src/components/Tabs/Tabs.style.ts b/HDesign/src/components/Tabs/Tabs.style.ts deleted file mode 100644 index 3ea38924c..000000000 --- a/HDesign/src/components/Tabs/Tabs.style.ts +++ /dev/null @@ -1,53 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -export const tabListStyle = (theme: Theme) => - css({ - position: 'relative', - - backgroundColor: theme.colors.white, - - cursor: 'pointer', - - WebkitTapHighlightColor: 'transparent', - - '&::after': { - position: 'absolute', - left: 0, - bottom: 0, - zIndex: 1, - - width: '100%', - height: '0.0625rem', - - backgroundColor: theme.colors.gray, - - content: '""', - }, - }); - -export const tabItemStyle = css({ - flex: 1, - - textAlign: 'center', -}); - -export const tabTextStyle = (theme: Theme, selected: boolean) => - css({ - color: selected ? theme.colors.onTertiary : theme.colors.gray, - }); - -export const indicatorStyle = (theme: Theme, leftPosition: string, tabLength: number) => - css({ - position: 'absolute', - left: leftPosition, - bottom: 0, - zIndex: 2, - - width: `calc(100% / ${tabLength})`, - height: '0.125rem', - - backgroundColor: theme.colors.onSecondary, - transition: 'left 0.3s', - }); diff --git a/HDesign/src/components/Tabs/Tabs.tsx b/HDesign/src/components/Tabs/Tabs.tsx deleted file mode 100644 index 0245b5ba7..000000000 --- a/HDesign/src/components/Tabs/Tabs.tsx +++ /dev/null @@ -1,53 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import React, {useState} from 'react'; -import {css} from '@emotion/react'; - -import {useTheme} from '@theme/HDesignProvider'; - -import Text from '../Text/Text'; -import Flex from '../Flex/Flex'; - -import {tabListStyle, indicatorStyle, tabItemStyle, tabTextStyle} from './Tabs.style'; -import {TabsProps} from './Tab.type'; - -const Tabs: React.FC = ({children, tabsContainerStyle}) => { - const {theme} = useTheme(); - const [activeTabIndex, setActiveTabIndex] = useState(0); - - const isActive = (index: number) => activeTabIndex === index; - const tabItemCount = children.length; - - return ( - -
    - - {children.map((tabItem, index) => ( - - ))} -
    - -
-
- {children[activeTabIndex].props.content} -
-
- ); -}; - -export default Tabs; diff --git a/HDesign/src/components/Title/Title.tsx b/HDesign/src/components/Title/Title.tsx deleted file mode 100644 index e17de5e88..000000000 --- a/HDesign/src/components/Title/Title.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import Flex from '@components/Flex/Flex'; -import Text from '@components/Text/Text'; -import {priceContainerStyle, titleContainerStyle} from '@components/Title/Title.style'; -import {TitleProps} from '@components/Title/Title.type'; - -import {useTheme} from '@theme/HDesignProvider'; - -export const Title: React.FC = ({title, description, price}: TitleProps) => { - const {theme} = useTheme(); - return ( -
- {title} - {description && ( - - {description} - - )} - {price !== undefined && ( -
- - 전체 지출 금액 - - - {price.toLocaleString('ko-kr')} - - -
- )} -
- ); -}; - -export default Title; diff --git a/HDesign/src/components/Toast/Toast.stories.tsx b/HDesign/src/components/Toast/Toast.stories.tsx deleted file mode 100644 index fd672959c..000000000 --- a/HDesign/src/components/Toast/Toast.stories.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import type {Meta, StoryObj} from '@storybook/react'; - -import Toast from '@components/Toast/Toast'; - -const meta = { - title: 'Components/Toast', - component: Toast, - tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, - args: { - type: 'confirm', - position: 'top', - top: '80px', - message: `서버 오류로 인해 인원을 설정하는데 실패했어요. -두글자면 이렇게 보여요.`, - onUndo: () => alert('되돌리기 버튼이 눌렸습니다. 실행할 로직을 전달해주세요'), - }, -} satisfies Meta; - -export default meta; - -type Story = StoryObj; - -export const ConfirmToast: Story = { - args: { - ...meta.args, - type: 'confirm', - top: '80px', - message: `이 첫번째 토스트 그림자 짙은거 두 개 떠서 그런거임 css 잘못한거 아닙니다. 잘못 없습니다. 스토리북이 잘못한거에요. 저희는 최선을 다했어요.. `, - }, -}; - -export const ConfirmToastWithoutUndo: Story = { - args: { - ...meta.args, - onUndo: undefined, - top: '160px', - }, -}; - -export const ErrorToast: Story = { - args: { - ...meta.args, - top: '240px', - type: 'error', - message: `님 이거 다 작성했는데, 혹시 되돌림? - 되돌릴 수도 있음 ㅇㅇ 굿`, - }, -}; - -export const ErrorToastWithoutUndo: Story = { - args: { - ...meta.args, - top: '320px', - onUndo: undefined, - type: 'error', - }, -}; - -export const NoneToast: Story = { - args: { - ...meta.args, - top: '400px', - onUndo: undefined, - type: 'none', - message: '웨디는 커비의 먹잇감인가요? 그치만 감자는 웨디한테 먹힘 쿠스쿠스 ㅋ', - }, -}; diff --git a/HDesign/src/components/Toast/Toast.style.ts b/HDesign/src/components/Toast/Toast.style.ts deleted file mode 100644 index 0496bc722..000000000 --- a/HDesign/src/components/Toast/Toast.style.ts +++ /dev/null @@ -1,44 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -import {ToastPosition} from './Toast.type'; - -type ToastMarginStyle = { - position?: ToastPosition; - bottom?: string; - top?: string; -}; - -export const toastMarginStyle = ({position, bottom, top}: ToastMarginStyle) => - css({ - position: 'absolute', - bottom: position === 'bottom' ? `${bottom}` : 'auto', - top: position === 'top' ? `${top}` : 'auto', - left: '50%', - transform: 'translate(-50%)', - - width: '100%', - maxWidth: '48rem', - paddingInline: '0.5rem', - }); - -export const toastStyle = (theme: Theme) => - css({ - width: '100%', - padding: '0.625rem 1rem', - - backgroundColor: theme.colors.gray, - boxShadow: '0 8px 12px rgba(0, 0, 0, 0.16);', - - borderRadius: '1.25rem', - }); - -export const textStyle = (theme: Theme) => - css({ - width: '100%', - - color: theme.colors.white, - - whiteSpace: 'pre-line', - }); diff --git a/HDesign/src/components/Toast/Toast.tsx b/HDesign/src/components/Toast/Toast.tsx deleted file mode 100644 index 972ce6220..000000000 --- a/HDesign/src/components/Toast/Toast.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import {createPortal} from 'react-dom'; - -import Text from '@components/Text/Text'; -import Flex from '@components/Flex/Flex'; -import Icon from '@components/Icon/Icon'; - -import {useTheme} from '@theme/HDesignProvider'; - -import Button from '../Button/Button'; - -import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; -import {ToastProps, ToastType} from './Toast.type'; - -const renderIcon = (type: ToastType) => { - switch (type) { - case 'error': - return ; - - case 'confirm': - return ; - - case 'none': - return null; - - default: - return null; - } -}; - -const Toast = ({ - type = 'confirm', - top = '0px', - bottom = '0px', - isClickToClose = true, - position = 'bottom', - message, - onUndo, - onClose, - ...htmlProps -}: ToastProps) => { - const {theme} = useTheme(); - const styleProps = {position, top, bottom}; - - const handleClickToClose = () => { - if (!isClickToClose || !onClose) return; - - onClose(); - }; - - return createPortal( -
-
- - - {renderIcon(type)} - - {message} - - - {onUndo && ( - - )} - -
-
, - document.body, - ); -}; - -export default Toast; diff --git a/HDesign/src/components/Toast/Toast.type.ts b/HDesign/src/components/Toast/Toast.type.ts deleted file mode 100644 index 12a436c2d..000000000 --- a/HDesign/src/components/Toast/Toast.type.ts +++ /dev/null @@ -1,21 +0,0 @@ -export type ToastPosition = 'bottom' | 'top'; -export type ToastType = 'error' | 'confirm' | 'none'; - -export interface ToastStyleProps { - bottom?: string; - top?: string; -} - -export interface ToastOptionProps { - position?: ToastPosition; - type?: ToastType; - onUndo?: () => void; - isClickToClose?: boolean; - onClose?: () => void; -} - -export interface ToastRequiredProps { - message: string; -} - -export type ToastProps = React.ComponentProps<'div'> & ToastStyleProps & ToastOptionProps & ToastRequiredProps; diff --git a/HDesign/src/components/Toast/ToastProvider.stories.tsx b/HDesign/src/components/Toast/ToastProvider.stories.tsx deleted file mode 100644 index 32c8c6917..000000000 --- a/HDesign/src/components/Toast/ToastProvider.stories.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import type {Meta, StoryObj} from '@storybook/react'; - -import Button from '../Button/Button'; - -import {ToastProvider, useToast} from './ToastProvider'; - -const meta = { - title: 'Components/ToastProvider', - component: ToastProvider, - tags: ['autodocs'], - decorators: [ - Story => ( - - - - ), - ], -} satisfies Meta; - -export default meta; - -type Story = StoryObj; - -export const Playground: Story = { - decorators: [ - () => { - const {showToast} = useToast(); - - return ( - - ); - }, - ], -}; diff --git a/HDesign/src/components/Toast/ToastProvider.tsx b/HDesign/src/components/Toast/ToastProvider.tsx deleted file mode 100644 index 9201fdc6d..000000000 --- a/HDesign/src/components/Toast/ToastProvider.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import {createContext, useCallback, useContext, useEffect, useState} from 'react'; - -import {ToastProps} from './Toast.type'; -import Toast from './Toast'; - -export const ToastContext = createContext(null); - -interface ToastContextProps { - showToast: (args: ShowToast) => void; -} - -type ShowToast = ToastProps & { - showingTime?: number; - isAlwaysOn?: boolean; -}; - -const ToastProvider = ({children}: React.PropsWithChildren) => { - const [currentToast, setCurrentToast] = useState(null); - - const showToast = useCallback(({showingTime = 3000, isAlwaysOn = false, ...toastProps}: ShowToast) => { - setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); - }, []); - - const closeToast = () => { - setCurrentToast(null); - }; - - useEffect(() => { - if (!currentToast) return; - - if (!currentToast.isAlwaysOn) { - const timer = setTimeout(() => { - setCurrentToast(null); - }, currentToast.showingTime); - - return () => clearTimeout(timer); - } - }, [currentToast]); - - return ( - - {currentToast && } - {children} - - ); -}; - -const useToast = () => { - const context = useContext(ToastContext); - - if (!context) { - throw new Error('useToast는 ToastProvider 내에서 사용되어야 합니다.'); - } - - return context; -}; - -export {ToastProvider, useToast}; diff --git a/HDesign/src/components/TopNav/Back.tsx b/HDesign/src/components/TopNav/Back.tsx deleted file mode 100644 index cfb55e24d..000000000 --- a/HDesign/src/components/TopNav/Back.tsx +++ /dev/null @@ -1,17 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import React from 'react'; -import {useNavigate} from 'react-router-dom'; - -import TextButton from '@components/TextButton/TextButton'; - -function Back() { - const navigate = useNavigate(); - - return ( - navigate(-1)} textSize="bodyBold" textColor="gray"> - 뒤로가기 - - ); -} - -export default Back; diff --git a/HDesign/src/components/TopNav/TopNav.stories.tsx b/HDesign/src/components/TopNav/TopNav.stories.tsx deleted file mode 100644 index 0c96161a5..000000000 --- a/HDesign/src/components/TopNav/TopNav.stories.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import type {Meta, StoryObj} from '@storybook/react'; - -import React from 'react'; -import {reactRouterParameters, withRouter} from 'storybook-addon-react-router-v6'; - -import TopNav from '@components/TopNav/TopNav'; - -import Switch from '../Switch/Switch'; - -import Back from './Back'; - -const meta = { - title: 'Components/TopNav', - component: TopNav, - tags: ['autodocs'], - decorators: [withRouter], - parameters: { - reactRouter: reactRouterParameters({ - location: { - pathParams: { - eventId: '123123', - }, - }, - routing: {path: '/event/:eventId/home'}, - }), - // layout: 'centered', - }, - argTypes: { - children: { - description: '', - control: {type: 'select'}, - options: ['Back', 'Switch', 'Any'], - mapping: { - Back: , - Switch: console.log(value)} />, - Any:
, - }, - }, - }, - args: { - children: 'Back', - }, -} satisfies Meta; - -export default meta; - -type Story = StoryObj; - -export const Playground: Story = {}; diff --git a/HDesign/src/components/TopNav/TopNav.style.ts b/HDesign/src/components/TopNav/TopNav.style.ts deleted file mode 100644 index 9ca69c7b0..000000000 --- a/HDesign/src/components/TopNav/TopNav.style.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {css} from '@emotion/react'; - -export const topNavStyle = css({ - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - padding: '0 1rem', - width: '100%', -}); - -export const topNavNonStyle = css({ - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - padding: '0 1rem', - width: '100%', - height: '1.5rem', -}); diff --git a/HDesign/src/components/TopNav/TopNav.tsx b/HDesign/src/components/TopNav/TopNav.tsx deleted file mode 100644 index 643cd5e3b..000000000 --- a/HDesign/src/components/TopNav/TopNav.tsx +++ /dev/null @@ -1,20 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import React from 'react'; - -import Switch from '@components/Switch/Switch'; - -import {topNavNonStyle, topNavStyle} from './TopNav.style'; -import Back from './Back'; - -const TopNav: React.FC = ({children}) => { - const hasBack = React.Children.toArray(children).some(child => React.isValidElement(child) && child.type === Back); - const hasSwitch = React.Children.toArray(children).some( - child => React.isValidElement(child) && child.type === Switch, - ); - - const isExistNav = hasBack || hasSwitch; - - return
{children}
; -}; - -export default TopNav; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx deleted file mode 100644 index 656690951..000000000 --- a/HDesign/src/index.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import BottomSheet from '@components/BottomSheet/BottomSheet'; -import Button from '@components/Button/Button'; -import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; -import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; -import EditableItem from '@components/EditableItem/EditableItem'; -import ExpenseList from '@components/ExpenseList/ExpenseList'; -import FixedButton from '@components/FixedButton/FixedButton'; -import Flex from '@components/Flex/Flex'; -import Icon from '@components/Icon/Icon'; -import IconButton from '@components/IconButton/IconButton'; -import Input from '@components/Input/Input'; -import LabelInput from '@components/LabelInput/LabelInput'; -import ListButton from '@components/ListButton/ListButton'; -import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; -import Search from '@components/Search/Search'; -import Switch from '@components/Switch/Switch'; -import Tab from '@components/Tabs/Tab'; -import Tabs from '@components/Tabs/Tabs'; -import Text from '@components/Text/Text'; -import TextButton from '@components/TextButton/TextButton'; -import Title from '@components/Title/Title'; -import Toast from '@components/Toast/Toast'; -import Back from '@components/TopNav/Back'; -import TopNav from '@components/TopNav/TopNav'; -import {ToastProvider, useToast} from '@components/Toast/ToastProvider'; - -import {MainLayout} from '@layouts/MainLayout'; -import {ContentLayout} from '@layouts/ContentLayout'; - -import {HDesignProvider} from '@theme/HDesignProvider'; - -export { - BottomSheet, - Button, - DragHandleItem, - DragHandleItemContainer, - EditableItem, - ExpenseList, - FixedButton, - Flex, - Icon, - IconButton, - Input, - LabelInput, - ListButton, - LabelGroupInput, - Search, - Switch, - Tab, - Tabs, - Text, - TextButton, - Title, - Toast, - TopNav, - Back, - MainLayout, - ContentLayout, - ToastProvider, - useToast, - HDesignProvider, -}; diff --git a/HDesign/tsconfig.json b/HDesign/tsconfig.json deleted file mode 100644 index ca7b8b78f..000000000 --- a/HDesign/tsconfig.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "compilerOptions": { - "sourceMap": true, - "outDir": "./dist", - "target": "ES5", - "skipLibCheck": true, - "module": "commonjs", - "moduleResolution": "node", - "strict": true, - "declaration": true, - "declarationDir": "./dist", - "resolveJsonModule": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "jsx": "react-jsx", - "allowJs": true, - "baseUrl": ".", - "paths": { - "@*": ["src/*"], - "@components/*": ["src/components/*"], - "@layouts/*": ["src/layouts/*"], - "@token/*": ["src/token/*"], - "@type/*": ["src/type/*"], - "@theme/*": ["src/theme/*"], - "@assets/*": ["src/assets/*"], - "@utils/*": ["src/utils/*"] - }, - "jsxImportSource": "@emotion/react", - "allowSyntheticDefaultImports": true - }, - "include": ["src"], - "exclude": ["./node_modules", "dist"] -} diff --git a/README.md b/README.md index 4bf6bd7c1..c0b59222a 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# 2024-haeng-dong \ No newline at end of file +# 행동대장들의 정산을 간편하게💰행동대장 + +![service introduce](https://github.com/user-attachments/assets/9e51f7a3-0326-4c06-8b03-65aca574c10c) diff --git a/client/.gitignore b/client/.gitignore index cf03bec6b..54b01c541 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -12,3 +12,6 @@ dist # Sentry Config File .env.sentry-build-plugin + +storybook-static +*storybook.log diff --git a/client/.storybook/main.ts b/client/.storybook/main.ts new file mode 100644 index 000000000..a06f80f22 --- /dev/null +++ b/client/.storybook/main.ts @@ -0,0 +1,59 @@ +/** @type { import('@storybook/react-webpack5').StorybookConfig } */ +import type {StorybookConfig} from '@storybook/react-webpack5'; +import path from 'path'; +import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: [ + '@storybook/addon-webpack5-compiler-swc', + '@storybook/addon-onboarding', + '@storybook/addon-links', + '@storybook/addon-essentials', + '@chromatic-com/storybook', + '@storybook/addon-interactions', + ], + framework: { + name: '@storybook/react-webpack5', + options: {}, + }, + webpackFinal: async config => { + if (config.resolve) { + config.resolve.alias = { + ...config.resolve.alias, + '@apis': path.resolve(__dirname, '../src/apis/'), + '@assets': path.resolve(__dirname, '../src/assets/'), + '@components': path.resolve(__dirname, '../src/components/'), + '@constants': path.resolve(__dirname, '../src/constants/'), + '@hooks': path.resolve(__dirname, '../src/hooks/'), + '@store': path.resolve(__dirname, '../src/store/'), + '@mocks': path.resolve(__dirname, '../src/mocks/'), + '@pages': path.resolve(__dirname, '../src/pages/'), + '@utils': path.resolve(__dirname, '../src/utils/'), + '@errors': path.resolve(__dirname, '../src/errors/'), + '@HDesign': path.resolve(__dirname, '../src/components/Design/'), + '@HDcomponents': path.resolve(__dirname, '../src/components/Design/components/'), + '@HDutils': path.resolve(__dirname, '../src/components/Design/utils/'), + '@token': path.resolve(__dirname, '../src/components/Design/token/'), + '@theme': path.resolve(__dirname, '../src/components/Design/theme/'), + '@layouts': path.resolve(__dirname, '../src/components/Design/layouts/'), + '@type': path.resolve(__dirname, '../src/components/Design/type/'), + }; + } + + config.module = config.module || {}; + config.module.rules = config.module.rules || []; + + const imageRule = config.module.rules.find(rule => rule?.['test']?.test('.svg')); + if (imageRule) { + imageRule['exclude'] = /\.svg$/; + } + + config.module.rules.push({ + test: /\.svg$/, + use: ['@svgr/webpack'], + }); + return config; + }, +}; +export default config; diff --git a/HDesign/.storybook/preview.tsx b/client/.storybook/preview.tsx similarity index 91% rename from HDesign/.storybook/preview.tsx rename to client/.storybook/preview.tsx index 22008ad03..a3c83803f 100644 --- a/HDesign/.storybook/preview.tsx +++ b/client/.storybook/preview.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import type {Preview} from '@storybook/react'; -import {HDesignProvider} from '../src/theme/HDesignProvider'; +import {HDesignProvider} from '../src/components/Design'; const preview: Preview = { parameters: { diff --git a/client/cypress/e2e/createEvent.cy.ts b/client/cypress/e2e/createEvent.cy.ts index 5b4a93884..30e50b4f5 100644 --- a/client/cypress/e2e/createEvent.cy.ts +++ b/client/cypress/e2e/createEvent.cy.ts @@ -1,24 +1,27 @@ +import {ROUTER_URLS} from '@constants/routerUrls'; import CONSTANTS from '../constants/constants'; +import RULE from '@constants/rule'; + beforeEach(() => { cy.blockSentry(); + cy.blockKakao(); }); describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 flow', () => { - it('랜딩페이지에서 "행사 생성하기" 버튼을 눌러 행사 이름 입력 페이지로 이동해야 한다.', () => { + it('랜딩페이지에서 "정산 시작하기" 버튼을 눌러 행사 이름 입력 페이지로 이동해야 한다.', () => { cy.visit('/'); - cy.get('header').find('button').click(); - cy.url().should('include', '/event/create/name'); + cy.get('button').contains('정산 시작하기').click(); + cy.url().should('include', ROUTER_URLS.createEvent); }); context('행사 이름 입력 페이지', () => { beforeEach(() => { - cy.visit('/event/create/name'); + cy.visit(ROUTER_URLS.createEvent); }); it('행사 이름 입력 페이지에서 input이 포커싱 되어 있고, "다음" 버튼이 비활성화 되어 있어야 한다.', () => { cy.get('input').focused(); cy.get('button').contains('다음').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/name'); }); it('행사 이름이 1자 이상 입력된 경우 "다음" 버튼이 활성화 되고, 값이 없는 경우 "다음" 버튼이 비활성화 되어야 한다.', () => { @@ -27,13 +30,14 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.get('input').clear(); cy.get('input').should('have.value', ''); cy.get('button').contains('다음').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/name'); }); it('행사 이름을 입력한 후 "다음" 버튼을 누르면 행사 비밀번호 설정 화면으로 이동해야 한다.', () => { cy.get('input').type(CONSTANTS.eventName); cy.get('button').contains('다음').click(); - cy.url().should('include', '/event/create/password'); + + // 다음 버튼을 클릭하면 /create/event 경로가 아니라 /create/event/?로 가네요.. 그래서 일단 제거함. + cy.contains('비밀번호').should('exist'); }); }); @@ -45,7 +49,6 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl it('행사 비밀번호 입력 페이지에서 input이 포커싱 되어 있고, "행동 개시!" 버튼이 비활성화 되어 있어야 한다.', () => { cy.get('input').focused(); cy.get('button').contains('행동 개시!').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/password'); }); it('행사 비밀번호에 숫자가 아닌 입력을 할 경우 값이 입력되지 않아야 한다.', () => { @@ -53,7 +56,7 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.get('input').should('have.value', ''); }); - it('행사 비밀번호에 4자리 이상 입력을 할 경우 처음 네 자리만 입력되어야 한다.', () => { + it(`행사 비밀번호에 ${RULE.maxEventPasswordLength}자리 이상 입력을 할 경우 처음 ${RULE.maxEventPasswordLength}자리만 입력되어야 한다.`, () => { cy.get('input').type('12345'); cy.get('input').should('have.value', CONSTANTS.eventPassword); }); @@ -64,7 +67,6 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.get('input').clear(); cy.get('input').should('have.value', ''); cy.get('button').contains('행동 개시!').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/password'); }); it('행사 비밀번호을 입력한 후 "행동 개시!" 버튼을 누르면 행사 생성 완료 화면으로 이동해야 한다.', () => { @@ -72,8 +74,6 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.interceptAPI({type: 'getEventName', statusCode: 200}); cy.get('input').type(CONSTANTS.eventPassword); cy.get('button').contains('행동 개시!').click(); - - cy.url().should('include', '/event/create/complete'); }); }); }); diff --git a/client/cypress/support/commands.ts b/client/cypress/support/commands.ts index c51d00580..6ef75b4dc 100644 --- a/client/cypress/support/commands.ts +++ b/client/cypress/support/commands.ts @@ -1,3 +1,4 @@ +import {ROUTER_URLS} from '@constants/routerUrls'; import CONSTANTS from '../constants/constants'; type APIType = 'sentry' | 'postEvent' | 'getEventName'; @@ -21,6 +22,13 @@ Cypress.Commands.add('blockSentry', () => { cy.intercept('POST', /.*sentry.io\/api.*/, {statusCode: 200}).as('sentry'); }); +Cypress.Commands.add('blockKakao', () => { + cy.intercept('GET', 'https://t1.kakaocdn.net/kakao_js_sdk/2.7.2/kakao.min.js', { + statusCode: 200, + body: '', + }).as('blockKakao'); +}); + Cypress.Commands.add('interceptAPI', ({type, delay = 0, statusCode = 200}: InterceptAPIProps) => { if (type === 'postEvent') cy.intercept(POST_EVENT, { @@ -39,16 +47,16 @@ Cypress.Commands.add('interceptAPI', ({type, delay = 0, statusCode = 200}: Inter }); Cypress.Commands.add('createEventName', (eventName: string) => { - cy.visit('/event/create/name'); + cy.visit(ROUTER_URLS.createEvent); cy.get('input').type(eventName); cy.get('button').contains('다음').click(); - cy.url().should('include', '/event/create/password'); }); declare global { namespace Cypress { interface Chainable { blockSentry(): Chainable; + blockKakao(): Chainable; interceptAPI(props: InterceptAPIProps): Chainable; createEventName(eventName: string): Chainable; } diff --git a/client/eslint.config.mjs b/client/eslint.config.mjs index 4ca5abb89..e8355aaed 100644 --- a/client/eslint.config.mjs +++ b/client/eslint.config.mjs @@ -71,6 +71,11 @@ export default [ group: 'internal', position: 'after', }, + { + pattern: '@HDesign/*', + group: 'internal', + position: 'after', + }, { pattern: '@utils/*', group: 'internal', diff --git a/client/index.html b/client/index.html index 4a21293f2..5252bb218 100644 --- a/client/index.html +++ b/client/index.html @@ -25,6 +25,11 @@ window.amplitude.init('<%= process.env.AMPLITUDE_KEY %>'); }); + 행동대장 diff --git a/client/jest.config.ts b/client/jest.config.ts index a75677a5a..5cdc6baab 100644 --- a/client/jest.config.ts +++ b/client/jest.config.ts @@ -6,6 +6,7 @@ const config: Config = { testEnvironment: 'jsdom', // 브라우저 내에서의 JavaScript 동작을 모방하여, DOM 조작, 이벤트 핸들링, 브라우저 관련 API 호출 transform: { '^.+\\.ts?$': 'ts-jest', + '^.+\\.(jpg|jpeg|png|gif|svg)$': '/src/mocks/imageFileMock.ts', }, collectCoverage: true, coverageReporters: ['text'], @@ -30,6 +31,7 @@ const config: Config = { moduleNameMapper: { '@/(.*)$': '/src/$1', // path alias를 적용하기 위함 '^@apis/(.*)$': '/src/apis/$1', + '^@assets/(.*)$': '/src/assets/$1', '^@constants/(.*)$': '/src/constants/$1', '^@components/(.*)$': '/src/components/$1', '^@hooks/(.*)$': '/src/hooks/$1', @@ -39,7 +41,14 @@ const config: Config = { '^@errors/(.*)$': '/src/errors/$1', '^@mocks/(.*)$': '/src/mocks/$1', '^@store/(.*)$': '/src/store/$1', - '\\.svg$': '/src/mocks/svg.ts', + '^@HDesign/(.*)$': '/src/components/Design/$1', + '^@HDcomponents/(.*)$': '/src/components/Design/components/$1', + '^@HDutils/(.*)$': '/src/components/Design/utils/$1', + '^@token/(.*)$': '/src/components/Design/token/$1', + '^@theme/(.*)$': '/src/components/Design/theme/$1', + '^@layouts/(.*)$': '/src/components/Design/layouts/$1', + '^@type/(.*)$': '/src/components/Design/type/$1', + '\\.(jpg|jpeg|png|gif|svg)$': '/src/mocks/imageFileMock.ts', }, testEnvironmentOptions: { customExportConditions: [''], diff --git a/client/package-lock.json b/client/package-lock.json index 61a529538..95211e1e6 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,8 +12,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.81", - "jest-canvas-mock": "^2.5.2", + "lottie-react": "^2.4.0", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -22,10 +21,20 @@ "zustand": "^4.5.5" }, "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", "@jest/types": "^29.6.3", "@sentry/webpack-plugin": "^2.22.0", + "@storybook/addon-essentials": "^8.2.2", + "@storybook/addon-interactions": "^8.2.2", + "@storybook/addon-links": "^8.2.2", + "@storybook/addon-onboarding": "^8.2.2", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@storybook/blocks": "^8.2.2", + "@storybook/react": "^8.2.2", + "@storybook/react-webpack5": "^8.2.3", + "@storybook/test": "^8.2.2", "@svgr/webpack": "^8.1.0", "@tanstack/react-query-devtools": "^5.52.0", "@testing-library/dom": "^10.4.0", @@ -48,16 +57,21 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^4.6.2", + "file-loader": "^6.2.0", "fork-ts-checker-webpack-plugin": "^9.0.2", "globals": "^15.8.0", "html-loader": "^5.0.0", "html-webpack-plugin": "^5.6.0", "jest": "^29.7.0", + "jest-canvas-mock": "^2.5.2", "jest-environment-jsdom": "^29.7.0", + "jest-transform-stub": "^2.0.0", "jsdom": "^24.1.1", "modify-source-webpack-plugin": "^4.1.0", "msw": "^2.3.5", "prettier": "3.3.2", + "storybook": "^8.2.2", + "storybook-addon-react-router-v6": "^2.0.15", "ts-jest": "^29.2.4", "ts-loader": "^9.5.1", "ts-node": "^10.9.2", @@ -84,6 +98,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -108,6 +123,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -116,6 +132,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", @@ -144,7 +161,8 @@ "node_modules/@babel/core/node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true }, "node_modules/@babel/generator": { "version": "7.25.0", @@ -164,6 +182,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dev": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -175,6 +194,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -187,6 +207,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.25.2", "@babel/helper-validator-option": "^7.24.8", @@ -202,6 +223,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz", "integrity": "sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-member-expression-to-functions": "^7.24.8", @@ -222,6 +244,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", @@ -238,6 +261,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -253,6 +277,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dev": true, "dependencies": { "@babel/traverse": "^7.24.8", "@babel/types": "^7.24.8" @@ -277,6 +302,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", @@ -294,6 +320,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dev": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -305,6 +332,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -313,6 +341,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-wrap-function": "^7.25.0", @@ -329,6 +358,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "dev": true, "dependencies": { "@babel/helper-member-expression-to-functions": "^7.24.8", "@babel/helper-optimise-call-expression": "^7.24.7", @@ -345,6 +375,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -357,6 +388,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -385,6 +417,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -393,6 +426,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "dev": true, "dependencies": { "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.0", @@ -406,6 +440,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", + "dev": true, "dependencies": { "@babel/template": "^7.25.0", "@babel/types": "^7.25.0" @@ -446,6 +481,7 @@ "version": "7.25.3", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/traverse": "^7.25.3" @@ -461,6 +497,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -475,6 +512,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -489,6 +527,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -505,6 +544,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/traverse": "^7.25.0" @@ -520,6 +560,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, "engines": { "node": ">=6.9.0" }, @@ -531,6 +572,7 @@ "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -554,6 +596,7 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -565,6 +608,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -579,6 +623,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -590,6 +635,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -597,10 +643,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", + "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -615,6 +677,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -629,6 +692,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -640,6 +704,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -651,6 +716,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -665,6 +731,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -676,6 +743,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -687,6 +755,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -698,6 +767,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -709,6 +779,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -720,6 +791,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -731,6 +803,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -745,6 +818,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -759,6 +833,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -773,6 +848,7 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -788,6 +864,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -802,6 +879,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-remap-async-to-generator": "^7.25.0", @@ -819,6 +897,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -835,6 +914,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -849,6 +929,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -863,6 +944,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -878,6 +960,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -894,6 +977,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz", "integrity": "sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-compilation-targets": "^7.24.8", @@ -913,6 +997,7 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, "engines": { "node": ">=4" } @@ -921,6 +1006,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/template": "^7.24.7" @@ -936,6 +1022,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -950,6 +1037,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -965,6 +1053,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -979,6 +1068,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.0", "@babel/helper-plugin-utils": "^7.24.8" @@ -994,6 +1084,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -1009,6 +1100,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dev": true, "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1024,6 +1116,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -1035,10 +1128,27 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.2.tgz", + "integrity": "sha512-InBZ0O8tew5V0K6cHcQ+wgxlrjOw1W4wDXLkOTjLRD8GYhTSkxTVBtdy3MMtvYBrbAWa1Qm3hNoTc1620Yj+Mg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-flow": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -1054,6 +1164,7 @@ "version": "7.25.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8", @@ -1070,6 +1181,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -1085,6 +1197,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1099,6 +1212,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -1114,6 +1228,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1128,6 +1243,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1143,6 +1259,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8", @@ -1159,6 +1276,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.25.0", "@babel/helper-plugin-utils": "^7.24.8", @@ -1176,6 +1294,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1191,6 +1310,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1206,6 +1326,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1220,6 +1341,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -1235,6 +1357,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" @@ -1250,6 +1373,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1267,6 +1391,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-replace-supers": "^7.24.7" @@ -1282,6 +1407,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -1297,6 +1423,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -1313,6 +1440,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1327,6 +1455,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1342,6 +1471,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-create-class-features-plugin": "^7.24.7", @@ -1359,6 +1489,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1373,6 +1504,7 @@ "version": "7.25.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.1.tgz", "integrity": "sha512-SLV/giH/V4SmloZ6Dt40HjTGTAIkxn33TVIHxNGNvo8ezMhrxBkzisj4op1KZYPIOHFLqhv60OHvX+YRu4xbmQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1387,6 +1519,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1401,6 +1534,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", @@ -1419,6 +1553,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dev": true, "dependencies": { "@babel/plugin-transform-react-jsx": "^7.24.7" }, @@ -1433,6 +1568,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1448,6 +1584,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "regenerator-transform": "^0.15.2" @@ -1463,6 +1600,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1477,6 +1615,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1491,6 +1630,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -1506,6 +1646,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1520,6 +1661,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1534,6 +1676,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1548,6 +1691,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-create-class-features-plugin": "^7.25.0", @@ -1566,6 +1710,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1580,6 +1725,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1595,6 +1741,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1610,6 +1757,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1625,6 +1773,7 @@ "version": "7.25.3", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz", "integrity": "sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.25.2", "@babel/helper-compilation-targets": "^7.25.2", @@ -1717,10 +1866,28 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz", + "integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-flow-strip-types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -1734,6 +1901,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", @@ -1753,6 +1921,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", @@ -1767,10 +1936,148 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/register": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", + "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/register/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/register/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/@babel/regjsgen": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true }, "node_modules/@babel/runtime": { "version": "7.25.0", @@ -1834,6 +2141,12 @@ "node": ">=6.9.0" } }, + "node_modules/@base2/pretty-print-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", + "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", + "dev": true + }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -1877,22 +2190,66 @@ "tough-cookie": "^4.1.4" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "node_modules/@chromatic-com/storybook": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-1.8.0.tgz", + "integrity": "sha512-vkB9dPVmM2Yvqc/0DJ4MYwOGY1MOjd/KbB9TXTMGN+qshaEyiZtSOgbz9u0ExFALEgDKLmtUnWyUtoGb0pCzUg==", "dev": true, - "optional": true, + "dependencies": { + "chromatic": "^11.4.0", + "filesize": "^10.0.12", + "jsonfile": "^6.1.0", + "react-confetti": "^6.1.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=0.1.90" + "node": ">=16.0.0", + "yarn": ">=1.22.18" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { + "node_modules/@chromatic-com/storybook/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@chromatic-com/storybook/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, "engines": { @@ -2084,532 +2441,606 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=12" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/@eslint/compat": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", - "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" } }, - "node_modules/@eslint/config-array": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", - "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" } }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/@eslint/js": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", - "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" } }, - "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">=12" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=12" } }, - "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=12" } }, - "node_modules/@inquirer/confirm": { - "version": "3.1.22", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.22.tgz", - "integrity": "sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "@inquirer/core": "^9.0.10", - "@inquirer/type": "^1.5.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/@inquirer/core": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.10.tgz", - "integrity": "sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==", + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.2", - "@types/mute-stream": "^0.0.4", - "@types/node": "^22.1.0", - "@types/wrap-ansi": "^3.0.0", - "ansi-escapes": "^4.3.2", - "cli-spinners": "^2.9.2", - "cli-width": "^4.1.0", - "mute-stream": "^1.0.0", - "signal-exit": "^4.1.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=7.0.0" + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@inquirer/core/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@inquirer/core/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@inquirer/figures": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz", - "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==", + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/@inquirer/type": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.2.tgz", - "integrity": "sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "dependencies": { - "mute-stream": "^1.0.0" + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, "engines": { - "node": ">=12" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/@eslint/compat": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", + "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@eslint/js": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=14" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@inquirer/confirm": { + "version": "3.1.22", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.22.tgz", + "integrity": "sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@inquirer/core": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.10.tgz", + "integrity": "sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.2", + "@types/mute-stream": "^0.0.4", + "@types/node": "^22.1.0", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=18" } }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@inquirer/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/console/node_modules/color-convert": { + "node_modules/@inquirer/core/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -2621,266 +3052,258 @@ "node": ">=7.0.0" } }, - "node_modules/@jest/console/node_modules/color-name": { + "node_modules/@inquirer/core/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@jest/console/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@jest/console/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz", + "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.2.tgz", + "integrity": "sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==", + "dev": true, + "dependencies": { + "mute-stream": "^1.0.0" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "engines": { + "node": ">=18" } }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@jest/core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" } }, - "node_modules/@jest/core/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } }, - "node_modules/@jest/core/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/@jest/core/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "p-locate": "^4.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "jest-get-type": "^29.6.3" + "p-try": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "p-limit": "^2.2.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/reporters": { + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", "jest-message-util": "^29.7.0", "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "slash": "^3.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } } }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { + "node_modules/@jest/console/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -2895,17 +3318,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@jest/reporters/node_modules/chalk": { + "node_modules/@jest/console/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -2921,7 +3334,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/reporters/node_modules/color-convert": { + "node_modules/@jest/console/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -2933,34 +3346,13 @@ "node": ">=7.0.0" } }, - "node_modules/@jest/reporters/node_modules/color-name": { + "node_modules/@jest/console/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/reporters/node_modules/has-flag": { + "node_modules/@jest/console/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -2969,49 +3361,7 @@ "node": ">=8" } }, - "node_modules/@jest/reporters/node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters/node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@jest/reporters/node_modules/supports-color": { + "node_modules/@jest/console/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -3023,89 +3373,54 @@ "node": ">=8" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { + "node_modules/@jest/core": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "dependencies": { "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "dependencies": { + "@jest/reporters": "^29.7.0", "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", + "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "pirates": "^4.0.4", + "pretty-format": "^29.7.0", "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "strip-ansi": "^6.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@jest/transform/node_modules/ansi-styles": { + "node_modules/@jest/core/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -3120,7 +3435,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/transform/node_modules/chalk": { + "node_modules/@jest/core/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -3136,7 +3451,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/transform/node_modules/color-convert": { + "node_modules/@jest/core/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -3148,19 +3463,13 @@ "node": ">=7.0.0" } }, - "node_modules/@jest/transform/node_modules/color-name": { + "node_modules/@jest/core/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@jest/transform/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/@jest/transform/node_modules/has-flag": { + "node_modules/@jest/core/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -3169,7 +3478,7 @@ "node": ">=8" } }, - "node_modules/@jest/transform/node_modules/supports-color": { + "node_modules/@jest/core/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -3181,58 +3490,1617 @@ "node": ">=8" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "jest-get-type": "^29.6.3" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", + "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "dev": true, + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", + "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true + }, + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "dev": true, + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", + "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "dev": true, + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@open-draft/deferred-promise": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@remix-run/router": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", + "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@sentry-internal/browser-utils": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.25.0.tgz", + "integrity": "sha512-nlWgp1lVhNQOTUplW85G3qm0fOIgAhJ/sl/31OIuScVrITYhYDF2bO+Zv/jQ8YsdUBAUXqY1tPT9wwPJklnPhw==", + "dependencies": { + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.25.0.tgz", + "integrity": "sha512-327I5XJAFrsgjc5qUKxZ9rff3WNCfGvf1fIii70LQ2YQhQgG4XHZILmkD06ETEyXb+H1tkrNQQEJ1/d4ai+q5g==", + "dependencies": { + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.25.0.tgz", + "integrity": "sha512-3f7x8EYthyj157uV9V8vBjun+1gJnHhh2+i0qxYLhMGx7N2Fq0J3Bvvo1rosSg+fYh5HzPNZDufwIRdg5C/MQw==", + "dependencies": { + "@sentry-internal/browser-utils": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.25.0.tgz", + "integrity": "sha512-dPXlkAbkFL1DBum8rGTaHS+apJKaXEZJF9gLcBBKTruhTCizrugFLxajzIfVSiFVuwNKuJWa2fzhzbeQM0ee7w==", + "dependencies": { + "@sentry-internal/replay": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.0.tgz", + "integrity": "sha512-UzH+NNhgnOo6UFku3C4TEz+pO/yDcIA5FKTJvLbJ7lQwAjsqLs3DZWm4cCA08skICb8mULArF6S/dn5/butVCA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/browser": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.25.0.tgz", + "integrity": "sha512-51bdVGXjyooqVGzaSGsnExqRTt9NvZ1zGFsxbbCSXi5UoEFN6zdMUz6jKYsL2K80eeELP2VKOVlobHlEzeJQfw==", + "dependencies": { + "@sentry-internal/browser-utils": "8.25.0", + "@sentry-internal/feedback": "8.25.0", + "@sentry-internal/replay": "8.25.0", + "@sentry-internal/replay-canvas": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.0.tgz", + "integrity": "sha512-/xXN8o7565WMsewBnQFfjm0E5wqhYsegg++HJ5RjrY/cTM4qcd/ven44GEMxqGFJitZizvkk3NHszaHylzcRUw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "2.22.0", + "@sentry/cli": "^2.33.1", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^9.3.2", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/cli": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", + "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.33.1", + "@sentry/cli-linux-arm": "2.33.1", + "@sentry/cli-linux-arm64": "2.33.1", + "@sentry/cli-linux-i686": "2.33.1", + "@sentry/cli-linux-x64": "2.33.1", + "@sentry/cli-win32-i686": "2.33.1", + "@sentry/cli-win32-x64": "2.33.1" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", + "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", + "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", + "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", + "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", + "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", + "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", + "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/core": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.25.0.tgz", + "integrity": "sha512-7KtglbrW1eX4DOHkf6i4rRIExEf2CgtQ99qZ8gn5FUaAmNMg0rK7bb1yZMx0RZtp5G1TSz/S0jQQgxHWebaEig==", + "dependencies": { + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/react": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.25.0.tgz", + "integrity": "sha512-A3QeSCJEa+lpo5nh0kxKeqsmnuW2nycKNN/0bpXPv5T5jiEfExSmEBVM0zutrQpf+J0WRIl1AGunUYGPO+GPQg==", + "dependencies": { + "@sentry/browser": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0", + "hoist-non-react-statics": "^3.3.2" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, + "node_modules/@sentry/types": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.25.0.tgz", + "integrity": "sha512-ojim0gDcRhGJPguYrtms4FsprX4xZz3LGNk9Z0hwTbSVEdlhQIInsQ7CYcdM3sjUs+qT7kfpxTRZGUeZNRRJcA==", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/utils": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.25.0.tgz", + "integrity": "sha512-mVlkV7S62ZZ2jM38/kOwWx2xoW8fUv2cjw2IwFKoAIPyLBh3mo1WJtvfdtN/rXGjQWZJBKW53EWaWnD00rkjyA==", + "dependencies": { + "@sentry/types": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/webpack-plugin": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.22.0.tgz", + "integrity": "sha512-u2brctki0AMCoZksdAConQSYE6PokRVeZ4YYsbnJYkAi0KuaQnczsRwS9e2L0bK2CmZ7QdyYcrjaXHNlXaFDbQ==", + "dev": true, + "dependencies": { + "@sentry/bundler-plugin-core": "2.22.0", + "unplugin": "1.0.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "webpack": ">=4.40.0" + } + }, + "node_modules/@sentry/webpack-plugin/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@storybook/addon-actions": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.2.9.tgz", + "integrity": "sha512-eh2teOqjga7aoClDVV+/b1gHJqsPwjiU1t+Hg/l4i2CkaBUNdYMEL90nR6fgReOdvvL5YhcPwJ8w38f9TrQcoQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-actions/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@storybook/addon-backgrounds": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.2.9.tgz", + "integrity": "sha512-eGmZAd742ORBbQ6JepzBCko/in62T4Xg9j9LVa+Cvz/7L1C/RQSuU6sUwbRAsXaz+PMVDksPDCUUNsXl3zUL7w==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-controls": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.2.9.tgz", + "integrity": "sha512-vaSE78KOE7SO0GrW4e+mdQphSNpvCX/FGybIRxyaKX9h8smoyUwRNHVyCS3ROHTwH324QWu7GDzsOVrnyXOv0A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-docs": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.2.9.tgz", + "integrity": "sha512-flDOxFIGmXg+6lVdwTLMOKsGob1WrT7rG98mn1SNW0Nxhg3Wg+9pQuq1GLxEzKtAgSflmu+xcBRfYhsogyDXkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@mdx-js/react": "^3.0.0", + "@storybook/blocks": "8.2.9", + "@storybook/csf-plugin": "8.2.9", + "@storybook/global": "^5.0.0", + "@storybook/react-dom-shim": "8.2.9", + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "fs-extra": "^11.1.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "rehype-external-links": "^3.0.0", + "rehype-slug": "^6.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-docs/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/addon-essentials": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.2.9.tgz", + "integrity": "sha512-B2d3eznGZvPIyCVtYX0UhrYcEfK+3Y2sACmEWpSwtk8KXomFEsZnD95m397BYDRw3/X6qeSLWxqgMfqDTEDeMA==", + "dev": true, + "dependencies": { + "@storybook/addon-actions": "8.2.9", + "@storybook/addon-backgrounds": "8.2.9", + "@storybook/addon-controls": "8.2.9", + "@storybook/addon-docs": "8.2.9", + "@storybook/addon-highlight": "8.2.9", + "@storybook/addon-measure": "8.2.9", + "@storybook/addon-outline": "8.2.9", + "@storybook/addon-toolbars": "8.2.9", + "@storybook/addon-viewport": "8.2.9", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-highlight": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.2.9.tgz", + "integrity": "sha512-qdcazeNQoo9QKIq+LJJZZXvFZoLn+i4uhbt1Uf9WtW6oU/c1qxORGVD7jc3zsxbQN9nROVPbJ76sfthogxeqWA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-interactions": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.2.9.tgz", + "integrity": "sha512-oSxBkqpmp1Vm9v/G8mZeFNXD8k6T1NMgzUWzAx7R5m31rfObhoi5Fo1bKQT5BAhSSsdjjd7owTAFKdhwSotSKg==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/instrumenter": "8.2.9", + "@storybook/test": "8.2.9", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-links": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.2.9.tgz", + "integrity": "sha512-RhJzUNdDb7lbliwXb64HMwieIeJ+OQ2Ditue1vmSox6NsSd+pshR+okHpAyoP1+fW+dahNENwAS2Kt2QiI78FA==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-measure": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.2.9.tgz", + "integrity": "sha512-XUfQtYRKWB2dfbPRmHuos816wt1JrLbtRld5ZC8J8ljeqZ4hFBPTQcgI5GAzZqjQuclLC0KuhlA/0bKxdxMMGA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-onboarding": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.2.9.tgz", + "integrity": "sha512-9FAWwlnF4JqxOdaZCqe4HeEDj95rqQmITPugPUV3Ra8aJuukPWzlFZgfYubI50TTrnJDAFc8kYeatbxFvoagNQ==", + "dev": true, + "dependencies": { + "react-confetti": "^6.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-outline": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.2.9.tgz", + "integrity": "sha512-p22kI4W7MT0YJOCmg/FfhfH+NpZEDA5tgwstjazSg4ertyhaxziMwWZWiK2JCg0gOAfRJjoYjHz+6/u56iXwgQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-toolbars": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.2.9.tgz", + "integrity": "sha512-9LMZZ2jRD86Jh6KXedDbAYs4eHj9HtJA9VhSEE2wiqMGwXozpySi7B1GWniNzmFfcgMQ4JHfmD/OrBVTK7Ca/w==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-viewport": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.2.9.tgz", + "integrity": "sha512-lyM24+DJEt8R0YZkJKee34NQWv0REACU6lYDalqJNdKS1sEwzLGWxg1hZXnw2JFdBID9NGVvyYU2w6LDozOB0g==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-webpack5-compiler-swc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", + "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", + "dev": true, + "dependencies": { + "@swc/core": "^1.7.3", + "swc-loader": "^0.2.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@storybook/blocks": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.2.9.tgz", + "integrity": "sha512-5276q/s/UL8arwftuBXovUNHqYo/HPQFMGXEmjVVAMXUyFjzEAfKj3+xU897J6AuL+7XVZG32WnqA+X6LJMrcQ==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@types/lodash": "^4.14.167", + "color-convert": "^2.0.1", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.4.5", + "memoizerific": "^1.11.3", + "polished": "^4.2.2", + "react-colorful": "^5.1.2", + "telejson": "^7.2.0", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/blocks/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@storybook/blocks/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.9.tgz", + "integrity": "sha512-D3oYk4LkteWZ3QLcdUTu/0rUvVNUp/bWwEKAycZDr2uFCOhv8VoS2/l/TaHjn3wpyWpVVKS6GgdP72K++YVufg==", + "dev": true, + "dependencies": { + "@storybook/core-webpack": "8.2.9", + "@types/node": "^18.0.0", + "@types/semver": "^7.3.4", + "browser-assert": "^1.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "cjs-module-lexer": "^1.2.3", + "constants-browserify": "^1.0.0", + "css-loader": "^6.7.1", + "es-module-lexer": "^1.5.0", + "express": "^4.19.2", + "fork-ts-checker-webpack-plugin": "^8.0.0", + "fs-extra": "^11.1.0", + "html-webpack-plugin": "^5.5.0", + "magic-string": "^0.30.5", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "semver": "^7.3.7", + "style-loader": "^3.3.1", + "terser-webpack-plugin": "^5.3.1", + "ts-dedent": "^2.0.0", + "url": "^0.11.0", + "util": "^0.12.4", + "util-deprecate": "^1.0.2", + "webpack": "5", + "webpack-dev-middleware": "^6.1.2", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.6.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { "color-name": "~1.1.4" @@ -3241,13 +5109,85 @@ "node": ">=7.0.0" } }, - "node_modules/@jest/types/node_modules/color-name": { + "node_modules/@storybook/builder-webpack5/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@jest/types/node_modules/has-flag": { + "node_modules/@storybook/builder-webpack5/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", + "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -3256,7 +5196,37 @@ "node": ">=8" } }, - "node_modules/@jest/types/node_modules/supports-color": { + "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -3268,627 +5238,937 @@ "node": ">=8" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@storybook/builder-webpack5/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", + "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", + "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@storybook/builder-webpack5/node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true + }, + "node_modules/@storybook/codemod": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.2.9.tgz", + "integrity": "sha512-3yRx1lFMm1FXWVv+CKDiYM4gOQPEfpcZAQrjfcumxSDUrB091pnU1PeI92Prj3vCdi4+0oPNuN4yDGNUYTMP/A==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/preset-env": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/core": "8.2.9", + "@storybook/csf": "0.1.11", + "@types/cross-spawn": "^6.0.2", + "cross-spawn": "^7.0.3", + "globby": "^14.0.1", + "jscodeshift": "^0.15.1", + "lodash": "^4.17.21", + "prettier": "^3.1.1", + "recast": "^0.23.5", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "node_modules/@storybook/codemod/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/components": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.2.9.tgz", + "integrity": "sha512-OkkcZ/f/6o3GdFEEK9ZHKIGHWUHmavZUYs5xaSgU64bOrA2aqEFtfeWWitZYTv3Euhk8MVLWfyEMDfez0AlvDg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/core": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.2.9.tgz", + "integrity": "sha512-wSER8FpA6Il/jPyDfKm3yohxDtuhisNPTonMVzd3ulNWR4zERLddyO3HrHJJwdqYHLNk4SBFzwMGpQZVws1y0w==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" + "@storybook/csf": "0.1.11", + "@types/express": "^4.17.21", + "@types/node": "^18.0.0", + "browser-assert": "^1.2.1", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0", + "esbuild-register": "^3.5.0", + "express": "^4.19.2", + "process": "^0.11.10", + "recast": "^0.23.5", + "util": "^0.12.4", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "node_modules/@storybook/core-webpack": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.9.tgz", + "integrity": "sha512-6yL1su+d8IOTU+UkZqM9SeBcVc/G6vUHLsMdlWNyVtRus2JTMmT0K0/ll56jrm/ym0y98cxUOA1jsImkBubP2Q==", + "dev": true, + "dependencies": { + "@types/node": "^18.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@storybook/core-webpack/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", + "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "undici-types": "~5.26.4" } }, - "node_modules/@jsonjoy.com/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "node_modules/@storybook/core-webpack/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/core/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, - "engines": { - "node": ">=10.0" + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/core/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/csf": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.11.tgz", + "integrity": "sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==", + "dev": true, + "dependencies": { + "type-fest": "^2.19.0" + } + }, + "node_modules/@storybook/csf-plugin": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.2.9.tgz", + "integrity": "sha512-QQCFb3g12VQQEraDV1UfCmniGhQZKyT6oEt1Im6dzzPJj9NQk+6BjWoDep33CZhBHWoLryrMQd2fjuHxnFRNEA==", + "dev": true, + "dependencies": { + "unplugin": "^1.3.1" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "type": "opencollective", + "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "tslib": "2" + "storybook": "^8.2.9" } }, - "node_modules/@jsonjoy.com/json-pack": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", - "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "node_modules/@storybook/csf-plugin/node_modules/unplugin": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.13.1.tgz", + "integrity": "sha512-6Kq1iSSwg7KyjcThRUks9LuqDAKvtnioxbL9iEtB9ctTyBA5OmrB8gZd/d225VJu1w3UpUsKV7eGrvf59J7+VA==", "dev": true, "dependencies": { - "@jsonjoy.com/base64": "^1.1.1", - "@jsonjoy.com/util": "^1.1.2", - "hyperdyperid": "^1.2.0", - "thingies": "^1.20.0" + "acorn": "^8.12.1", + "webpack-virtual-modules": "^0.6.2" }, "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "node": ">=14.0.0" }, "peerDependencies": { - "tslib": "2" + "webpack-sources": "^3" + }, + "peerDependenciesMeta": { + "webpack-sources": { + "optional": true + } } }, - "node_modules/@jsonjoy.com/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", - "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "node_modules/@storybook/csf-plugin/node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true + }, + "node_modules/@storybook/csf/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, "engines": { - "node": ">=10.0" + "node": ">=12.20" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", "dev": true }, - "node_modules/@mswjs/interceptors": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", - "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "node_modules/@storybook/icons": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.10.tgz", + "integrity": "sha512-310apKdDcjbbX2VSLWPwhEwAgjxTzVagrwucVZIdGPErwiAppX8KvBuWZgPo+rQLVrtH8S+pw1dbUwjcE6d7og==", "dev": true, - "dependencies": { - "@open-draft/deferred-promise": "^2.2.0", - "@open-draft/logger": "^0.3.0", - "@open-draft/until": "^2.0.0", - "is-node-process": "^1.2.0", - "outvariant": "^1.2.1", - "strict-event-emitter": "^0.5.1" - }, "engines": { - "node": ">=18" + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@storybook/instrumenter": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.2.9.tgz", + "integrity": "sha512-+DNjTbsMzlDggsvkhRuOy7aGvQJ4oLCPgunP5Se/3yBjG+M2bYDa0EmC5jC2nwZ3ffpuvbzaVe7fWf7R8W9F2Q==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@storybook/global": "^5.0.0", + "@vitest/utils": "^1.3.1", + "util": "^0.12.4" }, - "engines": { - "node": ">= 8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@storybook/manager-api": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.2.9.tgz", + "integrity": "sha512-mkYvUlfqDw+0WbxIynh5TcrotmoXlumEsOA4+45zuNea8XpEgj5cNBUCnmfEO6yQ85swqkS8YYbMpg1cZyu/Vw==", "dev": true, - "engines": { - "node": ">= 8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@storybook/preset-react-webpack": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.2.9.tgz", + "integrity": "sha512-uBLsUfwymWXGmfN/0vB7gLCC0CWDHc778605SWxakqFx7wGF1FZUW4R46qbDFrHTaKh+bundseRdy5/uklksLQ==", "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@storybook/core-webpack": "8.2.9", + "@storybook/react": "8.2.9", + "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", + "@types/node": "^18.0.0", + "@types/semver": "^7.3.4", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "magic-string": "^0.30.5", + "react-docgen": "^7.0.0", + "resolve": "^1.22.8", + "semver": "^7.3.7", + "tsconfig-paths": "^4.2.0", + "webpack": "5" }, "engines": { - "node": ">= 8" + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@open-draft/deferred-promise": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz", - "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", - "dev": true - }, - "node_modules/@open-draft/logger": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", - "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "node_modules/@storybook/preset-react-webpack/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, "dependencies": { - "is-node-process": "^1.2.0", - "outvariant": "^1.4.0" + "undici-types": "~5.26.4" } }, - "node_modules/@open-draft/until": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", - "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", - "dev": true - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@storybook/preset-react-webpack/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, - "optional": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=14" + "node": ">=14.14" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "node_modules/@storybook/preset-react-webpack/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "bin": { + "semver": "bin/semver.js" }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@remix-run/router": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", - "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", "engines": { - "node": ">=14.0.0" + "node": ">=10" } }, - "node_modules/@sentry-internal/browser-utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.25.0.tgz", - "integrity": "sha512-nlWgp1lVhNQOTUplW85G3qm0fOIgAhJ/sl/31OIuScVrITYhYDF2bO+Zv/jQ8YsdUBAUXqY1tPT9wwPJklnPhw==", + "node_modules/@storybook/preset-react-webpack/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, "dependencies": { - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">=14.18" + "node": ">=6" } }, - "node_modules/@sentry-internal/feedback": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.25.0.tgz", - "integrity": "sha512-327I5XJAFrsgjc5qUKxZ9rff3WNCfGvf1fIii70LQ2YQhQgG4XHZILmkD06ETEyXb+H1tkrNQQEJ1/d4ai+q5g==", - "dependencies": { - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "node_modules/@storybook/preset-react-webpack/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/preview-api": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.2.9.tgz", + "integrity": "sha512-D8/t+a78OJqQAcT/ABa1C4YM/OaLGQ9IvCsp3Q9ruUqDCwuZBj8bG3D4477dlY4owX2ycC0rWYu3VvuK0EmJjA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/react": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.2.9.tgz", + "integrity": "sha512-F2xZcTDxxjpbqt7eP8rEHmlksiKmE/qtPusEWEY4N4jK01kN+ncxSl8gkJpUohMEmAnVC5t/1v/sU57xv1DYpg==", + "dev": true, + "dependencies": { + "@storybook/components": "^8.2.9", + "@storybook/global": "^5.0.0", + "@storybook/manager-api": "^8.2.9", + "@storybook/preview-api": "^8.2.9", + "@storybook/react-dom-shim": "8.2.9", + "@storybook/theming": "^8.2.9", + "@types/escodegen": "^0.0.6", + "@types/estree": "^0.0.51", + "@types/node": "^18.0.0", + "acorn": "^7.4.1", + "acorn-jsx": "^5.3.1", + "acorn-walk": "^7.2.0", + "escodegen": "^2.1.0", + "html-tags": "^3.1.0", + "lodash": "^4.17.21", + "prop-types": "^15.7.2", + "react-element-to-jsx-string": "^15.0.0", + "semver": "^7.3.7", + "ts-dedent": "^2.0.0", + "type-fest": "~2.19", + "util-deprecate": "^1.0.2" }, "engines": { - "node": ">=14.18" + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@sentry-internal/replay": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.25.0.tgz", - "integrity": "sha512-3f7x8EYthyj157uV9V8vBjun+1gJnHhh2+i0qxYLhMGx7N2Fq0J3Bvvo1rosSg+fYh5HzPNZDufwIRdg5C/MQw==", + "node_modules/@storybook/react-docgen-typescript-plugin": { + "version": "1.0.6--canary.9.0c3f3b7.0", + "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", + "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", + "dev": true, "dependencies": { - "@sentry-internal/browser-utils": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "debug": "^4.1.1", + "endent": "^2.0.1", + "find-cache-dir": "^3.3.1", + "flat-cache": "^3.0.4", + "micromatch": "^4.0.2", + "react-docgen-typescript": "^2.2.2", + "tslib": "^2.0.0" }, - "engines": { - "node": ">=14.18" + "peerDependencies": { + "typescript": ">= 4.x", + "webpack": ">= 4" } }, - "node_modules/@sentry-internal/replay-canvas": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.25.0.tgz", - "integrity": "sha512-dPXlkAbkFL1DBum8rGTaHS+apJKaXEZJF9gLcBBKTruhTCizrugFLxajzIfVSiFVuwNKuJWa2fzhzbeQM0ee7w==", + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { - "@sentry-internal/replay": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" - }, - "engines": { - "node": ">=14.18" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@sentry/babel-plugin-component-annotate": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.0.tgz", - "integrity": "sha512-UzH+NNhgnOo6UFku3C4TEz+pO/yDcIA5FKTJvLbJ7lQwAjsqLs3DZWm4cCA08skICb8mULArF6S/dn5/butVCA==", + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, "engines": { - "node": ">= 14" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@sentry/browser": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.25.0.tgz", - "integrity": "sha512-51bdVGXjyooqVGzaSGsnExqRTt9NvZ1zGFsxbbCSXi5UoEFN6zdMUz6jKYsL2K80eeELP2VKOVlobHlEzeJQfw==", + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "dependencies": { - "@sentry-internal/browser-utils": "8.25.0", - "@sentry-internal/feedback": "8.25.0", - "@sentry-internal/replay": "8.25.0", - "@sentry-internal/replay-canvas": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" }, - "engines": { - "node": ">=14.18" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@sentry/bundler-plugin-core": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.0.tgz", - "integrity": "sha512-/xXN8o7565WMsewBnQFfjm0E5wqhYsegg++HJ5RjrY/cTM4qcd/ven44GEMxqGFJitZizvkk3NHszaHylzcRUw==", + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "@babel/core": "^7.18.5", - "@sentry/babel-plugin-component-annotate": "2.22.0", - "@sentry/cli": "^2.33.1", - "dotenv": "^16.3.1", - "find-up": "^5.0.0", - "glob": "^9.3.2", - "magic-string": "0.30.8", - "unplugin": "1.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 14" + "node": "*" } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" + "glob": "^7.1.3" }, - "engines": { - "node": ">=16 || 14 >=14.17" + "bin": { + "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "node_modules/@storybook/react-dom-shim": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.9.tgz", + "integrity": "sha512-uCAjSQEsNk8somVn1j/I1G9G/uUax5byHseIIV0Eq3gVXttGd7gaWcP+TDHtqIaenWHx4l+hCSuCesxiLWmx4Q==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/react-webpack5": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.2.9.tgz", + "integrity": "sha512-c5udaEIFFlBfOQJlPsJvrhyK02B3ltZ86SS0j5bhOa6UgqYOo+KtKaVyegXWgsRw8vVO9ZdmXCfwVvFsHkgJdA==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "@storybook/builder-webpack5": "8.2.9", + "@storybook/preset-react-webpack": "8.2.9", + "@storybook/react": "8.2.9", + "@types/node": "^18.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "node_modules/@storybook/react-webpack5/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "undici-types": "~5.26.4" } }, - "node_modules/@sentry/cli": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", - "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "node_modules/@storybook/react-webpack5/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/react/node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@storybook/react/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, - "hasInstallScript": true, "dependencies": { - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.7", - "progress": "^2.0.3", - "proxy-from-env": "^1.1.0", - "which": "^2.0.2" - }, + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/react/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, "bin": { - "sentry-cli": "bin/sentry-cli" + "acorn": "bin/acorn" }, "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@sentry/cli-darwin": "2.33.1", - "@sentry/cli-linux-arm": "2.33.1", - "@sentry/cli-linux-arm64": "2.33.1", - "@sentry/cli-linux-i686": "2.33.1", - "@sentry/cli-linux-x64": "2.33.1", - "@sentry/cli-win32-i686": "2.33.1", - "@sentry/cli-win32-x64": "2.33.1" + "node": ">=0.4.0" } }, - "node_modules/@sentry/cli-darwin": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", - "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "node_modules/@storybook/react/node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=10" + "node": ">=0.4.0" } }, - "node_modules/@sentry/cli-linux-arm": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", - "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", - "cpu": [ - "arm" - ], + "node_modules/@storybook/react/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], + "bin": { + "semver": "bin/semver.js" + }, "engines": { "node": ">=10" } }, - "node_modules/@sentry/cli-linux-arm64": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", - "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", - "cpu": [ - "arm64" - ], + "node_modules/@storybook/react/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], "engines": { - "node": ">=10" + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@sentry/cli-linux-i686": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", - "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", - "cpu": [ - "x86", - "ia32" - ], + "node_modules/@storybook/react/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/test": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.2.9.tgz", + "integrity": "sha512-O5JZ5S8UVVR7V0ru5AiF/uRO+srAVwji0Iik7ihy8gw3V91WQNMmJh2KkdhG0R1enYeBsYZlipOm+AW7f/MmOA==", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/instrumenter": "8.2.9", + "@testing-library/dom": "10.1.0", + "@testing-library/jest-dom": "6.4.5", + "@testing-library/user-event": "14.5.2", + "@vitest/expect": "1.6.0", + "@vitest/spy": "1.6.0", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/test/node_modules/@testing-library/dom": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", + "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@sentry/cli-linux-x64": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", - "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", - "cpu": [ - "x64" - ], + "node_modules/@storybook/test/node_modules/@testing-library/jest-dom": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz", + "integrity": "sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], + "dependencies": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, "engines": { - "node": ">=10" + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@jest/globals": ">= 28", + "@types/bun": "latest", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/bun": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } } }, - "node_modules/@sentry/cli-win32-i686": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", - "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", - "cpu": [ - "x86", - "ia32" - ], + "node_modules/@storybook/test/node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@sentry/cli-win32-x64": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", - "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", - "cpu": [ - "x64" - ], + "node_modules/@storybook/test/node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@storybook/test/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@sentry/core": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.25.0.tgz", - "integrity": "sha512-7KtglbrW1eX4DOHkf6i4rRIExEf2CgtQ99qZ8gn5FUaAmNMg0rK7bb1yZMx0RZtp5G1TSz/S0jQQgxHWebaEig==", + "node_modules/@storybook/test/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, "dependencies": { - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" - }, - "engines": { - "node": ">=14.18" + "dequal": "^2.0.3" } }, - "node_modules/@sentry/react": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.25.0.tgz", - "integrity": "sha512-A3QeSCJEa+lpo5nh0kxKeqsmnuW2nycKNN/0bpXPv5T5jiEfExSmEBVM0zutrQpf+J0WRIl1AGunUYGPO+GPQg==", + "node_modules/@storybook/test/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@sentry/browser": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0", - "hoist-non-react-statics": "^3.3.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=14.18" + "node": ">=10" }, - "peerDependencies": { - "react": "^16.14.0 || 17.x || 18.x || 19.x" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@sentry/types": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.25.0.tgz", - "integrity": "sha512-ojim0gDcRhGJPguYrtms4FsprX4xZz3LGNk9Z0hwTbSVEdlhQIInsQ7CYcdM3sjUs+qT7kfpxTRZGUeZNRRJcA==", + "node_modules/@storybook/test/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=14.18" + "node": ">=7.0.0" } }, - "node_modules/@sentry/utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.25.0.tgz", - "integrity": "sha512-mVlkV7S62ZZ2jM38/kOwWx2xoW8fUv2cjw2IwFKoAIPyLBh3mo1WJtvfdtN/rXGjQWZJBKW53EWaWnD00rkjyA==", - "dependencies": { - "@sentry/types": "8.25.0" - }, + "node_modules/@storybook/test/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@storybook/test/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=14.18" + "node": ">=8" } }, - "node_modules/@sentry/webpack-plugin": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.22.0.tgz", - "integrity": "sha512-u2brctki0AMCoZksdAConQSYE6PokRVeZ4YYsbnJYkAi0KuaQnczsRwS9e2L0bK2CmZ7QdyYcrjaXHNlXaFDbQ==", + "node_modules/@storybook/test/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "dependencies": { - "@sentry/bundler-plugin-core": "2.22.0", - "unplugin": "1.0.1", - "uuid": "^9.0.0" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" }, "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "webpack": ">=4.40.0" + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@sentry/webpack-plugin/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "node_modules/@storybook/test/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/@storybook/test/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/@storybook/test/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "node_modules/@storybook/theming": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.2.9.tgz", + "integrity": "sha512-OL0NFvowPX85N5zIYdgeKKaFm7V4Vgtci093vL3cDZT13LGH6GuEzJKkUFGuUGNPFlJc+EgTj0o6PYKrOLyQ6w==", "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@storybook/addon-webpack5-compiler-swc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", - "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", - "dependencies": { - "@swc/core": "^1.7.3", - "swc-loader": "^0.2.3" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" }, - "engines": { - "node": ">=18" + "peerDependencies": { + "storybook": "^8.2.9" } }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, "engines": { "node": ">=14" }, @@ -3904,6 +6184,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, "engines": { "node": ">=14" }, @@ -3919,6 +6200,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, "engines": { "node": ">=14" }, @@ -3934,6 +6216,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, "engines": { "node": ">=14" }, @@ -3949,6 +6232,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, "engines": { "node": ">=14" }, @@ -3964,6 +6248,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, "engines": { "node": ">=14" }, @@ -3979,6 +6264,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, "engines": { "node": ">=14" }, @@ -3994,6 +6280,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, "engines": { "node": ">=12" }, @@ -4009,6 +6296,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, "dependencies": { "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", @@ -4034,6 +6322,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4053,6 +6342,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, "dependencies": { "@babel/types": "^7.21.3", "entities": "^4.4.0" @@ -4069,6 +6359,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4090,6 +6381,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dev": true, "dependencies": { "cosmiconfig": "^8.1.3", "deepmerge": "^4.3.1", @@ -4110,6 +6402,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@babel/plugin-transform-react-constant-elements": "^7.21.3", @@ -4132,6 +6425,7 @@ "version": "1.7.14", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.14.tgz", "integrity": "sha512-9aeXeifnyuvc2pcuuhPQgVUwdpGEzZ+9nJu0W8/hNl/aESFsJGR5i9uQJRGu0atoNr01gK092fvmqMmQAPcKow==", + "dev": true, "hasInstallScript": true, "dependencies": { "@swc/counter": "^0.1.3", @@ -4172,6 +6466,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -4187,6 +6482,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -4202,6 +6498,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -4217,6 +6514,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -4232,6 +6530,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -4247,6 +6546,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -4262,6 +6562,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -4277,6 +6578,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -4292,6 +6594,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -4307,6 +6610,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -4318,12 +6622,14 @@ "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true }, "node_modules/@swc/types": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dev": true, "dependencies": { "@swc/counter": "^0.1.3" } @@ -4630,6 +6936,19 @@ } } }, + "node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -4643,6 +6962,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, "engines": { "node": ">=10.13.0" } @@ -4762,6 +7082,21 @@ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", "dev": true }, + "node_modules/@types/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/doctrine": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", + "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", + "dev": true + }, "node_modules/@types/dotenv-webpack": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/dotenv-webpack/-/dotenv-webpack-7.0.7.tgz", @@ -4773,6 +7108,18 @@ "webpack": "^5" } }, + "node_modules/@types/emscripten": { + "version": "1.39.13", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.13.tgz", + "integrity": "sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw==", + "dev": true + }, + "node_modules/@types/escodegen": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.6.tgz", + "integrity": "sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==", + "dev": true + }, "node_modules/@types/eslint": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", @@ -4832,6 +7179,15 @@ "@types/node": "*" } }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -4910,6 +7266,18 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", + "dev": true + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "dev": true + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -4994,12 +7362,24 @@ "@types/react": "*" } }, + "node_modules/@types/resolve": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", + "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", + "dev": true + }, "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -5079,6 +7459,18 @@ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "dev": true }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "node_modules/@types/wrap-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", @@ -5316,6 +7708,53 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", @@ -5518,6 +7957,44 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/@yarnpkg/fslib": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", + "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", + "dev": true, + "dependencies": { + "@yarnpkg/libzip": "^2.3.0", + "tslib": "^1.13.0" + }, + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" + } + }, + "node_modules/@yarnpkg/fslib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@yarnpkg/libzip": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", + "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", + "dev": true, + "dependencies": { + "@types/emscripten": "^1.39.6", + "tslib": "^1.13.0" + }, + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" + } + }, + "node_modules/@yarnpkg/libzip/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -5789,7 +8266,8 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/aria-query": { "version": "5.1.3", @@ -5983,6 +8461,27 @@ "node": ">=0.8" } }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -6067,6 +8566,15 @@ "deep-equal": "^2.0.5" } }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -6238,6 +8746,7 @@ "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.2", @@ -6251,6 +8760,7 @@ "version": "0.10.6", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2", "core-js-compat": "^3.38.0" @@ -6263,6 +8773,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2" }, @@ -6371,6 +8882,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -6444,7 +8966,8 @@ "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true }, "node_modules/brace-expansion": { "version": "2.0.1", @@ -6467,10 +8990,17 @@ "node": ">=8" } }, + "node_modules/browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, "node_modules/browserslist": { "version": "4.23.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "dev": true, "funding": [ { "type": "opencollective", @@ -6632,6 +9162,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "engines": { "node": ">=10" }, @@ -6643,6 +9174,7 @@ "version": "1.0.30001649", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001649.tgz", "integrity": "sha512-fJegqZZ0ZX8HOWr6rcafGr72+xcgJKI9oWfDW5DrD7ExUtgZC7a7R7ZYmZqplh7XDocFdGeIFn7roAxhOeYrPQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -6658,12 +9190,48 @@ } ] }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -6694,6 +9262,18 @@ "node": ">=10" } }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, "node_modules/check-more-types": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", @@ -6739,6 +9319,38 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chromatic": { + "version": "11.7.1", + "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.7.1.tgz", + "integrity": "sha512-LvgPimdQdnQB07ZDxLEC2KtxgYeqTw0X71GA7fi3zhgtKLxZcE+BSZ/5I9rrQp1V8ydmfElfw0ZwnUH4fVgUAQ==", + "dev": true, + "bin": { + "chroma": "dist/bin.js", + "chromatic": "dist/bin.js", + "chromatic-cli": "dist/bin.js" + }, + "peerDependencies": { + "@chromatic-com/cypress": "^0.*.* || ^1.0.0", + "@chromatic-com/playwright": "^0.*.* || ^1.0.0" + }, + "peerDependenciesMeta": { + "@chromatic-com/cypress": { + "optional": true + }, + "@chromatic-com/playwright": { + "optional": true + } + } + }, "node_modules/chrome-trace-event": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", @@ -6763,6 +9375,15 @@ "node": ">=8" } }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "dependencies": { + "consola": "^3.2.3" + } + }, "node_modules/cjs-module-lexer": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", @@ -6987,6 +9608,15 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -7066,6 +9696,18 @@ "node": ">=4.0.0" } }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/compare-versions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", + "dev": true + }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -7123,6 +9765,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true + }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", @@ -7132,6 +9780,21 @@ "node": ">=0.8" } }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -7185,6 +9848,7 @@ "version": "3.38.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz", "integrity": "sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==", + "dev": true, "dependencies": { "browserslist": "^4.23.3" }, @@ -7203,6 +9867,7 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -7335,6 +10000,80 @@ "node": ">= 8" } }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/css-select": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", @@ -7355,6 +10094,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -7367,6 +10107,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, "engines": { "node": ">= 6" }, @@ -7380,15 +10121,29 @@ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", "dev": true }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/cssfontparser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/cssfontparser/-/cssfontparser-1.2.1.tgz", - "integrity": "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==" + "integrity": "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==", + "dev": true }, "node_modules/csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, "dependencies": { "css-tree": "~2.2.0" }, @@ -7401,6 +10156,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" @@ -7413,7 +10169,8 @@ "node_modules/csso/node_modules/mdn-data": { "version": "2.0.28", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true }, "node_modules/cssom": { "version": "0.5.0", @@ -7833,6 +10590,18 @@ } } }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-equal": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", @@ -7875,6 +10644,7 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -7919,6 +10689,18 @@ "node": ">= 10" } }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -7965,6 +10747,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -8002,6 +10790,15 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -8113,6 +10910,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, "funding": [ { "type": "github", @@ -8175,6 +10973,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -8265,7 +11064,8 @@ "node_modules/electron-to-chromium": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", - "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==" + "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==", + "dev": true }, "node_modules/emittery": { "version": "0.13.1", @@ -8312,6 +11112,23 @@ "once": "^1.4.0" } }, + "node_modules/endent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", + "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", + "dev": true, + "dependencies": { + "dedent": "^0.7.0", + "fast-json-parse": "^1.0.3", + "objectorarray": "^1.0.5" + } + }, + "node_modules/endent/node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, "node_modules/enhanced-resolve": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", @@ -8342,6 +11159,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, "engines": { "node": ">=0.12" }, @@ -8553,10 +11371,61 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/esbuild-register": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz", + "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "peerDependencies": { + "esbuild": ">=0.12 <1" + } + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, "engines": { "node": ">=6" } @@ -9165,10 +12034,20 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -9410,6 +12289,12 @@ "node": ">= 6" } }, + "node_modules/fast-json-parse": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", + "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", + "dev": true + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -9467,6 +12352,15 @@ "bser": "2.1.1" } }, + "node_modules/fd-package-json": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-1.2.0.tgz", + "integrity": "sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==", + "dev": true, + "dependencies": { + "walk-up-path": "^3.0.1" + } + }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -9506,10 +12400,30 @@ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^4.0.0" + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, "node_modules/filelist": { @@ -9533,6 +12447,15 @@ "node": ">=10" } }, + "node_modules/filesize": { + "version": "10.1.6", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz", + "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==", + "dev": true, + "engines": { + "node": ">= 10.4.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -9578,6 +12501,38 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", @@ -9627,6 +12582,15 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/flow-parser": { + "version": "0.245.2", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.245.2.tgz", + "integrity": "sha512-FU4yuqC1j2IeWWicpzG0YJrXHJgKjK/AU8QKK/7MvQaNhcoGisDoE7FJLGCtbvnifzsgDWdm9/jtTF7Mp+PJXQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", @@ -9871,6 +12835,36 @@ "node": ">=12" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/fs-monkey": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", @@ -9936,6 +12930,7 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -9949,6 +12944,15 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -10036,6 +13040,31 @@ "assert-plus": "^1.0.0" } }, + "node_modules/giget": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", + "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.3", + "nypm": "^0.3.8", + "ohash": "^1.1.3", + "pathe": "^1.1.2", + "tar": "^6.2.0" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -10170,24 +13199,6 @@ "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, - "node_modules/haengdong-design": { - "version": "0.1.81", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.81.tgz", - "integrity": "sha512-IiXkt0zXSEmn7vstTLOeNZLFS35JO8lXbXavM55wdyAJd+w0e5kfRxyDk/K2oSiAnX2c2YPiGep/A0x2/gZPDg==", - "dependencies": { - "@emotion/react": "^11.11.4", - "@storybook/addon-webpack5-compiler-swc": "^1.0.5", - "@svgr/webpack": "^8.1.0", - "lottie-react": "^2.4.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-router-dom": "^6.24.1" - }, - "engines": { - "node": ">=20.15.1", - "npm": ">=10.7.0" - } - }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -10273,6 +13284,45 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-heading-rank": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", + "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", + "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -10419,6 +13469,18 @@ "node": "^14.13.1 || >=16.0.0" } }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/html-webpack-plugin": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", @@ -10657,6 +13719,18 @@ "node": ">=0.10.0" } }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -10796,6 +13870,18 @@ "node": ">= 10" } }, + "node_modules/is-absolute-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", + "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -11071,6 +14157,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -11652,6 +14747,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-2.5.2.tgz", "integrity": "sha512-vgnpPupjOL6+L5oJXzxTxFrlGEIbHdZqFU+LFNdtLxZ3lRDCl17FlTMM7IatoRQkrcyOTMlDinjUguqmQ6bR2A==", + "dev": true, "dependencies": { "cssfontparser": "^1.2.1", "moo-color": "^1.0.2" @@ -13288,6 +16384,12 @@ "node": ">=8" } }, + "node_modules/jest-transform-stub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-transform-stub/-/jest-transform-stub-2.0.0.tgz", + "integrity": "sha512-lspHaCRx/mBbnm3h4uMMS3R5aZzMwyNpNIJLXj4cEsV0mIUtS4IjYJLSoyjRCtnxb6RIGJ4NL2quZzfIeNhbkg==", + "dev": true + }, "node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -13565,7 +16667,142 @@ "node": ">= 10.13.0" } }, - "node_modules/jest-worker/node_modules/has-flag": { + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jscodeshift": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", + "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/preset-flow": "^7.22.15", + "@babel/preset-typescript": "^7.23.0", + "@babel/register": "^7.22.15", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.23.3", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jscodeshift/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jscodeshift/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jscodeshift/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jscodeshift/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jscodeshift/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -13574,43 +16811,29 @@ "node": ">=8" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/jscodeshift/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/jscodeshift/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, "node_modules/jsdom": { "version": "24.1.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.1.tgz", @@ -13774,6 +16997,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -14020,6 +17244,20 @@ "node": ">=6.11.5" } }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, "node_modules/loader-utils-webpack-v4": { "name": "loader-utils", "version": "2.0.4", @@ -14059,7 +17297,8 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -14295,10 +17534,20 @@ "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -14307,6 +17556,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "dependencies": { "yallist": "^3.0.2" } @@ -14374,10 +17624,29 @@ "tmpl": "1.0.5" } }, + "node_modules/map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "dev": true + }, + "node_modules/markdown-to-jsx": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.5.0.tgz", + "integrity": "sha512-RrBNcMHiFPcz/iqIj0n3wclzHXjwS7mzjBNWecKKVhNTIxQepIix6Il/wZCn2Cg5Y1ow2Qi84+eJrryFRWBEWw==", + "dev": true, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true }, "node_modules/media-typer": { "version": "0.3.0", @@ -14400,6 +17669,15 @@ "node": ">= 4.0.0" } }, + "node_modules/memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "dev": true, + "dependencies": { + "map-or-similar": "^1.5.0" + } + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -14533,6 +17811,61 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mlly": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", + "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + } + }, "node_modules/modify-source-webpack-plugin": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/modify-source-webpack-plugin/-/modify-source-webpack-plugin-4.1.0.tgz", @@ -14603,6 +17936,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/moo-color/-/moo-color-1.0.3.tgz", "integrity": "sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ==", + "dev": true, "dependencies": { "color-name": "^1.1.4" } @@ -14610,7 +17944,8 @@ "node_modules/moo-color/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/ms": { "version": "2.1.2", @@ -14758,6 +18093,24 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -14783,6 +18136,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" @@ -14794,6 +18148,40 @@ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", "dev": true }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-dir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/node-dir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -14814,6 +18202,12 @@ } } }, + "node_modules/node-fetch-native": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", + "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", + "dev": true + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -14832,7 +18226,8 @@ "node_modules/node-releases": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true }, "node_modules/normalize-path": { "version": "3.0.0", @@ -14852,26 +18247,181 @@ "path-key": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "dev": true + }, + "node_modules/nypm": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.11.tgz", + "integrity": "sha512-E5GqaAYSnbb6n1qZyik2wjPDZON43FqOJO59+3OkWrnmQtjggrMOVnsyzfjxp/tS6nlYJBA4zRA5jSM2YaadMg==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "pkg-types": "^1.2.0", + "ufo": "^1.5.4" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/nypm/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/nypm/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/nypm/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" + "node_modules/nypm/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nwsapi": { - "version": "2.2.12", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", - "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", - "dev": true - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -14998,12 +18548,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/objectorarray": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", + "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", + "dev": true + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, + "node_modules/ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "dev": true + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -15084,6 +18646,99 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ospath": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", @@ -15242,6 +18897,12 @@ "tslib": "^2.0.3" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -15310,6 +18971,21 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -15421,6 +19097,29 @@ "node": ">=8" } }, + "node_modules/pkg-types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.0.tgz", + "integrity": "sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==", + "dev": true, + "dependencies": { + "confbox": "^0.1.7", + "mlly": "^1.7.1", + "pathe": "^1.1.2" + } + }, + "node_modules/polished": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -15430,6 +19129,112 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.4.45", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz", + "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -15695,51 +19500,133 @@ "node": ">= 0.6" } }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "dev": true, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-confetti": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", + "integrity": "sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==", + "dev": true, + "dependencies": { + "tween-functions": "^1.2.0" + }, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.1 || ^18.0.0" + } + }, + "node_modules/react-copy-to-clipboard": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", + "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "dependencies": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.3.0 || 16 || 17 || 18" + } + }, + "node_modules/react-docgen": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-7.0.3.tgz", + "integrity": "sha512-i8aF1nyKInZnANZ4uZrH49qn1paRgBZ7wZiCNBMnenlPzEv0mRl+ShpTVEI6wZNl8sSc79xZkivtgLKQArcanQ==", "dev": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "@babel/core": "^7.18.9", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9", + "@types/babel__core": "^7.18.0", + "@types/babel__traverse": "^7.18.0", + "@types/doctrine": "^0.0.9", + "@types/resolve": "^1.20.2", + "doctrine": "^3.0.0", + "resolve": "^1.22.1", + "strip-indent": "^4.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=16.14.0" } }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/react-docgen-typescript": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", + "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", "dev": true, - "engines": { - "node": ">= 0.8" + "peerDependencies": { + "typescript": ">= 4.3.x" } }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "node_modules/react-docgen/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "dependencies": { - "loose-envify": "^1.1.0" + "esutils": "^2.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/react-copy-to-clipboard": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", - "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "node_modules/react-docgen/node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, "dependencies": { - "copy-to-clipboard": "^3.3.1", - "prop-types": "^15.8.1" + "min-indent": "^1.0.1" }, - "peerDependencies": { - "react": "^15.3.0 || 16 || 17 || 18" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/react-dom": { @@ -15754,6 +19641,36 @@ "react": "^18.3.1" } }, + "node_modules/react-element-to-jsx-string": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz", + "integrity": "sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==", + "dev": true, + "dependencies": { + "@base2/pretty-print-object": "1.0.1", + "is-plain-object": "5.0.0", + "react-is": "18.1.0" + }, + "peerDependencies": { + "react": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0", + "react-dom": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/react-is": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", + "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "dev": true + }, "node_modules/react-error-boundary": { "version": "4.0.13", "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz", @@ -15765,6 +19682,15 @@ "react": ">=16.13.1" } }, + "node_modules/react-inspector": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.2.tgz", + "integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==", + "dev": true, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -15826,6 +19752,31 @@ "node": ">=8.10.0" } }, + "node_modules/recast": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", + "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", + "dev": true, + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -15875,12 +19826,14 @@ "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true }, "node_modules/regenerate-unicode-properties": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, "dependencies": { "regenerate": "^1.4.2" }, @@ -15897,6 +19850,7 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -15923,6 +19877,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, "dependencies": { "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", @@ -15939,6 +19894,7 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, "dependencies": { "jsesc": "~0.5.0" }, @@ -15950,10 +19906,46 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, "bin": { "jsesc": "bin/jsesc" } }, + "node_modules/rehype-external-links": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rehype-external-links/-/rehype-external-links-3.0.0.tgz", + "integrity": "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-is-element": "^3.0.0", + "is-absolute-url": "^4.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-slug": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz", + "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "github-slugger": "^2.0.0", + "hast-util-heading-rank": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -16297,6 +20289,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -16618,6 +20611,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -16646,6 +20640,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -16669,6 +20664,16 @@ "node": ">=0.10.0" } }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", @@ -16760,16 +20765,241 @@ "node": ">= 0.8" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/storybook": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.2.9.tgz", + "integrity": "sha512-S7Q/Yt4A+nu1O23rg39lQvBqL2Vg+PKXbserDWUR4LFJtfmoZ2xGO8oFIhJmvvhjUBvolw1q7QDeswPq2i0sGw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/codemod": "8.2.9", + "@storybook/core": "8.2.9", + "@types/semver": "^7.3.4", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", + "chalk": "^4.1.0", + "commander": "^6.2.1", + "cross-spawn": "^7.0.3", + "detect-indent": "^6.1.0", + "envinfo": "^7.7.3", + "execa": "^5.0.0", + "fd-package-json": "^1.2.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "giget": "^1.0.0", + "globby": "^14.0.1", + "jscodeshift": "^0.15.1", + "leven": "^3.1.0", + "ora": "^5.4.1", + "prettier": "^3.1.1", + "prompts": "^2.4.0", + "semver": "^7.3.7", + "strip-json-comments": "^3.0.1", + "tempy": "^3.1.0", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0" + }, + "bin": { + "getstorybook": "bin/index.cjs", + "sb": "bin/index.cjs", + "storybook": "bin/index.cjs" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/storybook-addon-react-router-v6": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/storybook-addon-react-router-v6/-/storybook-addon-react-router-v6-2.0.15.tgz", + "integrity": "sha512-4vOYIQwehlQLyXaCT9K0Iu0po2Z+pANGsqkfm/BQuAEjE9MoN7vrsrQLHINhKbmQVtNMmuS/oBR3GGNbqQ1gew==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "compare-versions": "^6.0.0", + "react-inspector": "6.0.2" + }, + "peerDependencies": { + "@storybook/blocks": "^7.0.0", + "@storybook/channels": "^7.0.0", + "@storybook/components": "^7.0.0", + "@storybook/core-events": "^7.0.0", + "@storybook/manager-api": "^7.0.0", + "@storybook/preview-api": "^7.0.0", + "@storybook/theming": "^7.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-router-dom": "^6.4.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/storybook/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/storybook/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/storybook/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/storybook/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/storybook/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/storybook/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/storybook/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/storybook/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/storybook/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "internal-slot": "^1.0.4" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, "node_modules/strict-event-emitter": { @@ -17027,6 +21257,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -17057,12 +21303,14 @@ "node_modules/svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true }, "node_modules/svgo": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -17087,6 +21335,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, "engines": { "node": ">= 10" } @@ -17095,6 +21344,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", @@ -17110,6 +21360,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -17123,6 +21374,7 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, "dependencies": { "domelementtype": "^2.3.0" }, @@ -17137,6 +21389,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -17150,6 +21403,7 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "dev": true, "dependencies": { "@swc/counter": "^0.1.3" }, @@ -17189,6 +21443,166 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/telejson": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", + "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + } + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dev": true, + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/temp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/temp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/temp/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tempy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", + "dev": true, + "dependencies": { + "is-stream": "^3.0.0", + "temp-dir": "^3.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/terser": { "version": "5.31.3", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", @@ -17343,6 +21757,21 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -17450,6 +21879,15 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "engines": { + "node": ">=6.10" + } + }, "node_modules/ts-jest": { "version": "29.2.4", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", @@ -17691,7 +22129,8 @@ "node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -17705,6 +22144,12 @@ "node": "*" } }, + "node_modules/tween-functions": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", + "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==", + "dev": true + }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -17869,6 +22314,12 @@ } } }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -17906,6 +22357,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, "engines": { "node": ">=4" } @@ -17914,6 +22366,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -17926,6 +22379,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, "engines": { "node": ">=4" } @@ -17934,10 +22388,80 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, "engines": { "node": ">=4" } }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -17981,6 +22505,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -18015,6 +22540,19 @@ "punycode": "^2.1.0" } }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -18025,6 +22563,27 @@ "requires-port": "^1.0.0" } }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/url/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/use-sync-external-store": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", @@ -18033,6 +22592,19 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -18130,6 +22702,12 @@ "node": ">=18" } }, + "node_modules/walk-up-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", + "dev": true + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -18161,6 +22739,15 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -18486,6 +23073,17 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/webpack-hot-middleware": { + "version": "2.26.1", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", + "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", + "dev": true, + "dependencies": { + "ansi-html-community": "0.0.8", + "html-entities": "^2.1.0", + "strip-ansi": "^6.0.0" + } + }, "node_modules/webpack-merge": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", @@ -18906,7 +23504,8 @@ "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yaml": { "version": "1.10.2", diff --git a/client/package.json b/client/package.json index 6d673dd06..8c308b08b 100644 --- a/client/package.json +++ b/client/package.json @@ -8,6 +8,8 @@ "dev": "NODE_ENV=development webpack server --open --config webpack.dev.mjs", "build": "NODE_ENV=production webpack --config webpack.prod.mjs", "build-dev": "NODE_ENV=development webpack --config webpack.dev.mjs", + "build-storybook": "storybook build", + "storybook": "storybook dev -p 6006", "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", "cypress-open": "cypress open", @@ -18,10 +20,20 @@ "author": "", "license": "ISC", "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", "@jest/types": "^29.6.3", "@sentry/webpack-plugin": "^2.22.0", + "@storybook/addon-essentials": "^8.2.2", + "@storybook/addon-interactions": "^8.2.2", + "@storybook/addon-links": "^8.2.2", + "@storybook/addon-onboarding": "^8.2.2", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@storybook/blocks": "^8.2.2", + "@storybook/react": "^8.2.2", + "@storybook/react-webpack5": "^8.2.3", + "@storybook/test": "^8.2.2", "@svgr/webpack": "^8.1.0", "@tanstack/react-query-devtools": "^5.52.0", "@testing-library/dom": "^10.4.0", @@ -44,16 +56,21 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^4.6.2", + "file-loader": "^6.2.0", "fork-ts-checker-webpack-plugin": "^9.0.2", "globals": "^15.8.0", "html-loader": "^5.0.0", "html-webpack-plugin": "^5.6.0", "jest": "^29.7.0", + "jest-canvas-mock": "^2.5.2", "jest-environment-jsdom": "^29.7.0", + "jest-transform-stub": "^2.0.0", "jsdom": "^24.1.1", "modify-source-webpack-plugin": "^4.1.0", "msw": "^2.3.5", "prettier": "3.3.2", + "storybook": "^8.2.2", + "storybook-addon-react-router-v6": "^2.0.15", "ts-jest": "^29.2.4", "ts-loader": "^9.5.1", "ts-node": "^10.9.2", @@ -69,8 +86,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.81", - "jest-canvas-mock": "^2.5.2", + "lottie-react": "^2.4.0", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/App.tsx b/client/src/App.tsx index 4e9ce39e1..33ea71b6c 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,29 +1,35 @@ import {Outlet} from 'react-router-dom'; -import {HDesignProvider} from 'haengdong-design'; import {Global} from '@emotion/react'; import {ReactQueryDevtools} from '@tanstack/react-query-devtools'; -import {ToastProvider} from '@hooks/useToast/ToastProvider'; import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; import ErrorCatcher from '@components/AppErrorBoundary/ErrorCatcher'; +import ToastContainer from '@components/Toast/ToastContainer'; +import KakaoInitializer from '@components/KakaoInitializer/KakaoInitializer'; + +import {HDesignProvider} from '@HDesign/index'; + +import NetworkStateCatcher from '@utils/NetworkStateCatcher'; import {GlobalStyle} from './GlobalStyle'; -import UnhandledErrorBoundary from './UnhandledErrorBoundary'; +import UnPredictableErrorBoundary from './UnPredictableErrorBoundary'; const App: React.FC = () => { return ( - + - - - - + + + + + + - - - - + + + + ); }; diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts index ab16de8e1..b25bb94d1 100644 --- a/client/src/GlobalStyle.ts +++ b/client/src/GlobalStyle.ts @@ -2,159 +2,147 @@ import {css} from '@emotion/react'; // reset css -> index css export const GlobalStyle = css` - html, - body, - div, - span, - applet, - object, - iframe, - h1, - h2, - h3, - h4, - h5, - h6, - p, - blockquote, - pre, + @import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css'); + + *:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) { + all: unset; + display: revert; + } + + /* Preferred box-sizing value */ + *, + *::before, + *::after { + box-sizing: border-box; + } + + /* Fix mobile Safari increase font-size on landscape mode */ + html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; + } + + /* Reapply the pointer cursor for anchor tags */ a, - abbr, - acronym, - address, - big, - cite, - code, - del, - dfn, - em, - img, - ins, - kbd, - q, - s, - samp, - small, - strike, - strong, - sub, - sup, - tt, - b, - u, - i, - center, - dl, - dt, - dd, - ol, - ul, - li, - fieldset, - form, - label, - legend, - table, - caption, - tbody, - tfoot, - thead, - tr, - th, - td, - article, - aside, - canvas, - details, - embed, - figure, - figcaption, - footer, - header, - hgroup, - menu, - nav, - output, - ruby, - section, - summary, - time, - mark, - audio, - video { - vertical-align: baseline; - margin: 0; - border: 0; - padding: 0; - font-size: 100%; - font: inherit; - } - /* HTML5 display-role reset for older browsers */ - article, - aside, - details, - figcaption, - figure, - footer, - header, - hgroup, - menu, - nav, - section { - display: block; + button { + cursor: revert; + line-height: 0; } - body { - line-height: 1; + + button:disabled { + cursor: default; } + + /* Remove list styles (bullets/numbers) */ ol, - ul { + ul, + menu, + summary { list-style: none; } - blockquote, - q { - quotes: none; - } - blockquote:before, - blockquote:after, - q:before, - q:after { - content: ''; - content: none; - } + + /* Removes spacing between cells in tables */ table { border-collapse: collapse; - border-spacing: 0; } - button { - cursor: pointer; - border: none; - background-color: transparent; + + /* Safari - solving issue when using user-select:none on the text input doesn't working */ + input, + textarea { + -webkit-user-select: auto; } - * { + + /* Revert the 'white-space' property for textarea elements on Safari */ + textarea { + white-space: revert; + } + + /* Minimum style to allow to style meter element */ + meter { + -webkit-appearance: revert; + appearance: revert; + } + + /* Preformatted text - use only for this feature */ + :where(pre) { + all: revert; box-sizing: border-box; } - html { - height: 100%; + /* Fix the feature of 'hidden' attribute. + display: revert; revert to element instead of attribute */ + :where([hidden]) { + display: none; } - body { - max-width: 768px; - height: 100%; - margin: 0 auto; + /* Revert for bug in Chromium browsers + - Fix for the content editable attribute will work properly. + - webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element */ + :where([contenteditable]:not([contenteditable='false'])) { + -moz-user-modify: read-write; + -webkit-user-modify: read-write; + overflow-wrap: break-word; + -webkit-line-break: after-white-space; + -webkit-user-select: auto; + } + + /* Apply back the draggable feature - exist only in Chromium and Safari */ + :where([draggable='true']) { + -webkit-user-drag: element; + } + + /* Revert Modal native behavior */ + :where(dialog:modal) { + all: revert; + box-sizing: border-box; + } + + /* Remove details summary webkit styles */ + ::-webkit-details-marker { + display: none; + } - overflow-y: scroll; - &::-webkit-scrollbar { - display: none; - } + /* Chrome, Safari, Edge, Opera */ + input::-webkit-outer-spin-button, + input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; } - section { - width: 100%; + /* Firefox */ + input[type='number'] { + -moz-appearance: textfield; } #root { display: flex; - flex-direction: column; + justify-content: center; + } + + button { + cursor: pointer; + } + + body { + font-family: + 'Pretendard', + -apple-system, + BlinkMacSystemFont, + system-ui, + Roboto, + 'Helvetica Neue', + 'Segoe UI', + 'Apple SD Gothic Neo', + 'Noto Sans KR', + 'Malgun Gothic', + 'Apple Color Emoji', + 'Segoe UI Emoji', + 'Segoe UI Symbol', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + max-width: 768px; + margin: 0 auto; } `; diff --git a/client/src/UnPredictableErrorBoundary.tsx b/client/src/UnPredictableErrorBoundary.tsx new file mode 100644 index 000000000..7dce07a58 --- /dev/null +++ b/client/src/UnPredictableErrorBoundary.tsx @@ -0,0 +1,10 @@ +import {ErrorBoundary} from 'react-error-boundary'; + +import {StrictPropsWithChildren} from '@type/strictPropsWithChildren'; +import ErrorPage from '@pages/ErrorPage/ErrorPage'; + +const UnPredictableErrorBoundary = ({children}: StrictPropsWithChildren) => { + return }>{children}; +}; + +export default UnPredictableErrorBoundary; diff --git a/client/src/UnhandledErrorBoundary.tsx b/client/src/UnhandledErrorBoundary.tsx deleted file mode 100644 index 78d017344..000000000 --- a/client/src/UnhandledErrorBoundary.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import {StrictPropsWithChildren} from 'haengdong-design/dist/type/strictPropsWithChildren'; -import {ErrorBoundary} from 'react-error-boundary'; - -import ErrorPage from '@pages/ErrorPage/ErrorPage'; - -const UnhandledErrorBoundary = ({children}: StrictPropsWithChildren) => { - return }>{children}; -}; - -export default UnhandledErrorBoundary; diff --git a/client/src/apis/tempPrefix.ts b/client/src/apis/endpointPrefix.ts similarity index 63% rename from client/src/apis/tempPrefix.ts rename to client/src/apis/endpointPrefix.ts index 949981b73..18b5756cf 100644 --- a/client/src/apis/tempPrefix.ts +++ b/client/src/apis/endpointPrefix.ts @@ -1,2 +1,3 @@ // TODO: (@weadie) 반복되서 쓰이는 이 api/events가 추후 수정 가능성이 있어서 일단 편집하기 편하게 이 변수를 재사용하도록 했습니다. -export const TEMP_PREFIX = '/api/events'; +export const USER_API_PREFIX = '/api/events'; +export const ADMIN_API_PREFIX = '/api/admin/events'; diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index 2e1c2d067..a1c205739 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -1,120 +1,165 @@ -import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; +import {RequestGetError, WithErrorHandlingStrategy} from '@errors/RequestGetError'; import objectToQueryString from '@utils/objectToQueryString'; -import {UNKNOWN_ERROR} from '@constants/errorMessage'; - -import FetchError from '../errors/FetchError'; +import RequestError from '../errors/RequestError'; export type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; -type Body = ReadableStream | XMLHttpRequestBodyInit; +export type ObjectQueryParams = Record; + +type ErrorInfo = { + errorCode: string; + message: string; +}; + +/** + * fetch의 2번째 인자로 들어가는 데이터의 타입은 RequestInit으로 기본적으로 제공됩니다. + * 다만 이 RequestInit의 타입이 method가 optional이라서 이를 반드시 받도록하기 위해 RequestInitWithMethod라는 타입으로 확장하게 되었습니다. + */ +type RequestInitWithMethod = Omit & {method: Method}; + type HeadersType = [string, string][] | Record | Headers; -export type ObjectQueryParams = Record; +export type Body = BodyInit | object | null; type RequestProps = { baseUrl?: string; endpoint: string; headers?: HeadersType; - body?: Body | object | null; + body?: Body; queryParams?: ObjectQueryParams; -}; - -type FetcherProps = RequestProps & { method: Method; }; -type Options = { - method: Method; - headers: HeadersType; - body?: Body | null; -}; +type RequestMethodProps = Omit; -type ErrorHandlerProps = { +type FetchType = { url: string; - options: Options; - body: string; + requestInit: RequestInitWithMethod; }; const API_BASE_URL = process.env.API_BASE_URL ?? ''; -export const requestGet = async ({headers = {}, ...args}: RequestProps): Promise => { - const response = await fetcher({ +export const requestGet = async ({ + headers = {}, + errorHandlingStrategy, + ...args +}: WithErrorHandlingStrategy): Promise => { + const response = await request({ ...args, method: 'GET', headers, + errorHandlingStrategy, }); const data: T = await response!.json(); return data; }; -export const requestPatch = ({headers = {}, ...args}: RequestProps) => { - return fetcher({method: 'PATCH', headers, ...args}); +export const requestPatch = ({headers = {}, ...args}: RequestMethodProps) => { + return request({method: 'PATCH', headers, ...args}); }; -export const requestPut = ({headers = {}, ...args}: RequestProps) => { - return fetcher({method: 'PUT', headers, ...args}); +export const requestPut = ({headers = {}, ...args}: RequestMethodProps) => { + return request({method: 'PUT', headers, ...args}); }; -export const requestPostWithoutResponse = async ({headers = {}, ...args}: RequestProps) => { - await fetcher({method: 'POST', headers, ...args}); +export const requestPostWithoutResponse = async ({headers = {}, ...args}: RequestMethodProps) => { + await request({method: 'POST', headers, ...args}); }; -export const requestPostWithResponse = async ({headers = {}, ...args}: RequestProps): Promise => { - const response = await fetcher({method: 'POST', headers, ...args}); +export const requestPostWithResponse = async ({headers = {}, ...args}: RequestMethodProps): Promise => { + const response = await request({method: 'POST', headers, ...args}); const data: T = await response!.json(); return data; }; -export const requestDelete = ({headers = {}, ...args}: RequestProps) => { - return fetcher({method: 'DELETE', headers, ...args}); +export const requestDelete = ({headers = {}, ...args}: RequestMethodProps) => { + return request({method: 'DELETE', headers, ...args}); }; -const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, queryParams}: FetcherProps) => { - const options = { - method, +const prepareRequest = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, queryParams}: RequestProps) => { + let url = `${baseUrl}${endpoint}`; + + if (queryParams) url += `?${objectToQueryString(queryParams)}`; + + const requestInit: RequestInitWithMethod = { credentials: 'include', headers: { 'Content-Type': 'application/json', ...headers, }, + method, body: body ? JSON.stringify(body) : null, }; - let url = `${baseUrl}${endpoint}`; - - if (queryParams) url += `?${objectToQueryString(queryParams)}`; - - return errorHandler({url, options, body: JSON.stringify(body)}); + return {url, requestInit}; }; -const errorHandler = async ({url, options, body}: ErrorHandlerProps) => { +const executeRequest = async ({url, requestInit, errorHandlingStrategy}: WithErrorHandlingStrategy) => { try { - const response: Response = await fetch(url, options); + const response: Response = await fetch(url, requestInit); if (!response.ok) { - const serverErrorInfo: ErrorInfo = await response.json(); - - throw new FetchError({ - status: response.status, - requestBody: body, - endpoint: response.url, - errorInfo: serverErrorInfo, - name: serverErrorInfo.errorCode, - message: serverErrorInfo.message || '', - method: options.method, + throw await createError({ + response, + body: requestInit.body ? JSON.stringify(requestInit.body) : null, + requestInit, + errorHandlingStrategy, }); } return response; } catch (error) { if (error instanceof Error) { - throw error; // 그대로 FetchError || Error 인스턴스를 던집니다. + throw error; // 그대로 RequestError 또는 Error 인스턴스를 던집니다. } - throw new Error(UNKNOWN_ERROR); + throw error; } }; + +const request = async (props: WithErrorHandlingStrategy) => { + const {url, requestInit} = prepareRequest(props); + return executeRequest({url, requestInit, errorHandlingStrategy: props.errorHandlingStrategy}); +}; + +type CreateError = { + response: Response; + body: Body; + requestInit: RequestInitWithMethod; +}; + +const createError = async ({ + response, + body, + requestInit, + errorHandlingStrategy, +}: WithErrorHandlingStrategy) => { + const {errorCode, message}: ErrorInfo = await response.json(); + + if (requestInit.method === 'GET') { + return new RequestGetError({ + status: response.status, + requestBody: body, + endpoint: response.url, + name: errorCode, + method: requestInit.method, + errorHandlingStrategy, + message, + errorCode, + }); + } + + return new RequestError({ + status: response.status, + requestBody: body, + endpoint: response.url, + name: errorCode, + method: requestInit.method, + message, + errorCode, + }); +}; diff --git a/client/src/apis/request/auth.ts b/client/src/apis/request/auth.ts index 9c56d1f6b..aac5c622d 100644 --- a/client/src/apis/request/auth.ts +++ b/client/src/apis/request/auth.ts @@ -1,23 +1,23 @@ import {BASE_URL} from '@apis/baseUrl'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestPostWithoutResponse} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; - -export type RequestToken = { - password: string; -}; +import {WithEventId} from '@apis/withId.type'; export const requestPostAuthentication = async ({eventId}: WithEventId) => { await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/auth`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/auth`, }); }; -export const requestPostToken = async ({eventId, password}: WithEventId) => { +export interface RequestPostToken { + password: string; +} + +export const requestPostToken = async ({eventId, password}: WithEventId) => { await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/login`, + endpoint: `${USER_API_PREFIX}/${eventId}/login`, body: { password: password, }, diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index c08168520..f78a7e6b8 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -1,69 +1,80 @@ -import type {Bill, MemberReportInAction} from 'types/serviceType'; +import type {BillDetails} from 'types/serviceType'; + +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import {BASE_URL} from '@apis/baseUrl'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestDelete, requestGet, requestPostWithoutResponse, requestPut} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; +import {WithBillId, WithEventId} from '@apis/withId.type'; -type RequestPostBillList = { - billList: Bill[]; -}; +export interface RequestPostBill { + title: string; + price: number; + memberIds: number[]; +} -export const requestPostBillList = async ({eventId, billList}: WithEventId) => { +export const requestPostBill = async ({eventId, title, price, memberIds}: WithEventId) => { await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills`, body: { - actions: billList, + title, + price, + memberIds, }, }); }; -type RequestBillAction = { - actionId: number; -}; - -export const requestDeleteBillAction = async ({eventId, actionId}: WithEventId) => { +export const requestDeleteBill = async ({eventId, billId}: WithEventId) => { await requestDelete({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills/${billId}`, }); }; -type RequestPutBillAction = Bill & RequestBillAction; +export interface RequestPutBill { + title: string; + price: number; +} -export const requestPutBillAction = async ({eventId, actionId, title, price}: WithEventId) => { +export const requestPutBill = async ({eventId, billId, title, price}: WithEventId>) => { await requestPut({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, - body: { - title, - price, - }, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills/${billId}`, + body: {title, price}, }); }; -export type MemberReportList = {members: MemberReportInAction[]}; - -export const requestGetMemberReportListInAction = async ({eventId, actionId}: WithEventId) => { - return requestGet({ +export const requestGetBillDetails = async ({ + eventId, + billId, + ...props +}: WithEventId>) => { + return requestGet({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}/fixed`, + endpoint: `${USER_API_PREFIX}/${eventId}/bills/${billId}/details`, + ...props, }); }; -type RequestPutMemberReportList = RequestBillAction & MemberReportList; +export interface PutBillDetail { + id: number; + price: number; + isFixed: boolean; +} -export const requestPutMemberReportListInAction = async ({ +export interface RequestPutBillDetails { + billDetails: PutBillDetail[]; +} + +export const requestPutBillDetails = async ({ eventId, - actionId, - members, -}: WithEventId) => { - return requestPut({ + billId, + billDetails, +}: WithEventId>) => { + await requestPut({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}/fixed`, - body: { - members, - }, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills/${billId}/details`, + body: {billDetails}, }); }; diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index c9299c813..27104d0c8 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -1,32 +1,41 @@ -import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestGet, requestPostWithResponse} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; +import {Event, EventId} from 'types/serviceType'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; -export type RequestPostNewEvent = { - eventName: string; - password: number; -}; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; +import {requestGet, requestPatch, requestPostWithResponse, requestPut} from '@apis/fetcher'; +import {WithEventId} from '@apis/withId.type'; -export type ResponsePostNewEvent = { - eventId: string; -}; +export interface RequestPostEvent { + eventName: string; + password: string; +} -export const requestPostNewEvent = async ({eventName, password}: RequestPostNewEvent) => { - return await requestPostWithResponse({ - endpoint: TEMP_PREFIX, +export const requestPostEvent = async ({eventName, password}: RequestPostEvent) => { + return await requestPostWithResponse({ + endpoint: USER_API_PREFIX, body: { - eventName: eventName, - password: password, + eventName, + password, }, }); }; -type ResponseGetEventName = { - eventName: string; +export const requestGetEvent = async ({eventId, ...props}: WithEventId) => { + return await requestGet({ + endpoint: `${USER_API_PREFIX}/${eventId}`, + ...props, + }); +}; + +export type RequestPatchEvent = WithEventId & { + eventOutline: Partial; }; -export const requestGetEventName = async ({eventId}: WithEventId) => { - return requestGet({ - endpoint: `${TEMP_PREFIX}/${eventId}`, +export const requestPatchEvent = async ({eventId, eventOutline}: RequestPatchEvent) => { + return requestPatch({ + endpoint: `${ADMIN_API_PREFIX}/${eventId}`, + body: { + ...eventOutline, + }, }); }; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index dd7152575..756412784 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -1,84 +1,72 @@ -import type {MemberType} from 'types/serviceType'; +import type {AllMembers, Members} from 'types/serviceType'; + +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import {BASE_URL} from '@apis/baseUrl'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestDelete, requestGet, requestPut, requestPostWithoutResponse} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; +import {requestDelete, requestGet, requestPut, requestPostWithResponse} from '@apis/fetcher'; +import {WithEventId} from '@apis/withId.type'; -type RequestPostMemberList = { - memberNameList: string[]; - type: MemberType; -}; +export interface PostMember { + name: string; +} + +export interface RequestPostMembers { + members: PostMember[]; +} -export const requestPostMemberList = async ({eventId, type, memberNameList}: WithEventId) => { - await requestPostWithoutResponse({ +export const requestPostMembers = async ({eventId, members: newMembers}: WithEventId) => { + return await requestPostWithResponse({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/member-actions`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/members`, body: { - members: memberNameList, - status: type, + members: newMembers, }, }); }; -type RequestDeleteMemberAction = { - actionId: number; -}; +export interface RequestDeleteMember { + memberId: number; +} -export const requestDeleteMemberAction = async ({eventId, actionId}: WithEventId) => { +export const requestDeleteMember = async ({eventId, memberId}: WithEventId) => { await requestDelete({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/member-actions/${actionId}`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/members/${memberId}`, }); }; -type ResponseGetAllMemberList = { - memberNames: string[]; -}; +interface PutMember { + id: number; + name: string; + isDeposited: boolean; +} -export const requestGetAllMemberList = async ({eventId}: WithEventId) => { - return requestGet({ - endpoint: `${TEMP_PREFIX}/${eventId}/members`, - }); -}; - -export type MemberChange = { - before: string; - after: string; -}; +export interface RequestPutMembers { + members: PutMember[]; +} -type RequestPutAllMemberList = { - members: MemberChange[]; -}; - -export const requestPutAllMemberList = async ({eventId, members}: WithEventId) => { +export const requestPutMembers = async ({eventId, members}: WithEventId) => { await requestPut({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/members/nameChange`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/members`, body: { - members, + members: members, }, }); }; -type RequestDeleteAllMemberList = { - memberName: string; -}; - -export const requestDeleteAllMemberList = async ({eventId, memberName}: WithEventId) => { - await requestDelete({ +export const requestGetCurrentMembers = async ({eventId, ...props}: WithEventId) => { + return await requestGet({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/members/${memberName}`, + endpoint: `${USER_API_PREFIX}/${eventId}/members/current`, + ...props, }); }; -export type ResponseGetCurrentInMemberList = { - memberNames: string[]; -}; - -export const requestGetCurrentInMemberList = async ({eventId}: WithEventId) => { - return await requestGet({ - baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/members/current`, +export const requestGetAllMembers = async ({eventId, ...props}: WithEventId) => { + return await requestGet({ + endpoint: `${USER_API_PREFIX}/${eventId}/members`, + ...props, }); }; diff --git a/client/src/apis/request/report.ts b/client/src/apis/request/report.ts index 8992f9c30..51fc418a8 100644 --- a/client/src/apis/request/report.ts +++ b/client/src/apis/request/report.ts @@ -1,19 +1,16 @@ -import type {MemberReport} from 'types/serviceType'; +import type {Reports} from 'types/serviceType'; + +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import {BASE_URL} from '@apis/baseUrl'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestGet} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; - -type ResponseGetMemberReportList = { - reports: MemberReport[]; -}; +import {WithEventId} from '@apis/withId.type'; -export const requestGetMemberReportList = async ({eventId}: WithEventId) => { - const {reports} = await requestGet({ +export const requestGetReports = async ({eventId, ...props}: WithEventId) => { + return await requestGet({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/actions/reports`, + endpoint: `${USER_API_PREFIX}/${eventId}/reports`, + ...props, }); - - return reports; }; diff --git a/client/src/apis/request/step.ts b/client/src/apis/request/step.ts new file mode 100644 index 000000000..e0f205e22 --- /dev/null +++ b/client/src/apis/request/step.ts @@ -0,0 +1,17 @@ +import {Steps} from 'types/serviceType'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; + +import {BASE_URL} from '@apis/baseUrl'; +import {USER_API_PREFIX} from '@apis/endpointPrefix'; +import {requestGet} from '@apis/fetcher'; +import {WithEventId} from '@apis/withId.type'; + +export const requestGetSteps = async ({eventId, ...props}: WithEventId) => { + const {steps} = await requestGet({ + baseUrl: BASE_URL.HD, + endpoint: `${USER_API_PREFIX}/${eventId}/bills`, + ...props, + }); + + return steps; +}; diff --git a/client/src/apis/request/stepList.ts b/client/src/apis/request/stepList.ts deleted file mode 100644 index 0d47ab90e..000000000 --- a/client/src/apis/request/stepList.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type {StepList} from 'types/serviceType'; - -import {BASE_URL} from '@apis/baseUrl'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestGet} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; - -// TODO: (@weadie) 현재 토큰을 어떻게 관리할지.. 계속 사용되는데 -export const requestGetStepList = async ({eventId}: WithEventId) => { - // TODO: (@weadie) response가 어떻게 오는지 안나와서 data로만 써뒀어요. - const {steps} = await requestGet({ - baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/actions`, - }); - - return steps; -}; diff --git a/client/src/apis/withEventId.type.ts b/client/src/apis/withId.type.ts similarity index 50% rename from client/src/apis/withEventId.type.ts rename to client/src/apis/withId.type.ts index b88160e3e..2b1d3c2e8 100644 --- a/client/src/apis/withEventId.type.ts +++ b/client/src/apis/withId.type.ts @@ -1,3 +1,7 @@ export type WithEventId

= P & { eventId: string; }; + +export type WithBillId

= P & { + billId: number; +}; diff --git a/client/src/assets/image/Toss_Symbol_Primary.png b/client/src/assets/image/Toss_Symbol_Primary.png new file mode 100644 index 0000000000000000000000000000000000000000..c6105618f9b7893cfd027665c9db86a08d595f00 GIT binary patch literal 925412 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ⅅFDv9_ryl3gr9%Rs$J>J@5%+d@55N;SSSuuOu6 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

a!qgT8BRg_c#?m6 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

$E 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 |`GzQ;a3B&U4t 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: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

-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

iyCk?n7y4|U6#(}G6XDtMHDI84$E{^1VfHRr z;r|&hbdrxZg!+rbhR7Fyd1&lnEOnCr$6nY4+}ijIo4U& zMdmW0e_ujVHG4mF=9i_($ZusG64zF-V1LZT#tg#RLJ>m6` z28mkcSapsIcQC&RPrPM;9jS8wy*Bxj2eIwFwGFuqwwD;)XUtL=Mu(Utkn0+bb}hj5 z*2R0%3h6YX)C2%(SgpXML}V85iSbgD(=8okTCX2Pzv@(mYw+LMPdoMb<5ZR`(EQ#< ztFpQe)fpytwmik{f4-4`^*d+34*zF1JgG0f(DpxLJ-<{RkpcEPYBrwh4qs@ZPs2w5 zPqBUZ)0oDI|LX>hKdX14GEVZN-?DWcDVcA#`fiXxSoL0n0?M&%Bl$P}%PU*vDAg7- zqqZ5Z+FJW89o>Xukgjpg51`L0jPq+XxLV>zliPdDv<9%`=-rY%w+-;m3JuefDu13f z9Qb~@mDyXDHw|I(23_7s4fgdGz=v*qRQZ^}6Y5nw)>Z+nk z8Ay`e%Nl-r-O-jMy`M#@v0;xqz@=Z<0hEet@etKpGnnt4+2Tp9<2UXa#QU-eQQgBv zJ{NXrmm(E+ThKVvE7RiZ?HY<1h#~h%B46$`oahxPAsOBp?RVbIgEIg2!rKXl{2#L3 zJ)G(Oj~^$MlBOgnOroUZRACt95OONIi*iho9Je{!P&p(rn#^G=Hs8kG~IL}>ZP&isHcMQ)24~B$wdod?Q)mN;8PX+!J0{a`Q*DYrU{eOk}Sl!+X z<%Zq*#M0(NSR%|koO?xD@}P3O)Ho@^@m~DPNZaL~uFl+QkH_-|&L0+;R!-UokZ{<2 zd&g+T7mx(J2hCU&X*-D#_G?`+K0YgD;$FWb`1@u^tqZP6 z>Sl5v{sG-26>{#J=unng*R5myq@G!|@Qs#vchW$D`LW%R6kXf%Md={JsMXAs)2+bM z(#NR~=Y^_|d{4nqH||X~3GjA0F!+9qX?n#Z#g^>tqx-)9Rch$=&JQ1d_ zr*s1N35}Pq^<*L`1692(Z1G`{M6>smLDPJ1eA4ipdhM9MVRIIp{LT8EsTkWGfmv3l zDpcKUGI-UhHf$BX*|@E!=2x`$bprKI+l%J>-DDOJGs1=7Ru_T*%YgC*6ItFVTIJyb3$_;aDm*jQv>HdnJX;@ds~zFJF@| zd!+bMt1pzV3Q;ni>d1L(g>5oRy;#hLH^@AA!r5EEOFA5H4wrD)_9Bkj1@VB2 zq@Y{}m1RnH*LRLY1$0?b5dL~t=E)r6(coK@{l@9v!%@(P3LJ6o9lo0?oX8rNf17lT zEKks>s{-~WzOY=12C(%6n6Z$*sE>^&X?oxha+IUgh`+@*PoV94T~%5cCsud|6Udz3 z1-#^v=_w81pMMg1e4cK=z3CT+f`2ou>h0X#xE-N5#)DSO#W7L}vbZl}u#B;~71Lwh z0qT+9$l7E&P45_w*x-@pYXUS60sN{z8?gH|SI)$?dlC?`EDKa^8WP)iFQ8HxWkHe^ zZqj}07b$GOn#~W$OdXsp%zUsG(^SUTFh}KEx&93vLDSJIG+9GM(138$9Uit{I(_(fwa-6)EQC}dj6F}1%(9kr?In4t zj&&Ou`J)ftoYbi#ym;d0v4$}4M34QDudiL5jZwO~q-&NZ^TUvzdA~J(`5pPMbOmDK z#iwWfGTwT&jhoX57@LlnrQe27f89MiT*qyGAYdgC$-FF}52_?~Pxt!%()c2ytskAb z;RL%%eLF}ml&%0Py86EV#x!VKorf+neY++*nYA6DE?lxlCe=Hidzj#htEX;T)7Qvu2eycF|1|b>@OS|k22XGr zJVCAnQ}Fd)bkFwZ$`~$DuiZVU3$OcHJ+}I0YxL2)_U`^oy85V3Ti_{9T`kTaNUvin zM`2ZBy%EAV(83|+(TDF1>_-`u)zqVG77p4fbSHTAy53jT5gZzKdASt5T5_zbz}|eV z;kRD{3$iHV6AC^f^+^VbFA+fe!ls}>jBWHE;Pgy5)m^(n7^N7-j5hxL1*_T)13Oy#mE z!9K^@i`2S)v?YM6B1Hq2r1o7BL@-nj(OQ)SQcj#c;BT48sw!Xk8Th-W7Nv-&i*2c`%#^MSglO}-u2|*`N%MiBtoig15fbrP7^rG;S z_~QBu&@X!RT(q{oeQ&+Ukge-8x?%|2W$jdjdI|lk08@trv-T$ztyoVuR_4UFbJyW%a_G~fOM&Cj_N6J-zmB$FG&uNiApP3knuRd?b-!+B28t44P2X@p9qC9^8Qbt451z`xSs$=~?;o}>9;@RJm!e3)1Rll1C2THG=_8kYoYm4Td z$_UT)#yqRedX4+CitS4d`;zG3K5N1-R9atj(8=|nc)yosw>y4il{7NMWd3q6*k+H0Sq$6=fq0=ij~yu^ zK3}={L=AoGI_lDpY<@b1TrO;zw8lBEGGC!!EfP45r&Ua)20>2M;r!AJ1PR}cu=wd`}Lot-g68W-GIe*$}TsE zOMeu51mv|JOg{7WUVK82uKp-@s(nYnE!N1AdFACb54m0PEa{;aMCq;6{d8& zt9+3wwe@l;_+Frpm(mBJZK=|d2B2jkk}qC&Ek&b5$99mfYeU)?)N@ibyjOPaln6uW zk>)Zs;kO~8MY2GdcHRyR{erf;-N)>7vh0j7(ohD!)*vkdPwn>h4V?h}>MWWAi_!uE z;_dc12h!Cd29d|btU_C)C$Hn32U~IwUU4m-T+oN7GU_@Ygb;4@>@TgJPl_u_^^d;F zP@}VmpDgR*^kFwTos1Us2h2n76+C1}tA<#hJUr2p-pI3zPX9+AmdhTjW^EeR9_!cP_xM{d`_WGp;lawK| z(?t985#+4HyTz+Y^w;&Rk*5AhT3(q~xCXVhWbe0nd)c(!iCXu%$rIx04ET`}9Cqca z@|dfh4b?v>cu~KZkAE&nLHuDg-$2q?&t_0hhWq0)jo)W+Ci*^`}G0) zFl~QHheLpMmK5V-u2)hzX^Eeew&c6}t8m#?<*2kPY|VPV$ZD^DH8&*Mczamx*xbp8 z@|?fK?vrz1I$cOom6`rjWl~xb+?uy!Sc=GFFmq<%rx7)TA^lh*%E-QjUv_Gqb=5B- z?zesi$K_8MtF4L8;Negs>bvXY(I>5L#b$)mk)(l!ayIvd->;eDxwN(9?!iRsH;sZH zi_`zEha0H(FO5w8p~3mIanWw|mHsce_rDLWWSJ8Kqx}8q4!GT&I^Lvowvik!u!)@t z9YZ>@9i}HhzZm0)AndoU6P*Ob0GA6Kqsz#d&4+DXO`euQUK5p3TH{_+uIlRUhteLq ziIz)CNnkJUBt9<;y%W?!;{mLM9wv?_mP0}kK_Co1P_iR)*-7hWr-x?S1 zV#MMx0HZN6A=f_k&$g3a;iO{~vVCgJ?JjN-4p$@A@U9=dZW68408W)h3%g6h@^!c? zBzaVB0$=S5btLEW^vkt$TV!t}b~+_dK5Imy)5bCg3sRLL$dX?)$-C6pSM7TPLbdw7 zV=|T~W>?Ri;odq~vnqnvT{4C;Rc*lqI;ta2cXc9ASVo2u?pC?;ll(k$4bX~5c` z4By+{d6%Sq;h-gKb&^Sk%KTG?t--8C6={DqCI2I^;NJf^R@-IjKWiuRx~%>0`vb*-uTkDgwwTZ z^6hye^&A%9`m$uak#^&)PRHm;Hp3;;>aCB)ticka=D*@d49;&7qt@V2;qV!$JL>S7 zgz%?zt$9LiVO%eUJoEADZG!)*xf6KYJme2!6?e1ygD{zOFVJ7^Bjai2M^_c z-}zfA`_pyfPT9GiY28s+^MPEB41(wynR>-{j?GJD!w?k;YpAXSw@O52M!--;Yw9=%xyyRh*CBfyVjv0^laBpbx=5(c=2e&OKtUC_n;zQit0JQ0Z?@d&w0ATeMw%+{YFxh>dmr!fxG$>i4=0|;^C_$xtb2bIiXcA*&P@5Cxu#W( zzSngLT5d~fzChdQKiM_;@IHfPWGj_1Vy4`1i6=pJHdW2Y1q?MpzaPm8o=DWJX-VQG z?oR0ce3-!)HN z{kbbdq8;=){J6C{d7``HJ!2uLyL|WV8vehm=@#&x(o;9`Kd=A_a%&ArQtUTRD5yzj zs<>&T^@L|um5lSiQkPzOE^B#@kJYA_ztON!ymFLh(44#4=4!!u5%r?ai6sqQqWM*~ z5fWwrPe^qHJHs$}pMQiy3Ng=x*+@qfAXXPc2cKD$Qj8E&t5O~3Q6{yj8C3S38|M!5>*(>`dam}mxAyj<;NNOceaspdb zK){W4mP5Nt@>sT98Pa`p+iF%u&F?bCV=FRLq+>~f=lbnjdSg~b`DIL+XjIV3e3-1k z&F5PKYvZ{NJ66Xi>U(Q@E99&v1^=Lne$wp&{XcigzaK^K)d;ujY@3dZ%nu=eh=9ti zu{Qzhn4wzfU}`Ve>;!{Ls1;7D^+*)tR^c2pXFK`A$|IfZ{@O8)ER&+I^3L{2{Bf% zE5+#ns$JTi(rD=)7cx$m#X$m1ZYf_DYTs6+6&nx&rSI)_?8R9wLS8<@22-ZUq?y_| ziZl6;Y6SgCfBId!<)9%F$iTP8Wz=+h(UaFbDe5qE{oJQ}k@n73uOi3A+x*SWk^Om9 zWl0*wu(!sHo4_b_SYzv>im}le9<_oKcZ665f~U0>k@ur5Ryr?bt6qIrZHzSEwGk;iRtGp+W5+B0ipy(iU> zcK6u&6Lr7TnSUhq4#`LVd&iH)yZw+0Sdw&U-Gcx;_K!zXG2`Uf6fMtC;W@qw@Qy$= zM@VLB>+fsmb&(Z&3T*P+ba@dH0>zpNcf6r6WW)W!9!->TyhZBed5uROcH+;n)KOTs zC7-G>^rZ2K2aSgQUJ(&`Jjmg!Da|su$Qq`iI1d}A_9iLVc#{i*owLg#V|mN-yV4|kT5ZUx%LRvnsVV=Y-&CQ>8zgz) zDb*0D2#*4&+uPfBa%=>pIVrlOXB7C_7*ykO0n5UCea}9SOtK}Z%W-MRsxKNm^&1~5 z3uka73xDD>sxh9`g=BTja_^X{c_gC3iYm;5fhrf3&B&))fOzt1gEEgDIC5Hbu0p)D z70_bEk=d%0clT`-XPRb7l|)w6qOBlj-=^&RWxBEOOzd@pDqCF^#Gp?!k`D;J*Wm`V z)6poSy`PW}9UJmD)3=9wEz09)I`vBZhNW?z2jBhip2Vw)3@$cV3PCrK?IyH$s%$LFIa1km|6EonY{nTh7SytukmyVnvi z8qT1{$91Z+x1MQ!_<%0t+lS{Mq092xciVg4#F;h~GrOewNyPRf-d5vA#(F%$(z1^@ z0yeQa7_ohmULqedRLfUo84&1RU&irV-|?EbeI?vzuc6KVBTa{EQGTv^OdU`mjjvP8 zWk!1G5W_Img@Oa}7L6=ZAABfn}8M9t0rz92h4esBx z+4J&BqZ0QVaD+;t=$QE(GCWgHOGNirUWls$oq@X=4ego{J=9QmBD6#A4!VHYm^zlw z?Su}>H za<(zKwJ#3Vc$bov(xDWjW-F%*v{sW6SUXufkwfzlL7QEe<;!Y0u%*WC2L6?b*G9TY zgxKzm!yHFVw@BW7c67@NxlFB8m54x+-x+vdqr%>Aci8xx z{h8M#m3)}3hVdOwd;b1lpCyjfA8d|4U={7UYuQ%WSI@I3|0CDFT>t0Mk$1NvsvWEu zXT}-b9n7+~j$ZIP#IznVwe7uW<7BQ}`r1cFPZit(2yA%ev82 zM?;~oS5Ot6j(4sk?ddh3#w2 z!fdo=b!V08z#7g_bgCpm0j+lxO)ssBm6;$km7$)geZ?OyRcDtoD-~o7-6m2y)y?x> z4!%e^CtNw@w|wzCi9=dAnrhMQdZCrrd=cm{=It)n@r1D3*(%z#J!!^i=ZL&eaew+p zd(pV@CGR?j-5QEIk|9eOV8@_U!vgBAq{409U^*qp+JQ`Z3gX zU<>{!5)$9+6Rjc?BfJ~{#TctM0ua9yxkW)er*pt*ov;YCutc{jF(W;kiXTIKTrrfW2-{a`zM!W2f^&VeH zeCSX`v=na6iFCV>W&$i}%`$lyOIyu=$h0%xDlomN3`tc2XilRS2Cl z674(2VFhSDV%o+oof{@+`eM0dOWwUn$45a6pccea673K zszC87%=Z%sbAKpV_fWLq%sjotSc5CXe^R|?g8YEsRer7|G+n4aW9<L%C zf@x7SL<>=VHIN`a&PDl3Ro{YMUqH6_CYEHoCBh53HNJ@ro&ah<2qgWtKF4kqWJFKu zgxN)^|DNS*G|h^#QOG{*{tonxSL6VDZF1q zZXOk5VX)e7-x*<_-_OV@7~sX zuba%fw5S7}C#%ycB8bAhlm9B(4^u+_!EJWhUaLx*46TRArQ_ zKd&hukJ$vpX%Q1qapYZm+tQ8kTI0Kv)}$|SM5d(lsz{uVwMxSS;Mi5)JUo_G;Uy#8 z{cxaw1V%?~Y`DiPKbbd_q1_Z-%dudL-2DQzl;>^hO+{tgx{xJ%l62dlXiVX#q0@qu z3;R?MWo6wzcWF&O*NJgLu6a^*GWQ?IT-=Pj8!Gv?^8LqJf@Qlj5yif$S_Z1_O6Tn9 zqJC+eK`uggAAx>t``CE9wiLrmn>$;5s##GCwa$r*~R5ES(Gp6G$S zF04CWSUuX{X)}8Fjs}4!o4f>>>E)izmjg(>IhI!EwGx2go4bqb~@J!4lbmFvk(4*^GrF-Pw=W_I1~+NvbVm);&E z`$ynKJ3+dwpa|{RX<;*(V~42Pxy9PHBTT?Zg_`ynjC`B5wPe89c2L-PG~yW7BiB)u zaLSuym#+xl2PF1q-B~a(@|Xg)1ORS&1tE?*sWi8@Ctp%K%+vRv&8yjwG9Y$O$92n{ zN9!UTAnNt%G41^{|G>-B$^1V#PT#=<_YPflSWqRd$0otQFv2#%jc4c$H094R9Ce&M z-NDL)Bg8e#MktvGsGbrNxzbQHr6anw`*wY6>DwVDuI)tGerGwHxDNItcrs&YMzw)@ z@#|T0AL@f!x#;>$8>Sk)*76l2OZxfb9GY?XX4yNfNbXz$Rg&jG3Ng4o9X9m_-$`=9 zd4M}Pw9DY6GLXCFuzG!*lO*h`>9t7Tab7^5S`-ydmW%drT{~63E%D^QDsrbAX;qUO z^$*7$s~Ge@-XrM-WvY-|9j$8bmJ_{w1|;i^MKUl9p*B`#KkSLA^>tnq*2LGr?jO|s zIu8`k-N(~K;h7=~yGnsy6Z8V$3AWx9jW4TN_E|U<26Zb}VT*^xREwvus5SNqPF=oA z-?}7?e1`aoRf>Y1%@mY^VpvY@I67amdqba|?REw;I1?rAyoIIk^nYGC&!0=}KA2p6VQ8bY}$kT<+ z_j25muh=q*2W(-1c%<-e)hBE@K$RIBQR=Im0sudQ zs}YHR7+fI}BRY?>j4UOkq zDy1#r(*;kFKQMt?B{EF1J$A=v%yA`LnXyInhX13?VY3U2N8=mS)nB*wbKdi;oDC;; zU#ljLUgsD+R1UU5P=9-u2R`3&P=g0DmM-M~L${K;Q~$@cbXlv0ky$kocu(Ejz}1Tb|8D8UEI&_2W^3`@$f>P@h>RwUG^#=eJS^eti znO4yY-_B&#%)8{1Z&)}uh*rF-X!ms${!!^N60JpHaj!@vGPkwmLr}e|Vv5E{RGdbS z!mj|ttf|q~)Eloe(D=0+_|Dk#k_#7&Z^3%S<;-A134CKW-$9B(TMrMotQs6&mW>Z(`|!*|I| zJ7L30QoWtgok9~k7Q-e+R?;%mqg2o6-Duc?mtq+;)~#lRJd4Cd(miG4G#M&#Eqp2C zqNJ@%)fs^8vaJD{Dvd-yu^fQ%RORwTC}F7uZy-`Wl?9)UiM{>~eoV}01=X;;uy-tM zfs7jmO@c_)t65_UFFRN(J5w*39?xsyn&KCVz-;>PQN`@-i|>qZ+14 zb|fD4o_m0v9<%#Oe3Wn#yy6hkSH*vYZZSkDF32cW6t;qg>$gnfAmbw!NQi?+uR(b0 zunZ>%gY9+7e@9WaJKeto7nz21Vx+4+zie;bv>6sk zmDW!cyl4w1y-3l0PG|qCMYR6O8RGf#q5iLra|CWaIo;9i?2x9^=Nek<_jADLk{8hI z!xYobB?9CbjZe|l(8uwr0P}q3NrYn zWN^FF{d@>dL)N?Ve13aFp^ixaIr?TB)k9C*;cjwkG!4aig8lOMGH9`RPv(`-So;Jw zjJ8VvVG9dYZ(HwBF54aKc+H8NquGS3zPf0O#yQHuFtEVP^FQ-K)nAR^WhUT#h&7g$ zvYPvkhy26FkN>@nk2D8KM3B4bm67A*pCS>zV`*kJuH=F~OlGkOE3?}XT?&bu^Ahnd z6-*iP?hA6ynh87yr{HAQ={c}nx4epJFgrVi zDx{op&?x4Z>Qy7DWeXK0Y1H^bus#i&eWGC&gw%0;c1-I_9Yq8FP4h=ro-pQy6o3OS z*VS91gr?iZe>Hs->=Waj^9pmZ5u`_USxmpNQgp$##Dpnkr%OdreR9U$8*=?{>MHmV zbL>f}jCL0cm##0dno)B+h9>uR>9YOhg4y@=Usvn^qOmNO?sNe0qkmN5b*3cdnca%j zrzWpm|1Sdtm|VUNw37Fi*@cVU;j87)eP-=bLe6roYUyPjMX(q6j#qLP_Qq7zT2C!F zzzqRr_Np9w-+sq3@&_EijsM{$I+nitPgOh;smWX%d|fY5r0U1}D|yI;BZZ*w~h?*7)`TBnN%gP=zYt zz4>BKl*3%erzpS9^?!DCssI!k2Cd#;F`ap0Z${&#Vp+SQ&>9%n!4slVy|1oqzqtX> zOZ@99#e!>E4e0FW<_Q+Rn}W|ma(qT|sw`1i6eq67bYV9KJP2C~>c9P+rCjYyJl`41 z^cyR8#OK|JxL#M`F1*s|Q)sHhg!cp;NtlM6m}K!+UZp8S7v8sd94(C*^o-eRKG;{M z1fIWiAx^4u0iA`b;vI}(QTBSGtDD`M^)-MtNOyV!oJU<_1SF!2T|JkewF0Wnn$IhW zD)_!3ptgd2qM^?!DX_zVCq@mX2eKZlzvrt0b4OVjgZc%@CD;A0-Q<4{;gTVOen@0h zyuohI21rNVo_nphCZ4Cm>D1mxQ2^&92SZS-X{+*zFR0n_Pu+>Q$!k$!@yo;cLLP7zb2nq^z~Rb)#-7o zZ<}wP$)kdmTBbA#_U-rR+x90jCmdTJZNniM}jq)q__f#cm!MnU9Nr&> zHop-~`r~w{Gam}rYQJ*)be+y?qDGa}GfSQvH`jwTxh+Y20TnaUzrtXuk-*-L2lpXa z71nl$BWGoZl$=&i6k*-L%?r<$nF(pdGS64^VYn9Uclqq(~XzN1ru2iw#Ba?SM&77=Z2P0{;DbE>v@m z8WrfUiOmSGM?zG&GslONmfy1LVqTBf@}jyQiL{$jlmSao?YFxx$>1t?v$|3VQL9tr zErn4qP;KH1;`&!PW(sDAMLc(A5N1>>&_;I&xkjnA_`G}}kuN<3C(f`?amyq;V{NeM^c*WeH_2|JLoM(o@aaEUW z11V7MsVS&E(E9vNw=(1a5k$M!FD{|4IDu)>2as1ufz^R}vGTcEk>7eZ}6gzw%r z8##mi3uk`b`vmqdboA3raPYE$;>+JRS;Xy4k{f6AZAV zet|q$9sSmiTUT@n7b)5KmgQf|aDr7XXIfv6uFBRjVxs>hH|E2*Da zj}@9&HFwlv<9Yf!YmkKR6ACQ*OGOJ-c`wyniPI#Q3_ z-4#BOo9II*a6-gB4_tg8GiY@}&pO~77PGW@{dS16TbJ{})nEquQW8r+{@b3GRG;-9 zc@hcupF{z{hP!T&)#$`4*t>508r$mYEtsh(@C?K3~pO zkCCw)0F(CvA_ewlXT;Gk=^yjO%Mtw8`URn7bWLFRP_35B!5r;QLK57uz&Im1d#lrh zm00wA+OcZoU+{p;oG;CUzV@YJ>cz82W4K;f!!1?r&unghFPR|S~0$mL?RET=>Drn!IySUXGt|_aT%D23@z2XKD2UDMBE$6K`gZADfcZU}o zM-tPFO44c;O3(Fr8oPuNT>zq!)#e0`FCK@;kk_D}ID-#1^3T~xTU&ZVnKZbz>@4Wh zlrt+?qGUFdqdB^5isie9!KAS&o>gS$V**g_(0h}^f4IZ+18!ICpQl5|FRVNR8}#9u z0djv>#pfLK#h!+hQW2W$7e6m9n5z`&eimpay=LCF`4`zmxyQ!9nA6&Tr!%QTqYQD} z0QQFcqn)wwh3Vz3E#wlsj zC$awODvutQ#&~{ZBNXgDjiX-Y;eynw*6|HG*-q+<*1`kBr~lIOw_ou8ew72jiZk%! zr{JuaWcB*J(SHa97Dft)j~7@nI;y>U%{CHb{Wol4`RzM4U?O9znVo^<3@kWfMTw;B zP*KS}3T$D91@I5$rWRt8C2xIf z&J~(f9eWdel+#Y=`KGKS(dThWBxLRmPoLRO_7*%X0NP1DwejASmkcscY1OBkZUvkM z4ERNAqBlN=-LaQdDq(k*)&0VoDF1W!$s!m-ctATNepk zViaLurPgnmW3rOB0#9FJ%GtFOXY8hnWE}mkb?s)X=vT11ollcuy!!z&v=^1zrjvI1 zF7|ZJ09L*NM0{H5Rd>%s3hgxG2X!{LqL|~X#4e?~w|TLdM!|wMFpBm5dvK<@XiMN( zvHi95bECx6KPE2qqkpvB1d)=1-v8LT(wIK$E9bn4kw5(1(qu;2(k1R94u;o7R`=8{ zMTy68#N!4`M9Nc&ER^4oXS&%pt<_&&{y{bP-g;W-9$YQT1Le?IIsPEtYc#sY@X`;y z8N^pVLqT_+;VbLP$9cqXojfwnBHtO>{v1>cxPp;gX_;O75X|}yv(T=qkV3~i6EpNK z!F-A}h)>naWyM&VkZd_?lARJJTdp^i>iZM^yzrP>Sc1$CDapCdX*;~d`8DS{$EI#Q zPWf6CAT9gRvoTg^98d^si5?|Gma-w zvaSudp*^W{{>MqmSs>9*OXIhs!^cm%UWpV7-$M-n*#M5%`RL$nM`!-}EX_m3#yA>Z zOC4u)Co3yLapQH`HMMMykv^jD>()jiisE0_FJdO`vDU$C2eTN?J;^2zb;z@S1FdgM zmo#F^N5T!wthiRKRK7fPB2GTckPWyth>#=<(ywY34{DUvOP6=o_gS73$rBD(`YpJ= z+8Q+Zc-rD`-k8*iR%A{B|68_YgjcN)c(5|3pFkG8W63uGGN)kO5lC2Jvr!dNVbf?6 zozRbKqK&*1IgQ{Yj(+@Dht1_*Zg@F}3mzvAgruKZTK+w+))XHC89b?j`@j-$LY&Z~ z4PS2YX0&I=SP6z@{3{Oeyk#7~rn}p8*`h_-y8<9Nr#ed;MzE$DD7s{GAxZEtWub6T z&Pq>31oSCpa=b;AC~zgKB3m$>XqSY`cFXiV->Ffqf5;=a6B%;^KBC(< zXE7%i?XMC!?tCCNHV33#)vV~OpxaaValF{anO3I(gv<*PRU`=w?w}1r~(` zwCKe7!En`qo9s>@#~dP;xY>5pf?!_+VR!lfg;9KmxIO}VO4$cM&gCkJrYbyd)RxC$ zb4Q;K#R&Qhfh@qIjo(>jJY*PBQT&*3!8;U7U2}hfh(o)M5P$JBq=m_ zYVwx(0&|yac`+O#hPqB{S6|eu>SY5txz5xFx|?3zuF1(yFJc#eXvwu_F|Yg^)oKGl zc!Dn;y}r>d_Fck-X&faq^w}c}XUmp6zSM$6wLyZ&4%5iyleRe1se@BfEYix`MG~5^qg?>Td ztCB!Xvu)FpVCQNMGJgfZG<&=KA;AvfKe`>Xxad2ZSvGF$+bJOdQjM%-{k2-{&6JKQ zTaZ-MqDev#P2B5Qg96yO&)9ZBb&Q6RkE&B#`)&RoJ}z%ElNu=EWVNB z(B{HRvG3_a@7VQI>ttN~7pLDO4oO+-TX^pWMQZK4N(xVt*poAAXIIY-b5_U{@Sq0) z%r?e-0;;|U#gDuGhW;lM4Cx;^wCZE$aPf>p@>=mR2(|93RQe2%PE$ud3cFVBnA zgx4t%L1FG_`{g?hEGA>lO3+GM$cjDpx(#M?Z2e9FPr>{ijRxY$YhG15a)$t8Lj~30 z3#-#;{*vO)VksW4^|_h~VUj$`=p)9@*D0vTj&oL5`rUN1Gc*rP7FeY2uOmF=WdF#^?cS*S(1~t-uoCk(;)#tz7D$bqzN7%-&*REuUE^kH z&>-lS-!%sVV<$6W=kv;LY0Bd5Ad4$Y!whp)0#2m1oaX3!{tAM>xYkEzRnI`<{2kY| z%Xgm*d}euSOUT(I!$4u9@9V80&;si)eQlR~TCCG1{tG{J?-Q;=+4%Tqz-y+wo6m|0 zlKdcm+&?e9)GiN1x5li@)l}BPjq~@$yr(72v^cLm?^^B|WrNR7s=;MKcf9SI-2(oY zAs7FCG9(@3?~o6l9u5YC|Er)?XG~{ zRZh10^g)Ptd1{f=W+@jS4Z#kW%sUnVsxCz%kCAQ1Sb4ru&Kzy{4rQ_UiH6c9iIeAe`z->zLBs+D0_(4}Kw zN?TwP!sql$v6FTgQ)V{w@2}Vi(ism0?EC;dZz^Qj zR-R3#j_*vC5DxCq%I49Jl>S6&0zUmM(p_l!Hy*_rM|Zd-k&Mh?tpKqHY(jVhba-r1 z&eaAV+4%u4>1K5(WcgtK;}K*wTvv`&kf+od0gvQR;w7?oLBGKEUHLCVb)x%t){a9l=F=kd@RF>+4Ij0rxo^j>mUf61 zneulMC>BDQnrM$qPvQ7}6=@tV-@ra*iHEtq z+>@1|RnG`^utp^*im~r{Zd{FVhZLfs%~LjRd_Wh>Ds&@fL1Kj}(&R ztBEPo@A;ZGUm85HbB4=eYgGmfRc)?tzQwmrZ1%~dK%q7bmfLfAv+zPnOLD`~yqTC7 z>KKLqcqnpAS+w;E;paP6LsJnMEMiZ$k0w{WeH_s}1q)lPY= z+`alFI+AYiqWwtFEib;7fp1T?zGx@4R_ZJ%YI1;jjOj>36e(iG$}x>JQ=Ys}Jx-Kj zrg!BE`MuTHV2<1YpKGssR@RD;rEv?&*{_%h1TYmvWRfYW@o8<6`e=~_mqoKj@i-sn z=l0(FhlSQ_lfxdY?}#|MTtt_2Zu>ujIqm9JoK7ZM|72=Xj?6I!mVI3lxvhDZ%y(C$ z4^NMX)r-GsYB82u*GW8R9Ij#`(2MI7Lh{!;a94hMlc2vNIr-4cpR_@k6I$yolNq*Y zOBblco)MAf$+fv$ww9^J;oc6GhhBAeg0WgxQIOd7Klm}iaj7{BrA_NIbv7Mg{K`kI z`jgf=)T~;@Q!mv&s4lR^o1?nKqnv*I%$FgfdeS_zx(1H^2CU_3vhDu6Pa=!o{cAAQ z-@NTX#V-9Vp8#KNoC*qRCu=uT4muq2;W_2J69fw$!Ge-nB}Q~lbC0wy%L{xC5HA|6 zstgX{R1H`E0r#!OO=BVumgR$V0bTz)HfjV2m;pq>ysv0OzJ>pMmpanB_(JC+-s?K? z>8x*F(VTZ0?eg`6`OB^$O57-p}67#Q?gFg?NAKH-ZCtw;@lo`%OtMM`0XAPdp5hjPu_A-j& zoMkCh22C@34BLFe>^9e7$%6)Pk4pQWeZFngG!M^q+cyJ7&K>?7yD1`q>qmEP4aB$? z^>gLsox%(K-1IsdzBQ6GCK02#cI53TjP)<`6R$}d?><@`9@OfKMHu&N7;ZL=_kcJA6js<+M8uk%izqi=WTCj$;q-ZHVIdNjax}OAYx~T6-S5O93(vzknoUAe|3T$Z}J0g#{uSIuAsgMAK z#_d$k96UV4RmZOhppNO9rtyCTjK>5@o0bEO8sVJaq`ho2N_paJf z0E;19^w-ZW>)Gl0T(#S?RgQ=oUo7vBvL>5BPiB z<(RlqjTaA_2D-u>>|tkGK!8O_5qQ~fmjlI_CQ8FXlh@iQ4m$fCiqmGH6M-bt`! zB)>ts$EF&E@n-XZT^p+)8t{TNZfM0xj9ME6c6j(k8#)zsF03t`H$JlkJTC78a1|B) ze?(AH@b0?X|I7`P`X=9@*(@2G1JR1K3y{BWYa3_~Jq)kCO((&3qw>B{6c#az0HFfp z>{S|ztu?h24~qnt0Q^S*`=Rz1+|u3mbtIiv41R^v&f7(YOM{ooPu$E5o7z0qrKooKMo7>`3M?T(^wULrw*!>p@>df&&jXybbum8kFY;$E$v+{pMW4>E?S08yRyF z=p)#=Fd(q&XpgM9%zA=!%pkntb8yn=@wRo>?LW4SM zGv*!=vt@%jEhuZUtur3a$TjO3XXhXIupcyF(JKmXUGS@-<*S*U{zUFU;7kxCKRiqB z#0SqUMJcw}{LbaE<|TjM)Ey>b{~y)!W(E+^-WJ!~?nw_`uiAjUqv<)YOxp z-%xm-gs>e84<5+~2Q<9fBTMNK{hFxvy_rY+2Gbj3#>90m-bkWtKT5Mb8@k3|p=4id zzb{%!Ft-YKij|;+u>8}a#%TfzN-i~wMVEjv^N@yWK*P2+e#ehvJA8a>ulre&^}*9A z85L-V{_5$FEXTBOBy@ozJwUp@#iYpJ|pl{`5Rm`NJQF`a2KrgRBy1@LZyOf~H} zMPe0xaK094uW?PYLJzn8I>(v=1hQM%Lp?CAmbX3XcJvMEkA?OOxn}nSW+r(~A|7#{ zdMnm_bISs|)$zxO3m?5gXv$Hde-rif))}1|?0Y`)u1In?TmHFWW5k|ntWA(GdVQBo zD;~?NQ<1C5Wwr?tbgHcUcj0L)(jw)g^ICF8j(SZ$wcTp^7PbV>lFwxE7l*8T?(XbLLMf(6uWjhT1Tc(wX-#}!x`FVc+MtRKH~XN;6kSL zNr3ROncU((zcCf4{SHS_;0GL%(L5ZLvR@RtQ-gd58@>YbH<)S|)2t+f)U;8JznVe2 za=Z_aUx1gXpY`k8Bbm)hJ7Kyk&{v5Uvfk+Ff&%W1ohq%(4mJfjD2`@oB{|QmOnem} zmo72X1b+^e1>ck^OtQHNH$m22m!+7_Hm8)&h8z<7K=Cr#SAs>nPq4@A_u@{u@$m}l zs*L_G&{geMZ7C6#RCGp6kf}|M_FI-Rp0mQ-()U$IT=Jz{jt8Gn6qeZwZ}Xb1p#be2 zg0!gs*|`mi{jr>?YUG;J@#ed%b1;A5)vo25RO<2p>FqCT!JmAskFA+N^PRD8(>Q7p z^R^Y=ZJGCfyX+$zLwZy1;4pX4(&vVTJi+1zl@*}Pc*r|l#-1t}e*j}5Y7KwhA>x(^ zxRv=tW4&u3z72t$bfo<(^OUYI>68k4p1uflM*Co@i2tCd_5u9{|J%hKh*l;S_Q2Gd zIT6{0?*wEmOkYNP47!~6I!@~p5`o1wcs=259^-f#KaUZK;HsXIc03-4ZOlQ!SI+|H z^Eln|Qpo_YY{S!Y*&6EU5dQ6Iap6{H`}P2enMENFJi2%$#_@J06T>CtiELwCzW-Lf z=EIe9S^{y_3AWO7j9^ViS!*1>Om7pMc+QIVe$FG`o0tyda;XCCk^$`ppsoj=G+bnA zl)e`&e$P55QQ?FH&(BC_Xvs)*s&~ZFXCl(Wy{65@m}UZw#Wt@;l-!h_llFZPASE2j zAbe=+!VxE9#?rsqRFU4ee-pop!S_3A-yS&?ATV(Uw)%W1(32p8L{&2oNv#98iUOX8c&77ecC-}dNd2f_kf?nR~wGPXl< zMT_vxxy67bPvONuPwV4h73MPDg3X&yo}nu|eFg8aLa+=(0)t*+W-E%T!_|5vHm1)n zR}UX~)sI*Ai?t4Kj2WWSM{cQ(Yny7q)x}&oY=~>VwO{5Xcw`%CS6;1bb8}bZs+IE$ zXje+TX8N-q@KV#in&3KG!}R%9f#gMkbB~?IK<_TFPyt-|fF&$btXf?0hsN-mJHa0{ zal6(-Ho~diKJ@Dw@ddYq^OALxdz4%AZ906q9L#Fs;Yfbr@4#g0%Wpq>wDF<~0oAJc z9Q#fnMXV97c`P8INK{?0`Hf)%0&H`JPX~M@FpY~tgc-koVSux;t3i!+FxJx~;?G2* zMPHZ9JXcsZ%;WmjKo08UhUK6ve^pJSlb-d_7)?JcRXnee>*uzWPsgxaYrIaS>y~5% zyK@uoo@ML(rprUzU@h0f(sOl(U1VIUCSGg(I-boo`&r|8&!!s=*(+mA%id=#{~1$t z$%?ng5F?mnA}R)fo~8D$#L9O?>86mk&}T~60R)n7>iokPYq4*SSSUycnn*`5Ht|hr zRYZgfisL&AS6zM0&|gZFiil0?E0(ES-Te47pD!&b)OAHd2}fcC%`epy?zL~+-<`J^ z+*RMB1hW?af6(^u9 zv@O|&v71Lf;Ljcnd=~n$Y;bhb()1~L5W=pCx=M7-9PQ!H9o?`@@!kx=F9W!^qQUq_ zM@|E=Rg0!a^^bkf^LLr=k2jEa>vOb#XbpfJ%wf%_migse!q5(NHs%ww98S>8@@jMh zsW=xOgLjpTPugP_#2f>s6E+xXAIevjmzEFKl0d9c(Zx~*a~Futk8`Cj%DqbM|B2a1 zBkMKi1k@p7bK<184_qx^c0)wf!?O*E%#vW?FK=qjkx{z*CkY(61|r+~*>8u3U+B>k z%mRhK(_(u4w;&PoPA>L-Ksbv2k|*yj0Lc7ir%02t_m(XdY#LD@Or2kZT6jt zYb(En8mBdKrsgin^Em|u_ZmP_;A~U}uGHP{RXV%dkK(I5Ga@cI1st2BZ*R-? z>+Kr0?4Ps43*|bbg1@)~ucj8Rw(rOVy0w)IvEr&7DL%;~2_+f^S5ir3m~(}n7MNzL zdj9^(bqv>Zg3Do-@@f9D9iSY9&z^nZw{c;u_02ygmw*!+&-eWQ60QDuRVr4#vJW`r zi}~JrYacYy+40X&Ro+3lQQCJ8;{6k~I{-0+>2dmgl`GYDGRGq0fH2@2m%Q>Y()KtX znk!`fq-ts3J&THnPi&trBH2` z=MuVlZ8GN}w%m~RcAjcMLN=k-`-@i6Iuw>n7R(Fhg3lO zk~XVd1|7k>4p1|UySS~I@ zE33!K@+lVav2+--eM4fHBKF#pG5w=njdw6eXrEZp(qfDG(_g+;Xu@?Fjic*(^3StGqWrZDc(oq^#$?5n7Zi|?M z9`G8&Z5T0Oe&66IKtouAkmUfp>u`z5i7{)c9&Ozr(^JeqZK}1=N|uH*RIEvkwWeEN z6w(O3+#v&2PD{E`cfW@ex*r*{F8D$gbEwyJ5*w!3!RUIvW*?`caur2D z(G82T#HuyV*GW|r3(c|kF9Vad?tl;D@los7nzH@eZbt*IGZH>J9M@-@r0Kxr`*LhVHbHhG14?r_=NfL=tB;qBpm`g;Rnwlo;sP^U-F5NdJua*VWRSKmq| z_e&h`LA6~Md-1u;D8{`1p<3^0T08e2GXXQ%S!ay_pVz&E(-IAr+iZuL8IC=1zV!ad z?3&kg!D}w;;HClg&~NOrJ4)~G8Hw^G)99c1uw2?(e znY#N#p0|c@S_#_d2Dcpz1Zit= zl>hNuS%GJQY+m5OdqSKOc;xNiq!rT|3!+BmE=T&GPk62ziQo6Gbw_c7JgGRME zh~EzPi(I~x9ds{GWbY})Y3C?hY+ul4az1<(d0w}IY4O5(=emQZ(TK+Vt(3iJ$<|DK z6krL0T~Ijwr}JcUPNn6sOfuM|0Rb|L#90lIO877wuxAYSYG;{cy~gR#YkA z;Q9&3O#Cej+GJ1U{iD;N9W4@3v@c)UUj=>F7g?~!7nc$vGjyZBtooIDc?{qzp)?H| zH@esttPyWoJxGt|=$dM!!zCkcdEtx!ghNSuIt_n^|GU&j#uMj9mBb>X?}qQCV>Z6l z6pIp<(wz0}NE~k|Uhi_A$tqgV5$ni1<-zU-4jT7`1AH?$B5SdXFrkmn zHiG27C#~HqzTHn@6U_o1oWzDNTcPzTABGnjh?M@wNNI8tZiW>47T7QB^eR#w(om&` zFnS9EJh!WK0a%Yhe3qPUrX%O3@L8#T)}?GejS+EZOHXykbO6Q5QE&nkAUsO&cq6oz zF1L2Paq*`X+CGWwFv1dH5!yQm#mL=R6bf>=->Oa!rQHtoKtW0Jg1`&d!;2>~4~Vvo z6{_!%ooosWsBh)x+vlaQ=rcHsIS?hXF`TTePA+S-046$3d5_U$O-U?)MPTG3xg}>t zOeFM~%W=W6$x~1~>Bufe@Jt94i1OvRVyya`fA9(cxWBj? z_en#0i*qfz%H+XP)DJ>6t^2mvPBrF0*pB1oo}Fw=B*l!ctD>N8F_m+V}74QpwEn|N$C8$ zV|KpxN}scejLVU)liB|&eii5ALvOx$jAEt*&iFdWTQWY;X| z^JZgACGyt7?!^Le7NkzSqqt*TxjvIDMK;T6q0YE6W-c9!8eZM5du5ls%j zR#_VhgbXb%i%(W9r9Ny9-svyhsCcv_|C^*fX$$;F7CowboMUw-Bxh|pqlGIa$)g?TVV9-AF(*Bd@4HM9Qj%MZglWM zX4}XJB{aNs{ha=?IeorF8-g+XaJm*~332-{V0~E82KHWQPffBl9`yqki^#C@t~ULC zCx{zyVvmn2-Zv9;jPELoxZzgi!`80y;~(Gr6}IU1@t?HbJB%&>l>S?(x}CW1FYFwu`X;qhVk*_A;t0A)k>K2~>I-h=g?vbY| zyE4IB@upZS*7jzwlcldCNPZab!VPK?H)_7Bb)&vQ^tJ&vl+AQp##GL!I!lTcI$Q^l zoDh`(l8bA!QoCMytT)pOEB~kQ%5;>w6!q*;@6X!D96rhNL9tLC28EN0+uq9iHn}0& z&{iGV?SHz;lDK@Qrfs}7oReoli7()MMQ^3&GlR-IduNVyE@azI z7c=+1Uc)DNR|MN4dEMzYCcihqo(u}A2D$0v2lM7kr=mK=2sp#yEh`v3XL&C2LCjmE zeB%!^IkFH5u|OB%z6$jjN?56N6A(c`&*%YHKMMVH=6)p>#y1E*DcFT`DW|RjDY^~( z{qgTU_sHwV?OxVxR=x$)Z{Sa2;d$*3`FH;o3xKcMx2r|DY;BZDY;vyLN+EL7b}Sv?S&iM7~!#QIavgR885C{a%rdO7RVn zo76HqhYzqmR;GHZc7#8qz$aDR;x$b9=y@`;)UO1?>o4MY^#e^IP)yzo=ZX|_=K-jb z(yg8|ar6ddHOi4lzF6YC@)@k(f?4H;B^>B3TSZ%9D&#*|cBB%Wt4a1NLb=+ZDY?3< z%pbIzDD{X~ZjPSNy?`_No^ar$b~%V&?>5{oYyPFHPq6!C5rrE}jXDiGH zLCmyL5sm-h>`&2Ou?M9WlF*~()#TKb*FF(rPuJwPanj3 zPyb$(0ILx|o&dw-Ng1thmEM?@0zl5`$N?BAK33k$02Ti(`%6F?i=svH+VlYYMpRJT zp(clK6Ihk?Q;SiF)>0@`dLxTQdk$WT{zmflgMCeReXIpc*9D5zJn6}a4t$*XTk)8RNPZt zzoCKl!eO=(b$sVYW2F5+eLcVpKE63d z2ST{q;Z9VJR>!h4ateh+83`2j)p(N7>#iDl(cD{qkYOkI3V)#>nQp*_rFQom|DG>X zc~3<wK4(4slPI_e>1s}X(Oj)SHhEBOkvaJ2%kD|yOoWi~Nimc6Pq*=s))nX;R0xJhai zDj4+=u6Im&KKg6=(a&!ZfOQ`PH=@8ZbZhD$d7p}fZUUVk;<$z!$;|oUW0;IY;Je_! z1OgYFoyAl>q%Hj#i5!1ey|%Wg`r9>r#zzy-pRpX$KQ)H`gsP~cPaFmg=@Y(Pq<%i|F_N=sN zTlr-P5@dpM60Y8v(H^&~1o-pICoJd zu<#b{-1NF3Of+yQ->9!->`~T`EKa_lz26S-*!zF6JOOUx?}DrUoY5f)2gf<4*35_c zo0x)iHoJ}CP8_%1J?EnZ0U(b|c^}&q(e$i z!(z@xtO$bYY6qzpit>F*yl)HYXU=ul8GhdDw}W1pUG|(0`E^}ZySn7*Jru@Um*@kn zQ$iOPbAlCORi2==mS8|@G}CkBw0cb&+3n4gS`K&+i#Zi2 zC;CWQ(dKDh_I%ChRGwc5AX2)YwiaSmpG!EeM z$|+$_0Jm85Uw(`?KX-cm%CC3D=Kn411@!$8p#Sfcc_6(IUoqNJ8|V}WNkduvO&TF8+bnwedfvNz=M~;V_^HlbLEBOdy1lTRg>&b9ZpG(9_ z9&oq!kos17nl$By&#qdygSH*A)Z-6Aq?yo>brl8@WAfNiBY%~Jky{!x<)k$v$UaJB zA%DysB#-&5F7KnNW@5uT|6>1=2-r?w%}9P|>r5g}V8kNdF;tbh4tSAVDuuiQ@5w*O zewcjfC`=1Y!_2h55yK~rVC3E1GQH@U)qme)Iye=;_umLS02k)G`ACd0$RUw z@$_OV-?aITr*_UxV8GLtW^8LaMQyK$R=tnD3#`^0W(}L^?w4;kpJ<1;SjakyEPT~d zV&WZ)PK*>v-tYAYO7=sAWO;6)BPBY@4D+@>X(l`8izSMLDs;D}KXLd0*tf<~hD;*8 z)B2XU|4kqYOcnl9|M&V`^?w1W5R1B=kxJqi=F9zK#INqLCk=qM+g;|#OGkAz9G9zS zRK=HHzARHb?W`UN7x%6=t@Jva73#IttG}xCL}G+fumg&b*S;QbZf(lUL**bZ5aEN* zUgIuNfF+~X(0ZW68D%tr%(wRiT+IOD9RWx>UdV26=zvSwO7g1HT{8Udgv7xRHl zq&>QToG@i|x7Xq9t;`P9?8Fwhpz|l=p8g2Co|n7QK0Z*bNR`4aXJNk`oikPi+OGy$ z&frJ{zuRKG6H6-zAF&N3Cb6jlV)O6V%V&UfMv&C!`{5ov8?%o>WgZIH$x{@uKU-fm z8zzn$jWEpQmQ)n;45{k_HU0~g%G{d4KAGtzizhGY|B%tGA~!udaWZ4x!=H{9Dl)tu ze37*kFIkHz1k)gqUv8CxBP5UjVVpfm&zMA4EpGfqo3VfA=UZcQ|Bj(32}C%NDAM1P(9Ub*#lB|67Ka|8Y>-@@J(+TvNfOpSp&UbAWing5uX}Ti$}VTa*&OlyXm6vfOqK2 zJgRfk+yVFpU@O6A_sETJRf7O~$*AbzGR~bm5a3H{zX(r{+ZxvXfw2?;;7Mb?S-PBx zr_02>L0`Va&9w)Os(nDka;?q#r|)M2>y6bar%!SbunH#=A0H3^WB3H>>YAP#gm-A( zS_8?)?mdKy$|35|4di%>^BFnet+$`9qzZIyPWp>nqCk&>R-{x30l&GQDxfhBhp4%8zw;7qd@)cM z_r6ip^OMb>L9}Rq_$S!X)di=;o$8BHvRsu4Fe&^QD5aPVFh*4I>>Q{L#q?w;_YFr)@cvL$+k zgWoTz*NoLyg4~jMB>#s~8QYJGAMy@h@YR+M+|XDXvF?fG{P$ZqA;xvc6=n`2`z&|h znhU(uB!H)Y0d+mjRyL&E$3w6jFqaM7Zu{&1OX{k(xb~>2?{uPN%)b-Pt z*+aKi(~J&-VSTNOjMA4NaC`_TjtK^4&6&>w%3?WVyqz{U3k zPzrstm9;L9QKZ8{$GWCiU(nt}Hz}Q_4u+NA2mqo4>T~A(*5~b)w*X?t8wb&@1kv*J zi*E>a=7Z;At$EFqCl>%x1JHrdebz6~A}(Y9%w=q@3|7x>*bKIu`jlYZzM_=pCjpeP z6s(L{k8$btyS%-R#4abpSbbCI$!RvB3}4b3jMmk#dwQYgcz6 zGdue^YGd6;+0z+y$76;Q?R+g+QCS#f&f2pxtM;v$7&K$LXbVI&m$_AfJ=vooQ$E^T zkG7p-#ediA+)hOPh4%cvu&>D7hQjKt40`z{Lo?@M)C@Qy&HC3$pzx2K7%)}w@lnkf zXtX-*Dq7BSR+>oq^t@gRgnyKFG#QZOXjrMoJrhQ!K5u$% z(st`@y_!K|J$62<7!!C~;{_j}m%ccWfx(~?qXGs7-xtx9dNr<2U7@Kv9i#uvAzzv4IEkg4T?&!LowV@PyR5ALE1OY><>hSPCmn>oV6Sf zgmw<*s2yt*S0OTf`&@eyy#rwW=F%=V^pC9+ni(_$;HGN{2 zEWVFOz`oc}TatI=*S4$ndAS;u)xU+M`g7=%eM?v}uWVmR-mU zE+A~(#UDMmhp2Gf<>3pm8KwTdX8;n>?~WuGBiQ|abA*l3Z`#F)GX>ag?-9pIu&OYr z@%nR4Q~q(#<7JJQHSn+gx5yfN4)*&YF7eQtI^Ow`SLw`&X(?65=J(QLB{E(6l%u4~ zI^Rk}<1ok+!^beD`9@9i-1$yD6i2%?-1_>Na-psq3nKTvd;(HFgA(KxOO=`QmMtg* zm;@zSx3=|fb8<*64_BFbS@nlknaNyG1mXkRAFAt*A64h*u1bqog~AT?C43YOAX zWZX-GCQrHIk{^tB#-{}E?gnHEk_>ONdugnvSklZE?4(VQTO!h;BNV1CWBSF0c$asF z{ebu<3|+FP6s}(AGh3?~(dkNj4wb|L+VNCaS)-eEAXnW9U8c$JL{4PvDWiY3Oqns% z|3hIVn~Hy&Rf`*h7Oc7!G!6Q(KH3UJ!2 zYi2kck8XkM#aR-}jM6AfD!#)b@py*5yYR5$;bBTt*ugsw@I3X+kMNczDCnCZ$ zlKKv=v`#@oq%x0trAqxUdJg4j8l=D{4wHS*`mPYUhOYTPRl7{O{y3wtEj3_%C$wj| z2ohXHTGPX#j6h{zDn+cb;~C}S;Z%pgx9*m+h0+Cbl)QpBYbjx1hk`Xkb)NfYS6uGU zcFx1CPsoXNSpddlh^*1;EzsZmn3S}W$er?7X5En5wB`)$M29aUSv~RF)qn;Wcrv}Q zEd7aI>B-$Je@8aGOJ$UMkL@07Wef# zg*>*h0I*Ke%D}kBOoOFa#tID5>e|Qg1MUKFsXrESVz#TDfQ18A&ne25X6Cyxf!tWP zrFAoNj|_~yRS5K@#1Ay=`!@eVpJmGjwc48VyIyz}!@>-XLKo;%-e@79nyPbaKVrj+ zcy|m?C>b2x8kSk&{F`;(;i3v+E)N=aL;E`eJIW54G;H{0)!_Zg8<%hqj8d*39|QWP z_w=NH`jB}gJFbIss1<-cRjik?S3->J?%<9W9)_kx1yJ7Vl+hYR60$TY!g=0ew(bho z!jX=VxY07tNCIc5{!~Fl=JE&R2Bj)Hpr|nYpNFI zPm}B+eev9WhSbZ*w|3832YzamT-U;l_KX+>OSPOjETX&SyV!sGmyezSw2v?{3u)CD zjWqI?T@sHt8w>LAWQHB=neQI7I)GrRZ>0cran>X1cj0Dopd zpKq3*>}w_)7ftKSUttJ@47CURvXXAZF;x+TM2fAWs^$$KV|hfgMHdLQKRPK$984Yi z#=q>WJ-vr!u#1-*_xgf2e)mKIURe24|E_t*WdHNOqxxW1n%Fi8apLeCJP@S~Sd@ot z{lLH~vl-_v zWk5-g;jt{s|Y?z*zlJXj^_&|V!jX3@?_B`T$F* zvdE%&_~x&uSs@m0KBFUnx~J10zDscbg_W=U4X_#V61YDgSPlrv6W0QKKwSgf=-06f$3XG}0;s1HUZL%3%#K zT!DcJy2DJ^iBpJQQ@^{~Ife{B6Z~%#tSmqJncpBp1@12Ca~cfV{EW6rzl0bhbwH8l?aX)E&jPrL%rX*;Svj?Tab>i*SuzPq*V@?fUI3z zIM0ZgZvvIi9(`^Ir>m~xzWxFtwrZ!>8`d&uX^5mK&EhwPfh(Bw@^e4aktwH4Vvs_( zt~{(+uLjyc!<8JdmOQi%Dpc8tB{I#ZyEc^{jZCw{ow!IkG@}VDi7NoV@>j9I4*zeya=+o*Z&R2 z0IHteknBL@QSEP~LBJFOP-k63?E&z(^_*@wdXr38ZYv8xZ^J3Xg^ZDD5aC`q}$-$^6tS)=8Yz+w)a2`_c-cD z4|3Z4I;wyK?d++_Wz)dP*2KxDRzz1A^}=y4b8$>zO$oM-1ot#x^y%H1s9Z35NsD6o z?RVH-DeGj_g!A1GB4z~M0I|$cs7k_dG%Se{WGvC_4ar1e4WR=jU3iVF-vis&^JP1? zu&rl=YFtQ#gzam@B-|Yh6X$2tx(d}>{vxwJF|HThc>Hy=_P!M0=%u->`~FSNq-Yv(W-(_MkCMdXB|i6 z_A?c_nIa05MR>w@CD4^ueGB&-D>fz_{AX5czww>UPCLLb`(7tBtKkTcRsd)jrP~X3 ztmN_b8t~EM+8pYHw9*lOL_+pZ*B!b=PXZ%~0=mDrYGsO}$)RYQ{UITvF<<_XY}EWM zhvJ+RKJTD$u7hp3E}GneNI~AxufeZ@y$mUM`sXEiFm++U`?LYO8_}%A9ov3F-dO1+ z^6a4Nm}nWLn05d@SBibLIlDVyHQyp}ZBkl{`Jks;zLFyEbr8+^br!y+WP(~mxn|az z8!sZT@+WA$>}S{nrE}0i=7{5`D`Iu`=b1u=jM`4-so$C{Fvr;hO6~@xP%E?n&6e%-{-55Gj^mO4 zkvI1Dr)sl4ZXMA~gKYVfUgMpFM+neatsr;rtXOlgfxf$%F6s)T8UoJoh!!AA2Ws;) zQaS9eZH#4&n%a3GZVs<GvEsfu(PP^OO5Aqny;8(4oLyoQZ z^mV_irTL!PrIWtwNdO5p})`%(lszfK&lNQRn?j-+I>LSxm0OZ^Axm;K%yQ?cob-)56Sn_zF>mt zv}}t3Dc&ly%$M6THfc^1xRFIuO2Zq*CUS{t;RamIOQ>#T)= z?XaZ=cU;gusWd~@=3i?FpS|9VCK#8}lSDC@ zP@r5T&1n3xyn}Y9BR8u@O$*#QxN3o#6LXtHE`Xw8G}TdrT+#%RPB7x4gN&!}cV`DY z{>Wlz9?E_5i^x6DIZmVNVPvv2@%^tSL`)`^h zulU#u<>hZzA#sU$(dOwiT+qe?^47jNS9HtUHOhRBqJ<0KgF$SW90=;2P|)`YMHpI{t+B!D8{Xqo(6Is%sXJ z%jUWlk0}-UcxQ`8z+=yh06~u!Vl9<`KmOQmmSse6 z;Eusk@QeC7)4!24LG0VVTP6RKdUt3L31BKtL9f~l8R>HrA4YW&0%!)vk1uIwh01*o z2sX!FFiTm#_OkE2OkuQTIRBG+p8;qkJf)9PqNJ@t19s;VV{kU0OZY8xi}8QE0X~^= zz!~J0*?*yF=>f>=gy0yE9vvo0Y&+bp6B-M}iL}B|91vOcC^%*tGxpvfm6V}7bxPgF z9`dg2RGo~fma&FUvq?xp{x-m(8l`N1FSggLc_NX~OhNhj2*;I5`qMjTiXRe2EWV38 zJLO>)3YN>zy>omD`Ub1NEae?57u6jRr}c0uK1)8&H2kiBCnc@i{qeF(;u$ z_~4Ei=W6fHUEXS7>xyvN&Qt3*Ssb;u5X4hd9YnT=I71NHk3X*G1j%O$trM2fa~C73 zwf~TYHB62WRt!NF98e+kD2nVyrt_eizj8qNV9fYK8~!@a9WkvGow9#3neW(o{~=D_ zq~4y|gf#eq)6fJ?-f`Hm9$dcAgagrPiX$txJJv$5-*O_!cEobR;dTJnMespCP>SuA zKv0an0`#Y?q9-kPQ6Pj8^m{dQyC&(peCC7cF@OZ|Ar`SsCx58J=4!950Ou6mH#yoXq`)vf*ol$Kj zT{i3Ysj`Low25-1*e#s%!>UnkOHpF#lQ)qg(Xj$;GC$=K2X>kID@yb&s52srXW^k8oG z3gDDQr&GUijj~dJlDr&`mpW@t1*#(yS2O1i?l+MDitkSQrt7)N*>hLQz7MFf|OyhU4Mi+B(`ba_Mq5{bBWdYBkA*HMYNI}o}UF~_1ngv5Su z7|3Cd)4+~`qA*__JYC;S3T^1dEBCEw;(ionE*1fZ9$&VC^>NU)(c+r}ztglPc2&im zDcQ-FEa`*IO$F}p_J|jUi!r0rS&7Dyu(_n{!NI$7$hQWOlAN&BKN=T>#C9C~YMQD}law|yH$>j<=FJWs2|w&RF6J#^syfi!kKgLzi7?=$A5Y8o(85UQTn;^bA6fB$NQ`c4+y_m`! zOUuAZu+Ho|D6_vKaCr-d8E%PVHGAPM#u9KuXWLN}Om>xAa3q+P$Qt&|8o%4s@qznl zU7<_D0c23PP}WRH;ZEl+TE&JHJZZDjK;8@E2g1(cK^wd4{IP{0|6cpYOKG(DzcWI> zM!Z&|DFloEM&DZ8oZoT0bA`?cAex-+ttRMuw$Hr|5`$%k4^K#38xaYMJjAislKa@J z1w2vphn*GYY1@ZtL<-Wf9Dq8j3Xccye@kEZNcBs11tLSt68U`mnp1V(n(0^O(y}zg zRQqlVrMvmJKouG51XJ=seU)QbCKJ}&wOFI0(u?AkK);#L@z0_ zKjp6m_;&vt;78Q7+T(PXL9&V?@d8#zW3t8PRuEFS17{Otl3dK;<|kMLG-`^5P->e7 zuJN)sfH?Z=b=mJs(&hEHrvuf4FH#-Sj1QGn+=$*!J#LpA6)*`kM{e93rT0|lbKS}j zts^4Uj*t^{=s5PYLrqS(*=Z`yYEHn$uMiW(pgl(p8uQi}`Xl7}IHQJYNzhh#%LG2W zeCtKpw;8~f)y}vJw+Y(a^jfTHXFRYh1Q$xD5InkBJwmTVIsQ^6G#Rr?=ik*R-B2)* z7#-&7S7~He1vc)C#%c}hJ}4{x_u}mTudkVBz7y+z6YrsYym!8MApp9u^vaRtr?fdi#t4gwl9-V;waP;4cU{&)?P;yyf5%U|vpXHt)d)P` ztzze4H)ZG9r^BMyC)cZR*B-rHRL;_kbqnTU7 zZ%q7~&xnXCJ*o!`D>>e`Ajvhxm9E0{_(T5>Tkjsu^#8_>lS)OTgmS2)yoEUx=GcL^ zFh0SZdaQBD>RXZL}|1 zhNh8xP)){_Eu$I;ia3U(h0tO7mHxaG@hb1uF(9>=6=)g)aV9U`=kaO7K_kOC!xl|C zTHru#N%6ldWqW1Axb^cjAEs%em z034?oOJn=RR5&{8*wv;h^7Q=8Wj`MOk-)i>xV;O1mc)P6I&8ALaPH5l-!>qsLbP7~ z+OYJF8F-vM4m<7@+Vgaxnq8(^X-AFBC$=av)|h?jHSwoxxa*ngQ=5`@^J3V=5Nk4vm>5fSQ<5;Ns=ZE(9Etd0ExlRrAS~x)^q)8<~f$JBN`Hbyf_pY`>N(ziqwj zm^T2_gBZAHStSVnRChK1xD>ZK8@GC6`nh0{1;g7Zq;l`jljyw7t31j_XPWB1a`as} z|8hqx@*}~U$0TtkI{@k!K=}+BP%&$?IOd3W5pYk;NgxBvTd%*a)1P87j@MZ@>$_l< z3k~nx;$nS?=AUu(KuxezOVl2M!gbEKUA zhbNISTZ=ugb?G(}+|IM6>Kq7fpMdBjN zK5{W_>W{Up!b*%<$+?Rq$g>fJ_|f+Vq&i>xxUAqF>zvBG_iBEIzb58_`hMQLv3)HABe69P2ahq1`4xbk~z^n1RM^%W{VRPoehXLXQodx(L{gZ0w6^|{a z&tN>HrGUN-#Gh3Dtmz}?ea6GwKr}PQ2?Wof+ZCvxL=WjhKJf4FHAKuCMzIalj@8WP zwl6Eo7xg{&gA7rZN6Km+ygbA>TdVLT9$e&fR_i;gb>3|UkUPaqTG}SIoVc|Eq@#Ig zTQ1!Fd*g;a*z|PY?QgRZV7{Dj;x>NiC6`0#OQB{T^1B*2X(HZ$UwX@78^cG^SSoS- zgEP4Q7-z$Y@3wm2@3xrtV|urlDA-}ri635eKs?%0T6R~2mIDx>H`T%ZDVvJsRJNAu zJd@uvxfZ@GkhS=m0$^xkXKM!V)YcyM)Ph^!wc38h{%lfFYJ}wX<7D?UADV~I0s?jv zE$W7MSQy~QC>pxt4EtC$tbKQaA@oF>$tzGyV=vd@Bf%IubkifG4YqOV%89J61Z05^ ziEBE*FGl_CzD>+ZXMxY$!gB6zhv~k^F)gZwwzp8E&pL~DHJ_^+ed zwI@Ss!x0Z608Hj6fA)UUW06_v)afq`MT9x8IZ3X|d@6_8UfRloJ+_SwvN`bx{grg5 z_Y6dxc3u%V|09FOF7Y5aGTt0PGzbV3_NZ;lXk|2TH_E&+2-1RBN=0H(9O*}CmuxK5 z`XQQ9=tiDG(9)o@0W52%;Q67lkKv^sD-2XZe$$TqGN2)pzGKwWj}Yf77Y3mHlI-fS zlTy8`uszo;i93>CMJ;#iwz^@g8rmCOW*bY3$975)jf|yABu(N+AFnV3d?lj6u_^r; zopv$RSNBzqGRAPs^eAZNEtw(S$Bqaj;!!=niLFaQ51dElQxEKp;{$+G271pQL z5V-~J_M^9q7377bt%G*=Qp^0paUb9zke?s9iRcl4vlF<_AHK4s$+Y;tD8Z@i9YK~L zEnSwPQ?H+@(m$pDD^U7(&mni``X<#ZzmqEXD#T^tBT5M=f9IJ^9B;W?E5bCmyB5A z^B10NG6TyVygL;!=4dTW>Io|9woCmaaYo2wTRwF~1d@|kY=g$X9|h=I?FapM(0>I4 ze?Gp%`G)tL&$(jhOpc|(ir>zpfz0sOlc*sz7)evdy zgQ$aR0m)dFb;7+$ez)clIVv!v<+{(kv%6WQi+fF#*(Pg2p8Rgjq(DUFVwCiF!%mKs z+7NsXI9*cI>S}7uiDk$v+!6=1dUf?K9aFe+sb-1tI}+tlk2}xZn2nVai8rf>0k3+$ zv$e+b31|y3cUwZY3r3f|3GFW_O!NMRx0|&7@&U8|^Z#Z1vPZ@sgFTWJOB!`v&9ezG zkR0H+ZKpHQPcnx(d}H#*g%;=sYy|m2qZAy|IC8#0*}C<|BN~ivR?rS}tLq&YOF7ld zeaKb|Ar355gEC6vM7+WZOZZna%-Vu1Ia^Ei&qBPW0KMm4|F!AswD&e-*afb49EVrg z00s)>)?tbHMv3$)qJ3@1ovsk6jU2sKl#>FnT<_Im(K$yZwbql{YFe`AS$A4)FY0#y z4C32q&l)m19o{xwPN()f(lY&`qG`BrLhmHb6Jj5Cixanv z(U7&?EOwqd zIzr3B_CzwoRkZ+^t~eFhf)JO|v3kXLS1W_S9c$onus`K-A+Ko5mm3lAM~dj{cy^=W7c*cln@U`XtE7{<5TU-646wq1R&+ zKET6m=1u|gleDOeT2HL5-!IH{vIJmK_5Pa1UhkO+JjJE7VDFn41e%aFB#)XTOPU>_ z`X|Elre~9euP`ev58L?(IqBD@5n`!OeWXDfea8+-AP4`HwWWQeD3*(Izd^OR(`-gf zG6b7t5R55b%SZ&YT=eW4P9e7tncozFP`vKKL$%(jhxW&&rIk+Mz?1M&`c}@$Wc~e} z35x9w>BO|Q+24-Yy7!LsJ^g3-{OW)W;Qk0IRHZYZ#P1(1Il@h}GwRPL^mgRV!TX1R ztW>RNsl$=Kgmvma@zx3pdj_){*c`%6Ip!FY`OItgim`!l0R85CO(Ri)N>;s#UK)f2 zpYQ5OvOdslUU7qmbhlgWnl=O%>MLz{-A zHwy8;!f=i}kveOIy=!x@;4gP`C$e%GwArNVCT*2?vRSi`ddH6oo9-Pxwx=0ji(qd4 zwsAuzgNn0VZ9zTyTBsq?RnF&9V-4M4qFIF5=O7+I@2nlWI8ky!0!Z61(RY?o=9Fvl z>C=egg6Tu%FK7ty_USs#M=j}0Yl@P+p9OY%0LEA*n}()^-CnU$dyg{tlOieiV$t-v zG2tt2NgJ$}%ZWg|Uqnr=yuqYB3(6qbPz2;Y-VjpfZLxbGKj!&YlIxrLGS( zv|E2&2w!yBXbIiT-9Hz;ztjY{A@8t=5ug82u>7@D_`88%UtafyMeHR7n@VurzUy)i z@UZu5Hv8>=TufS}Z+xcohS9et022_lqrcXwo+?)>gBLqLx@rQECBH(h zcv~UIcFI0#l7qiq90c-n&FP8jPHdJP?kanaqaq6)W%1NrSP^17I_YaC(C!)Vvg&pp zq@U&t%i7L*fkR6QZc2Q|M+Nt{4{z&B2$ByRIwe>HYKFUD(0Unk)zI)ieqebLYc z0bx_0VyIypC(4%!)RJ3~Lkc}#mdrvFc;1wcYap3TUPj!qM8Y4s-U1KF?%^#P@MKbt z?_*nfRf!xnZPlMZ>2OMg%3%=nB|qb`VtgSmh-;T)J>j8c7qM_$4NES}C6y3^No7#r zJ?^HpR7I4epG}!X*<6Lskw9G7#D7#p1)kkuT2w%+x2#UouGmugolrjc`N=Z)oJpYywctVQ#_9!21?HNVG_Q+R_ns8TJreuJU6*8 z40WpQrEE#nq2_*L1R?W{U5C&q9JXoDn1G({@SOGF5tQ^QKPZf*`` z#!$tGQ)gZ!fyc<8Y;8a?0cwMonon#)Btl&@nXZ=su5US6UOQE~(ccA{;U9@86in+; zjSB6PvZa-mND~2nTz98b24edgWM@}0XPBIs$7QERbZ7PDDUHF*(bW?_Q|+N^gpKNe z&G-D%?%U?L8}$B@BH@||5}5^i1#cG1l#V#>`!Qh^ zW61G`I_ILFMDlgU-Bhi6BOU_NNR$w$IsuVMk_YMfOW9rXyzOakp~2~QWW#Kll_ZZV zM|7-Og&b{hewsiK<>)g|bC4=&)|@ZrKQ3jWcDk}E+n%8|c^h!HMneVOy27U8x%P>2 zL}4W6wz&M!<-w-e1q$fU%J9>ZNyu~#s;=NJZtFI9WIS|1RrEkiu1>G-s5OVstpiT< z;uCbIJZ_#&RULkudpk1u(Q)x;jXnd)U5udwmB2P>a2w{%YDd`_jg^sy(w1by(%isx zCP%4xPi%2eDIL}&W*`c;dj9&EJIx+g(sGlVyOs*?8RM{koMRWPU(JwJH75N`(nQGR z+aoS3KpOm$t}wcqQXZk}QE)&`qL1xn?EOLe9 zPJK6s+dP*#$>G)WLafutMNK|dCix4Y+DvuM85MzxpsUTxwVmOp%;5!i*Fbv~>9``o zR>Gwpne?pQ^FZg<2fEq54+A{0C@2z8Edadt!^P4O70?}{3iL{Mm|dE|+h&T6OTktj zLv$xRXKZP=fc}Su1{u!m_QWkl=bV1@D1DKOPz7pb23+Q`!mub(CR@UMKM~nfE|@2v zXiFhz*w^XLCW^+v;bR_tj>)Yys`x$|8Nhl9r^~Y(X13qY!A1Ug9~bt8IM#}vaMBCz zn7P6$T9P3`|8qmdQS`(MdAHz`?HAdUN`=n{29q4mo=+H;$fRgtvq^*76G5$pi#`iI z#@jaag@t1m|LnEdk~t|C)|r<5_kvAM##)}f08~u%& zxzB6?i_EN31k&>Zee;_>H&6vNO_ZOP@Lk{@a1K|0xc}V`-7V72G?5!FpWleiLhHa& zzmYN063S}_K?@u!-($4Ew|D!M{tjm5*ZoZs_-7~uo%oK?1mjCjNPR#eDmZfNkxa5nfCS?l4T0zdQ;Esrn(Ga>MIVIie9CVLs}!_x6*bw?%udePTpA7IaHBrMMZ z0)L7>)DXB)Wiw`Eunt(_?*A&fc~?rl6woF&O(W9SB_0CQkB^mrI)Tk{hq7TRB8S}s z*CCdC?O=1^fuc38R>v?rcSq<6JX~>{qb8#UXT3Fs&2f*MPA-MKE_MMp!#R8Cy22%b z^N&MXM+s7ETjqeRonsHfi1ppOAXubx-)>+XytByEX;3qQ&pJDl?SrtQ)ZTy zw?n=c<;hEsk_*m`Vs(-$e&T<89S%7b&x1^IG~0yrR2jRu@#-M_in6-(y@jpxfZ$ZE z27ZcWEan{tyQNIC$#&bK)52`k31|rYc~19r9u*u!u_sCarF|wXd&7x-Tkeq0NCE#A zmM|t*>ST9$I}P3k$;z$^*NT{H1GSG?>m7iNx~O~GzqFRK9oKM{jnYJ@NC$Vlq2@6^?&Sq|hnSk4Xo9vUIcpCG^r?uaXVA0f3?zBFwO8 z*(;^*A9%Cb_lPCcc?S&*cxS*Krt$qE_jRF*fOXoNthDgXw`0$LhJkG3T$}b7bK2gI zjR2Nn7h&O0XbwMEkOgf!{`sws#?ic$KvZ6KUi)-TZx+f1tYI55( zIG5oto^dU)1sOfH_@@I)g3;zHI}!;_JshAOcA3uDXk^s_-Z@EX_E|{3 z(#DKa+1L?Z9F2q=GIAVgUkOinkHtRWfvCbj(zl8XBsZM4QWiIx6?uc^X3FC4b8*Ps zYDHR^o$0X!Od*z6erDKFu23r#$JFrGUczGn!1SQ>pHBRY$6s?WQtjPxVP513yLqks z{VHaJcAA7`xa5YWGbMc2S?95?KdjFmc05AH1$^9X{mX|)-6gFf&vK7Ao_pXOJaa($ z3H#omw#X6>eeZ*R938#T_4Pms+r0x(-zpIz+(#FD-Gvr{%H9*B=Z1*3-;jJ zaDQBSJ)iGxL)OTT=OYR#Oqz;#RYPz?<7#N6PRBJBm3?1to%<9Fo;8|w;;>e*Q9#c% z6{D>sj8$=f6DF}SaQ2+{WPA(uZOi(qyOrmE8r7Zxy|DKm44)kO*D2jw-Niv8Bw5tX zqLL7!VZZwD@K%$b;=43z-_T6N_!l;r&akR0cRVc85pbj*CmII>wN67m%Z_r5wxiz`jZ%gQ;8UD*b~l-PH{z}maAlf zEX@++rahoj1~1_``0S!Gr?)evrJw_#MeP>H^*wE6Y``3rAbI{|M)o1qM*Ynp&oNpa zn4DtL)`UIT%+sx9`v8ACt-7mo9>})1Kr}je)+|-+t-4yl+F=pxCpQkucRnwX8(hFL zjjg^wJ66tyhRVEU`YrXqWtH#@Gf?%~cmiILJL?zLK()vf<|_?pB(Ti4d` zJ8_sdd)YUO@DN;OSb2rN1XlO6+_x>??MZfwNYOF>?(2BZh^!cS(l0)7vMMFf@(@}>e{g8ykLzj%ljH5MMYzu4A=d3WR@~^tF_f5O_82fZ<$I{ z(g$+$?*uwr@Ua*Ql8J6ws5?>Y{)kl(QkiB6sQ0nQR?XZ?eeYBgFmETd4Mya)Uw_uB zp_pl_tX~5WES+oQAiGv&A$_KmgrrcZNdzz3!1h2_^TSi*Ye8D99upOU z-ir2>_-^*lHkAYVanaY9@dIdEicBHHKP)jj!b_pXU4{Ey${!~W4Ma3cFMi8XExse@ zNZ-!C{Q-FT*t}!H>2==ag~dND$}J^Q;+LDhZn(*`3E!^Vn%>oX+2}mv+zbTVPHfVC zDOVivFXS(O(V#7)5yFgY_bPHr+gK+SU$vM?F;68h?+lIEtNSk*x?^jEgzKh(?lN@`U!GmSk)WQ*8T3JE*pQ? z20_xyf+Hgpy1iZ+Z0ki<%=Wf=shvZ;so~@dYS^pv(y2xAJQkhai)BXHW{MdbtcnMY zaQGCO?!^`@HYQTWVyg^d|ykU3xIVjiB2^yQ=6+|`ud2Y*@ItnefS+6spk zY~N(mT_ydM76!!0_D4U(JnsgmYeDA)8XS2i3t1?6&ny_h<+d+l}+jwV2dT?#Hbrkzr5 z3PEQJ@20%A<60hDvIHI-gBk@D665X^{wBV9z7vz=J{!D7s&I*JF(c zpMbD?d0nSe%4E^qIi0AUU)_&pb(Bi;qGCR44W0}&I$wSi%4$fduiRgKDk5jZJ{?LQ z^+lW^VcnLtLP+`eN}Fg}!lkv*^qsvVU~KYBq=mQ;T_?9fA+{*omKN$8<_7NGPzp-% z0p333$ve83Z_(DC(OW|XB~E^#Kqyg-*#y4Wp-}V0gpfhOCA=23-}T$3JzlQU+PX`u z{%6cX9vuCjh@j&S-B;)qI%+-*TTPlAFSlKBqZ$PE@k_1gSSZ`D-6A_%Z?_uXam%75 z1-dQkB7-fZ!kJdlG9ebb5 zv|DuHJ=>KDyujBvm%A0-VA40#t}I3@)(lPb6CrMngt^u3Jy|qqHw;B)4+w($R!%Cc z{R&b-P{)i0#|Fm~bEyIXPWq7(zkoELVA(b(%kqkQoapp$DpZk2H&?C@|DxB(ZON-2 zy&h)#6B>Lyve$@jyRz0(u3&yGlvmXb_o-?@&Iye~gUY42Rg@ICf6cl)27{moKWlVu zCba<`vVP63?&E&pF?SX^?fbK_=(Ce}rtO`@Et+3n-auN245qMnk zox>edSSJf!SNCG&mR6)piuYi)&0RsfZi5U%sM|g}u{heoev`2nv9s!Kv0vB&{kunG zCEt?%cZ7o%J9aXJHd$tjN2+Bv1&6K}f<@|FsB9fahMkM*t3Ac=P{hx|xx;b0FHMC5 z&j-Ks71W?#%rk@@hN@NgMjR&PpDI-9jnA@5AOa!frmzu@f(i+&*~={-m70)1VP3`7 zUETsW-@=}z{V4&Ww00w}JDggc^%OJ+bfxxXrI}_fImCb~1*K%xz(n&?PYqRL&&4_m zF{bude#jf@8I_~k6wBUcD)-lU1CM(MfAu(V*i1}Dh;9r2?hw$&>_@RCnrdfkF4jPn zTt=uOnw0zFg=Cf@Cd92Um)K0b19cJ=_mbZ|b;GL^lsdccptE5hVEof7IysbY-DbCn z;~tWp7%0zTBo06Cz4T}~?~q3OQ@?A$Zt6(uR)aiMCTo~y>ihFQnjIAmIHWM9f-^jpuegje>VIW}H%@xmRsACFoEu4o*%*gl^j%^XsZ>Yz>yeE0B3 zQG>&PWq>r1+kVn!bdsI8Pt`kTxBF}E;@{`))vD!()BjF(P2=*p&<=GIqf>CP_TbYE zCpgX}#t*7pCL@W?NejN0ILB2Z-x$8_Vq7&AV!q8Rosu`k1dktcQ8e53RlLq^X5dGN zKLWtoM%`Q{r9Vz3@q!+Srhg(*9wkweYS3fn(mUsyR)ejLWIGWI-Q4ohs?JK;&_2cJ z1_4)?!4}yjLvC34nc+cW8{igiB=6NJ*R{ zYrimtF#tWczXmS9EsnuzWMozSK*){~(3}(`z#5N}r4mfHVU>8qK;>S={8~-P##Z(a zu1>3foNX0AK+Ug%2cK;fD$kmX7m%;zS}_KKay0Gn*0t{7 zESP%=xfOa5E;TIi_6~plASE9u@gtF{SD$bq%u6`iy4K)jUDrzA3ru}r-j%S}nJ|O< z4d$Lh(=uBUlLa2jq49^SdX^!FSffI3W>Ds@36&wGR-)+^@9L;de2dsH8q7V@Q)YGd z3v}2H&dtoX`M8ipM?Up+MaL19DcdKfl+7kIK{N`E*`+G179-@! z!Z#@{p8);E@1Gu*7sven8KEbv&|A}6n&LawY%OWmdBL!%0#ZAgl5nnhpy| zt^Ar*Dz_c=l=D;(qH{R(o>ws`j5wpkk>sn{aaq;R1@C!fo3D{DUL#sgmOpG0 zA~K+j(uJZD)JC}j4~Kqj!R|}hb)qY4f)Tb{>?&#ajics+Tx zoPf_D7k-0J^x75;tZT;5O^Jc@)n)^CeR87+GVJ71)Bs&Gu5etP`$Tj32EJ13KqovZ z9inYRU;gzfY9p*cj1>7$Ov0xMiD|gsIF>v@bV^{L3qn-7>A|^oBmSHZpw$egx~mP^ zHF-^fFh!ORY_Vevm$pVxvgP+EE? zA6BQ>PY?)iseNZsHx|ejK96~J48t2YC~+q+SM8hx@W=TAcIXz$lQUf{J#mu}tZCcS z|CmAmpYE#Cv;Tg!DTjdPS~^Nzcaj}DXB!wAoX~ag{L!>6_v!1z;^Q2GY~p;EvTBpobfuy%e@u~ z-Z+96yT{9uZuQd%)c9hyV0|W(hQwPvc)gsey}m-|j3Pgj4W~g16Yt^Q?jqWPq-u4Q z38~B2xMefDN%$8IbePAB7UNQ6-)kU`oMxNXZaFcRp+{O8&;A-8xsH;y=|Z13E85yEOp;^Yi8ZS}j2LDWuS z-R2?cK5$!Y4{_2ex{KBz9%5N)Tc=e{{D!!*UG&O2{7)LZHiue5fYQS9+M3YemQLUY zOBRU)nWeWSwiYYM2He)Lse*lZi^kCCb2jAZ+Djes`^>6_RhwEAXqR|1`1;3O&37RQ z-au9p6zUogeR036*7ZMnT(ZmY^%t)cSI!)&_%G*h=SCD4&(2OETpWwcyvR^B^bB{O zuaLjY*YanQwkydd*Ps?ILFl%p-rTE7pymIx=9_YjM>!S|QF72eT1CzLaNa<$8GMgl zywxPu_x$~*a%5Izn7TY9OO9!OtD`~t(?SqmLXtFZNnM07@3l|6+D5gjPBKd0O-wD4 zT?(6&dFrJsvd7n4Y9CnWFOW#W>NT!%H*HpXio=l4re58aJ3YVdn&P%Rw};gbx2Ww_ zjSkNx^^NbCKT$J=Ba7ValWW%DgWypZ4=RR5c6mHfDWb}^|K&{&tZ^N(y;38xvXu?g z1GB&>`EwXHQkO!C1twpYbu@Bl60N%Nr{mtE)soFh4~y25<43ULQ& z@a29UtJ=PG<4ThoGTvT$`{dphMU1qD%--b<@k$n+l=klQtoK-(X-uYC)z3hI0&IF$(l z6Vr%X++_dwsWi4Ch zkxXSa(AaUuWzm)Ns;pf18V0EaZ;I9mIxd_szdwVOpS>z}3wK7c<+HK&)7#FOkFUKU zgIVGg7J+@K^N&sQf=7KXOzO@f>(N_K%zL~nX}3Clt8mm-?8xUbgM&MTJ#!6rLX8X& zPI5&klh|LGkkdiUEgssJzPYnnn&fKI?H;_6!xv0g6n!PA>B*G4dX7VI+lnq>rQ*94 z%KBdr!^DdO)|ECAoGf}7xK30Qf$ zeO7O;FHx&$3n6E3quDfK`Omj?RWjcB--rD{XQ7lhxB5Svrya?!$tM(64?VDOSea7Z@zYxV1LxxdF7IbC4 zMb<;b@4V`qb+MN)O^-iXJ47u0YVa@TX_QsXzt+k5d?U1Dm$y!DwM^4svE!1`Zq+-l z5iepkJ5S1kMVpKt1Hm?8QMXyYer|}~{?Ig&4!G)v_JHgu?+_acfvksvXv+`8K5*Nc zjhemzMXipei0p)m)PwZMBl4A@2shZ{*j!?Zq@zFOiov}I zH(VjIu0TxQ758~2i-WsJ!YZm7o9o)sQoxUe~HKeA)wyr-rVzR%pte311I ztbiA``j_X_W6hbhx ztu~>fy>E_J+Rm`_KkISN@n*PsHUG&sJYW(r?+K41LC*F*YZRb&zF&}B&F(dNTaw(= zl8v;x_GiF^aoEt=@c{D9rH>l1lM;B({^z%nrp4cY*T{)W1t@ap>aBw{3u&ZAFAxl3 z57(qAR?Irsd#ZGDW~ z{5i3rDFTp>XfcDwYe?9=0!kCe)DbiQ)PZX*2Z=v_*qpzgnU&lJIvlzp-L8UOrV{s6 z|J)n>J!7WTy8Ug?kb*RcVa-lD@smrRKgm`463Fli9cN!+ms7#I4jPrnnFH z?~FCrT74m2&hJ?+HNR4D-}wIHgplaPK{3)TGfG$blCY5AiRPTXz^tMzmJXR^dVMIB z!j|BNrB$@!P8T-+sksCouVUfV8Kn@LA_;^D!+-a1?FwX4K3{;A#g*ub?Cfm55uz*_ zF_z_LV){CO?K5$z09Bh)=VgL<{p(3?(|!S;dVLeGm$I{mmlH1OP_AEJw=r<-fxfQf zS4U8fL?$ouI+d*{gP&_yyh--WYf#^ksQYRr0C!8AD7XVpERtcBnO7%wvnXGU$}h6r zaX-V^@du0M8p18=(O=*@!>A4e|LHbKzjG--Xt(584%9l>*`6|#IwI1~61E=aVtZF@ zY+JhfFk~$W9{!=NA@^cs(8%SmkyoJ^g?3d#0%0tr%TA8zby?-blij_=oith@J`A4g zUOKyQla7%kaw`%ml8$BJ_)zCI-ZgWtvNH za$ns6Qrq#E`zxRr8T(VqeF1LcVt+yWGoXP2MJh_;B`|7VJVxA+Q(iIbk_I`Z~ zw@KSIa-xA)P|`cgm+en)og81yO&ywfFZW0ojy8|NYpIVtZBH>m_rBm{B{|vEK@dB> zg_k9hO^g+X!_uZSB8D&4*dtem42INDtex-Y!fN%SwB)y~3>MX(jjaWfShGqdzdLH$ zq_lBoK~|~Dg#1CSyd~|s_+DOW@Hlt^K1MF2ton0B)nR zo-0&ET=72x71lm=0|p81^BaRn(L$hahf<0*76p5iaJB}{>0MKC(EvaUgTWa%{4XbQ7qkPM*6 zODJhLrSQ`BR+y$h3aT{u`ADtc>i4{`*)sDo zC8WuLoNu4=NeC!bCE0_M#}e(beW$|2{Q*W0E;mRz$m>^VrD02|E-?=|mFHWD?pjH5 zPk`s4#>^!{EO~G!lMVc`$gZ1iHfJXVW~{3)AfKRV~3SO1h z$F>P38^K)A49ywYy_K-j44?>NTDxcdZPcn>{&&)xumbImQ8}G z1a7T{N|AJztk+lVaWzKSkT5;(S2}4Put^o&xJy5{hn*E6i!4>FfcCY^+Z_5YUu)Ro zU|Fid$;TKF>rHvX!8zbO&1}^NKEdl3Q6^&;uUy?>j{~;ubs6_evVDr z<~iS5i#QT3_OtsfO8U$^H`v%-@p~Rbec0&CLbmh-xXw0Fq<(yHNnd9_^KqC^|PuYLr6-ZgsgZJ8UW<+F)28ed$0;aPhK?i;CLvSybIZOLQxw{YWqdO3f^Eld$X_|D>M+} zW59q+(353rEzn2yxcCQ(gUe}z722oR& zo4Zmc9qaXz)bXicg?DkU**NdcsJ@AU0$tu%b&Gk5q-zH5EeRsfg)sXDzB_akbRUZG zG1F;0;&$HCpt8=ublhb7HCsU_ua3A`8eJqfXp+4?YNj%Iu?J07`x9&&D1qIbuI*XT zeMM-qmGE!wT!m>~9(WW2FR4MnR9jP_rKfZa>SWq=p|3g8Ig8N08(lO8E8Psk6_l>=bEr|~5s>Tlwz0F+q zxa#JHU%uyJQL-nS%e3rYtt<`#6STirZE70{w!=U|`Sz@wcM3Hw*; z;&^Fx(EVTHO)k(sEZ$f!UYT>=(S>&$k6U!`h?b`~RmQCGTrdXstdbzUPM%JqQX=Am zCU@bLun~&2mPur<3AHEtu_o!^LQ;-|ucla7pm|1)RU7_znYlF<%^0E;R)&?%!;N|f zsZ%vV<;8de_3G=Bvk91a7@>@jl5N+s5o|bQb!xfB$36k8Fhs}DVpa$lRs2)s2DZL- zOV$>d<=v|+8aq*Xe||)eXdnMKelsyE@i%;<%R=e?mz>aZD(V)1_gm77l<8O-0774r z&*%2%`&^rYg*r(6+<7beYT}fGG+*HP^Xp(|b2G^1{x##dbR}Pn#N#!ksg*4+g zdYtN!Rt*N%Sd=y=pjVqHY?w&lW=)kzk=mQFXQ;ptELu+HPu+IzSt$^4w^Ya3?W+!~ zhCX;}cR%_0R!W9g@}~1f-k}gaDmg?OVg==_6w?7Mo@$V3u!YOzt*h%rPMvT{>Y4h^ zKHJJd3jI-+%(%yaHaH}d}2nOJ8AwF!Mo;78^_C0TGnj7F+%m#}uk~)rwR`OLsZV>o7cWpdW zta&F@QZ1f5{2`Kl?J;l2P;>ON0Bf?g^|aI67N}o%`X@zEV36=xbH#*L>UHMreymesm!owJCs}=YeOH*C?-uyh*#OvRbF+;yR=RhfZ^?>!S8x#9 zy4WfO*G4VtkHQr#xsPQr@Br`|9hM`a5{GGiPMbCq0pLhep0k2xSToTD0SC3fAH>SM6QLkSrIaMfb`zfgCSPO@c z!zvq+Lt=26wdunOU3Iyz!NxHoqH1`$SGR-;yO@;1DPOFCxDw1G)+-v9inl$vJEvB_ z691Nbd#PuoCs^TJ78z~Q791=`al-bjj%-(aRxSS)91j3-nToY3L+ee~q|h4SvMpFx zrqfdp)f9>7C8^$TZ7JIcx3%2M2XLwr?4Z@`cAHn29hvxS6WNhO$POE!GclfPQvUcZ zeMGJvh{b9LxIZJ=g@4Va0Mn=Zf4Oe5A}cs2qEVV`G;uD(0fdjw89n@(U!~7x^vJ!( zjNKoX*Ho}^j&DiAhm*c5<9tuf2v688ejR%T9x3xhj>gFq_w-v`j;OIbl88DEm$_-% zd5~{e5#)|#mI=RB6=oJ5*!g0x{W_)?6BS%irf5&eL}rGp?CsTbe!8;zC5s+Q?C{H$ zkT!a|>gc~5R&<{C`PXmT+oAZM&9_s3x-Rb4a5%L7NTDI=RdCOHLYnv}RH%Jo-mCdj zr)LLig@SzyKM;q@s-Y@FPr;s5S!?WEPMkcc=8~36Wz|!O@A2R{(EXySYVQ`Q)AOAT z{t=_ttDxPkk0zKH6^AAE`OEJOHIJapZ#05x{-nO?j5i>BTe&=rndQUy=R7t$94zY* zkFCrx(^bERlxU1|0tJw_9+!msKuWJPdKK8Ye8g6SMW}rY9XV-hl}m6RdSo5dEYe=f zc(rLYYj7FWTS`b`t-}xWqlP@E5d^cu@}s`25j!vS@bsCWNtLJVYbTOIQ$zin3eB^k zFVs9iOn&XNJR2x##H%Et&2iA7Rj@@dl*HB28?nto=0`AFSnJF^m;ELC?dg3x^535N zAO48^pN7CWy=6_UUm0H@vUX{TZL__}O*MhBFfpZdKZhveH(Eu4H5mNzsd8dl-kti) zjT)KYP`z6vTJe9#I`eQS_y7NoR4O7ZQr09zjHR*+ z&Il7SjAf9r4I{*0tT8hfLyT>V<#+e_p3XVf_51H!UDx@exx4T8>-Bs-p3isV`hKWf zFDM_Cj0~>I)BObq41f((@~Gaq#{Knn5_I*#T8-&v&ZYgYQMX zt~YdNncfKT3YP)O0Cd=ygumKuy+RxaVU7=#IsT=Ws#5Xzpj>IfRJx5oq;y}Mg3*j$ zV!4tDb^l!$so+9wNyj-|n1a$|pan(Fh-z9~_;LFA)ImqJ8gLb21F0%YS}izGFPMeB z?EdhjXNGu1^tH3S8&E#|dN#6|3_ z;L+AQMS$44^Q*FP-=8BUH1`~(h}0t4NfpXpYYhB*cgnNnFB}V=1gj6m|-9 zhu1sjnK1h?Zs`7g@5sJ<)q@9tO~g9>K?{DJF4oDdqz3ptlzlr|O)uYXki#tBaPn^$ zBv9?I4nYN9OY^)}DZXK=usD`5YAvAl&0eXy3I@`#DkEQv`0Q-!J{3Bo0S=-j`8d_GECS~x)>EMvx{DdP;2WY$)%L+{S*t=)fQ^rg z8A%~^JPviXj^JVIj<)HsqT~Z}ov(+5SBAe0+T7M0Y3Tm~0cpgwI^oy1>gO3rD(;9S zeDH?F%>ZF9AGfT}mO$gau|0R!QbK(hF>2a4n`g*|X+G67QNLM0S$fJOb!|4|Pn+}P zb!h*eBpzaT@3*p(`5zrMnv_ZG)UvHe4FelPXPCZL{Qx!QQI|Z+7XE^!c(Oq=kvjMB zTe8EL{4pbq1D1FO@f6t@YbZhffUfc?({8xa?uX=~GoyCa_%IoR*7$3hDgNN&AvJoG zj|2q{Is7$Sfuxb9|*m{)PHzo6DIl4$J`S$Qx;#YibwO|spoRJs|ZiVeyW z=Y`BS4&noxZKYZ-G^&$xjEo^LKV3(5i_Rz7;R2*{zM36(HE=dh^UR7a%5#USet%?> zSe0^;nw%0l#ExM>(?rM0c)A+Q*fFQ{SyP$}$EK+e+h1 zG>?7iQnA&L{-nONrB1G&8KJ>#$BVX_!>hQ~dn}7dsm^1nZZQ{bec(v2OF9|nz(-$+ zzYdq4NmAzl?Stx6x5hLg*KHU_op&PznZZ(oKfxKqk$)G-`l=cNw4R_|r#nDd=qI*` zvcK(IO2N?Ob4L$od8*_zDiI!>nROS8isHTfZ1!kO^e-f1WPqwgP!D_jTHhU`dqhv7 zwrkkdt2bB3dAibF`#8;a8xcHDxs%NEq|KqJd_M=J0x9`}CdKf@MK8JQTHx1rs_@50 z1nW--`wrrw>{0ux+Xq&JZvl6K@nBQb3g#K& zq@)@bL6-(1v8lJH>ZWaR5?jY#c@#D+!QfktC?nkHX#{_M=#Y~^y3tY#)PtBuFW8U% z27ePZYxw|8j*=yQ)DDwjIgMA`ZNTkX1_E{K?rn&YzWQ-$+q*L9u#&COq1Ej8Lu>qj ziq2=H+~b=U;98ZoM(mm3@e#!kqCX`o>&a-C@cG8R2lT&3ul#zj)V~DW<#S&eH&hwi z)spPig8Ahs*~Kdn?vmzu`BR~t>O9jvto6@^;WX)RzTMlMq=GF$(81@+Tv}O#<}rs+ zBkV-qQ$U>Y1T2lEi}FIqPTDxK;@i3#vdpw`5nX*j$9jEiMu&Uee@x=-McikDYY!%${ z(5L6^1bCb|2-GhNzT`&scRgQzG_$xdZs^>V&bo~Km@LU5(ni@#6kfw$Z4K4Z^tmy_ zFjZ!RhFyV6Bj&{FXl3Ua~ty*cfBowRg7X~-HF(_mCAa|63Q+39j-{z zkc{2d@E{y2fBpH6vHF-EO5rrZrrHCYAmwM5NJ&x`(Ng|3APb-tFLybeH&{~Le_kKv z)qj~_ZN&5L69(gBFTIDlFFYPgt%2wrAH!78ALf(5F!j+NoUha;c)gpu*W=&xd5dFg zi?%F2R++lw5LbE_1PCkMW8&!m=Pp!~TP?^Q9=)-l^JvGQEqspc zsn1d@WrVVfSs{HyJ+-;jFgkq!ZRL+UNi}*C-G#9TAr8-qHNmp9pOm#@fX{r5WCipS z{lb@bMmGiuRkZj@rwV6YT`BVLn+8enwz_)CI6Bm@wdsXd&g5Df)i(MXRusZylfIJ0 zdpbr%x0r~*nT0&p*q+$vjP7dGvVWZIc=cOYvrkJ zX^~e`VLdc>qC@H7ZIiar$`P8+a9C;P_QeDT+>Gg|I#@qinrW>(E>i6#vV`qoPjuv< zs8D>eTO*usDxyE@8{{Tb_l#M2$knNVJ!Ze{n?ED*>;H^U#_7vN!X$9%$Z!$gB7S)l zauMNZ^0O>vfd0AzFi2b1*1z=?BkO}FlOsa4R)0$H0Hc%lThxm!MLg-sRnoNYdhLtg z$~En9y$iI>?~eAvj=cP_Bb9oW1DQC=ZlqOqL)urr4MW0cY4Hvml86M8SyD|O9k6o2kUx*A|Lru(kJ(0vcB>2;0c&dq0d z4BX)KqKdh+dIFzNvg-Ud?oqQ!-I{XUCJGqh)(?c&Wa0{+A7X#p8 zZ$GGO7oI$Z$&EG{#o zmOe;kE!Ydh&8qQd71Liq`Q|L7k|N7ds$+`6TBiDklZAgR$P6ic z5p11fIGDDuQ6&hUmXPGupT5?okkbWCCQ?n&=cFqKBV6~$fk>Fq{c5j0AFE1su@1zt zsxCuLuKfXhn6bIyZ-4?TsVt2Oax(l%f&ISzHEwSP@YE)L4ux_)UqY_Fqx^A0U$0ER z-}g_nq54FtECe&`SQJu|$GLh<7_ZIakkacxyb$Czg*yj|(vY*0mqdX0K_2&?UkrCv z`}rx0YshjDOKY`AS%tP10Gf_lqP@*|v%$4M>r;9MwN>%E{u+#;0>WhuiFW|}1Ne(y z9%~)EKvD-Dz^H%+Se;wVT=;n40@MV*<;UZZC841aR@+>4NmF|)7YW9gQ-od(>+Gub zcy=mZOtWmPhsrV9)1=@d~05Q1Z9ogl{L$cn@SdS&XP?|C5vC|rBlig514+VzOtFv zTbj9=Z|7zQJvZxm#=j9Ayu+Hh8h2LQ|2@o^3-|t+lwKzuj&!hC6i%SxAN1+9?`wZ_ zr?}U3s`X9fA&sU0nCDceNBRd#^*r9haKU3cifEr=gU#}j)by``InlV=*5AN)2G+Mj z5@(P1;v~|wyBc0S+~9cTvLqZ^JV3j%7VTngcvHoA*9oC@NIt%!{*rxxU>zvGBrz{~{-S|9)5ZPBFXzU5aIWpR>7Z2_C*s_9o`C&lw1 zi{mfeCA|)D&U=1Y#e2cIluCe-%QQDI2aS6mW3yx;a+6^4 zQ&^aUrkHZB5r;Q=u}t#>^;Hu+9|V8!%BeN#4R6+@y~? z`l-Y^6$uGmW<)qx)2^a6<&Gb+~+;xOiy^TJbFn@K6oF3ee(qATsr( zUbxy|f1CK2I0;$|Xelkj!NH?@pFCl*`H(7)G(i9X+!P+N5u)bEeq*lKyt?!xM-ojd z_Di5DNF2|8-{Sy(#SH*$3SO_eE@t_*bgW*Hhbanu`EImN**v#MeO2$+nkXp(fCX@l zapzY-7hDPD9K%sb zI;_D7G&zSIpGudU*k*Fj(MioZU5iS#xO=XD`Y$?-_#SC^Ru^3I61a640{Xu*J-J85 z7U{EdI;LQ+zs`1Ux1o(PaB41+G)<4Ry3Jp>;3V4dJ` z^-6v2TCE{H-qwi?Rq>}HtjuHZ^-ia1W6*~gmf`3(1FX)GUJ*|3$+fm{|MFc`hZW1g z676coDlc@Oif}+#yRnKF@BCW5&(ebz?+Yy{0&<^C7rF6Xad5e_Ykv{#hZiL!UNc(0MOyeNl{L9jU=81EhM(SQ5*ho20a{wQ0v_vIU_J8aAv%VXG`0EMsX=11N<`|!Dd+g_{@9JoY56VE8?p4% zV5r-+HqSI``nV@xj}pj$=8x-4|MgJd$+T|@Yyh|n`JnwBR*6|6kr5(-KRaoFQb-$I z5JV;nOOi&Z>qDW6JPVZ4RaXr|%uRmCAz@LTSPiq(IDn6>QtV;Dy|pn(ki24&WR-VZ zZ-K)@o^=hEf+G3p_>W(Tiak`q9IW}4RQSTl4R=`5q|!(>6Vk@0o6W5d>tzW3RFNdD z0Z`#SilK>i>*SF6*WN0P1=49cE|67&&=9GZQGQiXW55bGSq%pAu)v<`z-mDN?wmx=0^Xrxgnvu z-u89WvZ}b`!qZ_zp9j`-MOp?m??T)wf6C(R@S{}#`*iP(xX`RU-xF}I=uX4dOK>)qi{zM@erf@tXkdrBtf)> z3dh^Ca@_lEZ>i~YsGok7Yt`-2q5sRySI+phVOfY_d!g@gve%-0c9u(g3nWwsVUsun znk??|B;2m%CSxO%=_Vo^p!qP7lFCl^>()K8`^E_jyo<50ksdv0%;-YXX)3euN9iz4 zpFze{4INIPCI*A^Ll9tNl&8Sm4ZI=M27P&$VxUtU&@zEs2jhgFvDlq=>1nnm|DFOy z9RDuSm(bU_jCw4-*cWTqT3zg5gs+-ca_kd-J|=d!%M_VAQloj#%>p*XigM1vae(qa zKbGlv!>PQWIAl{0K&|q#Ix*MRx&4XMRoqDfw50;%#M@y4ndwawe6>jCZ(Bovgi~g& z`J2^g@?RxAY~3K5MD1i|mlOm+yxtUzRB_@X&(6PQ)P4)?9vONr2!FnGzTJ>|>?4M* zo68aJgJr+LqX3RZD1E$p(HB*$zGQT;;Aw5i>B3xc7d8m8YNz~mtE=l)osXQvlhdCp z{;GU7XL-q$DsiTn zJ+?fepe)96b(RZ7ElZE3Ccm;f&q(<7bKMn;UbG?YYe0lM-_Pi7OREO zJcL@SkHH$;;zC_RuEHZ4ZRWz%ouSgFX5CZv`u)}JIjLDI+3G!4)rp=xBlrPYo!5Or zQloJf^`h?3RLY41y{2;wCBITbd^1E-C}fs&lf!KEWAube2UthnY+kNxCJVp&JcU)6 zycwr%{%KqP49yufmPQoE&bg;diPgR^G2TPn^+LIY^-HZNp+s$SX+}>i-G~!yO*)B? zgJ5Ip8EgpOVCZ5Rt7zi_D6on0XuHVqH^tL|{1X5Ijz7ddZ@!Vpe=%4Q2p5wO$KL7W6J<{XPiJGI^eushnHE^=sA`9NRmRr8eYKq9u^;( zNIeoL`l<<7Z$F-y1-4!QW6Wf!IwVGi4q+7}s2%qS9Vv`)Xy5|c+D!o2PG3|ipQ$Ed z2mIF%tA(RCdFNIvDF%o+lLK4gt;kdgN^ESS{ElCS!~eK~ZnWbkSP>JqgNkjLqJ(}PRkrz}h(xU71c}k!9AAbaz8nS4T~WO! zH6fvClc02Hxez0r21UK34z*y?fQw~P*}0P|zrv>BB)}hci7q;_s!`?M({>fJOML^L zAi0JfA2Trvm1!9JiG7}N(gj;RHV@6%C=}cAx58 zq8GP5+<+bA8U{KPflu$yjGabq<($?@mS;j-9^@{aTL^^PYlg0CZ^*>1(_|Y1)}9DA zs{WC(lk>R$rQcpxJRSR>nMIwe%Bp=f?R}ZqXyOUbYwRYp^(kSeU5{W*(JGixG>}TZ z^a`#uQho7$!+E0r=x_3%ykX>gm4DtH2RHzinzvnK%l&FA^OrUkQ4E*bQ2{hut#~0y z08{&^ZE=JXaI^A$iSkglk}^YE!ijm6>G4y;;Nf4rMc2rxJZh0Ggp}ZOL>o}oj+ag-#egx#;Ndo*GK&e9~eOC8m|bBV#q6tqEg_ysd03_sGSZWTNoR%&;MqAw{~*LGpILs{F)d z6Y)A)Aw2nr-}KLtQkKF}eWc|4-aDRFcl$oQOL@|Avhv*(fW-RIfA z$~(ma=0w6}2l>qkTQ1x}Pqyy>`J)fEKt-1jq}o#zsUYsGHBOxi>bFd^!eI(yIs`>` zO7JbBnlgq?X~a^ZQymQT**@*an(;YLRMfI%2!8El#8mAZF@BW2fAUh{BLaw6^=k)2 z)Cln)QR+P1aRb(wdzY`+xJC#3@9jy>v;J{fs`EL<`)_3UH!954us0OoP$`FYdXhTm zqirKpn)fX+s?b}kQ!S`ROH?e{6al7_gk&$MRsx^0r&ZD-8z>l}Q+6Y2{7a2^y|q%| z1FCiS60x9mlI1MX<0PF^WUvx^f=$0Iv3@zzG77lZ90>Ls=QtGWrycRCex>;USJ}>3 zSJ!1)`bGAN#uP@atG>tbylM^Nk)2rk-^r3V6WWnVK&0p)B>(lm1p*JLUf!YGB*NLfM z5oF-nv!2DyKd{dI(29Tc(%-)`Zq=gXe1*GYgY&6Od9$*S0F5?GQy|BX0r!2)<{Gc> z9!vIFD00wh(sLWigAjD*fG7+ zdA|g*UN0{Br~iRk(_Br(+`)^WcYeo!pGXMAIen-%t}{sj_0YO_4#bshE%HHmh>jF%4X|!@lWkv#8W?ud>ac` z`!eQ~Td^zN_?0VWA3WDo;@xL_yBBBE#U|4RXh!6Ou)z}DwQJ3|5-=Koq~@2j%h=O9 z7`1)S=ZJY>?`$~0WQ0us!&2FMt5{045_L+TdvJ%XeP{i*ZRX|M{l`|gq{;c;ANnV- zcTEJl#eRlW3ru=zPCQ^X8^6Jwd?J?qC7o2w!(f7b{X##fM{ui-3dc+JaNM<+)iBQw z1_= zGK2F&*OPArt%hr=Cx|`HVS=MkUks3`?%~RG2 z6tY>{wU^!5lQ!3Pe$4NbyD{=^N3UO#551epDb`N@80FnxaOW_|n0Kl$qxE@^jR8M@ z;XAReh_wLvbD>D#A!xc+&Q3lH9kof;5y5R(p@aYPoId{hoU|?Mlo-S;YSUDJlT8*p z;j%8bz6=S*&b0yHW4I&qGu}09Up__96hYjdksJ7-h7s}^wS6Por$Au-SzX`nX%&`0 zKZVPw5n$K-#$w15-&ho1>;;qD&MnrKwI2$!Ssfv{)QVoK^S!Gm6RBiU|m)oDyr4$?X0AEdrLo87MOAeQMqZ1W*NSg&+4&Z(~4ns?r@FH$8Ime^(Cj6b{fa22GN zf>`KmD4nSGwTaZIcGO7#{1^2+nm0R<9I%uEI*kB3Ky!>#sji-hlMKv)LY(2}k7;Z3 zJ2Tg#^PF>;CS8_g?2iG#XJ?BR4 z+kjwW`3Ab@K7KYsC-5z-n2l8FeGCBcFDhw2ASssistf3`o^(J$b5aKq4|rxNpIB=8 zu@9GfnLajM9=B)uy!Y*J>yHtQbl*iSHzv+wcu~=3FwvTT994_&DDCYI8V82ncE91% zp9(tb%fM+HA3bS=-ly+-=z|8r3?L#U1M9f3q;8f3?@-}sQO?qv(NYZ8zjJ1`HA4TA z?Q~81(Rjur*v#ET)o=`BJqQ`$;GQ%+O7N}>n4S9G;#pha)o|N&PWU6&Y6#?(Czyax z6>)u!6AT;MDGCl9&9$!hY2;kz(mv?J#U}Wm^HbW!+}EBrhdfEfu6etr<5(ko99z zKg;O>SE?*8DpkQbD0CA3VW4`CS`2Nv#WS4r@T({vtflFkfNWl)@M|{C_b*_F{B5e* z83lLH@GfG!hi}I%j(bu)ZIKck=3aWit5;LkOA7*lq}UtF#Ga)VBMGe$#q#z*m9iP1 zIF@cM{Hh!{mBI5~aw*F(2c0twO?AM8jZ}9g5-Omrw~FyK?JGeVZ9iJa9)`z+@Ie!1 zb!!>=U)jxeu`X9h+)X$6Hu&tKqpQcX z_()rLt8$C0*p6rHg2bbKG6R|ho>z57XNtTPP@1B}iNZ$E9Eyll|WPScW zPRmKBh>nW+=Xt?0?fVX*jtHd}_qcDL3%?oe!`CY!42yQm`V3zUr~PGGA3d}0-u@aN zdx^G!t$Ko5BT$kuruNQ5WKqd`Ed3)IhMFn6+!=w&VXnKy$$7>)B36^MY){aQcMK$+ zI-IS9H39sJ4s3{M`JL$C2nxH?c7@v_d3ttpP9rC@^ZG583IFMj_3)%N<0|0qLOnHm zbmkq$aIVzA`EUvIv^cqxY{l4P2WN_X*<*!!sl^CV^9GMemC8F)9D5R!aG*uEkJ>pW z);RZEU5R_Y5}Gf~dXnvI)3zW+MW2UzNViJ>ZbQ-Gd3gDeI;iy=H_{@_!0i6wpcT4^ zor7P^x&@_3_oaihV0U;hjtMrJx9kM927=IfkVd`%Ysq1tB zLIySEj)>f1wRg_+EbIO9Z^8cs?Y3ZmZa93uhk*R(wZ}a=3+U=k2CA;ERBn*V(uKpY z(I0)*z5@k!2Sfx%7`hMGO*A(D55YHetn*awbV|cELB9|!Xf4)^$5q>sw}MC#`4AC2 z^T$%}?ntwLIP3#`D=0K%gD`ce1t`-EYmlj^7d~-I9Ee3X?1^`t@D~m$HWV>hP)p^4 zlWuPc1AgS*J%yHL;NS$hJA@ZyQI3%!(pnC@q^3g-YTos1-lMfpibXIYS<^<(FSZAM zT~*}pdQcgSi#yWL^Vl{hzDlkv@jFv+q3|-gz~O_qhr#eXb5~byXhFL<^!H-x<#ki&W`rJt2 zweTNh)+3+sK7*vsJdamMWEOj5sE+M+=jq1ggwT|Xusw40lPZJ%U3L09;LLDlB-{#Lj!k!^Lfc*k1hTdb}T#hGKr^pE;uZGclYXO0oq61+U#trcpsZxjgc*k zQ+=Bj=d;|LCchBiIu6v6z(+E!|TAlj7l zO0XoxX^-sVSQh1ox|_E2!m>E}@oCf|%XyF+NgN|T{rK2>Mf-|&pDiz!J z02z|LV3qSuI%8}t2v3;Acl}B<0W+u1RoR`Mf@oZI$}-JBlRahQeAdT>cSO88nYwkG z&a`HEp^IY|E8FFibe=*jtB5=Ye@vHMsa$}QV$2@Y&h(kM(g^bAy5@lTEl1uxqXTFY z-`{mz@RjSnN72OxB+xLhrru{U>>Ql^T>U;zwYeZMbmIqspX}B@!SvhYxm)+ku@ILT zQcLO$NM{tLlLE{ zq!k72i`TDejr8gCd^)` zR$JcB5q!j+Bi{%%p`9+Eba?suGY=4N0f%;Ru}_8T1i7){%!$sPo5-V%@hcN;o)QuL z>wvS!4T*v4xDU7wmX5#ClQrD65`}@flwL;IXR*m+Xe{-oGdX$1;A$Bm-Q_CGLV-}7 z0iz(XUa(D2Z)I(L;l|bh$LtsW(=x-G%bUk`mjR$V?AF0Ok=T--e`*6yUidHga73Xd z(9JO9i%;a#sv_@Pt9XPb=|?97(HTAqi5UYaYdLNO0V2P*=!BB!S>qJn3(K^5xJ~=5 z1Tvl|HrQh40<7}X_afFN*|FCTY7a*L5`Sjl9?-neT_Uq}7V~OSxhf*9K0t-A!$U=o z>4>xLJ%tD{{hf1Wl}Wl2#0n@TCqH#wY(0&N6$HYU6zpS}0V?KZP##%B1$5q!7eb|F z_*O{T3hMBXJa{X`UDo9Swl42fK(;Hc1wk$%QTmW!>bt^|L| zD{eqGnZi6D*RIbt9|W<5>%kU~IEfRW>0^j`-De1Q66)rYLcsA5VRgDhUZ~G9UH{J?v3SThiVZ4&ct( z4%705?$K7pKt6mb?QK(Bs@t-M4v(eazokq9SdWf)l}S1G?KIfO_Y{Ein+7U&vdlkZ=tV_YbD!hWv{n z#xDbBdp&@d`h?EVIv42JOMx0XU%1-wV*i)5rbT+3t4=m53G8iDQOIPN0F%nYpjU9U%}nrny_$^cysqmIB;Myb3a^b8QRB; zVB=;A8kwdT<=3m#^0_6i$|s)u2~9(ES^V1dUcL=IB{O+o=`gCET#r!O>O3VqUbeN@l|m(V>s z<(+<#X9LErZhX=+9{1PH2h921UL&fwLlZOx@1C%w@E|X)3$=l+?qEtFG|al91v&1G zR2I=+ZV+?bP~eG+^1Ja9F1+O2?I|`-cTjpoW4Sfz_QdZ&>AG*p>Rau^abuV;!$tn3 zfCpMo#PfP$r0~nEL|3o^NfGFp%<`LnnO8l|lNu_RhrImU2z%*k(6XbVOWKpeRL1y` zZ1$ypMF5Wt__I?gkY9d=>J3Z&2bc3bk4Td6JuN*wR zrp`O%ll`@(MCBtCJ%S+u4GKB=b^Cu)>sG8~wXh(DKV_ZvTdK42^8WabR5$Jx%j)~n zOp+fGi`|B2@yrtgfFjCB(%OzM$IKZY^)jt$AY=4bLqn(KEfHOlkI@bS!u@;kH2}}NFwF_1RDNgt4yGk&SZoW?3 zz=K~^**3v4(pP$%y1QTK@LPwb+l@@rh+}~uY8u~0@5N@B4In{k%F*YZ@DpF|s(v88 z4orTBJ{-W?p+MZ=#l;QTvL2~x7whTy@zPdwq-v~PK#P+bbdNC6D$}sdUX>S9&WeM% zkjuwwM_ZsUjnTX$8rMjr3rH@j<(&?{XD1V{$c-#Mh8~ozfS7+G8mnJ&`+>A_BH}uX6qeJPpW^&UsjU@ea#9xVd>a zV=MDk0KO*xXdZlI9h)G05GWEQ8E0H(IFgJ3MnqY-N96+ku-d^yxr+-AcLhB)TL1AE zViOt*SN?r1y1)PTvlivu9Fga6!Q`R0K)7I2XzmMeehoo0?lL_m0wL^!B0wI-AGPBV zT?BppByhuR0Bp9zkw^qhvT~tmU(054fb6!q61b@*N{)X>@d1{iJM`K#PvJXIZF$!p z+XWQO!iS%z=(Ms;?ndf9jN>_~obUK`$Z9=pH!CM0Md!};WsANU=J{^hz6xYwYfnWVSFZwO!174gAYmJH&qGV z#1?-^fidbvEkRxh_Doq^-pCJBbyWG`=bY>Oq^nQb^Q_sQH^;+zn$?lQAA%q;unsks z@kwvmosrVuypnSF^DkNON9%JMWVq1MnL-2j&B=;f*Mg%vrUu~B-iSGuYaPEZF#<`H zRHE7C0Mh=icJ|T{3&~Dk_XLA4b$m>D?=wk=*1r2d-4Y?$KX;tC>TltrArJb*+~|E7 z&h}2zjxie2|35%{LDRu=Z+B^DKo8dc$Ekh2B6{;^kbcdP`Xz*k?2w?a525!f zIH+K_u6VKmdeyX8pKY3MI7tkTPk8;Xy5KBQ#RUdIeW#=krW0VhBOBfKKdz&E)d>o1 zPFW;2WqmeGv$GeU8#-s*!sW2g`65OzFv%XVZ7hb$w~N>c|gZhn(i?-0atvf zsLKj3pGHgT^vSpxU}FH*eAa5*aV3o?FQ+8{>JPpb9e@Zg483=I1S{L-a7SfUY}m<$ z3p!I%av5FvPHc+2aj10tFjxEr_*)Y-66_tl{)lCyvO1y3>Qf6l-8JD%5vdRHS^I?f zM=^iB67(M_7WF9$wE`V^6?V3q+c87wgVZYjzOF7?Zcy$yLC0kmz_XJXyjA3*tFPk~ zeT))i;S`8{sYqybN8pml6$T?^kx*@E2H=9aEEzH!Su3M2>kei`V}EHZ2olD#EW3gK ztI6i(2TYW|tND^5&a@y}8Ld5CL9bhA#NKJMOj=7)&-)ORI5M}ZM3RpVP&p_&;~DOQ zIpmu_?$3OQ1P%yY@ruLgQn8iNaY-K4r3Z9)(p|e?iigfOCA>aqBr~wY*cC2wmmAd? z8cg$lL!V?tnmTcZBc1{8s2R)7*;qA3W^|oTzH1^)4kNb+44*?E9xTd_?(=&fj&(ig zosAC=i5NLw%H; zo?+T#2p_5ZTv}J(^ohg<;;vSMhWv8ksuLQeSP-uN2JTUBg1`7MopWsehcPhp=3_9*?AWfdH4+pdQ zgsqPuJhM=~f_GGA)<#X|at2GB5WyO$h>BD}jwX*i-`Es&z;vEoOYeF!4w@Vu0hHiX zVcv$DmDlPU6_ZujP0iY|U+N`bB2%jD3c8=Y(CQ+dN%!BphgSQ@O%(Yh4u1mD=(K=E7Fa_R;sM> zP_>MGO`RcZ(&{dc-&OV-pBVb<@;YMDQvEL|F|R+z4)mb51tYyj-K;T6F3FC;<3yk$ z1{ikQ?hCtRG%6mQ41Vc4d#NWxW}?1s|CYepIp9WUp>$9^E2Ue>;nQCDA=wP(#vXHT zYNAi^pSa5JY`uziw@6RD8n2>nSd|s9U~(rC-PVr{D%M6M{*1kFWo&~NxL#u8vRPvEU*k3^p}-uGfQ_JW={o=> zWuRvGqf{I{quF~ee0`y;MYb8AYQ#&Q zi7z#L!2Ga;h7`=Nrb{)-JZQ~(52?FM>%e;D7Rh4+5`JJBvb(9@-`CaNeZ)M|yhLRs z(Z732R{h13HEh|+)>U=PXrd@}Hm!f7JNzt(3oE1+`#}*D&U2*~{1h4*tDTC+>D?;s z8QkwYOj(0o-_Jzp!@tCyIi0L(3^L#l^yKD(#xL=3fyPpHHUXLe-P$w}$ox64_L1|S zvF}penXe(+r*CQ_NTNaYLV17pXE7%~irDN$o)-BmTdT*?OqO>g+EkmTrP7UG2y=&P zen{;B2+FTMZtT`AY*D;&63C-F;p_Rps=0e?Qc)2PcO_~#2^vjsY>p=v!(FGqwh@v% zkgAwioih}?yer)%j#xUJrZVg9P$3Jd0n=Te?G|GuE}jZN87-y&!m4=!1S{nhv!H8` zs{3hNehLh}#kq#ekvjO-lF~Y#-`0_lWlh=!DJwh8^ZH3=>P#&vUp>f#oZhyw>jCyi z>_+I1R7ab}<~H|II=2sz6j3t4tuPF*OHHb>6J+om&wu#teBwBxgqKSzS(-hAd2_78 zP*Fc)e)o*Wm6N^JD?Rc~ukrr6b*rmC;|W!+zV2(!RylQ6)w{bL)~Y&#T6w<=J-x}( zuSo7VOgY*<`gEG%ceEE^=G@-p5@+n-*Hl^*+3Y`y3fOT?vUok~w7Hn$+6OD~XBJ?t z(*!mru5_Ez*opmLANL2QSld)PrePKpBu-J>8IDKiUW+E|^S^*S6mZ50lP%l41cJIu zvDjKIj&Tbj-!69Ij&ST!zHxMW$uSy5zieo3{hGJE@ps2U=+plxbpN5gN+W(ZKikB~ ze8YbBIbCi;&1;kEV6@3aKlDwY!Y#!U_#R+#9x8D%YExLpNfPhPfgN4h7O$6=L%q?| z2o~#H3af#1UblTe9CXVo&bK21Q5P_w#DK1b8=GlpToq0FfGu|wvM{<;YnqSWwZEG5 z*AitRc>!3JCEa_y_};6uGv zj-BzWlYwT`)y10yjJWEpmF_6y?ks34}21#ES?|b8=0L zE-*~?1Zmg89DvloE1C2YVJ-TnR@&N9IriNO>~Uls!RQiYd3e6sX-NoGr;;n2a~i-b zPGcnZ!x$FO-A`pA2p?-`@)K~g6hrNNqf%lKw!m^YAU<`>_01uN;PjV()+v3gjSsky z@O?K6NE{hl34bp`+t)rYufh3*gLvR;dEQQ`ttE~Gy>2Kjz~Mc6J=RVir0<6I6nMIH zMh;rsQyFzJmcenXJs?WHOM@L3Cs&%1b-V!c@H|u+yErlN za~p4t=2n`@%aqt9RBjM(LclHN6FYYNWgRWC*~aoK6`g1grVr4d zaFk%0;A+rB6(3z|tQHvra_+olRKtB}$8#C~Q;U88N!!+=?&&x`#{6AvuwwH6-OP00 zcXmRU-xf-eCmQftgm4ojdw;E5vsz1r;fK3<-Vj;l8P-Tfs9K_-beEDAsTg@p5O4{Q^n@;t1S#A~s@hrD=#8<1g(l>}mDdA#v=u zQqwzG>b22}Q|gQTnYyo^IKiq7czC}?M5pIgjH+?%7$mGE`s9j3+WjTW5k@7tzY64R zUk3o08qX|yiBWe8&&+oVnpLS2Z&lul)g4Hnt||6|3g2bO*(S~)j!!8Rsl0a+SiuS| zS?!I!R`;s)8^dY-0wO}(N^|cro`jL38(T+1bIvpZMx*6F;g#1bl`kK>y?o^JKjDhW z-;fXMOXC>wvDMaP1-_e|T7Zv?plZBfvOl|dd^Ryc10Puyk68@8Gw~@*E7&I@QgiEm z#t1@sVfXRDVtG65tm_teuZG|a_s$q>*Ga!M+;%bR&Wd1YL_&nZ_4{Ng$46k zYB-*kzwp`5typbWO@4KVVi0QE7wDGe3DhGD&1^3vZwTGYq5zu^+q9r^I}YaAolB_$ zKdSe#%R=p_a%5fUK?+wEbO&)|Th+4Lf4=e#Cr<9Oir1Cd%(}8K5+VN76~ry+8PVBx zh1_$o!&82zivsV!Qd%##dJ4At`?)KvM)r)uc5S$}IUIi>|MRw7iQKxOo$((DC;5PJ zuK>_jwSwe|TM%d6Zc1O}xN|pPi2nMoux!+8vz6ww?6aqDrIHl+EFdtep6i-6H@`l~ ze$#=|yT5nRQBEyQ^`g}b_Om%aA1VZ8*aNu*xX-0iv>P&{i}JDWq40du0~$FT-4%=4 zmq-#%hru6ex)rvU-A~zrQ|1z1*u>QlL@9zkvBI8L!f$qJqhHjQ>&6=)rY&AaiYG;^ z#zA=jgUilia`q^%iX1;iD4pk}^1fSOm*Q&OU4etc_Xc%S7W%&xq%QUQ#2$;#)Hhp- zvhc|I5uo9S5_+#4gZcb4^4&HgVSkktpWNWNgSWeQ-o{_xuK)!<7d=Da*0NMXf+eH< zI26LaW?VdslV}BwTtCCPbD%Rx%&T>)ptlD$!&i+Yb(3`_o_=!h?YRW`YjSvl=Z7_f zr7ZX|%uQ*tsAn9xPUmN4$u<@a{Db*i(&YJfktdgiA380#sZt0Y2Am8j*l59#2ELE( zcQjUxn{1ax%^wZ_{1-|5dT7m<{r_w4&EKKk|NrsP6wV=ZI$0uGlvF6mzMhhVlqHch zTb8kA9SkWt5rwRose~*US!S$bJCSul*=EKNW9);$V2t@Zbe7k7zpn2;@V&0r^Cy=d zW}fp{?(6M-yV1Az#1d+_&E-?1n(DjMlw?z{uWnY0S)kC}(t0&_y_0c@-qll%%z<;1 zdY|jsKWL}QpZX6zD<7CQJro@9$~r*S{|ZozlB7eQd@uejTosj0sUL6YnG&4TUQJd< z7k$q9(7rH2^1N#kF0Mhv(3aoxTFLk54nUABlI+lnjECyoFz;_V9)oj2 ziRvBoTVg#~=jFbfl?m8c?XL)1eSdzoFGDA$@r^M*-xVH5v3MSCM;`g`7bC3#hOQ=J zQGf!>=7935wqxOJK**PSW1#cXmH{IW+lV2f8JO>3H>IxIA-H^_>laJm! zhW#W~wev#e&~&S+eXe%QM2dsgVbvsRK|rkx)v@q;KtTj`?3hWo^rn%4<*Uxmfb9G9 z7F1LyD9}+e;lwTzCF7a!yw=`vcmrclwsPb@aSxUI?`H7Rw{xo;L2NQ!ANk2wou49 zyE(Cy8o*$^`lAB__$1#|U4v!RPL^h|58axQ86=07b>9oO^3G_Nod8sL?l4%M7+rO+ zo`|(Jm;E-W$GBvXPD5jz4V^Z&aPi%rB*&Z)g8_97>nS*?cqS*|tZA#s*`V0&#}4*- zNm0l}4F`lw$c!|ds9gB2Cd2%BkcEY?SHH#!G5YwX+MLTDB}D6lDRA35*;=mOT7!P^+^89Ofi6-n|HmOIVc54WJcg_7t=9>aN#!jdm+R;PgI10YDb)%aReF1en_LzS<-JfW?~ zvwizfb;W&tXYujI`KUaCfI#C;BaYl#+pzMfp}ot_wUyQow(MH*uTBhAc$e(;KIfm} ziyef<26p8ff|0FNzgensk=;A8-Xc>Pg2ertgy4g;kQ5@WBY9e6+n3kB?*Y)3iSN;J zj*QufLm{%ictd=e8W$(o=}$dN&h~k@zrp=F+4+$|tPCHR+LLT%CknRi(^NCw)~-(L z_myd>0^G0Del}|XvQ+&nMkq4=+soO9pC1fnoO?^9M^!&aV`UIhe&Vx-Q-&BCAD$UJ z4#{?qJ$JW?r_wXg@-)bx{Z@S?q!VPUUGoYTuSdpy)CHA&56Dr%FZ&wX`x&@CRk)L(4K{qSs!ItsK?&zp5Xobh+e|M2BXQu6T@_ zt-s=NKHe{R4}9NW>~uDKS9i_F^2BWkbCp=i4&~K|{yQGuy^XQf;kInv8xK*Xj;%3y zgEK-+KYY3xC*N0_VGDwsI&;7L#uJf-&6UTP`+r5N5fMMAj6vmV-`~}*QO@0D0kOKB zHo~ujUtl}IYR%q4BhwTY9g-*!iLW%W3(W^duuwPnYPC^Ng}sDN73;)Zw>8_Y+57&U6YcbqQYKm>6veh@V!$ zhIz-?8;i`&XuLn$ohC9h!*UQ78izNpcPu*yeO7)5d%|CF7m)_w}Xdw^ZZLVmp9zuLo!Jh=u_C6bEFZhRSW8rM5Hu9-zheo9$%vs~j5H`n7@VR{LE0Tk9zq zdbcw<<@cVG2#rd2taBFaL?&!&RFR`=?*x!SeOD9C+#dP^a{8yCC%zH|!-qK|&-=Mk zk-FHU!_&CLqgg9G&-RO5&2#YxCUPC0NII*;(Hdw!VVYNU?2n@_7of3lgDbLVmC0DO zm4N1+!lwR8wMQRy{jV(Ptk3W8&iw&TM}GSOd(S6{nme!( zRn*>1Njw$cx=5;xRS+6SGvw;)X|Cr@QkYyCvL3tnL3o2-dl74gtLn4x&!~%89{osL=5Hf(yfYPUzo~PyL!r=i{;SsjsP`a8oUgn zv&x&`hI+uub2Revu>?Wi_|hyhjh?2rAueSVX&%dIu#T420tH742<9WbI_Exk?$H#8sEA z9lBM zD}}v+xKBWaEZ6;1d%iYni1A%}D5tOKHoo&~Vx_y#K&!1Qsb){T*EdJ z+N>ULn&m@QvMf|8?Ov`H$Q>X?KJm4nyo{~OYm&Sz6DHxOSyLbx4ABOvZ}B;O;u;@3 zuJZ&&=zmq_k7QhN#FG3YdHaUPA5pG-T330ZgC+5Em##Ad584x=T1s=jKGbOR#O8K0D-hwxjrFHCnsx?iP7W+Ku26pychWbfKtB(B7@{yIQ2AgEUR)q7v_q$`+lJ~z z;Gt`fV-bEkxzvVsVtAT})|aRMIiuKr%?Z~X64s+dZyIR3_v1n|_5HJodX(@W*qJw- zSAg&a&72+9e~mUr5dd5F{1;p6$RM@!Q}@_86=NVWf&j~Y)2fR4@}{e;!KE5-hCw|$ zZs8lQ>wVFuG)ITh+}y2^A!{6=4@biInq%Y!gEx9P0bHf?j>=qJLj?@YII?(HI8B~p z{IN@oYYJ3d-TfiCXAtm8JY(7c!>&TJJI=N(a(L=Uno|WQkfrrCZB<%#U*S`tWP$uw z*Dcu^d$D7c_ly^a0QhiypPILQaTF|eSUDq-74UB1Q1HCy9*M@@7T5{zyRp8sf)GLf zLv|FuvOQ3112QmF|AHyw7e-`-dWd4^uyJzQTzRB?H+M--Hia z_;t5@NxEgz<-s zE&qmmG(l5D7<5I>zOF}nT4vStm z0gz`U9~!K&5jJS46}vyy3p@_|H0sHk-Bo2?3-xg9ywnCdNQat2nd3lSOWcC^W zuqtQ$n;1d;3?`HqXo}-9*|()Cb1EvmuqZ8rnsgQf|0^{mSJ3nx=Q<=-QI?P@L!47w z>U2b9-o?VxswXZ(C-x{?Re7B|G}B5c1`0Ny@`^L|H#RSl5{WoB?5rMtychab$ywIl z3eQOK@77CVdS)HyGJWaiJ}#bk=F3S!nC;7iIR{J&%FrYfhe5T-x~ZWvbd0asSEZW1;+0MulcHtR!r>Whj-^9%Gi9 zJ(%hqK;TSh`h^Qp@gjmsL1v~tl{6+ao55_YTB(9_75WP#Y3G#WN@1EvNgPBS!c`{d zd!^@m+G!|%*^Kh>F_ob+ZFN28jkT2eX0jcccA{*s?TmA4!-)~vL7yb_$PxDl%MGFH zi{;)I=|Mj_1<0`ezW_iKncx0fcKygWK<=J|YQ*#dgsgT+#mj15LSNw(i9oe|hjbdT1AyhBUAFa}1AoOPESAP!ngR9{F99SqhDE(@s zgFycX<&5-29BqvH+ypZv z1SW`HFB6eYRF@oH;E#znDkCUBo4-(~525iV_PT|8O)>I^4~xSM271~|&4W5zsA2Kr zxRV6c$mB0mk;KsYkr#^Gz>Msb=Mxjw)&~3|uF&uH>#ej^x#`W9BW6=n&;iNO!1uG9%GwfQgf z5-VANm}#r-EjICXs=-=y*S@5i=%Vhy_5F^&5W5GWhXr4_i~hE%9|)!=S6_XjMK#~I zw}#yM{C2cSQCnC<5x!j$p!WP-9gsD^whx&g^MCde>wbnjaP^dn-9XAhm$<|If?+;& z&GRqzJrVO%^C6zlf{a0qLtYVZ6YoC=I$m}PFHpdCL)sO%=6l1+I0{BINOA;|0&OW# z6Z0x{<)mEIVGdtnqXJa<9iUS=;_0s~200VEe3aKSGgbMKI+ARxsr_#A(F3PD?7C~8 zs(tlS^6^)X)_#QWO){Y)aSPZ?*tQg4P}Fk7u#aEe>FGqfW&JtByL)6QzW-+lL)vVI zQe`8hnbv1|Il#zc_a#AlgC|JW?^%xSMn}r5(Pw*G8aJBJVUeuFJavC8$v#YZY%$pk zh6`t?U}#?A1)5s0VGj|R5YW*7Omn7eN`8V3;}i!m%lApDgVwD;v_}VY|6wgQrWiSD z=bTkM4Shs*RHD=40M$cf3MepLDA*(PZiT2wzaDU`oi5p$1^etrx-jffRUwU$>MB$+No{FwQWyPkYm z+=D~;k1s9F_F=(%2}k9zPr?mK%7qsRNzcS%QYBl&AouQfR<{QOf10kfq1pb=s~qo$ zW%|407l#5kTLZbFr(?w37NvfT2`YLC6pO73jtjl1udkW#C7YIC%3awWt_5S??iguo zokp#r3KGV3)vK(h>L}q9$B{NrLMZ7v=x`(^Raj{6dBebk1STSn8`Yp^+ng z@!7RS$&n_mbj1Kuz`t_!wQi^kNs!Z!(C=HV%CJI08~-c{c-5E%;6iY3S{5WYAVAEj zVS}NvGN`lhEK&38nSUb4Un%{UySxWdZ{E^OoGjJ;Gux#2cd=L5Wo*2s0b*bJ89d;P zaWs#zS&Te9+Il+)zJG1%VjJ(`~UWhDas6iTRe}6;xqX?lWd4 zM2>1z>8o|g8|k1)$w4o`&uH09$>8(7hGqTR-wk$`OG7n6c@j=LwjOhRj>fv63H5{I zLGziuk{>F*`!XAW0^={oi$&n9&c_aBj4+$8r z+UESR`$1jcKB(SEB-JS?`Uq!$X_m|U9a7$&W6N*ee0A5%meSMeG?v>WUod~0pSo~& zPo%JEPc@7y;Z1k-bb+(lb4^q$pIG!hE`z+2KBY%R8=Lkl9j(<7<5Ni!gQzRBJ=0UQ zm&96tsW%@N%aaf*-2W}q$wd4>{3+*a{b@5SF0)NVwa8x)VofI>C#lT zAYGU2__g&h zaYgL|wo48DDOdydZg|W6#$khnuMGP|d(q#7_xClh6o{UHD9(UqW135W@U=(mTA5nB zwN)7?;)h->Ke9V5li_*UQ&hDBOt#x%1JVMLAb7_~ZBvV2VLdU8WHB}K?1R-k=hFpZ zQX|E+x4MKy%Y1q|hgWqn8=!m_BIA!J@8$Wz*~sB=|94OOFPx8#Bv(FZ`bCdNUi^5K zvk@QUe)QMo@XOLd8kDju!QE(s@73OLgKNjt?U9ZN!*gcCd=NnsH(40*C(%9XotFi)}Dn8@{kO=~H$B-uf{8~9b zb?`t?lMHl2R*!r2`!?S` zbss4a;PK3h?wAvAU8_na9*7xhd$lZb$J%I@zZ7Kdop@iYv^Y`x3C^pbteNAYwp7JP z*}EF!INh$C=A_8c7#aHPfo97s+s!ZDFKk60EsK0S;up6L&97TgNQ^$|$bZg~a%`^; zv2n;okYckqphsA24vr$zh`4^olu#vXb9@b*7lk%|FwoIfi-|Ku&D zz+U%g+fDeWh0B5X7xG(zcf!l^)PV)e$#l*k_WjtPoi5!2)7nY1m(mdHDqcJ0hnc(a z1%h60f%@cp=*oSzvOn2r|ItcE^yBq)cdeq}w2!%fWc=IQldm7z5*R|38pqqIZbm@W zBpmwon8DJKcI8s(G6F+`L;4_4864b0U>wjdqunQ>fN(h`?+N2Ud=0XA@Lh5OAJvN|;($m`RM-eu26%Gvv|7eZ7zgF-WKO>%vcJvAxs= z?mLDsqNC=NWItd((uT|mE+_vXu41qfljHh*`j`ySsN`qt{tGQ8VxZHht$2QjdTvEQ zYa>+oX#ab8Y`^W~U%<0E*+%)=bOh4Sl9JEy+-9Vv|)Y>tW2j9Yk~r~!L6 zdOVbW;@#6%D;`!(dHJs%K)4+XS20Fi{-okeb(mWCXf8|*?&CBR6HL_e%jU??uQ<3T zT2XS(s}s?NBX(u&BB{z?BdWM`@lMuOEf{F*n_N(|nUB(0vDktT_{1(7NTZ1U!dCJ! zkRjp?ae;9@L$Z{EroC#LvtmdR)s67R3>9}D;2hXld{0Kv+i_W30s;Ua*j(pF*uRa8 zs8zX0CPa)6v(qxz%Ri9tz5gKL-)?vPO(&^)D+T*BcW6i9-K>A}#&h}ij*uS2_?{pX zQJj(|x9O`JYDxWFY;`ch|IFF?Qxs&ZJQ)Cb6;Kwh@;6P)L40IY*clOUNY%b`rz_vf zK9lRH1eQaX)p;x^M$vt%3)3kAc!KwqEtbK^iw zs(ch9FdPPEHEf_CX(v1#by_*DKw2d$h58}_*`oI*j+@M_*QM^~y?%(&9cYixZnp!& zQ4aTk#x)m|?9}eJ-yKUowL+W;D zMMmtz`oe?;^(kEvpLMZ07(Y~3-n65qHYB()j!2g8&V5-M#?Ecn;D}gSu+Ys!+?FAc zAJvfHGTn2_s_g9xA7!g2fqXOZlJgC?rukdBi(mRTW&l{IZg}f@E3{^#hv>^2-7s`(Iq<) zQHS);d3;l$f-)2gy|}U?-gAipKKt2yfD~LDlG3lD6d6I{F-Eg!_y9L?lfj~ z@~9HScn56&=rxjSl+{7^hCtfrcFwz9Pv2bg{{RR&@caJnXgEi^wjDu`51kfeJ4L-` zM zc1G^$w2vS=`(>filO8ZUdgu+Z5FeEih0F0pq!Nnz4WB9z4&bPDE@__vBWWVX2XzDG zJ_WmPA_X=9;@6xyp=ly^x2k9C0*9@s0gEyODvJxlHkNIe7DIQGdp{7it}8hz#GzSf zlcuI>cmvGukg(C%F?dfB$#>NdB5*a@1)eyKEw65jX=7c( z91~6}ByhYQPIxl9r&Np;H6=0~6@NmUk#hHAeuH5?TswWL{X){}sf*^}qIy8vmy^fz zd#nEq_(zFeD%ZovN?VOuueYn+paOI|BeYY2}3%vk;duVih21 z0jgf}fzA=XEbUJnI^`sSx&me#%E4%#od?5S^YSV*^43aq(V?&iSP1drB?5Ffk5b{n zXNUkW;qhq=5xsL|b-27~k=6sC9+mWUZR1#6&?(1>w>9coZ=xt%<^Wxpex?;Bf-dh8 zk>y!$)K8Tf7q55y?H5XKoEg8HkQnz+qnCDa3O|JNim^{Nfn(Jd+|(h(u!(sCA+{VK zR{3FHi(-|kgZ?!qRG#p!F}ySPt~C?9Ob&(eny&d5T*uDfZ$){xDnz=C7RUACO(>g5 zRv0~RWbrjLrPk~XH2EC5=*wXGm5|Sj2-_L^8{0;ewo3W|d$f5ccec2%nW)Ho@!ZeE zy^&lx5+BF?eeeMH(HkCqsozuMPjGTOcoxx*T|vDIDqn*rZib~pkov19K2x|9wzm(% z#)OG}yvIM~+Q0$&~_+-PZ&ocM1TB$42$O>OIGG1hNh) zIGaqoFOyyS=`TANr$yJ=Ik_FwKo5sB?*7k}=9SROeivN4C6;cHHR!J!GwAPBTj7yyC4#C@IREQ? zV=G%i>We2HA4rk^A_GJ3X$`-89N%A^D;5CY?qEiv3zO@y2Zjc5ps=VwU-W_gx>b=E zhW?JwzDzoAfFDV+1*Y7gf~Mp1JLsj;1;TN24<(h{6370q_dMm{v4C|hwlZ%A>99klKCqLHV~O^l^#%^YK4Ti$4fRasv-vuj+Kvi6+Vz_3 zOm2|#U8`ISRPtfe+x>?npL_pI#+=@g*jw+>J7srz>`-WboGoX)ckk#W-52X6xNEoe z+FmQ&-=ed3`086TwZ7JYP>YL2Cta2Ok+x#uJ>%!3+kHI^ItO{~oTGMKbiKAXD&QS~ zlCqSHjy@-jHwaI6zmR2jCur^^0iBk&-6q*@vJ!4O1%dd~Pd_d__WJVP2aw3QG1PW` zK0BmBZ6n%+goH;73ohDd%grgiR+2hNlWT#RbkD{ zlFK(7hP6FQ|7j_(cHLnHaU%^z8m-4Ez^Q~%##(-t92SssJ)08hIZF#~h@sy7s8qCG z-RpFxlG-RWQSUI&`7ULB`Tc17Jw+{YYIvPeguh<}Gbd&Hy<3N<{_#vGq;V}*s5wT4 z$N`D;cysu+Q0pIq61|mK0nGej0=-AhlZ;DN5AjB3*{O83PjnlJH;_gn&UZbY%Z|9i zE*|EaCEx=HMcBka>fqL0tdxHFVK0)$!MNl_-n9rHyQ$S+trlNzwaBl|3K0jn)I7jSOPg$obDa zj9cFRK1f!|{Q7OCy?ii~P-f9m6Ar7laJ`U~dw5_5VP2FR5)+W!>!cuI6hl)iTFzq1 z%{PoHQ1FFk7+C=!KD5Q&euD-92n14<2euwEW_5bbZ>YG4r=J?mYNHGzGu)r2l&=%K zerGKs)9#F-6pU94g&Sryy9;^#VEN#Zd*5X%c;`0{y0xszw{LhF!NUXOZ{pWD zZ*325=rLw*v%)q-<)pm5y?j=JU&tXQDBEkOQR5_H@bdZgsjyYNl_5=UW#Rp(jrZ*q zg(8Qm$^CTyUZ#iATuu9GxA&=vTXp-13-Awc>T8SoL5Wu=*eEU{WAZic)wtR3HTnbj zYHqhX-48POubbqWtKl#F;yz7fd1{C|4vBKIh3bu(3S&O zgN~WllbxID(Y`MyVqw2FY`$!ve;}aaWK-;%1LQT?RT7Q0bF87!*}V2NJke1hBgJU@ zhPRC<+BlK$(^}lzYgTE@5Hspl*S#k+^$vM5* z0p7byP#buj_$o@1SkU(hgBU~=^%tjBgBL9pT==><>5`q?7UyxWpSfITxxWXmMmyEZ zyjzP+rqByX&GlKDWR=>s8#S=cwR5o5Q58aHJx&tI_;7L5C~0}%N-$Of&YbY7y#xChA`L;^=pjv%JsIjLMwdi+B9iA z*tLe;yo1dQ*wnf7nPsxl0uM?o+1A<*j@9-8_wE)2EE{^(d2WS;W0Hd{gAxfc#H?@f zYD$4Ub{7i~mZ&LLJ)wT)t@`Zi-dbKcp=xfUwsXc=45_OATHDY;#`UuKhk@SkHLtST z2FjLs$x}+v*%HQyFhuA2BAxXfMvOgac{}=6p-biG`z9z|`n$uY%-s+ojsc1SUw_Bx&Y+0VRr;FWa?A4QMt1MwhFUF(%=DF}kn%3LfwhG+cXmRvG5yXX`iWi!aW;GexSJoRC5*`;%RXRYZm%7p3~Rj1WE3R@Uu?~egJlB`Rl zIV}Dp&2Dahzq4Ei2S-KwEwgGpiVCw$&<15)yEiy&DW-kpnXG=z~Bh(u_Gq=k&M)~Or8gnfK%Pv7GIePPf?QF}Ida495M4CQR zYwq{_lP7X(>8O4gJGW(fKDOU5Auyk5H-t((#h2H=N>X*Me48%DX zI+TT#Rr#!|WbX{jr|GWac76@UVtA%VtDEm7J8hk4r#hKY;e_&AwHkn&YGH)wA*3(( zt+b>Ebyx1T(Bg$+f&^+X&KWo>g(Bw|H8m9tTcqAvdp8MNsFR^sJ~6PUnykMfkCXII#Tlum=*x>^W1g=!X4mG{@u3-CW4TnqYd+8P>!#9m z*S)?8VZ4ozXyBj*$bR)&mN=Y~5u$T#;RC6>^3F!H2nqK)Rf5HG$D+x>h;E=}LEzSjR{gT+9%+61eYeR$!> z_WMG=2DgswQIAtUjCJ|dA8YumU#e)hXXie~ikGj(!}+B`QFrE=-^CEk5m@wW3pTGB zEM$TNhz`GvX2T;`5BjGFI`zz|hCGSZTKX3(IyZ>*+Vgl2W`GyY2)D8cLr0Ga&fA>R zI*mtui?}&*Q$#KdUGK+SlXM$UW0x2Dp;N-hsqbE=r`1biE*ww|4B(jnSiv%Oqj3$V6Hw4Zn1XV~dfxVhi2A;l1|&VkFIk_V#tpLQeNk?9^CG(Q(!9lKaL z)^t9DSX^!^>p$_SCCo>#(^y=t2dbLA0EqYMJvw%*vA2(^Y4 zbVm+(YPh|$1nkdm;q3Z0_}Zpx(6&!%z0f)pe0}j@GvmzuwXC^*mm2nCQS#YbWq=d` zH}L|;5fGo<(6sKc&?@04NIb^iwHi9yU&PNE-9Z4-v1ZF@8|wyJ*{ch2Z^BsfE2C?@ zlShk^0~bn1Jy4eF3m-(*7ps-|DGN0_W>?@1q`R>y5y}Q|Oh}o(&$1qA?cR$f+aEFi zK(uAKySSP8;H~E-mT@9kQmq6cycIZDHG`taVyAnqr87oqG2()ZhfrBfJ%LiAdcYK>)B#j zo+$5@5RZd>N?yCiv~N;Jn)0l$quv`qpS~-xx$D5JFNYrU;ukJgwP>yI22x2qp@tPQ(p;~0c6)UO z&sg&`MkF$3c^E@DZ^m{oy5~N&2fRn1_Ys$RPn2Dc5Y;z~YG3}C>4*C~c|XWX;;V52 zV*P>YsAz*qb+sC7fWr0dC?mP+dOP&)N06R``GLhyhVCANK#+;u(6Tn-0->&pxyb-b zndS|^I!7in3gsH~*u1Owx1D*_T3)0cooot7Gzd*~z@SW(F@__EiSupza;+;pi`1Ze z=@66a$dmwj&khe0otD%v!tQITHGj!8GM!@BUUb;?UfbV)7}^o(lVrQF(k+Qv>{Y~2 zgC#9?;LmT57so_EriXWz-p>5Pk1QXYK_dtm^vtCs+Y%RM{JEy}9U= zuoobuM2Ri*q#6tIx56iauC7h50ngKy(x6i19}Fz#*B|DoQ7&4BcnsqMb|7JQ2RtT7 z%WU!Z*r23t!Ns)fs8Os&NCf!Kv=ZjI+U0x9OEBXEZ#!m)E&J9fy;_h0%o}H!Z`xk^ zj7>H)XlLm9K_HQK`|AZ10dXFPo_%as6YQnc#6q35SbfniL0*#lI5myL@A{&x4cpJs z@QzC@SWWnwZEE&8w(csTX{?hRtb$~W;GPv`=Jr5*uK1<|@xqR?=y z4GL@=d!ygy)E1tpvWmTJT%t+aF7)rl+L3nyRR@hwtO7;fQi&#p+pea|3>E1trX{&0 z@$Y7BTiBg@z*%po<$y20_`{~p5y8gMB+hD;j-sA zA4Gd@4y~~z^zHSQQtsCV#I_F-nEgZmsFo*f&Y)sm@7&UC9}L*7M}Z>A8M47kruj>F z&l&Kd!8`wyq#%kvPLH`ci)ofa)`-|xy`lBiyKVU{x*|~mw>FbNkq}yw0w*R}uPx~R zm>{*>$u-FzuY~me#{fmf;dVxH$kHdls8b=CIh;7krs|8n(ONL2p#A{&7no~SIcx|o z)%j`n#CaHk%#`EE@z+p@PqhV2bEK$nJMhx`2-;-tvX**y=vJk>auxj(!iV0vMRr)|Pe#NuR0sYC+(6IQ}5VBt)1R>0NTiOpH3@SVKw!jR`Cnx~C2J{V`s z^jak5y*h&0iPeH@Xw`c#8bc3CfdF)Bubx*H8-y}+rRQj53xCojhSf5c30kb=4Er~y_Z?^ zY^zkYD{wEbw3M@s8Yiu}T{KF{L5mxiQrz5Dlx(!ooYg2Nm$$&{@A7x>3>^!MFN`^Tfdd-Q)i*LJt_$D{qr|3316YYF+^A%gtx_CO&2 zGaHcq*-HrIe~tq3KMx7{UuXaVvHu^3S?z4DmBW$V)2X(Y-B3?o_r{fy-|Qd$Kb7y( A!~g&Q literal 0 HcmV?d00001 diff --git a/client/src/assets/image/banksprite.png b/client/src/assets/image/banksprite.png new file mode 100644 index 0000000000000000000000000000000000000000..6c68af62a16d0ef45dbc6c1aac3248776c0abf06 GIT binary patch literal 48163 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 + + diff --git a/HDesign/src/assets/confirm.svg b/client/src/assets/image/confirm.svg similarity index 100% rename from HDesign/src/assets/confirm.svg rename to client/src/assets/image/confirm.svg diff --git a/client/src/assets/image/editPencil.svg b/client/src/assets/image/editPencil.svg new file mode 100644 index 000000000..382e8ffd6 --- /dev/null +++ b/client/src/assets/image/editPencil.svg @@ -0,0 +1,3 @@ + + + diff --git a/HDesign/src/assets/error.svg b/client/src/assets/image/error.svg similarity index 100% rename from HDesign/src/assets/error.svg rename to client/src/assets/image/error.svg diff --git a/HDesign/src/assets/inputDelete.svg b/client/src/assets/image/inputDelete.svg similarity index 100% rename from HDesign/src/assets/inputDelete.svg rename to client/src/assets/image/inputDelete.svg diff --git a/HDesign/src/assets/loadingAnimation.json b/client/src/assets/image/loadingAnimation.json similarity index 100% rename from HDesign/src/assets/loadingAnimation.json rename to client/src/assets/image/loadingAnimation.json diff --git a/client/src/assets/image/meatballs.svg b/client/src/assets/image/meatballs.svg new file mode 100644 index 000000000..bc3e17d2f --- /dev/null +++ b/client/src/assets/image/meatballs.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/assets/image/pencil_mini.svg b/client/src/assets/image/pencil_mini.svg new file mode 100644 index 000000000..11a154e13 --- /dev/null +++ b/client/src/assets/image/pencil_mini.svg @@ -0,0 +1,3 @@ + + + diff --git a/HDesign/src/assets/rightChevron.svg b/client/src/assets/image/rightChevron.svg similarity index 100% rename from HDesign/src/assets/rightChevron.svg rename to client/src/assets/image/rightChevron.svg diff --git a/HDesign/src/assets/search.svg b/client/src/assets/image/search.svg similarity index 100% rename from HDesign/src/assets/search.svg rename to client/src/assets/image/search.svg diff --git a/HDesign/src/assets/trash.svg b/client/src/assets/image/trash.svg similarity index 100% rename from HDesign/src/assets/trash.svg rename to client/src/assets/image/trash.svg diff --git a/client/src/assets/image/trash_mini.svg b/client/src/assets/image/trash_mini.svg new file mode 100644 index 000000000..16436f446 --- /dev/null +++ b/client/src/assets/image/trash_mini.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/assets/image/x.svg b/client/src/assets/image/x.svg new file mode 100644 index 000000000..c3622bab5 --- /dev/null +++ b/client/src/assets/image/x.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/components/AmountInput/AmountInput.stories.tsx b/client/src/components/AmountInput/AmountInput.stories.tsx new file mode 100644 index 000000000..84cedb178 --- /dev/null +++ b/client/src/components/AmountInput/AmountInput.stories.tsx @@ -0,0 +1,23 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import AmountInput from './AmountInput'; + +const meta = { + title: 'Components/AmountInput', + component: AmountInput, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: {}, + args: { + value: '112,000', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/AmountInput/AmountInput.tsx b/client/src/components/AmountInput/AmountInput.tsx new file mode 100644 index 000000000..1169e6c4b --- /dev/null +++ b/client/src/components/AmountInput/AmountInput.tsx @@ -0,0 +1,47 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {Text, useTheme} from '@components/Design'; + +interface Props { + value: string; + onClick?: () => void; + underlined?: boolean; + activated?: boolean; +} + +const AmountInput = ({value, onClick, underlined, activated}: Props) => { + const {theme} = useTheme(); + return ( +

+ ); +}; + +export default AmountInput; diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx index 8d7946b8a..f263e18fb 100644 --- a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx @@ -1,16 +1,17 @@ import {render, screen, waitFor} from '@testing-library/react'; import {act, ReactNode} from 'react'; import {MemoryRouter} from 'react-router-dom'; -import {HDesignProvider} from 'haengdong-design'; -import FetchError from '@errors/FetchError'; -import {ToastProvider} from '@hooks/useToast/ToastProvider'; +import ToastContainer from '@components/Toast/ToastContainer'; +import RequestError from '@errors/RequestError'; import {useAppErrorStore} from '@store/appErrorStore'; +import {HDesignProvider} from '@HDesign/index'; + import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; -import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; +import UnPredictableErrorBoundary from '../../UnPredictableErrorBoundary'; import ErrorCatcher from './ErrorCatcher'; @@ -22,13 +23,12 @@ const TestComponent = ({triggerError}: {triggerError: () => void}) => { const setup = (ui: ReactNode) => render( - - - - {ui} - - - + + + + {ui} + + , ); @@ -38,16 +38,16 @@ describe('ErrorCatcher', () => { useNavigate: jest.fn(), })); - it('핸들링 가능한 에러인 경우 토스트가 표시된다.', async () => { - const errorCode = 'EVENT_NOT_FOUND'; - const error = new FetchError({ - errorInfo: {errorCode, message: '서버의 에러메세지'}, - name: errorCode, - message: '에러메세지', + it('예측 가능한 에러인 경우 토스트가 표시된다.', async () => { + const predictableErrorCode = 'EVENT_NOT_FOUND'; + const error = new RequestError({ + message: '서버의 에러메세지', + name: predictableErrorCode, status: 200, endpoint: '', method: 'GET', requestBody: '', + errorCode: predictableErrorCode, }); const {updateAppError} = useAppErrorStore.getState(); @@ -58,7 +58,7 @@ describe('ErrorCatcher', () => { screen.getByText('Trigger Error').click(); }); - const errorMessage = SERVER_ERROR_MESSAGES[errorCode]; + const errorMessage = SERVER_ERROR_MESSAGES[predictableErrorCode]; await waitFor(() => { expect(screen.getByText(errorMessage)).toBeInTheDocument(); @@ -66,15 +66,15 @@ describe('ErrorCatcher', () => { }); it('핸들링 불가능한 에러인 경우 에러 바운더리가 표시된다.', async () => { - const errorCode = '모르겠는 에러'; - const error = new FetchError({ - errorInfo: {errorCode, message: '모르겠는 에러메세지'}, - name: errorCode, - message: '에러메세지', + const unPredictableErrorCode = '모르겠는 에러'; + const error = new RequestError({ + message: '모르겠는 에러메세지', + name: unPredictableErrorCode, status: 400, endpoint: '', method: 'GET', requestBody: '', + errorCode: unPredictableErrorCode, }); const {updateAppError} = useAppErrorStore.getState(); diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx index dde5f3d64..9cb179602 100644 --- a/client/src/components/AppErrorBoundary/ErrorCatcher.tsx +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx @@ -1,60 +1,36 @@ import {useEffect} from 'react'; -import FetchError from '@errors/FetchError'; -import {useToast} from '@hooks/useToast/useToast'; +import toast from '@hooks/useToast/toast'; import {useAppErrorStore} from '@store/appErrorStore'; import {captureError} from '@utils/captureError'; +import isRequestError from '@utils/isRequestError'; -import {SERVER_ERROR_MESSAGES, UNKNOWN_ERROR} from '@constants/errorMessage'; +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; -export type ErrorInfo = { - errorCode: string; - message: string; -}; - -const convertAppErrorToErrorInfo = (appError: Error) => { - if (appError instanceof Error) { - const errorInfo = - appError instanceof FetchError ? appError.errorInfo : {errorCode: appError.name, message: appError.message}; - - return errorInfo; - } else { - const errorInfo = {errorCode: UNKNOWN_ERROR, message: JSON.stringify(appError)}; +const isPredictableError = (error: Error) => { + if (isRequestError(error)) if (error.errorCode === 'INTERNAL_SERVER_ERROR') return false; - return errorInfo; - } -}; - -const isUnhandledError = (errorInfo: ErrorInfo) => { - if (errorInfo.errorCode === 'INTERNAL_SERVER_ERROR') return true; - - return SERVER_ERROR_MESSAGES[errorInfo.errorCode] === undefined; + return SERVER_ERROR_MESSAGES[error.name] !== undefined; }; const ErrorCatcher = ({children}: React.PropsWithChildren) => { - const {appError} = useAppErrorStore(); - const {showToast} = useToast(); + const {appError: error} = useAppErrorStore(); useEffect(() => { - if (appError) { - const errorInfo = convertAppErrorToErrorInfo(appError); - captureError(appError, errorInfo); - - if (!isUnhandledError(errorInfo)) { - showToast({ - showingTime: 3000, - message: SERVER_ERROR_MESSAGES[errorInfo.errorCode], - type: 'error', - position: 'bottom', - bottom: '8rem', - }); - } else { - throw appError; - } - } - }, [appError]); + if (!error) return; + + captureError(error); + + if (!isRequestError(error) || !isPredictableError(error)) throw error; + + toast.error(SERVER_ERROR_MESSAGES[error.errorCode], { + showingTime: 3000, + position: 'bottom', + bottom: '8rem', + }); + }, [error]); return children; }; diff --git a/client/src/components/BillDetails/BillDetails.tsx b/client/src/components/BillDetails/BillDetails.tsx new file mode 100644 index 000000000..3d9be8461 --- /dev/null +++ b/client/src/components/BillDetails/BillDetails.tsx @@ -0,0 +1,52 @@ +import {css} from '@emotion/react'; +import {forwardRef} from 'react'; + +import EditableAmount from '@components/Design/components/Amount/EditableAmount'; +import {BillDetail} from 'types/serviceType'; + +import {Text} from '@components/Design'; + +interface Props { + billDetails: BillDetail[]; + onClickInput: (id: number) => void; + activatedId: number; +} + +const BillDetails = forwardRef(({billDetails, onClickInput, activatedId}, ref) => { + return ( +
+ {billDetails.map(billDetail => ( +
+ {billDetail.memberName} + + {}} + onClick={() => onClickInput(billDetail.id)} + isFixed={billDetail.isFixed} + activated={activatedId === billDetail.id} + /> +
+ ))} +
+ ); +}); + +export default BillDetails; diff --git a/client/src/components/Design/components/Amount/Amount.stories.tsx b/client/src/components/Design/components/Amount/Amount.stories.tsx new file mode 100644 index 000000000..bb9ce5b5c --- /dev/null +++ b/client/src/components/Design/components/Amount/Amount.stories.tsx @@ -0,0 +1,28 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Amount from '@HDcomponents/Amount/Amount'; + +const meta = { + title: 'Components/Amount', + component: Amount, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + amount: { + description: '', + control: {type: 'number'}, + }, + }, + args: { + amount: 112000, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/Amount/Amount.tsx b/client/src/components/Design/components/Amount/Amount.tsx new file mode 100644 index 000000000..c07fe1ae3 --- /dev/null +++ b/client/src/components/Design/components/Amount/Amount.tsx @@ -0,0 +1,28 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import Flex from '../Flex/Flex'; +import Text from '../Text/Text'; + +interface Props { + amount: number; +} + +const Amount = ({amount}: Props) => { + return ( +
+ {amount ? amount.toLocaleString('ko-kr') : 0} + + 원 + +
+ ); +}; + +export default Amount; diff --git a/client/src/components/Design/components/Amount/EditableAmount.tsx b/client/src/components/Design/components/Amount/EditableAmount.tsx new file mode 100644 index 000000000..c71ed1778 --- /dev/null +++ b/client/src/components/Design/components/Amount/EditableAmount.tsx @@ -0,0 +1,107 @@ +import {css} from '@emotion/react'; +import {useEffect, useRef, useState} from 'react'; + +import {useTheme} from '@components/Design/theme/HDesignProvider'; +import TYPOGRAPHY from '@components/Design/token/typography'; + +import Icon from '../Icon/Icon'; +import Text from '../Text/Text'; + +interface Props { + value: string; + onChange?: (event: React.ChangeEvent) => void; + onClick?: () => void; + readOnly?: boolean; + isFixed?: boolean; + activated?: boolean; +} + +const EditableAmount = ({value, onChange, onClick, readOnly = true, isFixed = false, activated}: Props) => { + const {theme} = useTheme(); + + const [width, setWidth] = useState(0); + + const spanRef = useRef(null); + + useEffect(() => { + if (spanRef.current) { + setWidth(spanRef.current.getBoundingClientRect().width); + } + }, [value]); + + return ( + + ); +}; + +export default EditableAmount; diff --git a/client/src/components/Design/components/BankSelect/BankSelect.stories.tsx b/client/src/components/Design/components/BankSelect/BankSelect.stories.tsx new file mode 100644 index 000000000..d7b6f88f6 --- /dev/null +++ b/client/src/components/Design/components/BankSelect/BankSelect.stories.tsx @@ -0,0 +1,23 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import BankSelect from './BankSelect'; + +const meta = { + title: 'Components/BankSelect', + component: BankSelect, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: {}, + args: { + onSelect: (name: string) => alert(name), + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/BankSelect/BankSelect.style.ts b/client/src/components/Design/components/BankSelect/BankSelect.style.ts new file mode 100644 index 000000000..5c42e3909 --- /dev/null +++ b/client/src/components/Design/components/BankSelect/BankSelect.style.ts @@ -0,0 +1,31 @@ +import {css} from '@emotion/react'; + +import ImageSprite from '@assets/image/banksprite.png'; + +export const iconStyle = (position: string) => + css({ + width: '80px', + height: '80px', + background: `url(${ImageSprite}) ${position}`, + }); + +export const bankSelectStyle = css({ + display: 'grid', + gridTemplateColumns: 'repeat(3, 1fr)', + gridRowGap: '1rem', + gridColumnGap: '2rem', + placeItems: 'center', + + height: '100%', + + '@media (min-width: 450px)': { + gridTemplateColumns: 'repeat(4, 1fr)', + }, + + overflowY: 'scroll', + scrollbarWidth: 'none', + + '&::-webkit-scrollbar': { + display: 'none', + }, +}); diff --git a/client/src/components/Design/components/BankSelect/BankSelect.tsx b/client/src/components/Design/components/BankSelect/BankSelect.tsx new file mode 100644 index 000000000..5fdc6f2df --- /dev/null +++ b/client/src/components/Design/components/BankSelect/BankSelect.tsx @@ -0,0 +1,30 @@ +/** @jsxImportSource @emotion/react */ +import BANKS from '@constants/bank'; + +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import {bankSelectStyle, iconStyle} from './BankSelect.style'; + +type BankSelectProps = { + onSelect: (name: string) => void; +}; + +const BankSelect = ({onSelect}: BankSelectProps) => { + return ( +
+ {BANKS.map(({name, iconPosition}) => ( + + ))} +
+ ); +}; + +export default BankSelect; diff --git a/client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx b/client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx new file mode 100644 index 000000000..3d68811ae --- /dev/null +++ b/client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx @@ -0,0 +1,29 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import BankSendButton from './BankSendButton'; + +const meta = { + title: 'Components/BankSendButton', + component: BankSendButton, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + isDeposited: { + description: '', + control: {type: 'boolean'}, + }, + }, + args: { + clipboardText: '토스뱅크 010100-10-123123', + onBankButtonClick: () => console.log('안녕'), + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/BankSendButton/BankSendButton.style.ts b/client/src/components/Design/components/BankSendButton/BankSendButton.style.ts new file mode 100644 index 000000000..bb6bbffb7 --- /dev/null +++ b/client/src/components/Design/components/BankSendButton/BankSendButton.style.ts @@ -0,0 +1,23 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@components/Design/theme/theme.type'; + +export const bankButtonStyle = (theme: Theme) => + css({ + width: '3.25rem', + height: '1.5rem', + + backgroundColor: theme.colors.tertiary, + + borderRadius: '0.5rem', + }); + +export const isDepositedStyle = (theme: Theme) => + css({ + width: '3.25rem', + height: '1.5rem', + + backgroundColor: theme.colors.grayContainer, + + borderRadius: '0.5rem', + }); diff --git a/client/src/components/Design/components/BankSendButton/BankSendButton.tsx b/client/src/components/Design/components/BankSendButton/BankSendButton.tsx new file mode 100644 index 000000000..3351b7dcc --- /dev/null +++ b/client/src/components/Design/components/BankSendButton/BankSendButton.tsx @@ -0,0 +1,48 @@ +/** @jsxImportSource @emotion/react */ +import CopyToClipboard from 'react-copy-to-clipboard'; + +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Icon from '../Icon/Icon'; +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import {bankButtonStyle, isDepositedStyle} from './BankSendButton.style'; + +type BankSendButtonProps = React.HTMLAttributes & { + clipboardText: string; + onBankButtonClick: () => void; + isDeposited?: boolean; +}; + +const BankSendButton = ({ + clipboardText, + onBankButtonClick, + isDeposited = false, + ...buttonProps +}: BankSendButtonProps) => { + const {theme} = useTheme(); + + return isDeposited ? ( + + ) : ( + + + + ); +}; + +export default BankSendButton; diff --git a/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx b/client/src/components/Design/components/BottomSheet/BottomSheet.stories.tsx similarity index 86% rename from HDesign/src/components/BottomSheet/BottomSheet.stories.tsx rename to client/src/components/Design/components/BottomSheet/BottomSheet.stories.tsx index 67d4cdb37..107f96c1f 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx +++ b/client/src/components/Design/components/BottomSheet/BottomSheet.stories.tsx @@ -3,8 +3,8 @@ import type {Meta, StoryObj} from '@storybook/react'; import {useState} from 'react'; -import Button from '@components/Button/Button'; -import BottomSheet from '@components/BottomSheet/BottomSheet'; +import Button from '@HDcomponents/Button/Button'; +import BottomSheet from '@HDcomponents/BottomSheet/BottomSheet'; const meta = { title: 'Components/BottomSheet', diff --git a/HDesign/src/components/BottomSheet/BottomSheet.style.ts b/client/src/components/Design/components/BottomSheet/BottomSheet.style.ts similarity index 94% rename from HDesign/src/components/BottomSheet/BottomSheet.style.ts rename to client/src/components/Design/components/BottomSheet/BottomSheet.style.ts index 08c373835..a15a1a959 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.style.ts +++ b/client/src/components/Design/components/BottomSheet/BottomSheet.style.ts @@ -10,7 +10,7 @@ export const display = (visible: boolean) => export const dimmedLayerStyle = (theme: Theme, isOpened: boolean) => css({ position: 'fixed', - zIndex: '30', + zIndex: theme.zIndex.bottomSheetDimmedLayer, top: '50%', left: '50%', transform: 'translate(-50%, -50%)', @@ -31,7 +31,7 @@ export const bottomSheetContainerStyle = (theme: Theme, isOpened: boolean, isDra flexDirection: 'column', alignItems: 'center', gap: '1.5rem', - zIndex: '50', + zIndex: theme.zIndex.bottomSheetContainer, inset: 'auto 0 0 50%', maxWidth: '768px', width: '100%', diff --git a/HDesign/src/components/BottomSheet/BottomSheet.tsx b/client/src/components/Design/components/BottomSheet/BottomSheet.tsx similarity index 94% rename from HDesign/src/components/BottomSheet/BottomSheet.tsx rename to client/src/components/Design/components/BottomSheet/BottomSheet.tsx index 3ffadc323..48d388625 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.tsx +++ b/client/src/components/Design/components/BottomSheet/BottomSheet.tsx @@ -1,11 +1,10 @@ /** @jsxImportSource @emotion/react */ import {createPortal} from 'react-dom'; -import {BottomSheetProps} from '@components/BottomSheet/BottomSheet.type'; - import {useTheme} from '@theme/HDesignProvider'; import {useBottomSheet} from './useBottomSheet'; +import {BottomSheetProps} from './BottomSheet.type'; import { bottomSheetContainerStyle, dimmedLayerStyle, diff --git a/HDesign/src/components/BottomSheet/BottomSheet.type.ts b/client/src/components/Design/components/BottomSheet/BottomSheet.type.ts similarity index 100% rename from HDesign/src/components/BottomSheet/BottomSheet.type.ts rename to client/src/components/Design/components/BottomSheet/BottomSheet.type.ts diff --git a/HDesign/src/components/BottomSheet/useBottomSheet.ts b/client/src/components/Design/components/BottomSheet/useBottomSheet.ts similarity index 99% rename from HDesign/src/components/BottomSheet/useBottomSheet.ts rename to client/src/components/Design/components/BottomSheet/useBottomSheet.ts index 3e2564550..e9a901c14 100644 --- a/HDesign/src/components/BottomSheet/useBottomSheet.ts +++ b/client/src/components/Design/components/BottomSheet/useBottomSheet.ts @@ -22,6 +22,8 @@ export const useBottomSheet = ({isOpened, onClose, onOpen}: UseBottomSheetProps) return () => clearTimeout(timer); } + + return; }, [opened]); useEffect(() => { diff --git a/HDesign/src/components/Button/Button.stories.tsx b/client/src/components/Design/components/Button/Button.stories.tsx similarity index 100% rename from HDesign/src/components/Button/Button.stories.tsx rename to client/src/components/Design/components/Button/Button.stories.tsx diff --git a/HDesign/src/components/Button/Button.style.ts b/client/src/components/Design/components/Button/Button.style.ts similarity index 94% rename from HDesign/src/components/Button/Button.style.ts rename to client/src/components/Design/components/Button/Button.style.ts index 24c46ec5b..0d274f116 100644 --- a/HDesign/src/components/Button/Button.style.ts +++ b/client/src/components/Design/components/Button/Button.style.ts @@ -1,8 +1,7 @@ import {css} from '@emotion/react'; -import {setDarker, setEmphasize, setLighter} from '@utils/colors'; - -import {Theme} from '../../theme/theme.type'; +import {setDarker, setEmphasize, setLighter} from '@HDutils/colors'; +import {Theme} from '@theme/theme.type'; import {ButtonStyleProps, ButtonSize, ButtonVariants} from './Button.type'; @@ -24,7 +23,7 @@ const getButtonDefaultStyle = (theme: Theme) => whiteSpace: 'nowrap', '&:disabled': { - backgroundColor: theme.colors.tertiary, + backgroundColor: theme.colors.grayContainer, color: theme.colors.onPrimary, cursor: 'default', }, diff --git a/HDesign/src/components/Button/Button.tsx b/client/src/components/Design/components/Button/Button.tsx similarity index 83% rename from HDesign/src/components/Button/Button.tsx rename to client/src/components/Design/components/Button/Button.tsx index f0277590b..3b8896a1c 100644 --- a/HDesign/src/components/Button/Button.tsx +++ b/client/src/components/Design/components/Button/Button.tsx @@ -3,13 +3,12 @@ import React, {forwardRef} from 'react'; import Lottie from 'lottie-react'; -import {buttonStyle} from '@components/Button/Button.style'; -import {ButtonProps, ButtonSize} from '@components/Button/Button.type'; - -import loadingAnimation from '@assets/loadingAnimation.json'; - +import loadingAnimation from '@assets/image/loadingAnimation.json'; import {useTheme} from '@theme/HDesignProvider'; +import {ButtonProps, ButtonSize} from './Button.type'; +import {buttonStyle} from './Button.style'; + const animationSize = (size: ButtonSize) => { switch (size) { case 'small': diff --git a/HDesign/src/components/Button/Button.type.ts b/client/src/components/Design/components/Button/Button.type.ts similarity index 100% rename from HDesign/src/components/Button/Button.type.ts rename to client/src/components/Design/components/Button/Button.type.ts diff --git a/client/src/components/Design/components/Chip/Chip.stories.tsx b/client/src/components/Design/components/Chip/Chip.stories.tsx new file mode 100644 index 000000000..08e7f259c --- /dev/null +++ b/client/src/components/Design/components/Chip/Chip.stories.tsx @@ -0,0 +1,36 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Chip from '@HDcomponents/Chip/Chip'; + +import Text from '../Text/Text'; +import Amount from '../Amount/Amount'; + +const meta = { + title: 'Components/Chip', + component: Chip, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + color: { + description: '', + control: {type: 'select'}, + }, + text: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + color: 'gray', + text: '망쵸', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/Chip/Chip.style.ts b/client/src/components/Design/components/Chip/Chip.style.ts new file mode 100644 index 000000000..a7ca3eaf7 --- /dev/null +++ b/client/src/components/Design/components/Chip/Chip.style.ts @@ -0,0 +1,20 @@ +import {css} from '@emotion/react'; + +import {ColorKeys} from '@components/Design/token/colors'; +import {Theme} from '@theme/theme.type'; + +interface ChipStyleProps { + theme: Theme; + color: ColorKeys; +} + +export const chipStyle = ({theme, color}: ChipStyleProps) => + css({ + display: 'flex', + padding: '0.125rem 0.5rem ', + borderRadius: '0.5rem', + color: `${theme.colors[color]}`, + boxSizing: 'border-box', + outline: 'none', + boxShadow: `inset 0 0 0 1px ${theme.colors[color]}`, + }); diff --git a/client/src/components/Design/components/Chip/Chip.tsx b/client/src/components/Design/components/Chip/Chip.tsx new file mode 100644 index 000000000..9566dfe7e --- /dev/null +++ b/client/src/components/Design/components/Chip/Chip.tsx @@ -0,0 +1,26 @@ +/** @jsxImportSource @emotion/react */ + +import {ColorKeys} from '@components/Design/token/colors'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Text from '../Text/Text'; + +import {chipStyle} from './Chip.style'; + +interface Props { + color: ColorKeys; + text: string; +} + +const Chip = ({color, text}: Props) => { + const {theme} = useTheme(); + return ( +
+ + {text} + +
+ ); +}; + +export default Chip; diff --git a/client/src/components/Design/components/ChipButton/ChipButton.stories.tsx b/client/src/components/Design/components/ChipButton/ChipButton.stories.tsx new file mode 100644 index 000000000..b3d3ea534 --- /dev/null +++ b/client/src/components/Design/components/ChipButton/ChipButton.stories.tsx @@ -0,0 +1,34 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import ChipButton from '@HDcomponents/ChipButton/ChipButton'; + +const meta = { + title: 'Components/ChipButton', + component: ChipButton, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + color: { + description: '', + control: {type: 'select'}, + }, + text: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + color: 'gray', + text: '망쵸', + onClick: () => {}, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/ChipButton/ChipButton.style.ts b/client/src/components/Design/components/ChipButton/ChipButton.style.ts new file mode 100644 index 000000000..ec0a19c0b --- /dev/null +++ b/client/src/components/Design/components/ChipButton/ChipButton.style.ts @@ -0,0 +1,21 @@ +import {css} from '@emotion/react'; + +import {ColorKeys} from '@components/Design/token/colors'; +import {Theme} from '@theme/theme.type'; + +interface ChipStyleProps { + theme: Theme; + color: ColorKeys; +} + +export const chipButtonStyle = ({theme, color}: ChipStyleProps) => + css({ + display: 'flex', + padding: '0.25rem 0.375rem 0.25rem 0.75rem', + gap: '0.5rem', + borderRadius: '1rem', + color: `${theme.colors[color]}`, + boxSizing: 'border-box', + outline: 'none', + boxShadow: `inset 0 0 0 1px ${theme.colors[color]}`, + }); diff --git a/client/src/components/Design/components/ChipButton/ChipButton.tsx b/client/src/components/Design/components/ChipButton/ChipButton.tsx new file mode 100644 index 000000000..7b0e1aa50 --- /dev/null +++ b/client/src/components/Design/components/ChipButton/ChipButton.tsx @@ -0,0 +1,27 @@ +/** @jsxImportSource @emotion/react */ + +import {ColorKeys} from '@components/Design/token/colors'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Text from '../Text/Text'; +import Icon from '../Icon/Icon'; + +import {chipButtonStyle} from './ChipButton.style'; + +interface Props { + color: ColorKeys; + text: string; + onClick: () => void; +} + +const ChipButton = ({color, text, onClick}: Props) => { + const {theme} = useTheme(); + return ( +
+ {text} + +
+ ); +}; + +export default ChipButton; diff --git a/client/src/components/Design/components/ChipGroup/ChipGroup.stories.tsx b/client/src/components/Design/components/ChipGroup/ChipGroup.stories.tsx new file mode 100644 index 000000000..f60a84a01 --- /dev/null +++ b/client/src/components/Design/components/ChipGroup/ChipGroup.stories.tsx @@ -0,0 +1,29 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import ChipGroup from '@HDcomponents/ChipGroup/ChipGroup'; + +const meta = { + title: 'Components/ChipGroup', + component: ChipGroup, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + color: { + description: '', + control: {type: 'select'}, + }, + }, + args: { + color: 'gray', + texts: ['망쵸', '감자', '백호', '이상'], + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/ChipGroup/ChipGroup.style.ts b/client/src/components/Design/components/ChipGroup/ChipGroup.style.ts new file mode 100644 index 000000000..fcd3433ee --- /dev/null +++ b/client/src/components/Design/components/ChipGroup/ChipGroup.style.ts @@ -0,0 +1,8 @@ +import {css} from '@emotion/react'; + +export const chipGroupStyle = css({ + display: 'flex', + gap: '0.25rem', + flexWrap: 'wrap', + overflow: 'hidden', +}); diff --git a/client/src/components/Design/components/ChipGroup/ChipGroup.tsx b/client/src/components/Design/components/ChipGroup/ChipGroup.tsx new file mode 100644 index 000000000..792228217 --- /dev/null +++ b/client/src/components/Design/components/ChipGroup/ChipGroup.tsx @@ -0,0 +1,27 @@ +/** @jsxImportSource @emotion/react */ + +import {ColorKeys} from '@components/Design/token/colors'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import {chipStyle} from '../Chip/Chip.style'; +import Text from '../Text/Text'; +import Chip from '../Chip/Chip'; + +import {chipGroupStyle} from './ChipGroup.style'; + +interface Props { + color: ColorKeys; + texts: string[]; +} + +const ChipGroup = ({color, texts}: Props) => { + return ( +
+ {texts.map(text => ( + + ))} +
+ ); +}; + +export default ChipGroup; diff --git a/client/src/components/Design/components/DepositCheck/DepositCheck.stories.tsx b/client/src/components/Design/components/DepositCheck/DepositCheck.stories.tsx new file mode 100644 index 000000000..7cfd25aea --- /dev/null +++ b/client/src/components/Design/components/DepositCheck/DepositCheck.stories.tsx @@ -0,0 +1,27 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import DepositCheck from '@HDcomponents/DepositCheck/DepositCheck'; + +const meta = { + title: 'Components/DepositCheck', + component: DepositCheck, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + isDeposited: { + description: '', + control: {type: 'boolean'}, + }, + }, + args: { + isDeposited: false, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/DepositCheck/DepositCheck.style.ts b/client/src/components/Design/components/DepositCheck/DepositCheck.style.ts new file mode 100644 index 000000000..22f1f52a9 --- /dev/null +++ b/client/src/components/Design/components/DepositCheck/DepositCheck.style.ts @@ -0,0 +1,21 @@ +import {css} from '@emotion/react'; + +import {WithTheme} from '@components/Design/type/withTheme'; + +import {DepositCheckStyleProps} from './DepositCheck.type'; + +export const DepositCheckStyle = ({theme, isDeposited}: WithTheme) => + css({ + display: 'flex', + alignItems: 'center', + gap: '0.125rem', + border: `1px solid ${isDeposited ? theme.colors.primary : theme.colors.gray}`, + borderRadius: '0.5rem', + padding: '0.25rem 0.375rem', + height: '1.25rem', + + '.deposit-check-text': { + color: isDeposited ? theme.colors.primary : theme.colors.gray, + paddingTop: '0.0625rem', + }, + }); diff --git a/client/src/components/Design/components/DepositCheck/DepositCheck.tsx b/client/src/components/Design/components/DepositCheck/DepositCheck.tsx new file mode 100644 index 000000000..10b21aabc --- /dev/null +++ b/client/src/components/Design/components/DepositCheck/DepositCheck.tsx @@ -0,0 +1,21 @@ +/** @jsxImportSource @emotion/react */ +import {useTheme} from '@components/Design'; + +import Icon from '../Icon/Icon'; +import Text from '../Text/Text'; + +import {DepositCheckStyle} from './DepositCheck.style'; +import {DepositCheckProps} from './DepositCheck.type'; + +const DepositCheck: React.FC = ({isDeposited = false}: DepositCheckProps) => { + const {theme} = useTheme(); + return ( +
+ + 입금 + + +
+ ); +}; +export default DepositCheck; diff --git a/client/src/components/Design/components/DepositCheck/DepositCheck.type.ts b/client/src/components/Design/components/DepositCheck/DepositCheck.type.ts new file mode 100644 index 000000000..fdb308170 --- /dev/null +++ b/client/src/components/Design/components/DepositCheck/DepositCheck.type.ts @@ -0,0 +1,11 @@ +export interface DepositCheckStyleProps { + isDeposited: boolean; +} + +export interface DepositCheckCustomProps { + isDeposited: boolean; +} + +export type DepositCheckOptionProps = DepositCheckStyleProps & DepositCheckCustomProps; + +export type DepositCheckProps = React.ComponentProps<'div'> & DepositCheckOptionProps; diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx b/client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx new file mode 100644 index 000000000..49a85d749 --- /dev/null +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx @@ -0,0 +1,51 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useEffect, useState} from 'react'; + +import DepositToggle from './DepositToggle'; + +const meta = { + title: 'Components/DepositToggle', + component: DepositToggle, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + isDeposit: { + description: '', + control: {type: 'boolean'}, + }, + onToggle: { + description: '', + control: {type: 'select'}, + options: [undefined, () => alert('change toggle')], + }, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + args: { + isDeposit: false, + onToggle: () => {}, + }, + render: ({isDeposit, onToggle, ...args}) => { + const [isDepositState, setIsDepositState] = useState(isDeposit); + + useEffect(() => { + setIsDepositState(isDeposit); + }, [isDeposit]); + + const handleToggle = () => { + setIsDepositState(!isDepositState); + onToggle(); + }; + + return ; + }, +}; diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts b/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts new file mode 100644 index 000000000..fff882251 --- /dev/null +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts @@ -0,0 +1,43 @@ +import {css} from '@emotion/react'; + +import {WithTheme} from '@components/Design/type/withTheme'; + +import {DepositToggleStyleProps} from './DepositToggle.type'; + +export const depositToggleStyle = ({theme, isDeposit}: WithTheme) => + css({ + display: `flex`, + flexDirection: 'row', + justifyContent: 'center', + padding: '0.25rem', + borderRadius: '0.75rem', + backgroundColor: theme.colors.tertiary, + cursor: 'pointer', + alignItems: 'center', + width: '4.75rem', + height: '1.4375rem', + + '.deposit-text': { + display: 'flex', + justifyContent: 'center', + borderRadius: '0.5rem', + padding: '0 0.25rem', + zIndex: theme.zIndex.depositToggleMovingAnimation, + height: '15px', + width: '34px', + paddingTop: '0.05rem', + }, + + '.toggle-background': { + position: 'absolute', + width: '34px', + height: '15px', + borderRadius: '0.5rem', + backgroundColor: theme.colors.white, + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + + transform: !isDeposit ? 'translateX(1.07rem)' : 'translateX(-1.06rem)', + }, + }); diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.tsx b/client/src/components/Design/components/DepositToggle/DepositToggle.tsx new file mode 100644 index 000000000..f68353ce5 --- /dev/null +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.tsx @@ -0,0 +1,26 @@ +/** @jsxImportSource @emotion/react */ + +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; + +import {DepositToggleProps} from './DepositToggle.type'; +import {depositToggleStyle} from './DepositToggle.style'; + +const DepositToggle: React.FC = ({isDeposit = false, onToggle}: DepositToggleProps) => { + const {theme} = useTheme(); + + return ( +
+
+ + 입금 + + + 미입금 + +
+ ); +}; + +export default DepositToggle; diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.type.ts b/client/src/components/Design/components/DepositToggle/DepositToggle.type.ts new file mode 100644 index 000000000..15f19d01f --- /dev/null +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.type.ts @@ -0,0 +1,12 @@ +export interface DepositToggleStyleProps { + isDeposit: boolean; +} + +export interface DepositToggleCustomProps { + isDeposit: boolean; + onToggle: () => void; +} + +export type DepositToggleOptionProps = DepositToggleStyleProps & DepositToggleCustomProps; + +export type DepositToggleProps = React.ComponentProps<'div'> & DepositToggleOptionProps; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx b/client/src/components/Design/components/DragHandleItem/DragHandleItem.stories.tsx similarity index 94% rename from HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx rename to client/src/components/Design/components/DragHandleItem/DragHandleItem.stories.tsx index c7125d4d8..8043777b5 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx +++ b/client/src/components/Design/components/DragHandleItem/DragHandleItem.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; +import DragHandleItem from '@HDcomponents/DragHandleItem/DragHandleItem'; const meta = { title: 'Components/DragHandleItem', diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts b/client/src/components/Design/components/DragHandleItem/DragHandleItem.style.ts similarity index 99% rename from HDesign/src/components/DragHandleItem/DragHandleItem.style.ts rename to client/src/components/Design/components/DragHandleItem/DragHandleItem.style.ts index b641c5fb3..7136e7b3c 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts +++ b/client/src/components/Design/components/DragHandleItem/DragHandleItem.style.ts @@ -1,7 +1,6 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export const dragHandleItemStyle = (theme: Theme, hasDragHandle: boolean, backgroundColor: ColorKeys) => diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx b/client/src/components/Design/components/DragHandleItem/DragHandleItem.tsx similarity index 85% rename from HDesign/src/components/DragHandleItem/DragHandleItem.tsx rename to client/src/components/Design/components/DragHandleItem/DragHandleItem.tsx index 9acf38084..4cca73a4f 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx +++ b/client/src/components/Design/components/DragHandleItem/DragHandleItem.tsx @@ -1,9 +1,8 @@ /** @jsxImportSource @emotion/react */ -import Icon from '@components/Icon/Icon'; -import Flex from '@components/Flex/Flex'; -import Text from '@components/Text/Text'; -import IsFixedIcon from '@components/IsFixedIcon/IsFixedIcon'; - +import Icon from '@HDcomponents/Icon/Icon'; +import Flex from '@HDcomponents/Flex/Flex'; +import Text from '@HDcomponents/Text/Text'; +import IsFixedIcon from '@HDcomponents/IsFixedIcon/IsFixedIcon'; import {useTheme} from '@theme/HDesignProvider'; import IconButton from '../IconButton/IconButton'; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts b/client/src/components/Design/components/DragHandleItem/DragHandleItem.type.ts similarity index 99% rename from HDesign/src/components/DragHandleItem/DragHandleItem.type.ts rename to client/src/components/Design/components/DragHandleItem/DragHandleItem.type.ts index fc0a1f520..8b62dd374 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts +++ b/client/src/components/Design/components/DragHandleItem/DragHandleItem.type.ts @@ -1,5 +1,4 @@ import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export interface DragHandleItemStyleProps { diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx similarity index 92% rename from HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx rename to client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx index 46c3db8a2..1e215ca9d 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx +++ b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx @@ -1,8 +1,8 @@ /** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; -import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; -import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; +import DragHandleItemContainer from '@HDcomponents/DragHandleItemContainer/DragHandleItemContainer'; +import DragHandleItem from '@HDcomponents/DragHandleItem/DragHandleItem'; const meta = { title: 'Components/DragHandleItemContainer', diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.style.ts similarity index 99% rename from HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts rename to client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.style.ts index b5bab9422..db2ada615 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts +++ b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.style.ts @@ -1,7 +1,6 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export const containerStyle = (theme: Theme, backgroundColor: ColorKeys) => diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.tsx similarity index 100% rename from HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx rename to client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.tsx diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.type.ts similarity index 100% rename from HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts rename to client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.type.ts diff --git a/client/src/components/Design/components/Dropdown/Dropdown.stories.tsx b/client/src/components/Design/components/Dropdown/Dropdown.stories.tsx new file mode 100644 index 000000000..2504ecae7 --- /dev/null +++ b/client/src/components/Design/components/Dropdown/Dropdown.stories.tsx @@ -0,0 +1,34 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Dropdown from '@HDcomponents/Dropdown/Dropdown'; + +import DropdownButton from './DropdownButton'; + +const meta = { + title: 'Components/Dropdown', + component: Dropdown, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + decorators: [ + Story => ( +
+ +
+ ), + ], + args: { + children: [ + alert('전체 참여자 관리 클릭')} />, + alert('계좌번호 입력하기 클릭')} />, + ], + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/Dropdown/Dropdown.style.ts b/client/src/components/Design/components/Dropdown/Dropdown.style.ts new file mode 100644 index 000000000..8b4fc91df --- /dev/null +++ b/client/src/components/Design/components/Dropdown/Dropdown.style.ts @@ -0,0 +1,33 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@components/Design/theme/theme.type'; + +import {FlexProps} from '../Flex/Flex.type'; + +export const dropdownStyle: FlexProps = { + flexDirection: 'column', + width: '12.5rem', + padding: '0.5rem', + paddingInline: '0.5rem', + gap: '0.25rem', + backgroundColor: 'white', + + otherStyle: { + position: 'absolute', + top: '2rem', + right: '-1rem', + borderRadius: '0.75rem', + boxShadow: '2px 4px 16px 0 rgba(0, 0, 0, 0.08)', + }, +}; + +export const dropdownButtonStyle = (theme: Theme) => + css({ + height: '2rem', + padding: '0.25rem 0.5rem', + + ':hover': { + borderRadius: '0.625rem', + backgroundColor: theme.colors.grayContainer, + }, + }); diff --git a/client/src/components/Design/components/Dropdown/Dropdown.tsx b/client/src/components/Design/components/Dropdown/Dropdown.tsx new file mode 100644 index 000000000..63045dd56 --- /dev/null +++ b/client/src/components/Design/components/Dropdown/Dropdown.tsx @@ -0,0 +1,36 @@ +/** @jsxImportSource @emotion/react */ +import Icon from '../Icon/Icon'; +import IconButton from '../IconButton/IconButton'; +import Flex from '../Flex/Flex'; + +import useDropdown from './useDropdown'; +import {DropdownProps} from './Dropdown.type'; +import DropdownButton from './DropdownButton'; +import {dropdownStyle} from './Dropdown.style'; + +const Dropdown = ({children}: DropdownProps) => { + const {isOpen, openDropdown, meetBallsRef, dropdownRef} = useDropdown(); + const isDropdownOpen = isOpen && meetBallsRef.current; + + return ( + + + {isDropdownOpen && ( +
+ + {children.map(button => ( + + ))} + +
+ )} +
+ ); +}; + +export default Dropdown; diff --git a/client/src/components/Design/components/Dropdown/Dropdown.type.ts b/client/src/components/Design/components/Dropdown/Dropdown.type.ts new file mode 100644 index 000000000..1b67bbc33 --- /dev/null +++ b/client/src/components/Design/components/Dropdown/Dropdown.type.ts @@ -0,0 +1,7 @@ +export type DropdownButtonProps = React.HTMLAttributes & { + text: string; +}; + +export type DropdownProps = { + children: React.ReactElement[]; +}; diff --git a/client/src/components/Design/components/Dropdown/DropdownButton.tsx b/client/src/components/Design/components/Dropdown/DropdownButton.tsx new file mode 100644 index 000000000..005a6042a --- /dev/null +++ b/client/src/components/Design/components/Dropdown/DropdownButton.tsx @@ -0,0 +1,21 @@ +/** @jsxImportSource @emotion/react */ + +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Text from '../Text/Text'; + +import {dropdownButtonStyle} from './Dropdown.style'; +import {DropdownButtonProps} from './Dropdown.type'; + +const DropdownButton = ({text, ...buttonProps}: DropdownButtonProps) => { + const {theme} = useTheme(); + return ( + + ); +}; + +export default DropdownButton; diff --git a/client/src/components/Design/components/Dropdown/useDropdown.ts b/client/src/components/Design/components/Dropdown/useDropdown.ts new file mode 100644 index 000000000..f484c62a0 --- /dev/null +++ b/client/src/components/Design/components/Dropdown/useDropdown.ts @@ -0,0 +1,39 @@ +import {useEffect, useRef, useState} from 'react'; + +const useDropdown = () => { + const [isOpen, setIsOpen] = useState(false); + const meetBallsRef = useRef(null); + const dropdownRef = useRef(null); + + const openDropdown = () => { + setIsOpen(true); + }; + + useEffect(() => { + const clickOutSide = (event: MouseEvent) => { + const targetNode = event.target as Node; + + if ( + (dropdownRef.current && dropdownRef.current.contains(targetNode)) || + (meetBallsRef.current && meetBallsRef.current.contains(targetNode)) + ) { + return; + } + + setIsOpen(false); + }; + document.addEventListener('mousedown', clickOutSide); + return () => { + document.removeEventListener('mousedown', clickOutSide); + }; + }, [dropdownRef]); + + return { + isOpen, + openDropdown, + meetBallsRef, + dropdownRef, + }; +}; + +export default useDropdown; diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts b/client/src/components/Design/components/EditableItem/EditableItem.Input.style.ts similarity index 97% rename from HDesign/src/components/EditableItem/EditableItem.Input.style.ts rename to client/src/components/Design/components/EditableItem/EditableItem.Input.style.ts index eadff482e..eeefb44ca 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts +++ b/client/src/components/Design/components/EditableItem/EditableItem.Input.style.ts @@ -1,8 +1,7 @@ import {css} from '@emotion/react'; -import {TextSize} from '@components/Text/Text.type'; +import {TextSize} from '@HDcomponents/Text/Text.type'; import {WithTheme} from '@type/withTheme'; - import TYPOGRAPHY from '@token/typography'; type UnderlineProps = { diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.tsx b/client/src/components/Design/components/EditableItem/EditableItem.Input.tsx similarity index 90% rename from HDesign/src/components/EditableItem/EditableItem.Input.tsx rename to client/src/components/Design/components/EditableItem/EditableItem.Input.tsx index c0a08bc0e..bc7d6ca6a 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.tsx +++ b/client/src/components/Design/components/EditableItem/EditableItem.Input.tsx @@ -1,10 +1,9 @@ /** @jsxImportSource @emotion/react */ import {forwardRef, useEffect, useImperativeHandle, useRef} from 'react'; -import Flex from '@components/Flex/Flex'; -import Text from '@components/Text/Text'; -import IsFixedIcon from '@components/IsFixedIcon/IsFixedIcon'; - +import Flex from '@HDcomponents/Flex/Flex'; +import Text from '@HDcomponents/Text/Text'; +import IsFixedIcon from '@HDcomponents/IsFixedIcon/IsFixedIcon'; import {useTheme} from '@theme/HDesignProvider'; import {editingContainerStyle, inputStyle, inputWrapperStyle, underlineStyle} from './EditableItem.Input.style'; @@ -29,10 +28,13 @@ export const EditableItemInput = forwardRef(functi return (
+ +
{htmlProps.value || htmlProps.placeholder}
+ {isFixed && }
diff --git a/HDesign/src/components/EditableItem/EditableItem.tsx b/client/src/components/Design/components/EditableItem/EditableItem.tsx similarity index 93% rename from HDesign/src/components/EditableItem/EditableItem.tsx rename to client/src/components/Design/components/EditableItem/EditableItem.tsx index f8b9ca434..97a295ccb 100644 --- a/HDesign/src/components/EditableItem/EditableItem.tsx +++ b/client/src/components/Design/components/EditableItem/EditableItem.tsx @@ -1,7 +1,6 @@ /** @jsxImportSource @emotion/react */ -import Text from '@components/Text/Text'; -import Flex from '@components/Flex/Flex'; - +import Text from '@HDcomponents/Text/Text'; +import Flex from '@HDcomponents/Flex/Flex'; import {useTheme} from '@theme/HDesignProvider'; import {editableItemStyle, labelTextStyle} from './EditableItem.style'; diff --git a/HDesign/src/components/EditableItem/EditableItem.type.ts b/client/src/components/Design/components/EditableItem/EditableItem.type.ts similarity index 99% rename from HDesign/src/components/EditableItem/EditableItem.type.ts rename to client/src/components/Design/components/EditableItem/EditableItem.type.ts index a56835855..e28114308 100644 --- a/HDesign/src/components/EditableItem/EditableItem.type.ts +++ b/client/src/components/Design/components/EditableItem/EditableItem.type.ts @@ -1,5 +1,4 @@ import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export interface EditableItemStyleProps { diff --git a/HDesign/src/components/EditableItem/useEditableItem.ts b/client/src/components/Design/components/EditableItem/useEditableItem.ts similarity index 100% rename from HDesign/src/components/EditableItem/useEditableItem.ts rename to client/src/components/Design/components/EditableItem/useEditableItem.ts diff --git a/HDesign/src/components/EditableItem/useEditableItemInput.ts b/client/src/components/Design/components/EditableItem/useEditableItemInput.ts similarity index 98% rename from HDesign/src/components/EditableItem/useEditableItemInput.ts rename to client/src/components/Design/components/EditableItem/useEditableItemInput.ts index 3253ad0ea..c9899a211 100644 --- a/HDesign/src/components/EditableItem/useEditableItemInput.ts +++ b/client/src/components/Design/components/EditableItem/useEditableItemInput.ts @@ -32,6 +32,8 @@ const useEditableItemInput = ({inputRef}: UseEditableItemInputProps) => { input.removeEventListener('blur', handleBlur); }; } + + return; }, [handleFocus, handleBlur, inputRef]); useEffect(() => { diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx new file mode 100644 index 000000000..ddaf1d50b --- /dev/null +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx @@ -0,0 +1,61 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import ExpenseList from '@HDcomponents/ExpenseList/ExpenseList'; + +const meta = { + title: 'Components/ExpenseList', + component: ExpenseList, + tags: ['autodocs'], + argTypes: { + expenseList: { + description: '', + }, + }, + args: { + memberName: '소하', + onSearch: () => console.log('쿠키'), + placeholder: '안녕', + + expenseList: [ + { + memberId: 1, + memberName: '소하', + price: 2000, + isDeposited: true, + clipboardText: '토스은행 2000원', + onBankButtonClick: () => console.log('소하'), + }, + { + memberId: 2, + memberName: '토다리', + price: 2000, + isDeposited: false, + clipboardText: '토스은행 2000원', + onBankButtonClick: () => console.log('토다리'), + }, + { + memberId: 3, + memberName: '웨디', + price: 1080, + isDeposited: true, + clipboardText: '토스은행 1080원', + onBankButtonClick: () => console.log('웨디'), + }, + { + memberId: 4, + memberName: '쿠키', + price: 3020, + isDeposited: false, + clipboardText: '토스은행 3020원', + onBankButtonClick: () => console.log('쿠키'), + }, + ], + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx new file mode 100644 index 000000000..f34cc1aaf --- /dev/null +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx @@ -0,0 +1,75 @@ +/** @jsxImportSource @emotion/react */ +import Text from '@HDcomponents/Text/Text'; + +import {isMobileDevice} from '@utils/detectDevice'; + +import BankSendButton from '../BankSendButton/BankSendButton'; +import Icon from '../Icon/Icon'; +import IconButton from '../IconButton/IconButton'; +import Flex from '../Flex/Flex'; +import Input from '../Input/Input'; +import Amount from '../Amount/Amount'; +import DepositCheck from '../DepositCheck/DepositCheck'; + +import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; + +function ExpenseItem({ + memberName, + price, + isDeposited, + onBankButtonClick, + clipboardText, + ...divProps +}: ExpenseItemProps) { + return ( + + + + + {memberName} + + + + + {isMobileDevice() ? ( + + ) : ( + + + + )} + + + ); +} + +function ExpenseList({memberName, onSearch, placeholder, expenseList = []}: ExpenseListProps) { + return ( + + + {expenseList.length !== 0 && expenseList.map(expense => )} + + ); +} + +export default ExpenseList; diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts b/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts new file mode 100644 index 000000000..90a44c842 --- /dev/null +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts @@ -0,0 +1,15 @@ +import {Report} from 'types/serviceType'; + +export type ExpenseItemCustomProps = Report & { + onBankButtonClick: () => void; + clipboardText: string; +}; + +export type ExpenseItemProps = React.ComponentProps<'div'> & ExpenseItemCustomProps; + +export type ExpenseListProps = { + memberName: string; + onSearch: ({target}: React.ChangeEvent) => void; + placeholder: string; + expenseList: ExpenseItemProps[]; +}; diff --git a/HDesign/src/components/FixedButton/FixedButton.stories.tsx b/client/src/components/Design/components/FixedButton/FixedButton.stories.tsx similarity index 93% rename from HDesign/src/components/FixedButton/FixedButton.stories.tsx rename to client/src/components/Design/components/FixedButton/FixedButton.stories.tsx index 47485f851..ad5a98ee9 100644 --- a/HDesign/src/components/FixedButton/FixedButton.stories.tsx +++ b/client/src/components/Design/components/FixedButton/FixedButton.stories.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; -import FixedButton from '@components/FixedButton/FixedButton'; +import FixedButton from '@HDcomponents/FixedButton/FixedButton'; const meta = { title: 'Components/FixedButton', diff --git a/HDesign/src/components/FixedButton/FixedButton.style.ts b/client/src/components/Design/components/FixedButton/FixedButton.style.ts similarity index 68% rename from HDesign/src/components/FixedButton/FixedButton.style.ts rename to client/src/components/Design/components/FixedButton/FixedButton.style.ts index 2e774918d..3698c2b52 100644 --- a/HDesign/src/components/FixedButton/FixedButton.style.ts +++ b/client/src/components/Design/components/FixedButton/FixedButton.style.ts @@ -1,11 +1,9 @@ import {css} from '@emotion/react'; -import {ButtonVariants} from '@components/Button/Button.type'; -import {FixedButtonStyleProps} from '@components/FixedButton/FixedButton.type'; - +import {ButtonVariants} from '@HDcomponents/Button/Button.type'; +import {FixedButtonStyleProps} from '@HDcomponents/FixedButton/FixedButton.type'; import {Theme} from '@theme/theme.type'; - -import {setDarker, setLighter} from '@utils/colors'; +import {setDarker, setLighter} from '@HDutils/colors'; export const fixedButtonContainerStyle = (theme: Theme) => css({ @@ -16,6 +14,7 @@ export const fixedButtonContainerStyle = (theme: Theme) => margin: '0 auto', backgroundColor: theme.colors.white, boxSizing: 'border-box', + zIndex: theme.zIndex.fixedButton, }); export const buttonContainerStyle = css({ @@ -37,30 +36,62 @@ const getHoverAndActiveBackground = (color: string) => }, }); -export const deleteButtonStyle = (theme: Theme) => [ +export const deleteButtonStyle = (theme: Theme) => css({ display: 'flex', justifyContent: 'center', - padding: '0.875rem 1rem', - borderRadius: '1.25rem', - backgroundColor: theme.colors.error, - color: theme.colors.white, + padding: '1rem 1.5rem', + borderRadius: '1rem', + width: '100%', fontFamily: 'Pretendard', - fontSize: '1rem', + fontSize: '1.25rem', fontWeight: '700', lineHeight: '1', transition: '0.2s', transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', - }), - getHoverAndActiveBackground(theme.colors.error), -]; + + backgroundColor: theme.colors.tertiary, + color: theme.colors.error, + + '&:disabled': { + backgroundColor: theme.colors.grayContainer, + color: theme.colors.onPrimary, + cursor: 'default', + }, + }); export const fixedButtonStyle = (props: Required) => { return [getFixedButtonDefaultStyle(props.theme), getFixedButtonVariantsStyle(props.variants, props.theme)]; }; +export const cancleButtonStyle = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'center', + padding: '1rem 1.5rem', + borderRadius: '1rem', + width: '100%', + + fontFamily: 'Pretendard', + fontSize: '1.25rem', + fontWeight: '700', + lineHeight: '1', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + + '&:disabled': { + backgroundColor: theme.colors.grayContainer, + color: theme.colors.onPrimary, + cursor: 'default', + }, + }); + const getFixedButtonDefaultStyle = (theme: Theme) => css({ display: 'flex', @@ -78,7 +109,7 @@ const getFixedButtonDefaultStyle = (theme: Theme) => transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', '&:disabled': { - backgroundColor: theme.colors.tertiary, + backgroundColor: theme.colors.grayContainer, color: theme.colors.onPrimary, cursor: 'default', }, diff --git a/HDesign/src/components/FixedButton/FixedButton.tsx b/client/src/components/Design/components/FixedButton/FixedButton.tsx similarity index 55% rename from HDesign/src/components/FixedButton/FixedButton.tsx rename to client/src/components/Design/components/FixedButton/FixedButton.tsx index 4430016d6..28192cd33 100644 --- a/HDesign/src/components/FixedButton/FixedButton.tsx +++ b/client/src/components/Design/components/FixedButton/FixedButton.tsx @@ -2,21 +2,21 @@ import {forwardRef} from 'react'; import Lottie from 'lottie-react'; +import loadingAnimation from '@assets/image/loadingAnimation.json'; import { fixedButtonContainerStyle, fixedButtonStyle, buttonContainerStyle, -} from '@components/FixedButton/FixedButton.style'; -import {FixedButtonProps} from '@components/FixedButton/FixedButton.type'; -import IconButton from '@components/IconButton/IconButton'; -import Icon from '@components/Icon/Icon'; - -import loadingAnimation from '@assets/loadingAnimation.json'; - + cancleButtonStyle, + deleteButtonStyle, +} from '@HDcomponents/FixedButton/FixedButton.style'; +import {FixedButtonProps} from '@HDcomponents/FixedButton/FixedButton.type'; +import IconButton from '@HDcomponents/IconButton/IconButton'; +import Icon from '@HDcomponents/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; export const FixedButton: React.FC = forwardRef(function Button( - {variants = 'primary', onDeleteClick, disabled, children, ...htmlProps}: FixedButtonProps, + {variants = 'primary', onDeleteClick, onBackClick, disabled, children, ...htmlProps}: FixedButtonProps, ref, ) { const {theme} = useTheme(); @@ -24,9 +24,14 @@ export const FixedButton: React.FC = forwardRef
{onDeleteClick && ( - - - + + )} + {onBackClick && ( + )} + ); +} diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx new file mode 100644 index 000000000..0778c506f --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx @@ -0,0 +1,44 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useRef, useState} from 'react'; + +import {Flex, Input} from '@components/Design'; + +import RULE from '@constants/rule'; + +import NumberKeyboard from './NumberKeyboard'; + +const meta = { + title: 'Components/NumberKeyboard', + component: NumberKeyboard, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + type: {description: '', control: {type: 'select'}, options: ['amount', 'number', 'string']}, + }, + args: { + type: 'amount', + maxNumber: RULE.maxPrice, + onChange: () => {}, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + render: ({type, maxNumber}) => { + const inputRef = useRef(null); + const [value, setValue] = useState(''); + return ( + + + + + ); + }, +}; diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx new file mode 100644 index 000000000..bc8d499df --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx @@ -0,0 +1,76 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {Button, useTheme} from '@components/Design'; + +import {Keypad} from './Keypad'; +import useNumberKeyboard from './useNumberKeyboard'; + +export type KeyboardType = 'number' | 'string' | 'amount'; + +export interface NumberKeyboardProps { + type: KeyboardType; + maxNumber: number; + initialValue?: string; + onChange: (value: string) => void; +} + +export default function NumberKeyboard({type, maxNumber, initialValue, onChange}: NumberKeyboardProps) { + const {theme} = useTheme(); + const amountKeypads = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '00', '0', '<-']; + const numberKeypads = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '', '0', '<-']; + + const {onClickKeypad, onClickDelete, onClickDeleteAll, onClickAddAmount} = useNumberKeyboard({ + type, + initialValue, + maxNumber, + onChange, + }); + + return ( +
+ {type === 'amount' && ( +
+ + + + +
+ )} + {(type === 'amount' ? amountKeypads : numberKeypads).map(el => ( + onClickKeypad(el)} + /> + ))} +
+ ); +} diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx new file mode 100644 index 000000000..cf9b07ada --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx @@ -0,0 +1,50 @@ +import {css} from '@emotion/react'; +import {createPortal} from 'react-dom'; +import {useEffect, useRef} from 'react'; + +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import FixedButton from '../FixedButton/FixedButton'; + +import NumberKeyboard, {NumberKeyboardProps} from './NumberKeyboard'; +import useNumberKeyboardBottomSheet from './useNumberKeyboardBottomSheet'; + +interface Props extends NumberKeyboardProps { + isOpened: boolean; + onClose: () => void; +} + +const NumberKeyboardBottomSheet = ({isOpened, onClose, ...props}: Props) => { + const {theme} = useTheme(); + const {bottomSheetRef} = useNumberKeyboardBottomSheet({isOpened}); + + return createPortal( +
+ + + 닫기 + +
, + document.body, + ); +}; + +export default NumberKeyboardBottomSheet; diff --git a/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx new file mode 100644 index 000000000..1c64f61b3 --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx @@ -0,0 +1,61 @@ +import {useEffect, useState} from 'react'; + +import {KeyboardType} from './NumberKeyboard'; + +interface Props { + type: KeyboardType; + maxNumber?: number; + initialValue?: string; + onChange: (value: string) => void; +} + +const useNumberKeyboard = ({type, maxNumber, initialValue, onChange}: Props) => { + const [value, setValue] = useState(initialValue ?? ''); + + useEffect(() => { + if (initialValue) { + setValue(initialValue); + } + }, [initialValue]); + + const onClickKeypad = (inputValue: string) => { + const newValue = (value + inputValue).replace(/,/g, ''); + setValueByType(newValue); + }; + + const onClickDelete = () => { + const newValue = value.slice(0, value.length - 1).replace(/,/g, ''); + setValueByType(newValue); + }; + + const onClickDeleteAll = () => { + setValue(''); + }; + + const onClickAddAmount = (amount: number) => { + const newValue = `${Number(value.replace(/,/g, '')) + amount}`; + setValueByType(newValue); + }; + + const setValueByType = (value: string) => { + if (type === 'string') { + setValue(value); + } else { + const limitedValue = maxNumber !== 0 ? (maxNumber && Number(value) > maxNumber ? `${maxNumber}` : value) : 0; + + if (Number(limitedValue) === 0) { + setValue(''); + } else { + setValue(type === 'amount' ? Number(limitedValue).toLocaleString() : `${limitedValue}`); + } + } + }; + + useEffect(() => { + onChange(value); + }, [value]); + + return {value, onClickKeypad, onClickDelete, onClickDeleteAll, onClickAddAmount}; +}; + +export default useNumberKeyboard; diff --git a/client/src/components/Design/components/NumberKeyboard/useNumberKeyboardBottomSheet.ts b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboardBottomSheet.ts new file mode 100644 index 000000000..28e5cc6a3 --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboardBottomSheet.ts @@ -0,0 +1,32 @@ +import {useEffect, useRef} from 'react'; + +interface Props { + isOpened: boolean; +} + +const useNumberKeyboardBottomSheet = ({isOpened}: Props) => { + const bottomSheetRef = useRef(null); + + useEffect(() => { + const bottomSheet = bottomSheetRef.current; + if (!bottomSheet) return; + + const preventScroll = (e: TouchEvent) => { + if (bottomSheet.contains(e.target as Node)) { + e.preventDefault(); + } + }; + + if (isOpened) { + document.addEventListener('touchmove', preventScroll, {passive: false}); + } + + return () => { + document.removeEventListener('touchmove', preventScroll); + }; + }, [isOpened]); + + return {bottomSheetRef}; +}; + +export default useNumberKeyboardBottomSheet; diff --git a/HDesign/src/components/Tabs/Tab.tsx b/client/src/components/Design/components/Tabs/Tab.tsx similarity index 100% rename from HDesign/src/components/Tabs/Tab.tsx rename to client/src/components/Design/components/Tabs/Tab.tsx diff --git a/HDesign/src/components/Tabs/Tab.type.ts b/client/src/components/Design/components/Tabs/Tab.type.ts similarity index 100% rename from HDesign/src/components/Tabs/Tab.type.ts rename to client/src/components/Design/components/Tabs/Tab.type.ts diff --git a/HDesign/src/components/Tabs/Tabs.stories.tsx b/client/src/components/Design/components/Tabs/Tabs.stories.tsx similarity index 93% rename from HDesign/src/components/Tabs/Tabs.stories.tsx rename to client/src/components/Design/components/Tabs/Tabs.stories.tsx index a40e60b07..b5767e40b 100644 --- a/HDesign/src/components/Tabs/Tabs.stories.tsx +++ b/client/src/components/Design/components/Tabs/Tabs.stories.tsx @@ -2,7 +2,7 @@ import type {Meta, StoryObj} from '@storybook/react'; import React from 'react'; -import Tabs from '@components/Tabs/Tabs'; +import Tabs from '@HDcomponents/Tabs/Tabs'; import Tab from './Tab'; diff --git a/client/src/components/Design/components/Tabs/Tabs.style.ts b/client/src/components/Design/components/Tabs/Tabs.style.ts new file mode 100644 index 000000000..842b34823 --- /dev/null +++ b/client/src/components/Design/components/Tabs/Tabs.style.ts @@ -0,0 +1,63 @@ +import {css} from '@emotion/react'; + +import {WithTheme} from '@components/Design/type/withTheme'; + +export const tabListStyle = ({theme}: WithTheme) => + css({ + position: 'relative', + + height: '3rem', + marginBottom: '0.5rem', + + borderRadius: '0.75rem', + backgroundColor: theme.colors.white, + + cursor: 'pointer', + + WebkitTapHighlightColor: 'transparent', + }); + +export const tabItemStyle = css({ + flex: 1, + + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + + height: '100%', +}); + +type WithSelected = WithTheme & { + selected: boolean; +}; + +type IndicatorType = WithTheme & { + tabWidth: number; + activeTabIndex: number; +}; + +export const tabTextStyle = ({theme, selected}: WithSelected) => + css({ + color: selected ? theme.colors.onTertiary : theme.colors.gray, + + zIndex: theme.zIndex.tabText, + }); + +export const indicatorStyle = ({theme, tabWidth, activeTabIndex}: IndicatorType) => + css({ + position: 'absolute', + bottom: '0.5rem', + left: '0.5rem', + width: `${tabWidth}px`, + height: 'calc(100% - 1rem)', + + borderRadius: '0.625rem', + backgroundColor: theme.colors.tertiary, + + transform: `translateX(${(tabWidth + 8) * activeTabIndex}px)`, + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + + zIndex: theme.zIndex.tabIndicator, + }); diff --git a/client/src/components/Design/components/Tabs/Tabs.tsx b/client/src/components/Design/components/Tabs/Tabs.tsx new file mode 100644 index 000000000..8a5e3fad0 --- /dev/null +++ b/client/src/components/Design/components/Tabs/Tabs.tsx @@ -0,0 +1,85 @@ +/** @jsxImportSource @emotion/react */ +import React, {useEffect, useRef, useState} from 'react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import {tabListStyle, tabItemStyle, tabTextStyle, indicatorStyle} from './Tabs.style'; +import {TabsProps} from './Tab.type'; + +const Tabs: React.FC = ({children, tabsContainerStyle}) => { + const {theme} = useTheme(); + const [activeTabIndex, setActiveTabIndex] = useState(0); + const [tabWidth, setTabWidth] = useState(0); + const tabRef = useRef(null); + + const isActive = (index: number) => activeTabIndex === index; + + const setTabWidthResizeObserveCallback = (entries: ResizeObserverEntry[]) => { + for (const entry of entries) { + if (entry.target === tabRef.current) { + setTabWidth(entry.contentRect.width); + } + } + }; + + useEffect(() => { + const tabCurrent = tabRef.current; + + if (tabCurrent) { + const resizeObserver = new ResizeObserver(setTabWidthResizeObserveCallback); + resizeObserver.observe(tabCurrent); + + return () => { + resizeObserver.unobserve(tabCurrent); + }; + } + + // useEffect 경고문구 제거를 위해 return 추가 (Not all code paths return a value.) + return; + }, [tabRef]); + + return ( + +
    + + {children.map((tabItem, index) => ( + + ))} + + {tabRef.current && tabWidth !== 0 &&
    } +
+
+ {children[activeTabIndex].props.content} +
+
+ ); +}; + +export default Tabs; diff --git a/HDesign/src/components/Text/Text.stories.tsx b/client/src/components/Design/components/Text/Text.stories.tsx similarity index 93% rename from HDesign/src/components/Text/Text.stories.tsx rename to client/src/components/Design/components/Text/Text.stories.tsx index 5e5ec2287..9007b4756 100644 --- a/HDesign/src/components/Text/Text.stories.tsx +++ b/client/src/components/Design/components/Text/Text.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import Text from '@components/Text/Text'; +import Text from '@HDcomponents/Text/Text'; const meta = { title: 'Components/Text', diff --git a/HDesign/src/components/Text/Text.style.ts b/client/src/components/Design/components/Text/Text.style.ts similarity index 90% rename from HDesign/src/components/Text/Text.style.ts rename to client/src/components/Design/components/Text/Text.style.ts index 650260e62..858d136af 100644 --- a/HDesign/src/components/Text/Text.style.ts +++ b/client/src/components/Design/components/Text/Text.style.ts @@ -23,6 +23,8 @@ export const getSizeStyling = ({size, textColor, theme}: Required = forwardRef diff --git a/HDesign/src/components/TextButton/TextButton.type.ts b/client/src/components/Design/components/TextButton/TextButton.type.ts similarity index 85% rename from HDesign/src/components/TextButton/TextButton.type.ts rename to client/src/components/Design/components/TextButton/TextButton.type.ts index 0299d89b9..5a1287734 100644 --- a/HDesign/src/components/TextButton/TextButton.type.ts +++ b/client/src/components/Design/components/TextButton/TextButton.type.ts @@ -1,6 +1,6 @@ import {TextSize} from '../Text/Text.type'; -export type TextColor = 'black' | 'gray'; +export type TextColor = 'black' | 'gray' | 'onTertiary'; export interface TextButtonStyleProps { textColor: TextColor; diff --git a/HDesign/src/components/Title/Title.stories.tsx b/client/src/components/Design/components/Title/Title.stories.tsx similarity index 59% rename from HDesign/src/components/Title/Title.stories.tsx rename to client/src/components/Design/components/Title/Title.stories.tsx index 2c91287b4..899c78b83 100644 --- a/HDesign/src/components/Title/Title.stories.tsx +++ b/client/src/components/Design/components/Title/Title.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import Title from '@components/Title/Title'; +import Title from '@HDcomponents/Title/Title'; const meta = { title: 'Components/Title', @@ -14,20 +14,14 @@ const meta = { description: '', control: {type: 'text'}, }, - description: { - description: '', - control: {type: 'text'}, - }, - price: { + amount: { description: '', control: {type: 'number'}, }, }, args: { - title: '페이지 제목이에요', - description: `이곳에는 페이지 설명이 들어가요. - 페이지에 대한 설명을 자세하게 적어주면 좋아요 :)`, - price: 100000, + title: '행동대장 야유회', + amount: 100000, }, } satisfies Meta; diff --git a/HDesign/src/components/Title/Title.style.ts b/client/src/components/Design/components/Title/Title.style.ts similarity index 51% rename from HDesign/src/components/Title/Title.style.ts rename to client/src/components/Design/components/Title/Title.style.ts index ab347a214..bd19002d1 100644 --- a/HDesign/src/components/Title/Title.style.ts +++ b/client/src/components/Design/components/Title/Title.style.ts @@ -2,18 +2,26 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; -export const titleContainerStyle = (theme: Theme) => +export const titleStyle = (theme: Theme) => css({ display: 'flex', flexDirection: 'column', width: '100%', gap: '0.5rem', backgroundColor: theme.colors.white, - padding: '1rem', + padding: '0.5rem', + borderRadius: '0.75rem', }); -export const priceContainerStyle = css({ +export const titleContainerStyle = css({ + display: 'flex', + justifyContent: 'space-between', + paddingLeft: '0.5rem', +}); + +export const amountContainerStyle = css({ display: 'flex', justifyContent: 'space-between', alignItems: 'end', + paddingInline: '0.5rem', }); diff --git a/client/src/components/Design/components/Title/Title.tsx b/client/src/components/Design/components/Title/Title.tsx new file mode 100644 index 000000000..deab3ec4a --- /dev/null +++ b/client/src/components/Design/components/Title/Title.tsx @@ -0,0 +1,27 @@ +/** @jsxImportSource @emotion/react */ +import Text from '@HDcomponents/Text/Text'; +import {amountContainerStyle, titleContainerStyle, titleStyle} from '@HDcomponents/Title/Title.style'; +import {TitleProps} from '@HDcomponents/Title/Title.type'; +import {useTheme} from '@theme/HDesignProvider'; + +import Amount from '../Amount/Amount'; + +export const Title: React.FC = ({title, amount, dropdown}: TitleProps) => { + const {theme} = useTheme(); + return ( +
+
+ {title} + {dropdown} +
+
+ + 전체 지출 금액 + + +
+
+ ); +}; + +export default Title; diff --git a/HDesign/src/components/Title/Title.type.ts b/client/src/components/Design/components/Title/Title.type.ts similarity index 82% rename from HDesign/src/components/Title/Title.type.ts rename to client/src/components/Design/components/Title/Title.type.ts index 4b12f23b2..cb28743f4 100644 --- a/HDesign/src/components/Title/Title.type.ts +++ b/client/src/components/Design/components/Title/Title.type.ts @@ -2,8 +2,8 @@ export interface TitleStyleProps {} export interface TitleCustomProps { title: string; - description?: string; - price?: number; + amount?: number; + dropdown?: React.ReactNode; } export type TitleOptionProps = TitleStyleProps & TitleCustomProps; diff --git a/client/src/components/Design/components/Top/EditableLine.tsx b/client/src/components/Design/components/Top/EditableLine.tsx new file mode 100644 index 000000000..743fe191e --- /dev/null +++ b/client/src/components/Design/components/Top/EditableLine.tsx @@ -0,0 +1,78 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; +import {useEffect, useRef, useState} from 'react'; + +import TYPOGRAPHY from '@components/Design/token/typography'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Icon from '../Icon/Icon'; + +interface Props { + value: string; + onChange: (event: React.ChangeEvent) => void; +} + +export default function EditableLine({value, onChange}: Props) { + const {theme} = useTheme(); + const [width, setWidth] = useState(0); + + const spanRef = useRef(null); + + useEffect(() => { + if (spanRef.current) { + setWidth(spanRef.current.getBoundingClientRect().width); + } + }, [value]); + + return ( + + ); +} diff --git a/client/src/components/Design/components/Top/Line.tsx b/client/src/components/Design/components/Top/Line.tsx new file mode 100644 index 000000000..06669eb1b --- /dev/null +++ b/client/src/components/Design/components/Top/Line.tsx @@ -0,0 +1,41 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import Text from '../Text/Text'; + +interface Props { + text: string; + emphasize?: string[]; +} + +export default function Line({text, emphasize = []}: Props) { + const getTextElements = ({text, emphasize = []}: Props) => { + if (emphasize.length === 0) return [text]; + + const regexPattern = new RegExp(`(${emphasize.join('|')})`, 'g'); + return text.split(regexPattern).filter(Boolean); + }; + + const elements = getTextElements({text, emphasize}); + + return ( +
+ {elements.map((text, index) => { + return ( + + {`${text}`} + + ); + })} +
+ ); +} diff --git a/client/src/components/Design/components/Top/Top.stories.tsx b/client/src/components/Design/components/Top/Top.stories.tsx new file mode 100644 index 000000000..180c360cb --- /dev/null +++ b/client/src/components/Design/components/Top/Top.stories.tsx @@ -0,0 +1,30 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Top from '@HDcomponents/Top/Top'; + +const meta = { + title: 'Components/Top', + component: Top, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: {}, + args: {}, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + render: () => { + return ( + + + + + ); + }, +}; diff --git a/client/src/components/Design/components/Top/Top.tsx b/client/src/components/Design/components/Top/Top.tsx new file mode 100644 index 000000000..56c41eb6e --- /dev/null +++ b/client/src/components/Design/components/Top/Top.tsx @@ -0,0 +1,21 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import Line from './Line'; +import EditableLine from './EditableLine'; + +Top.Line = Line; +Top.EditableLine = EditableLine; + +export default function Top({children}: React.PropsWithChildren) { + return ( +
+ {children} +
+ ); +} diff --git a/client/src/components/Design/components/TopNav/NavItem.style.ts b/client/src/components/Design/components/TopNav/NavItem.style.ts new file mode 100644 index 000000000..eb65ca32f --- /dev/null +++ b/client/src/components/Design/components/TopNav/NavItem.style.ts @@ -0,0 +1,9 @@ +import {css} from '@emotion/react'; + +export const navItemStyle = css({ + padding: '0 0.5rem', + + ':first-of-type': { + paddingLeft: 0, + }, +}); diff --git a/client/src/components/Design/components/TopNav/NavItem.tsx b/client/src/components/Design/components/TopNav/NavItem.tsx new file mode 100644 index 000000000..41c38a150 --- /dev/null +++ b/client/src/components/Design/components/TopNav/NavItem.tsx @@ -0,0 +1,55 @@ +/** @jsxImportSource @emotion/react */ +import type {NavItemProps} from './NavItem.type'; + +import {useLocation, useNavigate} from 'react-router-dom'; + +import getDeletedLastPath from '@utils/getDeletedLastPath'; + +import TextButton from '../TextButton/TextButton'; + +import {navItemStyle} from './NavItem.style'; + +const NavItem = ({displayName, routePath, onHandleRouteInFunnel, noEmphasis = false, children}: NavItemProps) => { + const navigate = useNavigate(); + const location = useLocation(); + const matchPath = location.pathname.includes(routePath); + + const handleNavigation = () => { + if (onHandleRouteInFunnel) { + onHandleRouteInFunnel(); + return; + } + + switch (routePath) { + case '/': + navigate('/'); + break; + case '-1': + navigate(-1); + break; + default: + navigate(`${getDeletedLastPath(location.pathname)}${routePath}`); + break; + } + }; + + const getTextColor = () => { + if (noEmphasis) return 'gray'; + + return matchPath ? 'onTertiary' : 'gray'; + }; + + return ( +
  • + {children ? ( + children + ) : ( + + {displayName} + + )} +
  • + ); +}; + +export default NavItem; diff --git a/client/src/components/Design/components/TopNav/NavItem.type.ts b/client/src/components/Design/components/TopNav/NavItem.type.ts new file mode 100644 index 000000000..d5b302468 --- /dev/null +++ b/client/src/components/Design/components/TopNav/NavItem.type.ts @@ -0,0 +1,14 @@ +export type NavItemOptionProps = { + displayName?: string; + onHandleRouteInFunnel?: () => void; +}; + +export type NavItemRequireProps = { + routePath: string; +}; + +export type NavItemStyleProps = { + noEmphasis?: boolean; +}; + +export type NavItemProps = NavItemRequireProps & NavItemOptionProps & NavItemStyleProps & React.PropsWithChildren; diff --git a/client/src/components/Design/components/TopNav/TopNav.style.ts b/client/src/components/Design/components/TopNav/TopNav.style.ts new file mode 100644 index 000000000..3c0c29c5e --- /dev/null +++ b/client/src/components/Design/components/TopNav/TopNav.style.ts @@ -0,0 +1,8 @@ +import {css} from '@emotion/react'; + +export const topNavStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '100%', +}); diff --git a/client/src/components/Design/components/TopNav/TopNav.tsx b/client/src/components/Design/components/TopNav/TopNav.tsx new file mode 100644 index 000000000..84a7f9376 --- /dev/null +++ b/client/src/components/Design/components/TopNav/TopNav.tsx @@ -0,0 +1,19 @@ +/** @jsxImportSource @emotion/react */ +import NavItem from './NavItem'; +import {topNavStyle} from './TopNav.style'; + +type TopNavProps = React.PropsWithChildren & { + Element?: React.ReactNode; +}; + +const TopNav = ({children}: TopNavProps) => { + return ( + + ); +}; + +TopNav.Item = NavItem; + +export default TopNav; diff --git a/client/src/components/Design/index.tsx b/client/src/components/Design/index.tsx new file mode 100644 index 000000000..a75245994 --- /dev/null +++ b/client/src/components/Design/index.tsx @@ -0,0 +1,66 @@ +import {MainLayout} from './layouts/MainLayout'; +import FunnelLayout from './layouts/FunnelLayout'; +import {ContentLayout} from './layouts/ContentLayout'; +import {HDesignProvider, useTheme} from './theme/HDesignProvider'; +import BankSelect from './components/BankSelect/BankSelect'; +import BottomSheet from './components/BottomSheet/BottomSheet'; +import Button from './components/Button/Button'; +import DragHandleItem from './components/DragHandleItem/DragHandleItem'; +import DragHandleItemContainer from './components/DragHandleItemContainer/DragHandleItemContainer'; +import EditableItem from './components/EditableItem/EditableItem'; +import ExpenseList from './components/ExpenseList/ExpenseList'; +import FixedButton from './components/FixedButton/FixedButton'; +import Flex from './components/Flex/Flex'; +import Icon from './components/Icon/Icon'; +import IconButton from './components/IconButton/IconButton'; +import Input from './components/Input/Input'; +import LabelInput from './components/LabelInput/LabelInput'; +import ListButton from './components/ListButton/ListButton'; +import LabelGroupInput from './components/LabelGroupInput/LabelGroupInput'; +import Top from './components/Top/Top'; +import Tab from './components/Tabs/Tab'; +import Tabs from './components/Tabs/Tabs'; +import Text from './components/Text/Text'; +import TextButton from './components/TextButton/TextButton'; +import Title from './components/Title/Title'; +import TopNav from './components/TopNav/TopNav'; +import DepositCheck from './components/DepositCheck/DepositCheck'; +import DepositToggle from './components/DepositToggle/DepositToggle'; +import Amount from './components/Amount/Amount'; +import Dropdown from './components/Dropdown/Dropdown'; +import DropdownButton from './components/Dropdown/DropdownButton'; + +export { + BankSelect, + BottomSheet, + Button, + DragHandleItem, + DragHandleItemContainer, + EditableItem, + ExpenseList, + FixedButton, + Flex, + Icon, + IconButton, + Input, + LabelInput, + ListButton, + LabelGroupInput, + Top, + Tab, + Tabs, + Text, + TextButton, + Title, + TopNav, + MainLayout, + FunnelLayout, + ContentLayout, + HDesignProvider, + useTheme, + DepositCheck, + DepositToggle, + Amount, + Dropdown, + DropdownButton, +}; diff --git a/HDesign/src/layouts/ContentLayout.tsx b/client/src/components/Design/layouts/ContentLayout.tsx similarity index 100% rename from HDesign/src/layouts/ContentLayout.tsx rename to client/src/components/Design/layouts/ContentLayout.tsx diff --git a/client/src/components/Design/layouts/FunnelLayout.tsx b/client/src/components/Design/layouts/FunnelLayout.tsx new file mode 100644 index 000000000..7dbe0c8e6 --- /dev/null +++ b/client/src/components/Design/layouts/FunnelLayout.tsx @@ -0,0 +1,19 @@ +import {Flex} from '..'; + +const FunnelLayout = ({children}: React.PropsWithChildren) => { + return ( + + {children} + + ); +}; + +export default FunnelLayout; diff --git a/HDesign/src/layouts/MainLayout.tsx b/client/src/components/Design/layouts/MainLayout.tsx similarity index 96% rename from HDesign/src/layouts/MainLayout.tsx rename to client/src/components/Design/layouts/MainLayout.tsx index 22012fde8..d7a699662 100644 --- a/HDesign/src/layouts/MainLayout.tsx +++ b/client/src/components/Design/layouts/MainLayout.tsx @@ -15,7 +15,7 @@ export function MainLayout({backgroundColor, children}: MainLayoutProps) { justifyContent="flexStart" flexDirection="column" padding="1rem 0 0 0" - gap="1rem" + gap="0.5rem" width="100%" height="100%" minHeight="100vh" diff --git a/HDesign/src/theme/GlobalStyle.ts b/client/src/components/Design/theme/GlobalStyle.ts similarity index 81% rename from HDesign/src/theme/GlobalStyle.ts rename to client/src/components/Design/theme/GlobalStyle.ts index f1b7b699b..b25bb94d1 100644 --- a/HDesign/src/theme/GlobalStyle.ts +++ b/client/src/components/Design/theme/GlobalStyle.ts @@ -1,6 +1,9 @@ import {css} from '@emotion/react'; +// reset css -> index css export const GlobalStyle = css` + @import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css'); + *:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) { all: unset; display: revert; @@ -120,4 +123,26 @@ export const GlobalStyle = css` button { cursor: pointer; } + + body { + font-family: + 'Pretendard', + -apple-system, + BlinkMacSystemFont, + system-ui, + Roboto, + 'Helvetica Neue', + 'Segoe UI', + 'Apple SD Gothic Neo', + 'Noto Sans KR', + 'Malgun Gothic', + 'Apple Color Emoji', + 'Segoe UI Emoji', + 'Segoe UI Symbol', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + max-width: 768px; + margin: 0 auto; + } `; diff --git a/HDesign/src/theme/HDesignProvider.tsx b/client/src/components/Design/theme/HDesignProvider.tsx similarity index 94% rename from HDesign/src/theme/HDesignProvider.tsx rename to client/src/components/Design/theme/HDesignProvider.tsx index 6c7c571a3..c5367afa1 100644 --- a/HDesign/src/theme/HDesignProvider.tsx +++ b/client/src/components/Design/theme/HDesignProvider.tsx @@ -3,9 +3,9 @@ import {Global} from '@emotion/react'; import {Theme} from '@theme/theme.type'; import {GlobalStyle} from '@theme/GlobalStyle'; - import {COLORS} from '@token/colors'; import {TYPOGRAPHY} from '@token/typography'; +import {ZINDEX} from '@token/zIndex'; interface ThemeContextProps { theme: Theme; @@ -14,6 +14,7 @@ interface ThemeContextProps { const defaultTheme: Theme = { colors: COLORS, typography: TYPOGRAPHY, + zIndex: ZINDEX, }; const ThemeContext = createContext(undefined); diff --git a/HDesign/src/theme/theme.type.ts b/client/src/components/Design/theme/theme.type.ts similarity index 72% rename from HDesign/src/theme/theme.type.ts rename to client/src/components/Design/theme/theme.type.ts index dffd961f0..c6dbe0544 100644 --- a/HDesign/src/theme/theme.type.ts +++ b/client/src/components/Design/theme/theme.type.ts @@ -1,7 +1,9 @@ import {ColorTokens} from '@token/colors'; import {TypographyTokens} from '@token/typography'; +import {ZIndexTokens} from '@token/zIndex'; export interface Theme { colors: ColorTokens; typography: TypographyTokens; + zIndex: ZIndexTokens; } diff --git a/HDesign/src/token/colors.ts b/client/src/components/Design/token/colors.ts similarity index 100% rename from HDesign/src/token/colors.ts rename to client/src/components/Design/token/colors.ts diff --git a/HDesign/src/token/typography.ts b/client/src/components/Design/token/typography.ts similarity index 100% rename from HDesign/src/token/typography.ts rename to client/src/components/Design/token/typography.ts diff --git a/client/src/components/Design/token/zIndex.ts b/client/src/components/Design/token/zIndex.ts new file mode 100644 index 000000000..60ec5a6cd --- /dev/null +++ b/client/src/components/Design/token/zIndex.ts @@ -0,0 +1,39 @@ +// Utils +const BASE = 0; +const ABOVE = 1; // use this for all values above the base +const BELOW = -1; // and this for all values below the base + +const NAV_BACKGROUND_COLOR = BASE + ABOVE; +const TAB_INDICATOR = BASE; +const TAB_TEXT = TAB_INDICATOR + ABOVE; +const FIXED_BUTTON = BASE + ABOVE; +const DEPOSIT_TOGGLE_INDICATOR_MOVING_ANIMATION = BASE + ABOVE; +const NUMBER_KEYBOARD_BOTTOM_SHEET = FIXED_BUTTON + ABOVE; +const BOTTOM_SHEET_DIMMED_LAYER = NUMBER_KEYBOARD_BOTTOM_SHEET + ABOVE; +const BOTTOM_SHEET_CONTAINER = BOTTOM_SHEET_DIMMED_LAYER + ABOVE; +const TOAST = BOTTOM_SHEET_CONTAINER + ABOVE; + +export const ZINDEX = { + bottomSheetDimmedLayer: BOTTOM_SHEET_DIMMED_LAYER, + bottomSheetContainer: BOTTOM_SHEET_CONTAINER, + numberKeyboardBottomSheet: NUMBER_KEYBOARD_BOTTOM_SHEET, + depositToggleMovingAnimation: DEPOSIT_TOGGLE_INDICATOR_MOVING_ANIMATION, + fixedButton: FIXED_BUTTON, + navBackgroundColor: NAV_BACKGROUND_COLOR, + tabIndicator: TAB_INDICATOR, + tabText: TAB_TEXT, + toast: TOAST, +} as const; + +type ZIndexKeys = + | 'bottomSheetDimmedLayer' + | 'bottomSheetContainer' + | 'numberKeyboardBottomSheet' + | 'depositToggleMovingAnimation' + | 'fixedButton' + | 'navBackgroundColor' + | 'tabText' + | 'tabIndicator' + | 'toast'; + +export type ZIndexTokens = Record; diff --git a/HDesign/src/type/strictPropsWithChildren.ts b/client/src/components/Design/type/strictPropsWithChildren.ts similarity index 100% rename from HDesign/src/type/strictPropsWithChildren.ts rename to client/src/components/Design/type/strictPropsWithChildren.ts diff --git a/HDesign/src/type/withTheme.ts b/client/src/components/Design/type/withTheme.ts similarity index 100% rename from HDesign/src/type/withTheme.ts rename to client/src/components/Design/type/withTheme.ts diff --git a/HDesign/src/utils/changeCamelCaseToKebabCase.ts b/client/src/components/Design/utils/changeCamelCaseToKebabCase.ts similarity index 100% rename from HDesign/src/utils/changeCamelCaseToKebabCase.ts rename to client/src/components/Design/utils/changeCamelCaseToKebabCase.ts diff --git a/HDesign/src/utils/colors.ts b/client/src/components/Design/utils/colors.ts similarity index 100% rename from HDesign/src/utils/colors.ts rename to client/src/components/Design/utils/colors.ts diff --git a/client/src/components/ExpenseDetailModal/ExpenseDetailModal.tsx b/client/src/components/ExpenseDetailModal/ExpenseDetailModal.tsx new file mode 100644 index 000000000..ddc151387 --- /dev/null +++ b/client/src/components/ExpenseDetailModal/ExpenseDetailModal.tsx @@ -0,0 +1,130 @@ +// import type {BillAction} from 'types/serviceType'; + +// import validatePurchase from '@utils/validate/validatePurchase'; +// import useRequestGetSteps from '@hooks/queries/step/useRequestGetSteps'; +// import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; +// import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; + +// import usePutAndDeleteBill from '@hooks/usePutAndDeleteBill'; + +// import {BottomSheet, EditableItem, FixedButton, Flex, Text} from '@HDesign/index'; + +// type ExpenseDetailModalProps = { +// billAction: BillAction; +// isBottomSheetOpened: boolean; +// setIsBottomSheetOpened: React.Dispatch>; +// }; + +// const ExpenseDetailModal = ({billAction, isBottomSheetOpened, setIsBottomSheetOpened}: ExpenseDetailModalProps) => { +// const { +// inputPair, +// handleInputChange, +// // handleOnBlur, +// // errorMessage, +// // errorInfo, +// canSubmit, +// onDelete, +// onSubmit: putBillAction, +// } = usePutAndDeleteBill({title: billAction.name, price: String(billAction.price), index: 0}, validatePurchase, () => +// setIsBottomSheetOpened(false), +// ); + +// const { +// memberReportListInAction, +// addAdjustedMember, +// onSubmit: putMemberReportListInAction, +// getIsSamePriceStateAndServerState, +// getOnlyOneNotAdjustedRemainMemberIndex, +// isExistAdjustedPrice, +// } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); +// const { +// inputList, +// onChange, +// canEditList, +// canSubmit: isChangedMemberReportInput, +// } = useMemberReportInput({ +// data: memberReportListInAction, +// addAdjustedMember, +// totalPrice: Number(inputPair.price), +// getIsSamePriceStateAndServerState, +// getOnlyOneNotAdjustedRemainMemberIndex, +// }); + +// const {steps} = useRequestGetSteps(); + +// const actionMemberList = steps.filter(({actions}) => +// actions.find(({actionId}) => actionId === billAction.actionId), +// )[0].members; + +// return ( +// setIsBottomSheetOpened(false)}> +//
    setIsBottomSheetOpened(false)}> +//

    +// 지출 내역 상세 +//

    +//
    +// +// ) => handleInputChange('title', event)} +// disabled +// /> +// +// ) => handleInputChange('price', event)} +// isFixed={isExistAdjustedPrice()} +// disabled +// /> +// +// +// + +// +// +// {inputList.map(({name, price, isFixed}, index) => ( +// +// +// +// onChange(event, index)} +// isFixed={isFixed} +// textSize="smallBody" +// value={price} +// placeholder="0" +// type="number" +// disabled +// style={{textAlign: 'right'}} +// > +// +// +// +// ))} +// +// +//
    +// +// 닫기 +// +//
    +//
    +// ); +// }; + +// export default ExpenseDetailModal; diff --git a/client/src/components/KakaoInitializer/KakaoInitializer.tsx b/client/src/components/KakaoInitializer/KakaoInitializer.tsx new file mode 100644 index 000000000..d3ed82bab --- /dev/null +++ b/client/src/components/KakaoInitializer/KakaoInitializer.tsx @@ -0,0 +1,15 @@ +import {useEffect} from 'react'; + +const KakaoInitializer = ({children}: React.PropsWithChildren) => { + useEffect(() => { + if (!window.Kakao) return; + + if (!window.Kakao.isInitialized()) { + window.Kakao.init(process.env.KAKAO_JAVASCRIPT_KEY); + } + }, []); + + return children; +}; + +export default KakaoInitializer; diff --git a/client/src/components/Common/Logo/Logo.style.ts b/client/src/components/Logo/Logo.style.ts similarity index 100% rename from client/src/components/Common/Logo/Logo.style.ts rename to client/src/components/Logo/Logo.style.ts diff --git a/client/src/components/Common/Logo/RunningDogLogo.tsx b/client/src/components/Logo/RunningDogLogo.tsx similarity index 100% rename from client/src/components/Common/Logo/RunningDogLogo.tsx rename to client/src/components/Logo/RunningDogLogo.tsx diff --git a/client/src/components/Common/Logo/StandingDogLogo.tsx b/client/src/components/Logo/StandingDogLogo.tsx similarity index 100% rename from client/src/components/Common/Logo/StandingDogLogo.tsx rename to client/src/components/Logo/StandingDogLogo.tsx diff --git a/client/src/components/Common/Logo/index.ts b/client/src/components/Logo/index.ts similarity index 100% rename from client/src/components/Common/Logo/index.ts rename to client/src/components/Logo/index.ts diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx deleted file mode 100644 index 1004540fa..000000000 --- a/client/src/components/MemberReportList/MemberReportList.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import {ExpenseList, Flex, Input} from 'haengdong-design'; -import React, {useState} from 'react'; - -import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; - -const MemberReportList = () => { - const [name, setName] = useState(''); - const {memberReportSearchList} = useSearchMemberReportList({name}); - - const changeName = ({target}: React.ChangeEvent) => { - setName(target.value); - }; - - return ( - - - - - ); -}; - -export default MemberReportList; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts b/client/src/components/Modal/BankSelectModal/BankSelectModal.style.ts similarity index 95% rename from client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts rename to client/src/components/Modal/BankSelectModal/BankSelectModal.style.ts index f58f43425..cec3609de 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts +++ b/client/src/components/Modal/BankSelectModal/BankSelectModal.style.ts @@ -24,5 +24,5 @@ export const inputContainerStyle = css({ flexDirection: 'column', gap: '1.5rem', overflow: 'auto', - paddingBottom: '14rem', + paddingBottom: '4rem', }); diff --git a/client/src/components/Modal/BankSelectModal/BankSelectModal.tsx b/client/src/components/Modal/BankSelectModal/BankSelectModal.tsx new file mode 100644 index 000000000..02082fd75 --- /dev/null +++ b/client/src/components/Modal/BankSelectModal/BankSelectModal.tsx @@ -0,0 +1,31 @@ +import {BankSelect, BottomSheet, Text} from '@HDesign/index'; + +import {bottomSheetHeaderStyle, bottomSheetStyle, inputContainerStyle} from './BankSelectModal.style'; + +type BankSelectProps = { + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch>; + selectBank: (name: string) => void; +}; + +const BankSelectModal = ({isBottomSheetOpened, setIsBottomSheetOpened, selectBank}: BankSelectProps) => { + const selectBankAndClose = (name: string) => { + selectBank(name); + setIsBottomSheetOpened(false); + }; + + return ( + setIsBottomSheetOpened(false)}> +
    +

    + 은행을 선택해주세요 +

    +
    + +
    +
    +
    + ); +}; + +export default BankSelectModal; diff --git a/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx b/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx deleted file mode 100644 index 645acb468..000000000 --- a/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import type {BillAction} from 'types/serviceType'; - -import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; - -import validatePurchase from '@utils/validate/validatePurchase'; -import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; -import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; -import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; - -import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; - -import { - bottomSheetHeaderStyle, - bottomSheetStyle, - inputContainerStyle, -} from '../SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style'; - -type PutAndDeleteBillActionModalProps = { - billAction: BillAction; - isBottomSheetOpened: boolean; - setIsBottomSheetOpened: React.Dispatch>; -}; - -const ExpenseDetailModal = ({ - billAction, - isBottomSheetOpened, - setIsBottomSheetOpened, -}: PutAndDeleteBillActionModalProps) => { - const { - inputPair, - handleInputChange, - // handleOnBlur, - // errorMessage, - // errorInfo, - canSubmit, - onDelete, - onSubmit: putBillAction, - } = usePutAndDeleteBillAction( - {title: billAction.name, price: String(billAction.price), index: 0}, - validatePurchase, - () => setIsBottomSheetOpened(false), - ); - - const { - memberReportListInAction, - addAdjustedMember, - onSubmit: putMemberReportListInAction, - getIsSamePriceStateAndServerState, - getOnlyOneNotAdjustedRemainMemberIndex, - isExistAdjustedPrice, - } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); - const { - inputList, - onChange, - canEditList, - canSubmit: isChangedMemberReportInput, - } = useMemberReportInput({ - data: memberReportListInAction, - addAdjustedMember, - totalPrice: Number(inputPair.price), - getIsSamePriceStateAndServerState, - getOnlyOneNotAdjustedRemainMemberIndex, - }); - - const {data: stepListData = []} = useRequestGetStepList(); - - const actionMemberList = stepListData.filter(({actions}) => - actions.find(({actionId}) => actionId === billAction.actionId), - )[0].members; - - return ( - setIsBottomSheetOpened(false)}> -
    setIsBottomSheetOpened(false)}> -

    - 지출 내역 상세 -

    -
    - - ) => handleInputChange('title', event)} - disabled - /> - - ) => handleInputChange('price', event)} - isFixed={isExistAdjustedPrice()} - disabled - /> - - - - - - - {inputList.map(({name, price, isFixed}, index) => ( - - - - onChange(event, index)} - isFixed={isFixed} - textSize="smallBody" - value={price} - placeholder="0" - type="number" - disabled - style={{textAlign: 'right'}} - > - - - - ))} - - -
    - - 닫기 - -
    -
    - ); -}; - -export default ExpenseDetailModal; diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts deleted file mode 100644 index 4bbefdba9..000000000 --- a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {css} from '@emotion/react'; - -export const bottomSheetStyle = css({ - display: 'flex', - flexDirection: 'column', - gap: '1.5rem', - width: '100%', - height: '100%', - padding: '0 1.5rem', -}); diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx deleted file mode 100644 index e3579ab6b..000000000 --- a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import type {MemberReport} from 'types/serviceType'; - -import {BottomSheet, FixedButton, Flex, Text} from 'haengdong-design'; - -import {bottomSheetStyle} from './MemberListInBillStep.style'; - -type MemberListInBillStepProps = { - stepName: string; - memberList: MemberReport[]; - isOpenBottomSheet: boolean; - setIsOpenBottomSheet: React.Dispatch>; -}; - -const MemberListInBillStep = ({ - stepName, - memberList, - isOpenBottomSheet, - setIsOpenBottomSheet, -}: MemberListInBillStepProps) => { - const closeModal = () => setIsOpenBottomSheet(false); - - return ( - -
    - - {`${stepName} 참석자`} - {`총 ${memberList.length}명`} - - -
      - {memberList.map(member => ( -
    • - - - {member.name} - - - {`${member.price.toLocaleString('ko-kr')} 원`} - - -
    • - ))} -
    -
    -
    - - 닫기 - -
    - ); -}; - -export default MemberListInBillStep; diff --git a/client/src/components/Modal/MemberListInBillStep/index.ts b/client/src/components/Modal/MemberListInBillStep/index.ts deleted file mode 100644 index 137df8c87..000000000 --- a/client/src/components/Modal/MemberListInBillStep/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as MemberListInBillStep} from './MemberListInBillStep'; diff --git a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx deleted file mode 100644 index 51e33589b..000000000 --- a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import {SetAllMemberListModal, SetInitialMemberListModal, SetActionListModal} from '@components/Modal/index'; - -interface ModalBasedOnMemberCountProps { - allMemberList: string[]; - isOpenBottomSheet: boolean; - isOpenAllMemberListButton: boolean; - setIsOpenBottomSheet: React.Dispatch>; - setIsOpenAllMemberListButton: React.Dispatch>; -} - -const ModalBasedOnMemberCount = ({ - allMemberList, - isOpenBottomSheet, - isOpenAllMemberListButton, - setIsOpenBottomSheet, - setIsOpenAllMemberListButton, -}: ModalBasedOnMemberCountProps) => { - if (isOpenAllMemberListButton) { - return ( - - ); - } - switch (allMemberList.length) { - case 0: - return ( - - ); - - default: - return ; - } -}; - -export default ModalBasedOnMemberCount; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts deleted file mode 100644 index 7fad2e001..000000000 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {css} from '@emotion/react'; - -const container = css({ - display: 'flex', - flexDirection: 'column', - gap: '1.5rem', - height: '100%', -}); - -const inputGroup = css({ - display: 'flex', - flexDirection: 'column', - gap: '1rem', - overflow: 'auto', - paddingBottom: '14rem', -}); - -const addMemberActionListModalContentStyle = { - container, - inputGroup, -}; - -export default addMemberActionListModalContentStyle; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx deleted file mode 100644 index ad6e63f28..000000000 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import type {MemberType} from 'types/serviceType'; - -import {FixedButton, LabelGroupInput} from 'haengdong-design'; - -import validateMemberName from '@utils/validate/validateMemberName'; -import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; - -import useDynamicInput from '@hooks/useDynamicInput'; - -import style from './AddMemberActionListModalContent.style'; -import InMember from './InMember'; -import OutMember from './OutMember'; - -interface AddMemberActionListModalContentProps { - inOutAction: MemberType; - setIsOpenBottomSheet: React.Dispatch>; -} - -const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: AddMemberActionListModalContentProps) => { - const dynamicProps = useDynamicInput(validateMemberName); - const {inputList, getFilledInputList, errorMessage, canSubmit, resetInputValue} = dynamicProps; - - const {mutate: postMemberList} = useRequestPostMemberList(); - - const handleUpdateMemberListSubmit = () => { - postMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: inOutAction}); - setIsOpenBottomSheet(false); - }; - - return ( -
    -
    - - {inOutAction === 'IN' ? : } - -
    - { - handleUpdateMemberListSubmit(); - resetInputValue(); - }} - /> -
    - ); -}; - -export default AddMemberActionListModalContent; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx deleted file mode 100644 index 5f9f9a2e0..000000000 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import {LabelGroupInput} from 'haengdong-design'; - -import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; - -interface InMemberProps { - dynamicProps: ReturnUseDynamicInput; -} - -const InMember = ({dynamicProps}: InMemberProps) => { - const { - inputList, - inputRefList, - handleInputChange, - deleteEmptyInputElementOnBlur, - focusNextInputOnEnter, - errorIndexList, - } = dynamicProps; - return inputList.map(({value, index}) => ( - (inputRefList.current[index] = el)} - isError={errorIndexList.includes(index)} - onChange={e => handleInputChange(index, e)} - onBlur={() => deleteEmptyInputElementOnBlur()} - onKeyDown={e => focusNextInputOnEnter(e, index)} - placeholder="이름" - autoFocus={inputList.length === 1 && index === 0} - /> - )); -}; - -export default InMember; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx deleted file mode 100644 index 9294b18ae..000000000 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import {LabelGroupInput, Search} from 'haengdong-design'; - -import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; -import useSearchInMemberList from '@hooks/useSearchInMemberList'; - -interface OutMemberProps { - dynamicProps: ReturnUseDynamicInput; -} - -const OutMember = ({dynamicProps}: OutMemberProps) => { - const { - inputList, - inputRefList, - errorIndexList, - deleteEmptyInputElementOnBlur, - focusNextInputOnEnter, - handleInputChange, - handleChange, - } = dynamicProps; - const {currentInputIndex, filteredInMemberList, handleCurrentInputIndex, searchCurrentInMember, chooseMember} = - useSearchInMemberList(handleChange); - - const validationAndSearchOnChange = (inputIndex: number, event: React.ChangeEvent) => { - handleCurrentInputIndex(inputIndex); - handleInputChange(inputIndex, event); - searchCurrentInMember(event); - }; - - return inputList.map(({value, index}) => ( - chooseMember(currentInputIndex, term)} - > - (inputRefList.current[index] = el)} - isError={errorIndexList.includes(index)} - onChange={e => validationAndSearchOnChange(index, e)} - onBlur={() => deleteEmptyInputElementOnBlur()} - onKeyDown={e => focusNextInputOnEnter(e, index)} - placeholder="이름" - autoFocus={inputList.length === 1 && index === 0} - /> - - )); -}; - -export default OutMember; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts deleted file mode 100644 index 6519283f4..000000000 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as AddMemberActionListModalContent} from './AddMemberActionListModalContent'; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts deleted file mode 100644 index 7be2f2141..000000000 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {css} from '@emotion/react'; - -export const bottomSheetStyle = css({ - display: 'flex', - flexDirection: 'column', - gap: '1.5rem', - width: '100%', - height: '100%', - padding: '0 1rem', -}); - -export const bottomSheetHeaderStyle = css({ - display: 'flex', - justifyContent: 'space-between', - alignContent: 'center', - - width: '100%', - padding: '0 0.5rem', -}); - -export const inputGroupStyle = css({ - display: 'flex', - flexDirection: 'column', - gap: '1rem', - overflow: 'auto', - paddingBottom: '11rem', -}); diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx deleted file mode 100644 index 04242fad1..000000000 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import type {MemberAction, MemberType} from 'types/serviceType'; - -import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from 'haengdong-design'; - -import useDeleteMemberAction from '@hooks/useDeleteMemberAction/useDeleteMemberAction'; -import {useToast} from '@hooks/useToast/useToast'; - -import {bottomSheetHeaderStyle, bottomSheetStyle, inputGroupStyle} from './DeleteMemberActionModal.style'; - -type DeleteMemberActionModalProps = { - memberActionType: MemberType; - memberActionList: MemberAction[]; - isBottomSheetOpened: boolean; - setIsBottomSheetOpened: React.Dispatch>; -}; - -const DeleteMemberActionModal = ({ - memberActionType, - memberActionList, - isBottomSheetOpened, - setIsBottomSheetOpened, -}: DeleteMemberActionModalProps) => { - const {showToast} = useToast(); - - const showToastAlreadyExistMemberAction = () => { - showToast({ - isClickToClose: true, - showingTime: 3000, - message: '이미 삭제된 인원입니다.', - type: 'error', - bottom: '160px', - }); - }; - - const showToastExistSameMemberFromAfterStep = (name: string) => { - showToast({ - isClickToClose: true, - showingTime: 3000, - message: `이후의 ${name}가 사라져요`, - type: 'error', - position: 'top', - top: '30px', - style: { - zIndex: 9000, - }, - }); - }; - - const {aliveActionList, deleteMemberActionList, addDeleteMemberAction} = useDeleteMemberAction({ - memberActionList, - setIsBottomSheetOpened, - showToastAlreadyExistMemberAction, - showToastExistSameMemberFromAfterStep, - }); - - return ( - setIsBottomSheetOpened(false)}> -
    -
    - {memberActionType === 'IN' ? '들어온' : '나간'} 인원 수정하기 - {`${aliveActionList.length}명`} -
    -
      - {aliveActionList.map(member => ( -
    • - -
      - -
      - addDeleteMemberAction(member)}> - - -
      -
    • - ))} -
    - -
    -
    - ); -}; - -export default DeleteMemberActionModal; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts deleted file mode 100644 index 2a6b52b45..000000000 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as DeleteMemberActionModal} from './DeleteMemberActionModal'; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx deleted file mode 100644 index 5f7d4501e..000000000 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import type {BillAction} from 'types/serviceType'; - -import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; - -import validatePurchase from '@utils/validate/validatePurchase'; -import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; -import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; -import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; - -import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; - -import {bottomSheetHeaderStyle, bottomSheetStyle, inputContainerStyle} from './PutAndDeltetBillActionModal.style'; - -type PutAndDeleteBillActionModalProps = { - billAction: BillAction; - isBottomSheetOpened: boolean; - setIsBottomSheetOpened: React.Dispatch>; -}; - -const PutAndDeleteBillActionModal = ({ - billAction, - isBottomSheetOpened, - setIsBottomSheetOpened, -}: PutAndDeleteBillActionModalProps) => { - const { - inputPair, - handleInputChange, - // handleOnBlur, - // errorMessage, - // errorInfo, - canSubmit, - onDelete, - onSubmit: putBillAction, - } = usePutAndDeleteBillAction( - {title: billAction.name, price: String(billAction.price), index: 0}, - validatePurchase, - () => setIsBottomSheetOpened(false), - ); - - const { - memberReportListInAction, - addAdjustedMember, - onSubmit: putMemberReportListInAction, - getIsSamePriceStateAndServerState, - getOnlyOneNotAdjustedRemainMemberIndex, - isExistAdjustedPrice, - } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); - const { - inputList, - onChange, - canEditList, - canSubmit: isChangedMemberReportInput, - } = useMemberReportInput({ - data: memberReportListInAction, - addAdjustedMember, - totalPrice: Number(inputPair.price), - getIsSamePriceStateAndServerState, - getOnlyOneNotAdjustedRemainMemberIndex, - }); - - const {data: stepListData = []} = useRequestGetStepList(); - - const actionMemberList = stepListData.filter(({actions}) => - actions.find(({actionId}) => actionId === billAction.actionId), - )[0].members; - - return ( - setIsBottomSheetOpened(false)}> -
    { - event.preventDefault(); - - if (canSubmit) await putBillAction(event, inputPair, billAction.actionId); - if (isChangedMemberReportInput) putMemberReportListInAction(); - }} - > -

    - 지출 내역 수정하기 -

    -
    - - ) => handleInputChange('title', event)} - /> - - ) => handleInputChange('price', event)} - isFixed={isExistAdjustedPrice()} - /> - - - - - - - {inputList.map(({name, price, isFixed}, index) => ( - - - - onChange(event, index)} - isFixed={isFixed} - textSize="smallBody" - value={price} - placeholder="0" - type="number" - readOnly={!canEditList[index]} - style={{textAlign: 'right'}} - > - - - - ))} - - -
    - onDelete(billAction.actionId)} - > - 수정 완료 - -
    -
    - ); -}; - -export default PutAndDeleteBillActionModal; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts deleted file mode 100644 index c7cbcfcb6..000000000 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as PutAndDeleteBillActionModal} from './PutAndDeleteBillActionModal'; diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts b/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts deleted file mode 100644 index ca6703309..000000000 --- a/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {css} from '@emotion/react'; - -export const container = css({ - display: 'flex', - flexDirection: 'column', - width: '100%', - height: '100%', - padding: '0 1.5rem', - gap: '1.5rem', -}); - -export const switchContainer = css({ - display: 'flex', - width: '100%', - justifyContent: 'space-between', -}); - -const setActionListModalStyle = {container, switchContainer}; - -export default setActionListModalStyle; diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx deleted file mode 100644 index 862bd91e3..000000000 --- a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import type {InOutType} from 'types/serviceType'; - -import {useState} from 'react'; -import {BottomSheet, Switch, Text} from 'haengdong-design'; - -import {AddMemberActionListModalContent} from './AddMemberActionListModalContent'; -import style from './SetActionListModal.style'; - -export type ActionType = '지출' | '인원'; - -interface SetActionModalContentProps { - isOpenBottomSheet: boolean; - setIsOpenBottomSheet: React.Dispatch>; -} - -const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetActionModalContentProps) => { - const [inOutAction, setInOutAction] = useState('탈주'); - - const handleParticipantTypeChange = (value: string) => { - setInOutAction(value as InOutType); - }; - - return ( - setIsOpenBottomSheet(false)}> -
    -
    - - 인원 변동 - - -
    - - -
    -
    - ); -}; - -export default SetActionListModal; diff --git a/client/src/components/Modal/SetActionModal/index.ts b/client/src/components/Modal/SetActionModal/index.ts deleted file mode 100644 index f689cb596..000000000 --- a/client/src/components/Modal/SetActionModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as SetActionListModal} from './SetActionListModal'; diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts deleted file mode 100644 index f54166c08..000000000 --- a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {css} from '@emotion/react'; - -export const allMemberListModalStyle = () => - css({ - display: 'flex', - flexDirection: 'column', - gap: '1rem', - width: '100%', - height: '100%', - }); - -export const allMemberListModalTitleStyle = () => - css({ - display: 'flex', - justifyContent: 'space-between', - width: '100%', - padding: '0 1.5rem', - }); - -export const allMemberListModalLabelGroupInputStyle = () => - css({ - display: 'flex', - flexDirection: 'column', - padding: '0 1rem', - paddingBottom: '10rem', - - overflow: 'auto', - }); - -export const InputAndDeleteButtonContainer = () => - css({ - display: 'flex', - alignItems: 'center', - width: '100%', - gap: '1rem', - }); diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx deleted file mode 100644 index 58e86b917..000000000 --- a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import {BottomSheet, Text, LabelGroupInput, FixedButton, IconButton, Icon} from 'haengdong-design'; - -import validateMemberName from '@utils/validate/validateMemberName'; - -import useSetAllMemberList from '@hooks/useSetAllMemberList'; - -import { - allMemberListModalLabelGroupInputStyle, - allMemberListModalStyle, - allMemberListModalTitleStyle, - InputAndDeleteButtonContainer, -} from './SetAllMemberListModal.style'; - -interface SetAllMemberListModalProps { - isOpenBottomSheet: boolean; - allMemberList: string[]; - setIsOpenBottomSheet: React.Dispatch>; - setIsOpenAllMemberListButton: React.Dispatch>; -} - -const SetAllMemberListModal = ({ - isOpenBottomSheet, - allMemberList, - setIsOpenBottomSheet, - setIsOpenAllMemberListButton, -}: SetAllMemberListModalProps) => { - const handleCloseAllMemberListModal = () => { - setIsOpenAllMemberListButton(prev => !prev); - setIsOpenBottomSheet(false); - }; - - const { - editedAllMemberList, - canSubmit, - errorMessage, - errorIndexList, - handleNameChange, - handleClickDeleteButton, - handlePutAllMemberList, - } = useSetAllMemberList({ - validateFunc: validateMemberName, - allMemberList, - handleCloseAllMemberListModal, - }); - - return ( - -
    -
    - 전체 참여자 수정하기 - - 총 {allMemberList.length}명 - -
    -
    - - {editedAllMemberList.map((member, index) => ( -
    -
    - handleNameChange(index, e)} - /> -
    - handleClickDeleteButton(index)}> - - -
    - ))} -
    -
    - -
    -
    - ); -}; - -export default SetAllMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts deleted file mode 100644 index ed835682c..000000000 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {css} from '@emotion/react'; - -export const setInitialMemberListModalStyle = () => - css({ - display: 'flex', - flexDirection: 'column', - gap: '1.5rem', - width: '100%', - height: '100%', - padding: '0 1.5rem', - }); - -export const setInitialMemberListModalInputGroupStyle = () => - css({ - display: 'flex', - flexDirection: 'column', - gap: '1rem', - overflow: 'auto', - paddingBottom: '11rem', - }); diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx deleted file mode 100644 index f73f2616d..000000000 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import {Text, BottomSheet, FixedButton, LabelGroupInput} from 'haengdong-design'; - -import validateMemberName from '@utils/validate/validateMemberName'; -import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; - -import useDynamicInput from '@hooks/useDynamicInput'; - -import { - setInitialMemberListModalInputGroupStyle, - setInitialMemberListModalStyle, -} from './SetInitialMemberListModal.style'; - -interface SetInitialMemberListProps { - isOpenBottomSheet: boolean; - setIsOpenBottomSheet: React.Dispatch>; -} - -const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetInitialMemberListProps) => { - const { - inputList, - inputRefList, - handleInputChange, - deleteEmptyInputElementOnBlur, - getFilledInputList, - errorMessage, - canSubmit, - errorIndexList, - focusNextInputOnEnter, - } = useDynamicInput(validateMemberName); - const {mutate: postMemberList} = useRequestPostMemberList(); - - const handleSubmit = () => { - postMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: 'IN'}); - setIsOpenBottomSheet(false); - }; - - return ( - setIsOpenBottomSheet(false)}> -
    - 시작 인원 추가하기 -
    - - {inputList.map(({value, index}) => ( - (inputRefList.current[index] = el)} - onChange={e => handleInputChange(index, e)} - onBlur={() => deleteEmptyInputElementOnBlur()} - onKeyDown={e => focusNextInputOnEnter(e, index)} - autoFocus={inputList.length === 1 && index === 0} - /> - ))} - -
    -
    - -
    - ); -}; - -export default SetInitialMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/index.ts b/client/src/components/Modal/SetInitialMemberListModal/index.ts deleted file mode 100644 index 18098e4f6..000000000 --- a/client/src/components/Modal/SetInitialMemberListModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as SetInitialMemberListModal} from './SetInitialMemberListModal'; diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts deleted file mode 100644 index 180063b03..000000000 --- a/client/src/components/Modal/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export {default as SetActionListModal} from './SetActionModal/SetActionListModal'; -export {default as SetInitialMemberListModal} from './SetInitialMemberListModal/SetInitialMemberListModal'; -export {default as SetAllMemberListModal} from './SetAllMemberListModal/SetAllMemberListModal'; -export {default as ModalBasedOnMemberCount} from './ModalBasedOnMemberCount/ModalBasedOnMemberCount'; diff --git a/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx b/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx index aeec24c3a..0ff8bf202 100644 --- a/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx +++ b/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx @@ -1,13 +1,24 @@ import {MutationCache, QueryCache, QueryClient, QueryClientProvider} from '@tanstack/react-query'; +import {RequestGetError} from '@errors/RequestGetError'; + import {useAppErrorStore} from '@store/appErrorStore'; const QueryClientBoundary = ({children}: React.PropsWithChildren) => { const {updateAppError} = useAppErrorStore(); const queryClient = new QueryClient({ + // errorBoundary를 사용하기 위해 true로 해줘야함. + defaultOptions: { + queries: { + throwOnError: true, + }, + }, queryCache: new QueryCache({ onError: (error: Error) => { + // errorBoundary로 처리해야하는 에러인 경우 updateAppError를 하지 못하도록 얼리리턴 + if (error instanceof RequestGetError && error.errorHandlingStrategy === 'errorBoundary') return; + updateAppError(error); }, }), diff --git a/client/src/components/Reports/Reports.tsx b/client/src/components/Reports/Reports.tsx new file mode 100644 index 000000000..74b59dbb9 --- /dev/null +++ b/client/src/components/Reports/Reports.tsx @@ -0,0 +1,26 @@ +import BillEmptyFallback from '@pages/EventPage/EventPageFallback/BillEmptyFallback'; + +import useReportsPage from '@hooks/useReportsPage'; + +import {ExpenseList, Flex} from '@HDesign/index'; + +const Reports = () => { + const {isEmpty, expenseListProp, memberName, changeName} = useReportsPage(); + + if (isEmpty) { + return ; + } + + return ( + + + + ); +}; + +export default Reports; diff --git a/client/src/components/ShareEventButton/ShareEventButton.tsx b/client/src/components/ShareEventButton/ShareEventButton.tsx new file mode 100644 index 000000000..f8a968003 --- /dev/null +++ b/client/src/components/ShareEventButton/ShareEventButton.tsx @@ -0,0 +1,62 @@ +import CopyToClipboard from 'react-copy-to-clipboard'; +import {useNavigate} from 'react-router-dom'; + +import toast from '@hooks/useToast/toast'; +import {Event} from 'types/serviceType'; + +import useShareEvent from '@hooks/useShareEvent'; + +import {Button} from '@components/Design'; + +import {isMobileDevice} from '@utils/detectDevice'; +import getDeletedLastPath from '@utils/getDeletedLastPath'; + +type ShareEventButtonProps = { + eventOutline: Event; +}; + +const ShareEventButton = ({eventOutline}: ShareEventButtonProps) => { + const {eventName, bankName, accountNumber} = eventOutline; + const navigate = useNavigate(); + + const isMobile = isMobileDevice(); + const {shareText, onShareButtonClick} = useShareEvent(eventName, isMobile); + + const induceBankInfoBeforeShare = () => { + if (bankName === '' || accountNumber === '') { + toast.confirm('잠깐! 정산을 초대하기 전에\n계좌를 등록해주세요', { + showingTime: 3000, + position: 'bottom', + }); + + const navigatePath = `${getDeletedLastPath(location.pathname)}/admin/edit`; + + navigate(navigatePath); + return; + } + + onShareButtonClick(); + }; + + return isMobile ? ( + + ) : ( + + toast.confirm('링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', { + showingTime: 3000, + position: 'bottom', + }) + } + > + + + ); +}; + +export default ShareEventButton; diff --git a/client/src/components/ShareEventButton/index.ts b/client/src/components/ShareEventButton/index.ts new file mode 100644 index 000000000..27b5883aa --- /dev/null +++ b/client/src/components/ShareEventButton/index.ts @@ -0,0 +1 @@ +export {default as ShareEventButton} from './ShareEventButton'; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx deleted file mode 100644 index 7fed9ef5c..000000000 --- a/client/src/components/StepList/BillStepItem.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import {DragHandleItem, DragHandleItemContainer, EditableItem, Flex, Text} from 'haengdong-design'; -import {Fragment, useState} from 'react'; -import {useOutletContext} from 'react-router-dom'; - -import {BillStep, MemberReport} from 'types/serviceType'; -import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutAndDeleteBillActionModal'; -import {MemberListInBillStep} from '@components/Modal/MemberListInBillStep'; -import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; -import ExpenseDetailModal from '@components/Modal/ExpenseDetailModal/ExpenseDetailModal'; - -import useSetBillInput from '@hooks/useSetBillInput'; - -interface BillStepItemProps { - step: BillStep; - isOpenBottomSheet: boolean; - setIsOpenBottomSheet: React.Dispatch>; - isAddEditableItem: boolean; - setIsAddEditableItem: React.Dispatch>; - isLastBillItem: boolean; - index: number; -} - -const BillStepItem: React.FC = ({ - step, - isOpenBottomSheet, - setIsOpenBottomSheet, - isAddEditableItem, - setIsAddEditableItem, - isLastBillItem, - index, -}) => { - const {isAdmin} = useOutletContext(); - const {handleBlurBillRequest, handleChangeBillInput, billInput} = useSetBillInput({setIsAddEditableItem}); - - const [clickedIndex, setClickedIndex] = useState(-1); - const [isOpenMemberListInBillStep, setIsOpenMemberListInBillStep] = useState(false); - - const totalPrice = step.actions && step.type === 'BILL' ? step.actions.reduce((acc, cur) => acc + cur.price, 0) : 0; - - const handleDragHandleItemClick = (index: number) => { - setClickedIndex(index); - setIsOpenBottomSheet(true); - }; - - const memberList: MemberReport[] = step.members.map(member => ({ - name: member, - price: totalPrice / step.members.length, - })); - - const handleTopRightTextClick = () => { - setIsOpenMemberListInBillStep(true); - }; - - return ( - <> - - {step.actions && - step.type === 'BILL' && - step.actions.map((action, index) => ( - - handleDragHandleItemClick(index)} - isFixed={action.isFixed} - /> - - {isOpenBottomSheet && clickedIndex === index && isAdmin && ( - - )} - {isOpenBottomSheet && clickedIndex === index && !isAdmin && ( - - )} - - ))} - - {isAddEditableItem && isLastBillItem && ( - { - if (e.key === 'Enter') { - handleBlurBillRequest(); - } - }} - > - handleChangeBillInput('title', e)} - autoFocus - > - - handleChangeBillInput('price', e)} - style={{textAlign: 'right'}} - > - - - - )} - - - - ); -}; - -export default BillStepItem; diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx deleted file mode 100644 index ed3f5bfe7..000000000 --- a/client/src/components/StepList/MemberStepItem.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import type {MemberStep} from 'types/serviceType'; - -import {DragHandleItem} from 'haengdong-design'; -import {useOutletContext} from 'react-router-dom'; - -import {DeleteMemberActionModal} from '@components/Modal/SetActionModal/DeleteMemberActionModal'; -import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; - -interface MemberStepItemProps { - step: MemberStep; - isOpenBottomSheet: boolean; - setIsOpenBottomSheet: React.Dispatch>; -} - -const MemberStepItem: React.FC = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { - const {isAdmin} = useOutletContext(); - - return ( - <> - name).join(', ')} ${step.type === 'IN' ? '들어옴' : '나감'}`} - onClick={() => setIsOpenBottomSheet(prev => !prev)} - /> - {isOpenBottomSheet && isAdmin && ( - - )} - - ); -}; - -export default MemberStepItem; diff --git a/client/src/components/StepList/Step.stories.tsx b/client/src/components/StepList/Step.stories.tsx new file mode 100644 index 000000000..0d2b64bb2 --- /dev/null +++ b/client/src/components/StepList/Step.stories.tsx @@ -0,0 +1,69 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {MemoryRouter} from 'react-router-dom'; + +import Step from './Step'; + +const meta = { + title: 'Components/Step', + component: Step, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + step: { + description: '', + }, + isAdmin: { + description: '', + control: {type: 'boolean'}, + }, + }, + args: { + step: { + bills: [ + { + id: 1, + title: '커피', + price: 10000, + isFixed: false, + }, + { + id: 2, + title: '인생네컷', + price: 20000, + isFixed: false, + }, + ], + members: [ + { + id: 1, + name: '망쵸', + }, + { + id: 2, + name: '백호', + }, + ], + }, + isAdmin: false, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = { + render: ({...args}) => { + return ( + +
    + +
    +
    + ); + }, +}; diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx index f6c89475b..997cf03c7 100644 --- a/client/src/components/StepList/Step.tsx +++ b/client/src/components/StepList/Step.tsx @@ -1,51 +1,56 @@ -import type {BillStep, MemberStep} from 'types/serviceType'; +/** @jsxImportSource @emotion/react */ +import {useNavigate} from 'react-router-dom'; +import {css} from '@emotion/react'; -import {useEffect, useState} from 'react'; +import Amount from '@components/Design/components/Amount/Amount'; +import ChipGroup from '@components/Design/components/ChipGroup/ChipGroup'; +import ListItem from '@components/Design/components/ListItem/ListItem'; +import {Bill, Step as StepType} from 'types/serviceType'; -import BillStepItem from './BillStepItem'; -import MemberStepItem from './MemberStepItem'; +import {Text} from '@components/Design'; -interface StepProps { - step: BillStep | MemberStep; - isAddEditableItem: boolean; - lastBillItemIndex: number; - lastItemIndex: number; - index: number; - setIsAddEditableItem: React.Dispatch>; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +interface Prop { + step: StepType; + isAdmin: boolean; } -const Step = ({step, isAddEditableItem, lastBillItemIndex, lastItemIndex, setIsAddEditableItem, index}: StepProps) => { - const [isOpenBottomSheet, setIsOpenBottomSheet] = useState(false); - const [isLastBillItem, setIsLastBillItem] = useState(false); - - useEffect(() => { - if (index === lastBillItemIndex && lastBillItemIndex === lastItemIndex) { - // index를 사용하여 마지막 BillStep인지 확인 - setIsLastBillItem(true); - } else { - setIsLastBillItem(false); - } - }, [index, lastBillItemIndex]); - - if (step.actions && step.type === 'BILL') { - return ( - - ); - } else if (step.actions && (step.type === 'IN' || step.type === 'OUT')) { - return ( - - ); - } else { - return <>; - } +const Step = ({step, isAdmin}: Prop) => { + const navigate = useNavigate(); + const eventId = getEventIdByUrl(); + const handleClickStep = (bill: Bill) => { + if (isAdmin) navigate(`/event/${eventId}/edit-bill`, {state: {bill}}); + }; + + return ( + + + member.name)} /> + + + {step.members.length}명 + + + {step.bills.map(bill => { + return ( + handleClickStep(bill)}> + {bill.title} + + + ); + })} + + ); }; export default Step; diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx deleted file mode 100644 index d6a507247..000000000 --- a/client/src/components/StepList/StepList.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import {Flex} from 'haengdong-design'; -import {useEffect, useMemo, useState} from 'react'; - -import {BillStep, MemberStep} from 'types/serviceType'; -import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; - -import Step from './Step'; - -interface StepListProps { - isAddEditableItem?: boolean; - setIsAddEditableItem?: React.Dispatch>; -} - -const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: StepListProps) => { - const {data: stepListData} = useRequestGetStepList(); - const [stepList, setStepList] = useState<(MemberStep | BillStep)[]>([]); - const existIndexInStepList = stepList.map((step, index) => ({...step, index})); - const [hasAddedItem, setHasAddedItem] = useState(false); - const nextStepName = stepList.length > 0 ? String(stepList[stepList.length - 1].stepName).match(/.*(?=차)/) : ''; - - useEffect(() => { - if (stepListData) { - setStepList(stepListData); - } - }, [stepListData]); - - const lastBillItemIndex = useMemo(() => { - const billSteps = existIndexInStepList.filter(step => step.type === 'BILL'); - - // billSteps 배열이 비어 있지 않으면 마지막 항목의 index를 반환, 그렇지 않으면 -1을 반환 - return billSteps.length > 0 ? billSteps.slice(-1)[0].index : -1; - }, [stepList]); - - const lastItemIndex = useMemo(() => { - return existIndexInStepList.length > 0 ? existIndexInStepList.slice(-1)[0].index : -1; - }, [existIndexInStepList]); - - useEffect(() => { - if (hasAddedItem) { - setHasAddedItem(false); - - setStepList(prev => [...prev.filter(({actions}) => actions.length !== 0)]); - } - - if (isAddEditableItem && lastBillItemIndex !== lastItemIndex && !hasAddedItem) { - setStepList(prev => [ - ...prev, - { - type: 'BILL', - stepName: `${Number(nextStepName) + 1}차`, - members: [], - actions: [], - }, - ]); - setHasAddedItem(prev => !prev); - } - }, [isAddEditableItem]); - - return ( - - {stepList.map((step, index) => ( - - ))} - - ); -}; - -export default StepList; diff --git a/client/src/components/StepList/Steps.tsx b/client/src/components/StepList/Steps.tsx new file mode 100644 index 000000000..308f9fda6 --- /dev/null +++ b/client/src/components/StepList/Steps.tsx @@ -0,0 +1,27 @@ +import {Step as StepType} from 'types/serviceType'; +import BillEmptyFallback from '@pages/EventPage/EventPageFallback/BillEmptyFallback'; + +import {Flex} from '@HDesign/index'; + +import Step from './Step'; + +interface Props { + data: StepType[]; + isAdmin: boolean; +} + +const Steps = ({data, isAdmin}: Props) => { + if (data.length <= 0 && !isAdmin) { + return ; + } + + return ( + + {data.map((step, index) => ( + + ))} + + ); +}; + +export default Steps; diff --git a/client/src/components/Toast/Toast.style.ts b/client/src/components/Toast/Toast.style.ts index a0b5c7cd4..d8c4c62f7 100644 --- a/client/src/components/Toast/Toast.style.ts +++ b/client/src/components/Toast/Toast.style.ts @@ -1,12 +1,6 @@ import {css, keyframes} from '@emotion/react'; -import {ToastPosition} from './Toast.type'; - -type ToastMarginStyle = { - position?: ToastPosition; - bottom?: string; - top?: string; -}; +import {ToastOptions} from 'types/toastType'; // 애니메이션 키프레임 정의 const fadeInWithTransformY = keyframes` @@ -31,13 +25,14 @@ const fadeOutWithTransformY = keyframes` } `; -export const toastMarginStyle = ({position, bottom, top}: ToastMarginStyle) => +export const toastMarginStyle = ({position, bottom, top, theme}: ToastOptions) => css({ position: 'absolute', bottom: position === 'bottom' ? `${bottom}` : 'auto', top: position === 'top' ? `${top}` : 'auto', left: '50%', transform: 'translate(-50%)', + zIndex: theme?.zIndex.toast, width: '100%', maxWidth: '48rem', diff --git a/client/src/components/Toast/Toast.tsx b/client/src/components/Toast/Toast.tsx index 5bf44d6fb..cbc6824f4 100644 --- a/client/src/components/Toast/Toast.tsx +++ b/client/src/components/Toast/Toast.tsx @@ -1,6 +1,8 @@ import {createPortal} from 'react-dom'; import {useState, useEffect} from 'react'; -import {Button, Flex, Icon, Text} from 'haengdong-design'; + +import {useTheme} from '@HDesign/index'; +import {Button, Flex, Icon, Text} from '@HDesign/index'; import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; import {ToastProps, ToastType} from './Toast.type'; @@ -16,8 +18,9 @@ const ANIMATION_TIME = 500; const Toast = ({ type = 'confirm', top = '0px', - bottom = '0px', - isClickToClose = true, + bottom = '6rem', + isCloseOnClick = true, + isAutoClosed = true, position = 'bottom', showingTime = 3000, message, @@ -25,10 +28,20 @@ const Toast = ({ onClose, ...htmlProps }: ToastProps) => { + const {theme} = useTheme(); const [isVisible, setIsVisible] = useState(true); - const styleProps = {position, top, bottom}; + const styleProps = {position, top, bottom, theme}; - useEffect(() => { + const handleClickToClose = () => { + if (!isCloseOnClick || !onClose) return; + + setIsVisible(false); + setTimeout(() => { + onClose(); + }, ANIMATION_TIME); // fadeOut 애니메이션 시간과 동일하게 설정 + }; + + const handleAutoClose = () => { const timer = setTimeout(() => { setIsVisible(false); setTimeout(() => { @@ -39,17 +52,12 @@ const Toast = ({ return () => { clearTimeout(timer); }; - }, [onClose]); - - const handleClickToClose = () => { - if (!isClickToClose || !onClose) return; - - setIsVisible(false); - setTimeout(() => { - onClose(); - }, ANIMATION_TIME); // fadeOut 애니메이션 시간과 동일하게 설정 }; + useEffect(() => { + if (isAutoClosed) handleAutoClose(); + }, []); + return createPortal(
    diff --git a/client/src/components/Toast/Toast.type.ts b/client/src/components/Toast/Toast.type.ts index 20b92c0db..a1ff70c40 100644 --- a/client/src/components/Toast/Toast.type.ts +++ b/client/src/components/Toast/Toast.type.ts @@ -1,22 +1,15 @@ -export type ToastPosition = 'bottom' | 'top'; -export type ToastType = 'error' | 'confirm' | 'none'; +import {ToastMessage, ToastOptions} from 'types/toastType'; -export interface ToastStyleProps { - bottom?: string; - top?: string; -} +export type ToastType = 'error' | 'confirm' | 'none'; -export interface ToastOptionProps { - position?: ToastPosition; +export type ToastOptionProps = ToastOptions & { type?: ToastType; - onUndo?: () => void; - isClickToClose?: boolean; onClose?: () => void; - showingTime?: number; -} + onUndo?: () => void; +}; -export interface ToastRequiredProps { - message: string; -} +export type ToastRequiredProps = { + message: ToastMessage; +}; -export type ToastProps = React.ComponentProps<'div'> & ToastStyleProps & ToastOptionProps & ToastRequiredProps; +export type ToastProps = React.ComponentProps<'div'> & ToastOptionProps & ToastRequiredProps; diff --git a/client/src/components/Toast/ToastContainer.tsx b/client/src/components/Toast/ToastContainer.tsx new file mode 100644 index 000000000..40439f9b6 --- /dev/null +++ b/client/src/components/Toast/ToastContainer.tsx @@ -0,0 +1,11 @@ +import {useToast} from '@hooks/useToast/useToast'; + +import Toast from './Toast'; + +const ToastContainer = () => { + const {currentToast, closeToast} = useToast(); + + return <>{currentToast && }; +}; + +export default ToastContainer; diff --git a/client/src/constants/bank.ts b/client/src/constants/bank.ts new file mode 100644 index 000000000..b730adb44 --- /dev/null +++ b/client/src/constants/bank.ts @@ -0,0 +1,32 @@ +type Bank = { + name: string; + iconPosition: string; +}; + +const BANKS: Bank[] = [ + {name: '우리은행', iconPosition: '-10px -10px'}, + {name: '제일은행', iconPosition: '-110px -10px'}, + {name: '신한은행', iconPosition: '-10px -110px'}, + {name: 'KB국민은행', iconPosition: '-110px -110px'}, + {name: '하나은행', iconPosition: '-210px -10px'}, + {name: '시티은행', iconPosition: '-210px -110px'}, + {name: 'IM뱅크', iconPosition: '-10px -210px'}, + {name: '부산은행', iconPosition: '-110px -210px'}, + {name: '경남은행', iconPosition: '-210px -210px'}, + {name: '광주은행', iconPosition: '-310px -10px'}, + {name: '전북은행', iconPosition: '-310px -110px'}, + {name: '제주은행', iconPosition: '-310px -210px'}, + {name: '기업은행', iconPosition: '-10px -310px'}, + {name: '산업은행', iconPosition: '-110px -310px'}, + {name: '수협은행', iconPosition: '-210px -310px'}, + {name: '농협은행', iconPosition: '-310px -310px'}, + {name: '새마을금고', iconPosition: '-410px -10px'}, + {name: '우체국은행', iconPosition: '-410px -110px'}, + {name: '신협은행', iconPosition: '-410px -210px'}, + {name: 'SBI저축', iconPosition: '-410px -310px'}, + {name: '카카오뱅크', iconPosition: '-10px -410px'}, + {name: '토스뱅크', iconPosition: '-110px -410px'}, + {name: '케이뱅크', iconPosition: '-210px -410px'}, +]; + +export default BANKS; diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index 42703bdf0..113b7c7e1 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -1,49 +1,61 @@ +import RULE from './rule'; + type ErrorMessage = Record; export const SERVER_ERROR_MESSAGES: ErrorMessage = { - EVENT_NOT_FOUND: '존재하지 않는 행사입니다.', - EVENT_NAME_LENGTH_INVALID: '행사 이름은 2자 이상 30자 이하만 입력 가능합니다.', - EVENT_NAME_CONSECUTIVE_SPACES: '행사 이름에는 공백 문자가 연속될 수 없습니다.', - EVENT_PASSWORD_FORMAT_INVALID: '비밀번호는 4자리 숫자만 가능합니다.', - - ACTION_NOT_FOUND: '존재하지 않는 액션입니다.', - - MEMBER_NAME_LENGTH_INVALID: '멤버 이름은 1자 이상 4자 이하만 입력 가능합니다.', - MEMBER_NAME_DUPLICATE: '중복된 행사 참여 인원 이름이 존재합니다.', - MEMBER_NOT_EXIST: '현재 참여하고 있지 않은 인원이 존재합니다.', - MEMBER_ALREADY_EXIST: '현재 참여하고 있는 인원이 존재합니다.', - - MEMBER_ACTION_NOT_FOUND: '존재하지 않는 멤버 액션입니다.', - MEMBER_ACTION_STATUS_INVALID: '유효하지 않은 멤버 액션 상태입니다.', - - BILL_ACTION_NOT_FOUND: '존재하지 않는 지출 액션입니다.', - BILL_ACTION_TITLE_INVALID: '앞뒤 공백을 제거한 지출 내역 제목은 %d자 ~ %d자여야 합니다.', - BILL_ACTION_PRICE_INVALID: '지출 금액은 10,000,000 이하의 자연수여야 합니다.', - - REQUEST_EMPTY: '입력 값은 공백일 수 없습니다.', - MESSAGE_NOT_READABLE: '읽을 수 없는 요청입니다.', - NO_RESOURCE_REQUEST: '존재하지 않는 자원입니다.', - REQUEST_METHOD_NOT_SUPPORTED: '지원하지 않는 요청 메서드입니다.', - + // 행사 관련 에러 코드 + EVENT_NAME_LENGTH_INVALID: `행사 이름의 길이는 2자 이상 ${RULE.maxEventNameLength}자 이하만 가능해요.`, + EVENT_NAME_CONSECUTIVE_SPACES: '행사 이름에는 공백 문자가 연속될 수 없어요.', + EVENT_PASSWORD_FORMAT_INVALID: `비밀번호는 ${RULE.maxEventPasswordLength}자리의 숫자만 가능해요.`, + EVENT_NOT_FOUND: '존재하지 않는 행사에요. 링크가 올바른지 확인해주세요.', + + // 멤버 관련 에러 코드 + MEMBER_NAME_LENGTH_INVALID: `멤버 이름은 한글 ${RULE.maxEventNameLength}자까지, 영어 ${RULE.maxEventNameLength * 2}자까지 입력 가능해요.`, + + MEMBER_NAME_CHANGE_DUPLICATE: '요청 본문에 중복된 이름이 존재해요. \n(ex. [이상, 이상, 감자, 백호])', + MEMBER_NAME_DUPLICATE: '요청 본문에 중복된 이름이 존재해요. \n(ex. [이상, 이상, 감자, 백호])', + MEMBER_ALREADY_EXIST: '이미 행사에 참여중인 인원이에요. \n겹치지 않도록 다른 이름을 사용해주세요.', + + MEMBER_NOT_EXIST: '현재 참여하고 있지 않은 인원이 존재해요', + MEMBER_UPDATE_MISMATCH: '업데이트 요청된 참여자 정보와 기존 행사 참여자 정보가 일치하지 않아요.', + + // 지출 관련 에러 코드 + BILL_NOT_FOUND: '존재하지 않는 지출 액션이에요.', + BILL_TITLE_INVALID: `지출 내역 이름은 1자 이상 ${RULE.maxBillNameLength} 이하여야 해요.`, + BILL_PRICE_INVALID: `지출 금액은 ${RULE.maxPrice.toLocaleString('ko-KR')} 이하의 자연수여야 해요.`, + BILL_DETAIL_NOT_FOUND: '존재하지 않는 참여자 지출입니다.', + BILL_PRICE_NOT_MATCHED: '지출 총액이 일치하지 않아요.', + DIFFERENT_STEP_MEMBERS: '회원 목록이 일치하지 않아요.', + + // 계좌 관련 에러 코드 + BANK_NAME_INVALID: '지원하지 않는 은행이에요. 다른 은행을 입력해주세요.', + ACCOUNT_LENGTH_INVALID: `계좌 번호는 8자 이상 ${RULE.maxAccountNumberLength}자 이하로 입력 가능해요.`, + + // 로그인 관련 에러 코드 + TOKEN_NOT_FOUND: '로그인이 필요한 서비스에요.', + TOKEN_EXPIRED: '로그인이 만료되었어요. 다시 로그인해주세요.', + TOKEN_INVALID: '비밀번호를 올바르게 입력해주세요.', + FORBIDDEN: '접근할 수 없는 행사에요.', + + // 사용자에게 뜨면 안되며 프론트 구현 미스인 에러 코드 + MESSAGE_NOT_READABLE: '읽을 수 없는 요청이에요.', + NO_RESOURCE_REQUEST: '존재하지 않는 자원이에요.', + REQUEST_METHOD_NOT_SUPPORTED: '지원하지 않는 요청 메서드에요.', + REQUEST_EMPTY: '요청 본문에 빈 값이 존재해요', + + // 예측할 수 없는 에러 코드 INTERNAL_SERVER_ERROR: '서버 내부에 에러가 발생했습니다.', - - PASSWORD_INVALID: '비밀번호가 일치하지 않습니다.', - TOKEN_NOT_FOUND: '토큰이 존재하지 않습니다.', - TOKEN_EXPIRED: '만료된 토큰입니다.', - TOKEN_INVALID: '유효하지 않은 토큰입니다.', - FORBIDDEN: '접근할 수 없는 행사입니다.', - UNHANDLED: '알 수 없는 에러입니다.', }; export const ERROR_MESSAGE = { - eventName: '행사 이름은 30자 이하만 가능해요', - eventPasswordType: '비밀번호는 숫자만 입력이 가능해요', - memberName: '참여자 이름은 4자 이하의 한글, 영어만 가능해요', - purchasePrice: '10,000,000원 이하의 숫자만 입력이 가능해요', - purchaseTitle: '지출 이름은 30자 이하의 한글, 영어, 숫자만 가능해요', + eventName: SERVER_ERROR_MESSAGES.EVENT_NAME_LENGTH_INVALID, + eventPasswordType: SERVER_ERROR_MESSAGES.EVENT_PASSWORD_FORMAT_INVALID, + memberName: SERVER_ERROR_MESSAGES.MEMBER_NAME_LENGTH_INVALID, + purchasePrice: `${RULE.maxPrice.toLocaleString('ko-kr')}원 이하의 숫자만 입력이 가능해요`, + purchaseTitle: `지출 이름은 ${RULE.maxBillNameLength}자 이하의 한글, 영어, 숫자만 가능해요`, preventEmpty: '값은 비어있을 수 없어요', invalidInput: '올바르지 않은 입력이에요.', + emptyBank: '계좌번호가 입력되지 않아서\n토스 송금 기능을 사용할 수 없어요', + invalidAccountNumber: '계좌번호는 8자에서 30자 사이로 입력 가능해요', }; - -export const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; diff --git a/client/src/constants/message.ts b/client/src/constants/message.ts new file mode 100644 index 000000000..d82d48e14 --- /dev/null +++ b/client/src/constants/message.ts @@ -0,0 +1,5 @@ +const MESSAGE = { + confirmEditEventMember: '수정이 완료되었어요 :)', +}; + +export default MESSAGE; diff --git a/client/src/constants/queryKeys.ts b/client/src/constants/queryKeys.ts index 17f3f4586..b0835cfd5 100644 --- a/client/src/constants/queryKeys.ts +++ b/client/src/constants/queryKeys.ts @@ -1,10 +1,10 @@ const QUERY_KEYS = { - stepList: 'stepList', - eventName: 'eventName', - allMemberList: 'allMemberList', - currentInMember: 'currentInMember', - memberReport: 'memberReport', - memberReportInAction: 'memberReportInAction', + steps: 'steps', + event: 'event', + allMembers: 'allMembers', + currentMembers: 'currentMembers', + reports: 'reports', + billDetails: 'billDetails', }; export default QUERY_KEYS; diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts index 4d910ac99..8a32f3755 100644 --- a/client/src/constants/regExp.ts +++ b/client/src/constants/regExp.ts @@ -1,8 +1,9 @@ const REGEXP = { eventPassword: /^[0-9]*$/, - memberName: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z\s]*$/, - purchaseTitle: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9\s]*$/, eventUrl: /\/event\/([a-zA-Z0-9-]+)\//, + billTitle: /^([ㄱ-ㅎ가-힣a-zA-Z0-9ㆍᆢ]\s?)*$/, + memberName: /^([ㄱ-ㅎ가-힣a-zA-Zㆍᆢ]\s?)*$/, + accountNumber: /^\d+([\s\-]\d+)*[\s\-]?$/, }; export default REGEXP; diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index 6a3634c3b..6be509841 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -1,10 +1,12 @@ export const ROUTER_URLS = { main: '/', - eventCreateName: '/event/create/name', - eventCreatePassword: '/event/create/password', - eventCreateComplete: '/event/create/complete', - event: '/event', // TODO: (@weadie) baseurl을 어떻게 관리할 것인가? + createEvent: '/event/create', + event: '/event', eventLogin: '/event/:eventId/login', eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', + member: '/event/:eventId/admin/member', + addBill: '/event/:eventId/add-bill', + editBill: '/event/:eventId/edit-bill', + eventEdit: 'event/:eventId/admin/edit', }; diff --git a/client/src/constants/rule.ts b/client/src/constants/rule.ts index 4b78031b9..71ac70c58 100644 --- a/client/src/constants/rule.ts +++ b/client/src/constants/rule.ts @@ -1,8 +1,13 @@ +const EVENT_PASSWORD_LENGTH = 4; + const RULE = { maxEventNameLength: 30, - maxEventPasswordLength: 4, + maxEventPasswordLength: EVENT_PASSWORD_LENGTH, maxMemberNameLength: 4, maxPrice: 10000000, + maxBillNameLength: 30, + minAccountNumberLength: 8, + maxAccountNumberLength: 30, }; export default RULE; diff --git a/client/src/errors/FetchError.ts b/client/src/errors/FetchError.ts deleted file mode 100644 index 9123a80b5..000000000 --- a/client/src/errors/FetchError.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {FetchErrorType} from '../types/fetchErrorType'; - -class FetchError extends Error { - requestBody; - status; - endpoint; - errorInfo; - method; - - constructor({requestBody, status, endpoint, errorInfo, method, name, message}: FetchErrorType) { - super(errorInfo.errorCode); - - this.requestBody = requestBody; - this.status = status; - this.endpoint = endpoint; - this.errorInfo = errorInfo; - this.method = method; - this.name = name; - this.message = message; - } -} - -export default FetchError; diff --git a/client/src/errors/RequestError.ts b/client/src/errors/RequestError.ts new file mode 100644 index 000000000..939b29586 --- /dev/null +++ b/client/src/errors/RequestError.ts @@ -0,0 +1,24 @@ +import {RequestErrorType} from './requestErrorType'; + +class RequestError extends Error { + requestBody; + status; + endpoint; + method; + errorCode; + message; + + constructor({requestBody, status, endpoint, errorCode, method, name, message}: RequestErrorType) { + super(errorCode); + + this.requestBody = requestBody; + this.status = status; + this.endpoint = endpoint; + this.errorCode = errorCode; + this.message = message; + this.method = method; + this.name = name; + } +} + +export default RequestError; diff --git a/client/src/errors/RequestGetError.ts b/client/src/errors/RequestGetError.ts new file mode 100644 index 000000000..da9a8e10b --- /dev/null +++ b/client/src/errors/RequestGetError.ts @@ -0,0 +1,21 @@ +import RequestError from './RequestError'; +import {RequestErrorType} from './requestErrorType'; + +type ErrorHandlingStrategy = 'toast' | 'errorBoundary'; + +export type WithErrorHandlingStrategy

    = P & { + errorHandlingStrategy?: ErrorHandlingStrategy; +}; + +class RequestGetError extends RequestError { + errorHandlingStrategy: string; + + // errorHandlingType은 기본적으로 제일 많이 사용되는 toast로 했습니다. + constructor({errorHandlingStrategy = 'toast', ...rest}: WithErrorHandlingStrategy) { + super(rest); + + this.errorHandlingStrategy = errorHandlingStrategy; + } +} + +export {RequestGetError}; diff --git a/client/src/errors/requestErrorType.ts b/client/src/errors/requestErrorType.ts new file mode 100644 index 000000000..22c9f05f5 --- /dev/null +++ b/client/src/errors/requestErrorType.ts @@ -0,0 +1,10 @@ +import {Body, Method} from '@apis/fetcher'; + +export type RequestErrorType = Error & { + requestBody: Body; + status: number; + endpoint: string; + errorCode: string; + message: string; + method?: Method; +}; diff --git a/client/src/global.d.ts b/client/src/global.d.ts index dbf6320af..63226360f 100644 --- a/client/src/global.d.ts +++ b/client/src/global.d.ts @@ -1,4 +1,5 @@ declare module '*.svg'; +declare module '*.png'; declare namespace NodeJS { interface ProcessEnv { @@ -7,5 +8,6 @@ declare namespace NodeJS { // env keys readonly API_BASE_URL: string; readonly AMPLITUDE_KEY: string; + readonly KAKAO_JAVASCRIPT_KEY: string; } } diff --git a/client/src/hooks/queries/useRequestPostAuthentication.ts b/client/src/hooks/queries/auth/useRequestPostAuthentication.ts similarity index 74% rename from client/src/hooks/queries/useRequestPostAuthentication.ts rename to client/src/hooks/queries/auth/useRequestPostAuthentication.ts index e533a501b..b44cfcafc 100644 --- a/client/src/hooks/queries/useRequestPostAuthentication.ts +++ b/client/src/hooks/queries/auth/useRequestPostAuthentication.ts @@ -7,17 +7,22 @@ import getEventIdByUrl from '@utils/getEventIdByUrl'; import {ROUTER_URLS} from '@constants/routerUrls'; -const useRequestPostAuthenticate = () => { +const useRequestPostAuthentication = () => { const eventId = getEventIdByUrl(); const navigate = useNavigate(); - return useMutation({ + const {mutate, ...rest} = useMutation({ mutationFn: () => requestPostAuthentication({eventId}), onError: () => { // 에러가 발생하면 로그인 페이지로 리다이렉트 navigate(`${ROUTER_URLS.event}/${eventId}/login`); }, }); + + return { + postAuthenticate: mutate, + ...rest, + }; }; -export default useRequestPostAuthenticate; +export default useRequestPostAuthentication; diff --git a/client/src/hooks/queries/useRequestPostLogin.ts b/client/src/hooks/queries/auth/useRequestPostLogin.ts similarity index 65% rename from client/src/hooks/queries/useRequestPostLogin.ts rename to client/src/hooks/queries/auth/useRequestPostLogin.ts index 21dce1791..f2f0d7c4c 100644 --- a/client/src/hooks/queries/useRequestPostLogin.ts +++ b/client/src/hooks/queries/auth/useRequestPostLogin.ts @@ -1,26 +1,24 @@ import {useMutation} from '@tanstack/react-query'; import {useNavigate} from 'react-router-dom'; -import {requestPostToken} from '@apis/request/auth'; +import {RequestPostToken, requestPostToken} from '@apis/request/auth'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import {ROUTER_URLS} from '@constants/routerUrls'; -interface PostLoginMutationProps { - password: string; -} - const useRequestPostLogin = () => { const eventId = getEventIdByUrl(); const navigate = useNavigate(); - return useMutation({ - mutationFn: ({password}: PostLoginMutationProps) => requestPostToken({eventId, password}), + const {mutate, ...rest} = useMutation({ + mutationFn: ({password}: RequestPostToken) => requestPostToken({eventId, password}), onSuccess: () => { navigate(`${ROUTER_URLS.event}/${eventId}/admin`); }, }); + + return {postLogin: mutate, ...rest}; }; export default useRequestPostLogin; diff --git a/client/src/hooks/queries/bill/useRequestDeleteBill.ts b/client/src/hooks/queries/bill/useRequestDeleteBill.ts new file mode 100644 index 000000000..68083d52b --- /dev/null +++ b/client/src/hooks/queries/bill/useRequestDeleteBill.ts @@ -0,0 +1,29 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteBill} from '@apis/request/bill'; + +import {WithBillId} from '@apis/withId.type'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestDeleteBill = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...rest} = useMutation({ + mutationFn: ({billId}: WithBillId) => requestDeleteBill({eventId, billId}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return { + deleteBill: mutate, + ...rest, + }; +}; + +export default useRequestDeleteBill; diff --git a/client/src/hooks/queries/bill/useRequestGetBillDetails.ts b/client/src/hooks/queries/bill/useRequestGetBillDetails.ts new file mode 100644 index 000000000..e59b10437 --- /dev/null +++ b/client/src/hooks/queries/bill/useRequestGetBillDetails.ts @@ -0,0 +1,28 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetBillDetails} from '@apis/request/bill'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +type UseRequestGetBillDetails = { + billId: number; +}; + +const useRequestGetBillDetails = ({billId, ...props}: WithErrorHandlingStrategy) => { + const eventId = getEventIdByUrl(); + + const {data, ...rest} = useQuery({ + queryKey: [QUERY_KEYS.billDetails, billId], + queryFn: () => requestGetBillDetails({eventId, billId, ...props}), + }); + + return { + members: data?.members ?? [], + ...rest, + }; +}; + +export default useRequestGetBillDetails; diff --git a/client/src/hooks/queries/bill/useRequestPostBill.ts b/client/src/hooks/queries/bill/useRequestPostBill.ts new file mode 100644 index 000000000..a9c7bce62 --- /dev/null +++ b/client/src/hooks/queries/bill/useRequestPostBill.ts @@ -0,0 +1,27 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestPostBill, requestPostBill} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPostBill = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...rest} = useMutation({ + mutationFn: ({title, price, memberIds}: RequestPostBill) => requestPostBill({eventId, title, price, memberIds}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return { + postBill: mutate, + ...rest, + }; +}; + +export default useRequestPostBill; diff --git a/client/src/hooks/queries/bill/useRequestPutBill.ts b/client/src/hooks/queries/bill/useRequestPutBill.ts new file mode 100644 index 000000000..88a47f6bf --- /dev/null +++ b/client/src/hooks/queries/bill/useRequestPutBill.ts @@ -0,0 +1,26 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestPutBill, requestPutBill} from '@apis/request/bill'; + +import {WithBillId} from '@apis/withId.type'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPutBill = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, mutateAsync, ...rest} = useMutation({ + mutationFn: ({billId, title, price}: WithBillId) => requestPutBill({eventId, billId, title, price}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return {putBill: mutate, putBillAsync: mutateAsync, ...rest}; +}; + +export default useRequestPutBill; diff --git a/client/src/hooks/queries/bill/useRequestPutBillDetails.ts b/client/src/hooks/queries/bill/useRequestPutBillDetails.ts new file mode 100644 index 000000000..9e9bb3e0f --- /dev/null +++ b/client/src/hooks/queries/bill/useRequestPutBillDetails.ts @@ -0,0 +1,48 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestPutBillDetails, requestPutBillDetails} from '@apis/request/bill'; + +import {WithBillId} from '@apis/withId.type'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPutBillDetails = ({billId}: WithBillId) => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...rest} = useMutation({ + mutationFn: ({billId, billDetails}: WithBillId) => + requestPutBillDetails({eventId, billId, billDetails}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.billDetails, billId]}); + }, + // onMutate: async (newMembers: MemberReportInAction[]) => { + // await queryClient.cancelQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); + + // const previousMembers = queryClient.getQueryData([QUERY_KEYS.memberReportInAction, actionId]); + + // queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], (oldData: MemberReportList) => ({ + // ...oldData, + // members: oldData.members.map((member: MemberReportInAction) => { + // const updatedMember = newMembers.find(m => m.name === member.name); + // return updatedMember ? {...member, ...updatedMember} : member; + // }), + // })); + + // return {previousMembers}; + // }, + // onError: (err, newMembers, context) => { + // if (context?.previousMembers) { + // queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], context.previousMembers); + // } + // }, + }); + + return {putBillDetails: mutate, ...rest}; +}; + +export default useRequestPutBillDetails; diff --git a/client/src/hooks/queries/event/useRequestGetEvent.ts b/client/src/hooks/queries/event/useRequestGetEvent.ts new file mode 100644 index 000000000..4ce9cd259 --- /dev/null +++ b/client/src/hooks/queries/event/useRequestGetEvent.ts @@ -0,0 +1,26 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetEvent} from '@apis/request/event'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetEvent = ({...props}: WithErrorHandlingStrategy | null = {}) => { + const eventId = getEventIdByUrl(); + + const {data, ...rest} = useQuery({ + queryKey: [QUERY_KEYS.event], + queryFn: () => requestGetEvent({eventId, ...props}), + }); + + return { + eventName: data?.eventName ?? '', + bankName: data?.bankName ?? '', + accountNumber: data?.accountNumber ?? '', + ...rest, + }; +}; + +export default useRequestGetEvent; diff --git a/client/src/hooks/queries/event/useRequestPatchEvent.ts b/client/src/hooks/queries/event/useRequestPatchEvent.ts new file mode 100644 index 000000000..e09a19c8b --- /dev/null +++ b/client/src/hooks/queries/event/useRequestPatchEvent.ts @@ -0,0 +1,31 @@ +import type {Event} from 'types/serviceType'; + +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestPatchEvent} from '@apis/request/event'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPatchEventOutline = () => { + const eventId = getEventIdByUrl(); + + const queryClient = useQueryClient(); + + const {mutateAsync, ...rest} = useMutation({ + mutationFn: (eventOutline: Partial) => requestPatchEvent({eventId, eventOutline}), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: [QUERY_KEYS.event], + }); + }, + }); + + return { + patchEventOutline: mutateAsync, + ...rest, + }; +}; + +export default useRequestPatchEventOutline; diff --git a/client/src/hooks/queries/event/useRequestPostEvent.ts b/client/src/hooks/queries/event/useRequestPostEvent.ts new file mode 100644 index 000000000..d59f6b913 --- /dev/null +++ b/client/src/hooks/queries/event/useRequestPostEvent.ts @@ -0,0 +1,18 @@ +import {useMutation} from '@tanstack/react-query'; + +import {RequestPostEvent, requestPostEvent} from '@apis/request/event'; + +const useRequestPostEvent = () => { + const {mutate, mutateAsync, ...rest} = useMutation({ + mutationFn: ({eventName, password}: RequestPostEvent) => requestPostEvent({eventName, password}), + }); + + // 실행 순서를 await으로 보장하기 위해 mutateAsync 사용 + return { + postEvent: mutateAsync, + isPostEventPending: rest.isPending, + ...rest, + }; +}; + +export default useRequestPostEvent; diff --git a/client/src/hooks/queries/member/useRequestDeleteMember.ts b/client/src/hooks/queries/member/useRequestDeleteMember.ts new file mode 100644 index 000000000..770218e6b --- /dev/null +++ b/client/src/hooks/queries/member/useRequestDeleteMember.ts @@ -0,0 +1,26 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestDeleteMember, requestDeleteMember} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestDeleteMember = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutateAsync, ...rest} = useMutation({ + mutationFn: ({memberId}: RequestDeleteMember) => requestDeleteMember({eventId, memberId}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMembers]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.billDetails]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return {deleteAsyncMember: mutateAsync, ...rest}; +}; + +export default useRequestDeleteMember; diff --git a/client/src/hooks/queries/member/useRequestGetAllMembers.ts b/client/src/hooks/queries/member/useRequestGetAllMembers.ts new file mode 100644 index 000000000..bd28e5836 --- /dev/null +++ b/client/src/hooks/queries/member/useRequestGetAllMembers.ts @@ -0,0 +1,21 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetAllMembers} from '@apis/request/member'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetAllMembers = ({...props}: WithErrorHandlingStrategy | null = {}) => { + const eventId = getEventIdByUrl(); + + const {data, ...rest} = useQuery({ + queryKey: [QUERY_KEYS.allMembers], + queryFn: () => requestGetAllMembers({eventId, ...props}), + }); + + return {members: data?.members ?? [], ...rest}; +}; + +export default useRequestGetAllMembers; diff --git a/client/src/hooks/queries/member/useRequestGetCurrentMembers.ts b/client/src/hooks/queries/member/useRequestGetCurrentMembers.ts new file mode 100644 index 000000000..536438b36 --- /dev/null +++ b/client/src/hooks/queries/member/useRequestGetCurrentMembers.ts @@ -0,0 +1,21 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetCurrentMembers} from '@apis/request/member'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetCurrentMembers = ({...props}: WithErrorHandlingStrategy | null = {}) => { + const eventId = getEventIdByUrl(); + + const {data, ...rest} = useQuery({ + queryKey: [QUERY_KEYS.currentMembers], + queryFn: () => requestGetCurrentMembers({eventId, ...props}), + }); + + return {currentMembers: data?.members ?? [], ...rest}; +}; + +export default useRequestGetCurrentMembers; diff --git a/client/src/hooks/queries/member/useRequestPostMembers.ts b/client/src/hooks/queries/member/useRequestPostMembers.ts new file mode 100644 index 000000000..bddb9a322 --- /dev/null +++ b/client/src/hooks/queries/member/useRequestPostMembers.ts @@ -0,0 +1,26 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestPostMembers, requestPostMembers} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPostMembers = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, mutateAsync, data, ...rest} = useMutation({ + mutationFn: ({members}: RequestPostMembers) => requestPostMembers({eventId, members}), + onSuccess: responseData => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMembers]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + return responseData; + }, + }); + + return {postMembers: mutate, postMembersAsync: mutateAsync, responseMemberIds: data, ...rest}; +}; + +export default useRequestPostMembers; diff --git a/client/src/hooks/queries/member/useRequestPutMembers.ts b/client/src/hooks/queries/member/useRequestPutMembers.ts new file mode 100644 index 000000000..69df92c4c --- /dev/null +++ b/client/src/hooks/queries/member/useRequestPutMembers.ts @@ -0,0 +1,26 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestPutMembers, requestPutMembers} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPutMembers = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutateAsync, ...rest} = useMutation({ + mutationFn: ({members}: RequestPutMembers) => requestPutMembers({eventId, members}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMembers]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.billDetails]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return {putAsyncMember: mutateAsync, ...rest}; +}; + +export default useRequestPutMembers; diff --git a/client/src/hooks/queries/report/useRequestGetReports.ts b/client/src/hooks/queries/report/useRequestGetReports.ts new file mode 100644 index 000000000..e1a91fc74 --- /dev/null +++ b/client/src/hooks/queries/report/useRequestGetReports.ts @@ -0,0 +1,23 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetReports} from '@apis/request/report'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetReports = ({...props}: WithErrorHandlingStrategy | null = {}) => { + const eventId = getEventIdByUrl(); + + const {data, ...rest} = useQuery({ + queryKey: [QUERY_KEYS.reports], + queryFn: () => requestGetReports({eventId, ...props}), + }); + + return { + reports: data?.reports ?? [], + ...rest, + }; +}; +export default useRequestGetReports; diff --git a/client/src/hooks/queries/useRequestGetStepList.ts b/client/src/hooks/queries/step/useRequestGetSteps.ts similarity index 60% rename from client/src/hooks/queries/useRequestGetStepList.ts rename to client/src/hooks/queries/step/useRequestGetSteps.ts index 7dfc1799c..7b70bacef 100644 --- a/client/src/hooks/queries/useRequestGetStepList.ts +++ b/client/src/hooks/queries/step/useRequestGetSteps.ts @@ -1,7 +1,8 @@ import {useQuery} from '@tanstack/react-query'; import {useEffect} from 'react'; -import {requestGetStepList} from '@apis/request/stepList'; +import {requestGetSteps} from '@apis/request/step'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; @@ -9,13 +10,13 @@ import getEventIdByUrl from '@utils/getEventIdByUrl'; import QUERY_KEYS from '@constants/queryKeys'; -const useRequestGetStepList = () => { +const useRequestGetSteps = ({...props}: WithErrorHandlingStrategy | null = {}) => { const eventId = getEventIdByUrl(); const {updateTotalExpenseAmount} = useTotalExpenseAmountStore(); const queryResult = useQuery({ - queryKey: [QUERY_KEYS.stepList], - queryFn: () => requestGetStepList({eventId}), + queryKey: [QUERY_KEYS.steps], + queryFn: () => requestGetSteps({eventId, ...props}), }); useEffect(() => { @@ -24,7 +25,10 @@ const useRequestGetStepList = () => { } }, [queryResult.data, queryResult.isSuccess, updateTotalExpenseAmount]); - return queryResult; + return { + steps: queryResult.data ?? [], + ...queryResult, + }; }; -export default useRequestGetStepList; +export default useRequestGetSteps; diff --git a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts deleted file mode 100644 index da6fc4223..000000000 --- a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {requestDeleteAllMemberList} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface DeleteAllMemberListMutationProps { - memberName: string; -} - -const useRequestDeleteAllMemberList = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({memberName}: DeleteAllMemberListMutationProps) => requestDeleteAllMemberList({eventId, memberName}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); - queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestDeleteAllMemberList; diff --git a/client/src/hooks/queries/useRequestDeleteBillAction.ts b/client/src/hooks/queries/useRequestDeleteBillAction.ts deleted file mode 100644 index 28be9dfd1..000000000 --- a/client/src/hooks/queries/useRequestDeleteBillAction.ts +++ /dev/null @@ -1,26 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {requestDeleteBillAction} from '@apis/request/bill'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface DeleteBillActionMutationProps { - actionId: number; -} - -const useRequestDeleteBillAction = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({actionId}: DeleteBillActionMutationProps) => requestDeleteBillAction({eventId, actionId}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestDeleteBillAction; diff --git a/client/src/hooks/queries/useRequestDeleteMemberAction.ts b/client/src/hooks/queries/useRequestDeleteMemberAction.ts deleted file mode 100644 index 08e69ac1f..000000000 --- a/client/src/hooks/queries/useRequestDeleteMemberAction.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {requestDeleteMemberAction} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface DeleteMemberActionMutationProps { - actionId: number; -} - -const useRequestDeleteMemberAction = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({actionId}: DeleteMemberActionMutationProps) => requestDeleteMemberAction({eventId, actionId}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); - }, - }); -}; - -export default useRequestDeleteMemberAction; diff --git a/client/src/hooks/queries/useRequestGetAllMemberList.ts b/client/src/hooks/queries/useRequestGetAllMemberList.ts deleted file mode 100644 index 531285fd6..000000000 --- a/client/src/hooks/queries/useRequestGetAllMemberList.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {useQuery} from '@tanstack/react-query'; - -import {requestGetAllMemberList} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestGetAllMemberList = () => { - const eventId = getEventIdByUrl(); - - return useQuery({ - queryKey: [QUERY_KEYS.allMemberList], - queryFn: () => requestGetAllMemberList({eventId}), - }); -}; - -export default useRequestGetAllMemberList; diff --git a/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts b/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts deleted file mode 100644 index 31dc058c2..000000000 --- a/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {useQuery} from '@tanstack/react-query'; - -import {requestGetCurrentInMemberList} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestGetCurrentInMemberList = () => { - const eventId = getEventIdByUrl(); - - return useQuery({ - queryKey: [QUERY_KEYS.currentInMember], - queryFn: () => requestGetCurrentInMemberList({eventId}), - }); -}; - -export default useRequestGetCurrentInMemberList; diff --git a/client/src/hooks/queries/useRequestGetEventName.ts b/client/src/hooks/queries/useRequestGetEventName.ts deleted file mode 100644 index 6ddb21858..000000000 --- a/client/src/hooks/queries/useRequestGetEventName.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {useQuery} from '@tanstack/react-query'; - -import {requestGetEventName} from '@apis/request/event'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestGetEventName = () => { - const eventId = getEventIdByUrl(); - - return useQuery({ - queryKey: [QUERY_KEYS.eventName], - queryFn: () => requestGetEventName({eventId}), - }); -}; - -export default useRequestGetEventName; diff --git a/client/src/hooks/queries/useRequestGetMemberReportList.ts b/client/src/hooks/queries/useRequestGetMemberReportList.ts deleted file mode 100644 index fe3372d35..000000000 --- a/client/src/hooks/queries/useRequestGetMemberReportList.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {useQuery} from '@tanstack/react-query'; - -import {requestGetMemberReportList} from '@apis/request/report'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestGetMemberReportList = () => { - const eventId = getEventIdByUrl(); - - return useQuery({ - queryKey: [QUERY_KEYS.memberReport], - queryFn: () => requestGetMemberReportList({eventId}), - }); -}; -export default useRequestGetMemberReportList; diff --git a/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts b/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts deleted file mode 100644 index 85b458228..000000000 --- a/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {useQuery} from '@tanstack/react-query'; - -import {requestGetMemberReportListInAction} from '@apis/request/bill'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestGetMemberReportListInAction = (actionId: number) => { - const eventId = getEventIdByUrl(); - - const {data, ...queryResult} = useQuery({ - queryKey: [QUERY_KEYS.memberReportInAction, actionId], - queryFn: () => requestGetMemberReportListInAction({eventId, actionId}), - select: data => data.members, - }); - - return { - memberReportListInActionFromServer: data ?? [], - queryResult, - }; -}; - -export default useRequestGetMemberReportListInAction; diff --git a/client/src/hooks/queries/useRequestPostBillList.ts b/client/src/hooks/queries/useRequestPostBillList.ts deleted file mode 100644 index 676da9d85..000000000 --- a/client/src/hooks/queries/useRequestPostBillList.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {requestPostBillList} from '@apis/request/bill'; -import {Bill} from 'types/serviceType'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface PostBillActionMutationProps { - billList: Bill[]; -} - -const useRequestPostBillList = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({billList}: PostBillActionMutationProps) => requestPostBillList({eventId, billList}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestPostBillList; diff --git a/client/src/hooks/queries/useRequestPostEvent.ts b/client/src/hooks/queries/useRequestPostEvent.ts deleted file mode 100644 index 5327710fc..000000000 --- a/client/src/hooks/queries/useRequestPostEvent.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {useMutation} from '@tanstack/react-query'; - -import {requestPostNewEvent} from '@apis/request/event'; - -interface PostEventMutationProps { - eventName: string; - password: number; -} - -const usePostEvent = () => { - return useMutation({ - mutationFn: ({eventName, password}: PostEventMutationProps) => requestPostNewEvent({eventName, password}), - }); -}; - -export default usePostEvent; diff --git a/client/src/hooks/queries/useRequestPostMemberList.ts b/client/src/hooks/queries/useRequestPostMemberList.ts deleted file mode 100644 index 8ed69db08..000000000 --- a/client/src/hooks/queries/useRequestPostMemberList.ts +++ /dev/null @@ -1,37 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {MemberType} from 'types/serviceType'; -import {requestPostMemberList} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface PostMemberListMutationProps { - type: MemberType; - memberNameList: string[]; -} - -const useRequestPostMemberList = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({type, memberNameList}: PostMemberListMutationProps) => - requestPostMemberList({eventId, type, memberNameList}), - // TODO: (@todari) : 낙관적 업데이트 적고 있었어용 - // onMutate: async ({type, memberNameList}) => { - // await queryClient.cancelQueries({queryKey: [QUERY_KEYS.stepList]}); - // const previousStepList = queryClient.getQueryData([QUERY_KEYS.stepList]); - // queryClient.setQueryData([QUERY_KEYS.stepList], (prev: (MemberStep | BillStep)[]) => prev && { - // }); - // }, - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestPostMemberList; diff --git a/client/src/hooks/queries/useRequestPutAllMemberList.ts b/client/src/hooks/queries/useRequestPutAllMemberList.ts deleted file mode 100644 index 4bd746d0c..000000000 --- a/client/src/hooks/queries/useRequestPutAllMemberList.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {MemberChange, requestPutAllMemberList} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface PutAllMemberListMutationProps { - members: MemberChange[]; -} - -const useRequestPutAllMemberList = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({members}: PutAllMemberListMutationProps) => requestPutAllMemberList({eventId, members}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); - queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestPutAllMemberList; diff --git a/client/src/hooks/queries/useRequestPutBillAction.ts b/client/src/hooks/queries/useRequestPutBillAction.ts deleted file mode 100644 index a58da8ea4..000000000 --- a/client/src/hooks/queries/useRequestPutBillAction.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {requestPutBillAction} from '@apis/request/bill'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface PutBillActionMutationProps { - actionId: number; - title: string; - price: number; -} - -const useRequestPutBillAction = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({actionId, title, price}: PutBillActionMutationProps) => - requestPutBillAction({eventId, actionId, title, price}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestPutBillAction; diff --git a/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts b/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts deleted file mode 100644 index a87fa44f1..000000000 --- a/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts +++ /dev/null @@ -1,49 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {MemberReportList, requestPutMemberReportListInAction} from '@apis/request/bill'; -import {MemberReportInAction} from 'types/serviceType'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestPutMemberReportListInAction = (actionId: number) => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - const {mutate, ...mutationProps} = useMutation({ - mutationFn: (members: MemberReportInAction[]) => requestPutMemberReportListInAction({eventId, actionId, members}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); - }, - onMutate: async (newMembers: MemberReportInAction[]) => { - await queryClient.cancelQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); - - const previousMembers = queryClient.getQueryData([QUERY_KEYS.memberReportInAction, actionId]); - - queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], (oldData: MemberReportList) => ({ - ...oldData, - members: oldData.members.map((member: MemberReportInAction) => { - const updatedMember = newMembers.find(m => m.name === member.name); - return updatedMember ? {...member, ...updatedMember} : member; - }), - })); - - return {previousMembers}; - }, - onError: (err, newMembers, context) => { - if (context?.previousMembers) { - queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], context.previousMembers); - } - }, - }); - - return { - putMemberReportListInAction: mutate, - mutationProps, - }; -}; - -export default useRequestPutMemberReportListInAction; diff --git a/client/src/hooks/useAccount.ts b/client/src/hooks/useAccount.ts new file mode 100644 index 000000000..418656cc5 --- /dev/null +++ b/client/src/hooks/useAccount.ts @@ -0,0 +1,97 @@ +import type {Event} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import validateAccountNumber from '@utils/validate/validateAccountNumber'; + +import RULE from '@constants/rule'; + +import useRequestPatchEvent from './queries/event/useRequestPatchEvent'; +import useRequestGetEvent from './queries/event/useRequestGetEvent'; + +const useAccount = () => { + const {bankName, accountNumber} = useRequestGetEvent(); + const [bankNameState, setBankName] = useState(bankName); + const [accountNumberState, setAccountNumber] = useState(accountNumber); + const [accountNumberErrorMessage, setAccountNumberErrorMessage] = useState(null); + const [canSubmit, setCanSubmit] = useState(false); + const [isPasting, setIsPasting] = useState(false); + + useEffect(() => { + setBankName(bankName); + setAccountNumber(accountNumber); + }, [bankName, accountNumber]); + + const {patchEventOutline} = useRequestPatchEvent(); + + const selectBank = (name: string) => { + setBankName(name); + }; + + const handleAccount = (event: React.ChangeEvent) => { + if (isPasting) return; + + const newValue = event.target.value; + const {isValid, errorMessage} = validateAccountNumber(newValue); + setAccountNumberErrorMessage(errorMessage); + + const isValidMinLength = newValue.length >= RULE.minAccountNumberLength; + + if (isValid) { + setAccountNumber(event.target.value); + } else if (!isValid && !isValidMinLength) { + setAccountNumber(event.target.value.replace(/[^0-9\s\-]/g, '').trim()); + } + }; + + const handleAccountOnPaste = (event: React.ClipboardEvent) => { + setIsPasting(true); + + const value = `${accountNumberState}${event.clipboardData.getData('text')}`; + const newValue = value.replace(/[^0-9\s\-]/g, '').trim(); + const {isValid, errorMessage} = validateAccountNumber(newValue); + + setAccountNumberErrorMessage(errorMessage); + if (isValid) setAccountNumber(newValue); + + setTimeout(() => setIsPasting(false), 0); + }; + + const getChangedField = () => { + const changedField: Partial = {}; + + if (bankNameState.trim() !== '' && bankName !== bankNameState) { + changedField.bankName = bankNameState; + } + + if (accountNumberState.trim() !== '' && accountNumber !== accountNumberState) { + changedField.accountNumber = accountNumberState; + } + + return changedField; + }; + + const enrollAccount = async () => { + await patchEventOutline(getChangedField()); + }; + + useEffect(() => { + const existEmptyField = bankNameState.trim() === '' || accountNumberState.trim() === ''; + const isChanged = bankName !== bankNameState || accountNumber !== accountNumberState; + + setCanSubmit(!existEmptyField && isChanged && accountNumberErrorMessage === null); + }, [bankName, accountNumber, bankNameState, accountNumberState, accountNumberErrorMessage]); + + return { + bankName: bankNameState, + accountNumber: accountNumberState, + accountNumberErrorMessage, + canSubmit, + selectBank, + handleAccount, + handleAccountOnPaste, + enrollAccount, + }; +}; + +export default useAccount; diff --git a/client/src/hooks/useAddBillFunnel.ts b/client/src/hooks/useAddBillFunnel.ts new file mode 100644 index 000000000..f0b1e87e8 --- /dev/null +++ b/client/src/hooks/useAddBillFunnel.ts @@ -0,0 +1,33 @@ +import {useEffect, useState} from 'react'; + +import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; + +import useRequestGetCurrentMembers from './queries/member/useRequestGetCurrentMembers'; + +export type BillStep = 'title' | 'price' | 'members'; + +const useAddBillFunnel = () => { + const {currentMembers} = useRequestGetCurrentMembers(); + const [step, setStep] = useState('price'); + const [billInfo, setBillInfo] = useState({ + price: '', + title: '', + members: [], + }); + + useEffect(() => { + document.body.style.overflow = 'hidden'; + + return () => { + document.body.style.overflow = 'auto'; + }; + }, []); + + useEffect(() => { + currentMembers && setBillInfo(prev => ({...prev, members: currentMembers})); + }, [currentMembers]); + + return {step, setStep, billInfo, setBillInfo, currentMembers}; +}; + +export default useAddBillFunnel; diff --git a/client/src/hooks/useCreateEventData.tsx b/client/src/hooks/useCreateEventData.tsx new file mode 100644 index 000000000..fed21d8ae --- /dev/null +++ b/client/src/hooks/useCreateEventData.tsx @@ -0,0 +1,17 @@ +import {useState} from 'react'; + +import useSetEventNameStep from './useSetEventNameStep'; + +// 행사 생성 페이지에서 여러 스텝에 걸쳐 사용되는 상태를 선언해 내려주는 용도의 훅입니다. +const useCreateEventData = () => { + const eventNameProps = useSetEventNameStep(); + const [eventToken, setEventToken] = useState(''); + + return { + eventNameProps, + eventToken, + setEventToken, + }; +}; + +export default useCreateEventData; diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx deleted file mode 100644 index 38836f677..000000000 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import {renderHook, waitFor} from '@testing-library/react'; -import {MemoryRouter} from 'react-router-dom'; -import {act} from 'react'; -import {HDesignProvider} from 'haengdong-design'; - -import {BillStep, MemberAction, MemberStep} from 'types/serviceType'; -import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; -import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; -import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; -import {ToastProvider} from '@hooks/useToast/ToastProvider'; - -import stepListJson from '@mocks/stepList.json'; -import invalidMemberStepListJson from '@mocks/invalidMemberStepList.json'; - -import useDeleteMemberAction from './useDeleteMemberAction'; - -const stepListMockData = stepListJson as (BillStep | MemberStep)[]; -let memberActionList: MemberAction[] = []; - -// filter로는 type narrowing이 안되어 부득이하게 for 문을 사용했습니다. -for (let i = 0; i < stepListMockData.length; i++) { - const curAction = stepListMockData[i]; - if (curAction.type !== 'BILL') curAction.actions.forEach(action => memberActionList.push(action)); -} - -describe('useDeleteMemberAction', () => { - const initializeProvider = (list: MemberAction[] = memberActionList) => - renderHook( - () => { - return { - stepListResult: useRequestGetStepList(), - deleteMemberActionList: useDeleteMemberAction({ - memberActionList: list, - setIsBottomSheetOpened: () => {}, - showToastAlreadyExistMemberAction: () => {}, - showToastExistSameMemberFromAfterStep: () => {}, - }), - }; - }, - { - wrapper: ({children}) => ( - - - - - {children} - - - - - ), - }, - ); - - it('멤버를 삭제할 멤버 목록에 추가한다.', async () => { - const {result} = initializeProvider(); - - // stepList 값이 채워지길 대기합니다. - await waitFor(() => { - expect(result.current.stepListResult.data).not.toStrictEqual([]); - }); - - act(() => { - const memberAction = { - actionId: 1, - name: '망쵸', - price: null, - sequence: 1, - isFixed: false, - }; - - result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); - }); - - expect(result.current.deleteMemberActionList.aliveActionList).not.toContainEqual({ - actionId: 1, - name: '망쵸', - price: null, - sequence: 1, - }); - }); - - it('삭제할 멤버 목록에 있는 멤버들을 모두 삭제해 삭제할 멤버 목록을 비운다.', async () => { - const {result} = initializeProvider(); - - // stepList 값이 채워지길 대기합니다. - await waitFor(() => { - expect(result.current.stepListResult.data).not.toStrictEqual([]); - }); - - await act(async () => { - memberActionList.forEach(memberAction => { - result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); - }); - }); - - await act(async () => result.current.deleteMemberActionList.deleteMemberActionList()); - - await waitFor(() => { - expect(result.current.deleteMemberActionList.aliveActionList).toHaveLength(0); - }); - }); - - it('삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 처음의 상태로 돌려놓는다.', async () => { - /** - * 이 테스트는 deleteMemberAction을 실행했을 때 오류가 나는 경우를 테스트하기 위해 작성되었습니다. - * 여기서 사용하는 stepList 목데이터는 999 actionId를 가진 MemberAction이 있는 데이터입니다. - * 999 actionId는 현재 모킹되어있는 msw에서 오류를 뱉도록 하는 id입니다. 이는 오류 상황을 시연하기 위한 임의 모킹입니다. - * (999가 아닌 경우는 모두 정상 응답 반환) - */ - - // 999 actionId를 가진 MemberAction이 있는 stepListJson 데이터를 사용해 MemberActions []으로 정제합니다. - const invalidMemberStepListMockData = invalidMemberStepListJson as (BillStep | MemberStep)[]; - let memberActionList: MemberAction[] = []; - - for (let i = 0; i < invalidMemberStepListMockData.length; i++) { - const curAction = invalidMemberStepListMockData[i]; - if (curAction.type !== 'BILL') curAction.actions.forEach(action => memberActionList.push(action)); - } - - // 오류 멤버가 포함된 memberAction[]을 useDeleteMemberAction의 초기값으로 주입합니다. - const {result} = initializeProvider(memberActionList); - - // stepList 값이 채워지길 대기합니다. - await waitFor(() => { - expect(result.current.stepListResult.data).not.toStrictEqual([]); - }); - - await act(async () => { - const memberAction = memberActionList[0]; // 현재 0번 참여자는 actionId가 999 이고, 999 actionId는 서버에서 에러를 뱉도록 조작된 상황입니다. - result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); - }); - - await act(async () => result.current.deleteMemberActionList.deleteMemberActionList()); - - // 삭제 요청에서 오류가 발생했기 때문에 aliveActionList를 초기에 주입했던 값으로 다시 돌려놓는지 확인합니다. - expect(result.current.deleteMemberActionList.aliveActionList).toStrictEqual(memberActionList); - }); -}); diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx deleted file mode 100644 index 913087a59..000000000 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import type {MemberAction} from 'types/serviceType'; - -import {useState} from 'react'; - -import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; -import useRequestDeleteMemberAction from '@hooks/queries/useRequestDeleteMemberAction'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -type UseDeleteMemberActionProps = { - memberActionList: MemberAction[]; - setIsBottomSheetOpened: React.Dispatch>; - showToastAlreadyExistMemberAction: () => void; - showToastExistSameMemberFromAfterStep: (name: string) => void; -}; - -const useDeleteMemberAction = ({ - memberActionList, - setIsBottomSheetOpened, - showToastAlreadyExistMemberAction, - showToastExistSameMemberFromAfterStep, -}: UseDeleteMemberActionProps) => { - const {data: stepListData} = useRequestGetStepList(); - const stepList = stepListData ?? []; - const {mutate: deleteMemberActionMutate} = useRequestDeleteMemberAction(); - - const [deleteActionList, setDeleteActionList] = useState([]); - - const eventId = getEventIdByUrl(); - - const deleteMemberAction = async (actionId: number) => { - deleteMemberActionMutate( - {actionId}, - { - onError: () => { - setDeleteActionList([]); - }, - }, - ); - setIsBottomSheetOpened(false); - }; - - // TODO: (@cookie: 추후에 반복문으로 delete하는 것이 아니라 한 번에 모아서 delete 처리하기 (backend에 문의)) - const deleteMemberActionList = async () => { - for (const {actionId} of deleteActionList) { - await deleteMemberAction(actionId); - } - }; - - const checkAlreadyExistMemberAction = (memberAction: MemberAction, showToast: () => void) => { - if (!memberActionList.includes(memberAction)) { - showToast(); - } - }; - - const checkExistSameMemberFromAfterStep = (memberAction: MemberAction, showToast: () => void) => { - if (isExistSameMemberFromAfterStep(memberAction)) { - showToast(); - } - }; - - const addDeleteMemberAction = (memberAction: MemberAction) => { - checkAlreadyExistMemberAction(memberAction, showToastAlreadyExistMemberAction); - checkExistSameMemberFromAfterStep(memberAction, () => showToastExistSameMemberFromAfterStep(memberAction.name)); - setDeleteActionList(prev => [...prev, memberAction]); - }; - - const isExistSameMemberFromAfterStep = (memberAction: MemberAction) => { - const memberActionList = stepList - .filter(step => step.type !== 'BILL') - .map(({actions}) => actions) - .flat(); - const currentActionIndex = memberActionList.findIndex(action => action.actionId === memberAction.actionId); - const memberActionListAfterCurrentAction = memberActionList.slice(Math.max(currentActionIndex - 1, 0)); - const memberNameList = memberActionListAfterCurrentAction.map(({name}) => name); - - return memberNameList.filter(member => member === memberAction.name).length >= 2; - }; - - const aliveActionList = memberActionList.filter( - memberAction => !deleteActionList.some(deleteAction => deleteAction.actionId === memberAction.actionId), - ); - return {aliveActionList, deleteMemberActionList, addDeleteMemberAction}; -}; - -export default useDeleteMemberAction; diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx deleted file mode 100644 index 452add193..000000000 --- a/client/src/hooks/useDynamicInput.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import {useEffect, useRef} from 'react'; - -import {ValidateResult} from '@utils/validate/type'; - -import useInput from './useInput'; - -type InputValue = { - value: string; - index: number; -}; - -export type ReturnUseDynamicInput = { - inputList: InputValue[]; - inputRefList: React.MutableRefObject<(HTMLInputElement | null)[]>; - errorMessage: string | null; - canSubmit: boolean; - errorIndexList: number[]; - handleChange: (index: number, value: string) => void; - handleInputChange: (index: number, event: React.ChangeEvent) => void; - deleteEmptyInputElementOnBlur: () => void; - getFilledInputList: (list?: InputValue[]) => InputValue[]; - focusNextInputOnEnter: (e: React.KeyboardEvent, index: number) => void; - setInputValueTargetIndex: (index: number, value: string) => void; - resetInputValue: () => void; -}; - -const useDynamicInput = (validateFunc: (name: string) => ValidateResult): ReturnUseDynamicInput => { - const initialInputList = [{index: 0, value: ''}]; - const inputRefList = useRef<(HTMLInputElement | null)[]>([]); - - const {inputList, errorMessage, errorIndexList, canSubmit, handleChange, setInputList} = useInput({ - validateFunc, - initialInputList, - }); - - useEffect(() => { - if (inputRefList.current.length <= 0) return; - - const lastInput = inputRefList.current[inputRefList.current.length - 1]; - - if (lastInput) { - lastInput.scrollIntoView({behavior: 'smooth', block: 'center'}); - } - }, [inputList]); - - const handleInputChange = (index: number, event: React.ChangeEvent) => { - const {value} = event.target; - - makeNewInputWhenFirstCharacterInput(index, value); - handleChange(index, value); - }; - - const makeNewInputWhenFirstCharacterInput = (index: number, value: string) => { - if (isLastInputFilled(index, value) && value.trim().length !== 0) { - // 마지막 인풋이 한 자라도 채워진다면 새로운 인풋을 생성해 간편한 다음 입력을 유도합니다. - setInputList(prevInputs => { - const updatedInputList = [...prevInputs]; - - // 새로운 인덱스를 inputs 배열 길이를 기준으로 설정 - const newIndex = updatedInputList[updatedInputList.length - 1].index + 1; - - return [...updatedInputList, {index: newIndex, value: ''}]; - }); - } - }; - - const deleteEmptyInputElementOnBlur = () => { - // 0, 1번 input이 값이 있는 상태에서 두 input의 값을 모두 x버튼으로 제거해도 input이 2개 남아있는 문제를 위해 조건문을 추가했습니다. - if (getFilledInputList().length === 0 && inputList.length > 1) { - setInputList([{index: 0, value: ''}]); - return; - } - - // *표시 조건문은 처음에 input을 클릭했다가 블러시켰을 때 filledInputList가 아예 없어 .index에 접근할 때 오류가 납니다. 이를 위한 얼리리턴을 두었습니다. - if (getFilledInputList().length === 0) return; - - if (getFilledInputList().length !== inputList.length) { - setInputList(inputList => { - const filledInputList = getFilledInputList(inputList); - - // 새 입력의 인덱스를 inputs 길이를 기준으로 설정 - const newIndex = filledInputList[filledInputList.length - 1].index + 1; - - return [...filledInputList, {index: newIndex, value: ''}]; - }); - } - }; - - const setInputValueTargetIndex = (index: number, value: string) => { - setInputList(prevInputs => { - const updatedInputList = [...prevInputs]; - const targetInput = findInputByIndex(index, updatedInputList); - - targetInput.value = value; - - return updatedInputList; - }); - }; - - const resetInputValue = () => { - setInputList(initialInputList); - }; - - const focusNextInputOnEnter = (e: React.KeyboardEvent, index: number) => { - if (e.nativeEvent.isComposing) return; - - if (e.key === 'Enter') { - inputRefList.current[index + 1]?.focus(); - } - }; - - const findInputByIndex = (index: number, list?: InputValue[]) => { - return (list ?? inputList).filter(input => input.index === index)[0]; - }; - - const getFilledInputList = (list?: InputValue[]) => { - return (list ?? inputList).filter(({value}) => value.trim().length !== 0); - }; - - const isLastInputFilled = (index: number, value: string) => { - const lastInputIndex = inputList[inputList.length - 1].index; - - return value !== '' && index === lastInputIndex; - }; - - return { - inputList, - inputRefList, - errorMessage, - canSubmit, - errorIndexList, - handleInputChange, - handleChange, - deleteEmptyInputElementOnBlur, - getFilledInputList, - focusNextInputOnEnter, - setInputValueTargetIndex, - resetInputValue, - }; -}; - -export default useDynamicInput; diff --git a/client/src/hooks/useEditBillActions.ts b/client/src/hooks/useEditBillActions.ts new file mode 100644 index 000000000..2b8ba9418 --- /dev/null +++ b/client/src/hooks/useEditBillActions.ts @@ -0,0 +1,78 @@ +import {useNavigate} from 'react-router-dom'; +import {useEffect} from 'react'; + +import {Bill, BillDetail} from 'types/serviceType'; +import {RequestPutBill} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import useRequestPutBill from './queries/bill/useRequestPutBill'; +import useRequestDeleteBill from './queries/bill/useRequestDeleteBill'; +import useRequestPutBillDetails from './queries/bill/useRequestPutBillDetails'; + +interface Props { + bill: Bill; + billDetails: BillDetail[]; + newBill: RequestPutBill; + newBillDetails: BillDetail[]; +} + +const useEditBillActions = ({bill, billDetails, newBill, newBillDetails}: Props) => { + const navigate = useNavigate(); + const eventId = getEventIdByUrl(); + + const {putBillAsync, isSuccess: isSuccessPutBill, isPending: isPendingPutBill} = useRequestPutBill(); + const {deleteBill, isSuccess: isSuccessDeleteBill} = useRequestDeleteBill(); + const { + putBillDetails, + isSuccess: isSusseccPutBillDetails, + isPending: isPendingPutBillDetails, + } = useRequestPutBillDetails({billId: bill.id}); + + const handleClickDelete = () => { + deleteBill({billId: bill.id}); + }; + + const isBillChanged = bill.title !== newBill.title || bill.price !== newBill.price; + const isBillDetailsChanged = JSON.stringify(billDetails) !== JSON.stringify(newBillDetails); + const canSubmit = newBill.price !== 0 && (isBillChanged || isBillDetailsChanged); + + const handleClickUpdate = async () => { + if (isBillChanged) { + await putBillAsync({billId: bill.id, price: newBill.price, title: newBill.title}); + } + if (isBillDetailsChanged) { + putBillDetails({ + billId: bill.id, + billDetails: newBillDetails.map(({id, price, isFixed}) => ({ + id, + price, + isFixed, + })), + }); + } + }; + + useEffect(() => { + if (isSuccessDeleteBill || isSusseccPutBillDetails || (isSuccessPutBill && !isBillDetailsChanged)) { + navigate(`/event/${eventId}/admin`); + } + }, [isSuccessDeleteBill, isSusseccPutBillDetails, isSuccessPutBill, isBillDetailsChanged]); + + const isPendingUpdate = () => { + if (!isBillChanged) { + return isPendingPutBill; + } + + return isPendingPutBill || isPendingPutBillDetails; + }; + + return { + handleClickDelete, + handleClickUpdate, + isPendingUpdate, + canSubmit, + }; +}; + +export default useEditBillActions; diff --git a/client/src/hooks/useEditBillKeyboardAction.ts b/client/src/hooks/useEditBillKeyboardAction.ts new file mode 100644 index 000000000..df971c5a8 --- /dev/null +++ b/client/src/hooks/useEditBillKeyboardAction.ts @@ -0,0 +1,45 @@ +import {useRef, useState} from 'react'; + +import {BillDetail} from 'types/serviceType'; +import {RequestPutBill} from '@apis/request/bill'; + +import RULE from '@constants/rule'; + +import useEditBillPageScroll from './useEditBillPageScroll'; + +interface Props { + billDetails: BillDetail[]; + newBill: RequestPutBill; + newBillDetails: BillDetail[]; +} + +const useEditBillKeyboardAction = ({newBill, billDetails, newBillDetails}: Props) => { + const [keyboardTargetId, setKeyboardTargetId] = useState(null); + const billDetailsRef = useRef(null); + const {handleScrollToFocus} = useEditBillPageScroll(); + + const handleClickBillDetailInput = (id: number) => { + setKeyboardTargetId(id); + handleScrollToFocus({id, billDetailsRef}); + }; + + const totalFixedPrice = newBillDetails.reduce( + (sum, detail) => (detail.isFixed && detail.id !== keyboardTargetId ? sum + detail.price : sum), + 0, + ); + const keyboardMaxPrice = keyboardTargetId === 0 ? RULE.maxPrice : Math.max(0, newBill.price - totalFixedPrice); + const keyboardInitialValue = + newBillDetails.find(({id}) => id === keyboardTargetId)?.price.toLocaleString('ko-kr') ?? + newBill.price.toLocaleString('ko-kr'); + + return { + handleClickBillDetailInput, + billDetailsRef, + keyboardMaxPrice, + keyboardInitialValue, + keyboardTargetId, + setKeyboardTargetId, + }; +}; + +export default useEditBillKeyboardAction; diff --git a/client/src/hooks/useEditBillPage.ts b/client/src/hooks/useEditBillPage.ts new file mode 100644 index 000000000..96d9bf25e --- /dev/null +++ b/client/src/hooks/useEditBillPage.ts @@ -0,0 +1,53 @@ +import {useLocation} from 'react-router-dom'; + +import {Bill} from 'types/serviceType'; + +import useRequestGetBillDetails from './queries/bill/useRequestGetBillDetails'; +import useEditBillActions from './useEditBillActions'; +import useEditBillKeyboardAction from './useEditBillKeyboardAction'; +import useEditBillState from './useEditBillState'; + +const useEditBillPage = () => { + const location = useLocation(); + + const bill: Bill = location.state.bill; + const {members: billDetails} = useRequestGetBillDetails({billId: bill.id}); + + const {newBill, newBillDetails, handleChangeBillPrice, handleChangeBillTitle, handleChangeBillDetails} = + useEditBillState({bill, billDetails}); + const {handleClickDelete, handleClickUpdate, isPendingUpdate, canSubmit} = useEditBillActions({ + bill, + billDetails, + newBill, + newBillDetails, + }); + + const { + keyboardTargetId, + setKeyboardTargetId, + keyboardMaxPrice, + keyboardInitialValue, + billDetailsRef, + handleClickBillDetailInput, + } = useEditBillKeyboardAction({newBill, newBillDetails, billDetails}); + + return { + newBill, + newBillDetails, + billDetailsRef, + handleChangeBillTitle, + handleChangeBillPrice, + handleChangeBillDetails, + handleClickBillDetailInput, + handleClickDelete, + handleClickUpdate, + isPendingUpdate, + canSubmit, + keyboardInitialValue, + keyboardMaxPrice, + keyboardTargetId, + setKeyboardTargetId, + }; +}; + +export default useEditBillPage; diff --git a/client/src/hooks/useEditBillPageScroll.ts b/client/src/hooks/useEditBillPageScroll.ts new file mode 100644 index 000000000..c2bf905ea --- /dev/null +++ b/client/src/hooks/useEditBillPageScroll.ts @@ -0,0 +1,35 @@ +import {useCallback} from 'react'; + +interface Props { + id: number; + billDetailsRef: React.RefObject; +} + +const useEditBillPageScroll = () => { + const handleScrollToFocus = useCallback(({id, billDetailsRef}: Props) => { + setTimeout(() => { + if (billDetailsRef.current) { + const selectedItem = billDetailsRef.current.querySelector(`[data-id="${id}"]`) as HTMLElement; + if (selectedItem) { + const screenHeight = window.screen.height; + const keyboardHeight = 416; + const itemTop = selectedItem.offsetTop; + const itemHeight = selectedItem.offsetHeight; + const itemBottom = itemTop + itemHeight; + const visibleY = screenHeight - keyboardHeight; + + const targetScrollTop = itemBottom < visibleY ? 0 : itemTop - (visibleY - itemHeight) / 2; + + window.scrollTo({ + top: targetScrollTop, + behavior: 'smooth', + }); + } + } + }, 100); + }, []); + + return {handleScrollToFocus}; +}; + +export default useEditBillPageScroll; diff --git a/client/src/hooks/useEditBillState.ts b/client/src/hooks/useEditBillState.ts new file mode 100644 index 000000000..cc7a079a7 --- /dev/null +++ b/client/src/hooks/useEditBillState.ts @@ -0,0 +1,95 @@ +import {useEffect, useState} from 'react'; + +import {RequestPutBill} from '@apis/request/bill'; +import {Bill, BillDetail} from 'types/serviceType'; + +import REGEXP from '@constants/regExp'; + +interface Props { + bill: Bill; + billDetails: BillDetail[]; +} + +interface HandleChangeBillDetailsProps { + value: string; + keyboardTargetId: number; +} + +const useEditBillState = ({bill, billDetails}: Props) => { + const [newBill, setNewBill] = useState({ + title: bill.title, + price: bill.price, + }); + const [newBillDetails, setNewBillDetails] = useState(billDetails); + + useEffect(() => { + if (billDetails) setNewBillDetails(billDetails); + }, [billDetails]); + + const onTitleInputChange = (value: string) => { + if (REGEXP.billTitle.test(value)) { + setNewBill(prev => ({...prev, title: value})); + } + }; + + const handleChangeBillTitle = (event: React.ChangeEvent) => { + if (event.target.value.length > 12) { + onTitleInputChange(newBill.title.slice(0, 12)); + } else { + onTitleInputChange(event.target.value); + } + }; + + const handleChangeBillPrice = (value: string) => { + if (value === newBill.price.toLocaleString('ko-kr')) return; + + const newPrice = Number(value.replace(/,/g, '')); + setNewBill(prev => ({...prev, price: newPrice})); + + const detailCount = newBillDetails.length; + const basePrice = Math.floor(newPrice / detailCount); + const remainder = newPrice % detailCount; + + setNewBillDetails(prev => + prev.map((detail, index) => ({ + ...detail, + price: index === detailCount - 1 ? basePrice + remainder : basePrice, + isFixed: false, + })), + ); + }; + + const isLastUnfixedMember = (keyboardTargetId: number) => + !newBillDetails.find(({id}) => id === keyboardTargetId)?.isFixed && + newBillDetails.filter(({isFixed}) => isFixed === false).length === 1; + + const handleChangeBillDetails = ({value, keyboardTargetId}: HandleChangeBillDetailsProps) => { + if (isLastUnfixedMember(keyboardTargetId)) return; + if (Number(value.replace(/,/g, '')) === newBillDetails.find(({id}) => id === keyboardTargetId)?.price) return; + setNewBillDetails(prev => { + const updatedDetails = prev.map(detail => + detail.id === keyboardTargetId ? {...detail, price: Number(value.replace(/,/g, '')), isFixed: true} : detail, + ); + + const totalFixedPrice = updatedDetails.reduce((sum, detail) => (detail.isFixed ? sum + detail.price : sum), 0); + + const remainingPrice = newBill.price - totalFixedPrice; + const unfixedCount = updatedDetails.filter(detail => !detail.isFixed).length; + + const unfixedPrice = Math.floor(remainingPrice / unfixedCount); + const lastUnfixedIndex = updatedDetails.map(detail => !detail.isFixed).lastIndexOf(true); + + return updatedDetails.map((detail, index) => { + if (detail.isFixed) return detail; + if (index === lastUnfixedIndex) { + return {...detail, price: remainingPrice - unfixedPrice * (unfixedCount - 1)}; + } + return {...detail, price: unfixedPrice}; + }); + }); + }; + + return {newBill, newBillDetails, handleChangeBillPrice, handleChangeBillTitle, handleChangeBillDetails}; +}; + +export default useEditBillState; diff --git a/client/src/hooks/useEventLogin.ts b/client/src/hooks/useEventLogin.ts index ccabe20c1..15d9b2676 100644 --- a/client/src/hooks/useEventLogin.ts +++ b/client/src/hooks/useEventLogin.ts @@ -4,18 +4,18 @@ import validateEventPassword from '@utils/validate/validateEventPassword'; import RULE from '@constants/rule'; -import useRequestPostLogin from './queries/useRequestPostLogin'; +import useRequestPostLogin from './queries/auth/useRequestPostLogin'; const useEventLogin = () => { - const [password, setPassword] = useState(''); + const [password, setPassword] = useState(''); const [errorMessage, setErrorMessage] = useState(null); const [canSubmit, setCanSubmit] = useState(false); - const {mutate: postLogin} = useRequestPostLogin(); + const {postLogin} = useRequestPostLogin(); const submitPassword = async (event: React.FormEvent) => { event.preventDefault(); - postLogin({password}, {onError: () => setErrorMessage('비밀번호가 틀렸어요')}); + postLogin({password: String(password).padStart(4, '0')}, {onError: () => setErrorMessage('비밀번호가 틀렸어요')}); }; const handleChange = (event: React.ChangeEvent) => { diff --git a/client/src/hooks/useEventMember.ts b/client/src/hooks/useEventMember.ts new file mode 100644 index 000000000..914a39da8 --- /dev/null +++ b/client/src/hooks/useEventMember.ts @@ -0,0 +1,121 @@ +import {useEffect, useState, useCallback, useMemo} from 'react'; + +import {Report} from 'types/serviceType'; +import validateMemberName from '@utils/validate/validateMemberName'; + +import MESSAGE from '@constants/message'; + +import toast from './useToast/toast'; +import useRequestDeleteMember from './queries/member/useRequestDeleteMember'; +import useRequestPutMembers from './queries/member/useRequestPutMembers'; +import useRequestGetReports from './queries/report/useRequestGetReports'; + +interface ReturnUseEventMember { + reports: Report[]; + canSubmit: boolean; + changeMemberName: (memberId: number, newName: string) => void; + toggleDepositStatus: (memberId: number) => void; + handleDeleteMember: (memberId: number) => void; + updateMembersOnServer: () => void; +} + +const useEventMember = (): ReturnUseEventMember => { + const {reports: initialReports} = useRequestGetReports(); + const {deleteAsyncMember} = useRequestDeleteMember(); + const {putAsyncMember} = useRequestPutMembers(); + + const [reports, setReports] = useState(initialReports); + const [deleteMembers, setDeleteMembers] = useState([]); + + useEffect(() => { + setReports(initialReports); + }, [initialReports]); + + const canSubmit = useMemo(() => { + // 중복되는 이름이 존재하는지 확인 + const hasDuplicateMemberName = (): boolean => { + const nameSet = new Set(reports.map(member => member.memberName)); + return nameSet.size !== reports.length; + }; + + if (hasDuplicateMemberName()) { + // 중복 이름이라면 false + return false; + } + + // 이름이 공백이라면 false + const hasEmptyName = reports.some(report => report.memberName.trim().length === 0); + if (hasEmptyName) return false; + + // 초기 값과 비교하여 변경된 사항이 존재하는지 확인 + const hasChanges = reports.some(report => + initialReports.find( + initial => + initial.memberId === report.memberId && + (initial.memberName !== report.memberName || initial.isDeposited !== report.isDeposited), + ), + ); + + // 변경된 사항이 존재 혹은 삭제된 member가 존재한다면 true + return hasChanges || deleteMembers.length > 0; + }, [reports, initialReports, deleteMembers]); + + const changeMemberName = useCallback( + (memberId: number, newName: string) => { + // 유효성 검사 (4자 이하) + if (!validateMemberName(newName).isValid) { + return; + } + + setReports(prevReports => + prevReports.map(report => (report.memberId === memberId ? {...report, memberName: newName} : report)), + ); + }, + [setReports, validateMemberName], + ); + + const toggleDepositStatus = useCallback( + (memberId: number) => { + setReports(prevReports => + prevReports.map(report => + report.memberId === memberId ? {...report, isDeposited: !report.isDeposited} : report, + ), + ); + }, + [setReports], + ); + + // 삭제할 member를 따로 deleteMembers 상태에서 id만 저장 + const handleDeleteMember = useCallback((memberId: number) => { + setDeleteMembers(prev => [memberId, ...prev]); + // 삭제할 member들의 데이터를 reports에서 제거 + setReports(prevReports => prevReports.filter(report => report.memberId !== memberId)); + }, []); + + const updateMembersOnServer = useCallback(async () => { + // DELETE 요청 선행 + // deleteMembers에 값이 하나라도 전재하면 반복문을 통해 DELETE api 요청 + if (deleteMembers.length > 0) { + for (const id of deleteMembers) { + await deleteAsyncMember({memberId: id}); + } + } + + // 변경된 값(filteredChangedMembers)이 존재한다면 PUT 요청 실행 + if (reports.length > 0) { + await putAsyncMember({ + members: reports.map(report => ({ + id: report.memberId, + name: report.memberName, + isDeposited: report.isDeposited, + })), + }); + } + + toast.confirm(MESSAGE.confirmEditEventMember); + }, [deleteMembers, reports, initialReports, deleteAsyncMember, putAsyncMember]); + + return {reports, canSubmit, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus}; +}; + +export default useEventMember; diff --git a/client/src/hooks/useEventPageLayout.ts b/client/src/hooks/useEventPageLayout.ts new file mode 100644 index 000000000..57fea80d2 --- /dev/null +++ b/client/src/hooks/useEventPageLayout.ts @@ -0,0 +1,30 @@ +import {useMatch} from 'react-router-dom'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +import useRequestGetEvent from './queries/event/useRequestGetEvent'; + +const useEventPageLayout = () => { + const eventId = getEventIdByUrl(); + const {eventName, bankName, accountNumber} = useRequestGetEvent(); + + const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; + const isLoginPage = useMatch(ROUTER_URLS.eventLogin) !== null; + + const eventOutline = { + eventName, + bankName, + accountNumber, + }; + + return { + eventId, + isAdmin, + isLoginPage, + eventOutline, + }; +}; + +export default useEventPageLayout; diff --git a/client/src/hooks/useFunnel.tsx b/client/src/hooks/useFunnel.tsx new file mode 100644 index 000000000..1347e59e7 --- /dev/null +++ b/client/src/hooks/useFunnel.tsx @@ -0,0 +1,61 @@ +import {useState} from 'react'; + +type UseFunnel = { + defaultStep: string; + stepList: string[]; +}; + +type StepProps = { + children: React.ReactNode; + name: string; +}; + +type FunnelProps = { + step: string; + children: React.ReactElement[]; +}; + +const Step = (stepProps: StepProps) => { + return <>{stepProps.children}; +}; + +const Funnel = ({children, step}: FunnelProps) => { + const targetStep = children.find(curStep => curStep.props.name === step); + + if (!targetStep) + throw new Error(`현재 ${step} 단계에 보여줄 컴포넌트가 존재하지 않습니다. Step 컴포넌트를 호출해 사용해주세요.`); + + return <>{targetStep}; +}; + +Funnel.Step = Step; + +const useFunnel = ({defaultStep, stepList}: UseFunnel) => { + const [step, setStep] = useState(defaultStep); + + const moveToNextStep = () => { + const curStepIndex = stepList.indexOf(step); + + if (curStepIndex === stepList.length - 1) return; + + setStep(stepList[curStepIndex + 1]); + }; + + const moveToPrevStep = () => { + const curStepIndex = stepList.indexOf(step); + + if (curStepIndex === 0) return; + + setStep(stepList[curStepIndex - 1]); + }; + + return { + Step, + step, + Funnel, + moveToNextStep, + moveToPrevStep, + }; +}; + +export default useFunnel; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx deleted file mode 100644 index 9c9cd80d9..000000000 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import type {MemberReportInAction} from 'types/serviceType'; - -import {useEffect, useState} from 'react'; - -import validateMemberReportInAction from '@utils/validate/validateMemberReportInAction'; - -type MemberReportInput = MemberReportInAction & { - index: number; -}; - -type UseMemberReportProps = { - data: MemberReportInAction[]; - addAdjustedMember: (memberReport: MemberReportInAction) => void; - getOnlyOneNotAdjustedRemainMemberIndex: () => number | null; - getIsSamePriceStateAndServerState: () => boolean; - totalPrice: number; -}; - -const useMemberReportInput = ({ - data, - addAdjustedMember, - totalPrice, - getOnlyOneNotAdjustedRemainMemberIndex, - getIsSamePriceStateAndServerState, -}: UseMemberReportProps) => { - const [inputList, setInputList] = useState(data.map((item, index) => ({...item, index}))); - const [canSubmit, setCanSubmit] = useState(false); - - const [canEditList, setCanEditList] = useState([]); - - const onChange = (event: React.ChangeEvent, index: number) => { - const {value} = event.target; - - validateAndAddAdjustedMember(value, index); - }; - - const validateAndAddAdjustedMember = (price: string, index: number) => { - const {isValid} = validateMemberReportInAction(price, totalPrice); - - if (isValid) { - const newInputList = [...inputList]; - newInputList[index].price = Number(price); - setInputList(newInputList); - - const memberReportData: MemberReportInAction = { - name: newInputList[index].name, - price: newInputList[index].price, - isFixed: newInputList[index].isFixed, - }; - addAdjustedMember(memberReportData); - } - }; - - // 서버와 값이 같지 않고 input price의 상태가 모두 valid하다면 can submit true - useEffect(() => { - const isSamePriceState = getIsSamePriceStateAndServerState(); - const isAllValid = inputList.every(input => validateMemberReportInAction(String(input.price), totalPrice)); - - setCanSubmit(!isSamePriceState && isAllValid); - }, [inputList]); - - // addAdjustedMember로 인해 data가 변했을 때 input list의 값을 맞춰주기 위함 - useEffect(() => { - setCanSubmit(!getIsSamePriceStateAndServerState()); - setInputList(data.map((item, index) => ({...item, index}))); - - // 남은 인원이 1명일 때 수정을 불가능하도록 설정 - const onlyOneIndex = getOnlyOneNotAdjustedRemainMemberIndex(); - - if (data.length !== 0) { - setCanEditList(new Array(data.length).fill(true)); - } - - if (onlyOneIndex !== null) { - const newCanEditList = new Array(data.length).fill(true); - newCanEditList[onlyOneIndex] = false; - setCanEditList(newCanEditList); - } - }, [data]); - - return { - inputList, - onChange, - canEditList, - canSubmit, - }; -}; - -export default useMemberReportInput; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx deleted file mode 100644 index 78c29ee03..000000000 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx +++ /dev/null @@ -1,327 +0,0 @@ -import type {MemberReportInAction} from 'types/serviceType'; - -import {renderHook, waitFor, act} from '@testing-library/react'; -import {MemoryRouter} from 'react-router-dom'; -import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; - -import memberReportListInActionJson from '../../mocks/memberReportListInAction.json'; - -import useMemberReportListInAction from './useMemberReportListInAction'; - -describe('useMemberReportListInActionTest', () => { - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - retry: 0, - }, - }, - }); - - const initializeProvider = (actionId: number, totalPrice: number) => - renderHook(() => useMemberReportListInAction(actionId, totalPrice, () => {}), { - wrapper: ({children}) => ( - - {children} - - ), - }); - - const actionId = 123; - const totalPrice = 100000; - - describe('Flow: 유저가 정상적으로 값을 불러왔을 때의 test', () => { - it('초기값을 정상적으로 불러온다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - expect(result.current.memberReportListInAction).toStrictEqual(memberReportListInActionJson); - }); - - it('망쵸의 가격을 100원으로 바꾸면 망쵸의 가격은 100원으로 설정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMember: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMember); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - - expect(targetMember?.price).toBe(100); - }); - - it('망쵸의 가격을 100원으로 바꾸면 망쵸의 가격은 100원으로 설정되고 나머지 인원의 가격이 33,300원으로 설정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMember: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMember); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - expect(targetMember?.price).toBe(100); - - const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); - - anotherMemberList.forEach(member => { - expect(member.price).toBe(33300); - }); - }); - - it('망쵸의 가격을 100원 쿠키의 가격을 100원으로 바꾸면 나머지 인원의 가격이 49,900원으로 설정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: true}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberCookie); - }); - - const anotherMemberList = result.current.memberReportListInAction.filter( - member => !(member.name === '망쵸' || member.name === '쿠키'), - ); - - anotherMemberList.forEach(member => { - expect(member.price).toBe(49900); - }); - }); - - it('망쵸의 가격을 100원 쿠키의 가격을 100원으로 바꾸면 나머지 인원의 가격이 49,900원으로 설정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberCookie); - }); - - const anotherMemberList = result.current.memberReportListInAction.filter( - member => !(member.name === '망쵸' || member.name === '쿠키'), - ); - - anotherMemberList.forEach(member => { - expect(member.price).toBe(49900); - }); - }); - - it('망쵸의 가격을 100원으로 바꾸고 다시 망쵸의 가격을 10,000원으로 바꾸면 나머지 인원의 가격이 30,000원으로 설정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberMangchoAfter: MemberReportInAction = {name: '망쵸', price: 10000, isFixed: true}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangchoAfter); - }); - - const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); - - anotherMemberList.forEach(member => { - expect(member.price).toBe(30000); - }); - }); - }); - - describe('예외 & 엣지케이스', () => { - it('동일한 인원의 가격을 동일하게 바꾸면 변함없다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember({...adjustedMemberMangcho, isFixed: true}); - }); - - const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); - - expect(anotherMemberList[0].price).toBe(33300); - }); - - it('망쵸에게 300원을 주면 나머지 사람들은 33233원이고 마지막 사람은 33234원이 된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 300, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - expect(targetMember?.price).toBe(300); - - const anotherMemberList = result.current.memberReportListInAction.filter( - member => member.name === '이상' || member.name === '소하', - ); - - anotherMemberList.forEach(member => { - expect(member.price).toBe(33233); - }); - - const lastMember = result.current.memberReportListInAction.find(member => member.name === '쿠키'); - - expect(lastMember?.price).toBe(33234); - }); - - it('망쵸, 쿠키의 가격을 100원으로 바꾼 후 다시 쿠키의 가격을 33000원으로 바꾸면 쿠키의 isFixed는 false가 된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: false}; - const adjustedMemberCookieReset: MemberReportInAction = {name: '쿠키', price: 33300, isFixed: true}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberCookie); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '쿠키'); - - expect(targetMember?.isFixed).toBe(true); - - act(() => { - result.current.addAdjustedMember(adjustedMemberCookieReset); - }); - - const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '쿠키'); - - expect(targetMemberReset?.isFixed).toBe(false); - }); - - it('망쵸의 가격을 100원으로 바꾼 후 다시 망쵸의 가격을 25000원으로 바꾸면 망쵸의 isFixed는 false가 된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberMangchoAfter: MemberReportInAction = {name: '망쵸', price: 25000, isFixed: true}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - expect(targetMember?.isFixed).toBe(true); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangchoAfter); - }); - - const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - expect(targetMemberReset?.isFixed).toBe(false); - }); - - it('아무도 조정된 값이 없다면 조정값이 있는지 확인 결과 false다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - expect(result.current.isExistAdjustedPrice()).toBe(false); - }); - - it('망쵸의 가격을 100원으로 바꾼 후 리스트 중 조정값이 있는지 확인 결과 true다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - expect(result.current.isExistAdjustedPrice()).toBe(true); - }); - }); - - describe('지출 인원이 2명인 상황', () => { - const actionId = 1; - const totalPrice = 50000; - - // 망쵸 이상 - it('망쵸의 가격을 100원으로 수정한 경우, 이상의 가격이 49900원으로 수정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '이상'); - - expect(targetMember?.price).toBe(49900); - }); - - it('망쵸의 가격을 100원으로 수정하고 다시 200원으로 수정한 경우, 이상의 가격이 49800원으로 수정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberMangchoOther: MemberReportInAction = {name: '망쵸', price: 200, isFixed: true}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangchoOther); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '이상'); - - expect(targetMember?.price).toBe(49800); - }); - }); - - // last - describe('onSubmit 실행 시 반영 테스트', () => { - it('망쵸의 가격을 100원으로 바꾸고 저장하면 망쵸 100원이 반영된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - await waitFor(() => { - result.current.onSubmit(); - }); - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - expect(targetMember?.price).toBe(100); - }); - }); -}); diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts deleted file mode 100644 index 0e32d740c..000000000 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts +++ /dev/null @@ -1,156 +0,0 @@ -import type {MemberReportInAction} from 'types/serviceType'; - -import {useEffect, useState} from 'react'; - -import useRequestGetMemberReportListInAction from '@hooks/queries/useRequestGetMemberReportListInAction'; -import useRequestPutMemberReportListInAction from '@hooks/queries/useRequestPutMemberReportListInAction'; - -const useMemberReportListInAction = (actionId: number, totalPrice: number, onClose: () => void) => { - const {memberReportListInActionFromServer, queryResult} = useRequestGetMemberReportListInAction(actionId); - const {putMemberReportListInAction} = useRequestPutMemberReportListInAction(actionId); - - const [memberReportListInAction, setMemberReportListInAction] = useState( - memberReportListInActionFromServer, - ); - - // isFixed를 모두 풀고 계산값으로 모두 처리하는 기능 - const reCalculatePriceByTotalPriceChange = () => { - const {divided, remainder} = calculateDividedPrice(memberReportListInAction.length, 0); - - const resetMemberReportList = [...memberReportListInAction]; - resetMemberReportList.forEach((member, index) => { - if (index !== resetMemberReportList.length - 1) { - member.price = divided; - } else { - member.price = divided + remainder; - } - member.isFixed = false; - }); - - setMemberReportListInAction(resetMemberReportList); - }; - - // 총 금액이 변동됐을 때 (서버에서 온 값과 다를 때) 재계산 실행 - useEffect(() => { - const totalPriceFromServer = memberReportListInActionFromServer.reduce((acc, cur) => acc + cur.price, 0); - - if (totalPriceFromServer !== totalPrice && totalPriceFromServer !== 0) { - reCalculatePriceByTotalPriceChange(); - } - }, [totalPrice, memberReportListInActionFromServer]); - - useEffect(() => { - if (queryResult.isSuccess) { - setMemberReportListInAction(memberReportListInActionFromServer); - } - }, [memberReportListInActionFromServer, queryResult.isSuccess]); - - const isExistAdjustedPrice = () => { - return memberReportListInAction.some(member => member.isFixed === true); - }; - - // 조정되지 않은 인원이 단 1명인 경우의 index - const getOnlyOneNotAdjustedRemainMemberIndex = (): number | null => { - const adjustedPriceCount = getAdjustedMemberCount(memberReportListInAction); - - if (adjustedPriceCount < memberReportListInAction.length - 1) return null; - - return memberReportListInAction.findIndex(member => member.isFixed === false); - }; - - // 조정값 멤버의 수를 구하는 함수 - const getAdjustedMemberCount = (memberReportListInAction: MemberReportInAction[]) => { - return memberReportListInAction.filter(member => member.isFixed === true).length; - }; - - const addAdjustedMember = (memberReport: MemberReportInAction) => { - const newMemberReportListInAction = memberReportListInAction.map(member => - member.name === memberReport.name ? {...member, price: memberReport.price, isFixed: true} : member, - ); - - calculateAnotherMemberPrice(newMemberReportListInAction); - }; - - const calculateDividedPrice = (remainMemberCount: number, totalAdjustedPrice: number) => { - return { - divided: Math.floor((totalPrice - totalAdjustedPrice) / remainMemberCount), - remainder: (totalPrice - totalAdjustedPrice) % remainMemberCount, - }; - }; - - // 계산값으로 값을 변경했을 때 isFixed를 푸는 함수 - // 100 true 33300 true 33300 false 33300 false - const setIsFixedFalseAtResetToDividedPrice = (memberReportListInAction: MemberReportInAction[], divided: number) => { - return memberReportListInAction.map(memberReport => { - if (memberReport.isFixed === true && memberReport.price === divided) { - return {...memberReport, isFixed: false}; - } - - return memberReport; - }); - }; - - const calculateAnotherMemberPrice = (memberReportListInAction: MemberReportInAction[]) => { - // 총 조정치 금액 - const totalAdjustedPrice = memberReportListInAction - .filter(memberReport => memberReport.isFixed === true) - .reduce((acc, cur) => acc + cur.price, 0); - - const remainMemberCount = memberReportListInAction.length - getAdjustedMemberCount(memberReportListInAction); - const {divided, remainder} = calculateDividedPrice(remainMemberCount, totalAdjustedPrice); - - const updatedList = memberReportListInAction.map(member => - member.isFixed === true ? member : {...member, price: divided}, - ); - - // 나머지를 조정되지 않은 멤버 중 마지막 멤버에게 추가 - if (remainder !== 0) { - const nonAdjustedMembers = updatedList.filter(member => member.isFixed === false); - const lastNonAdjustedMemberIndex = updatedList.findIndex( - member => member.name === nonAdjustedMembers[nonAdjustedMembers.length - 1].name, - ); - - if (lastNonAdjustedMemberIndex !== -1) { - updatedList[lastNonAdjustedMemberIndex].price += remainder; - } - } - - // 조정됐지만 계산값으로 가격이 변한 경우 fixed 상태를 풀어야한다. - const result = setIsFixedFalseAtResetToDividedPrice(updatedList, divided); - setMemberReportListInAction(result); - }; - - const onSubmit = () => { - putMemberReportListInAction(memberReportListInAction); - - onClose(); - }; - - const getIsSamePriceStateAndServerState = () => { - const serverStatePriceList = memberReportListInActionFromServer.map(({price}) => price); - const clientStatePriceList = memberReportListInAction.map(({price}) => price); - - let isSame = true; - - // isArrayEqual을 사용하지 않은 이유는 정렬이 영향을 받으면 안 되기 때문입니다 - for (let i = 0; i < serverStatePriceList.length; i++) { - if (serverStatePriceList[i] !== clientStatePriceList[i]) { - isSame = false; - } - } - - return isSame; - }; - - return { - memberReportListInAction, - addAdjustedMember, - isExistAdjustedPrice, - onSubmit, - getOnlyOneNotAdjustedRemainMemberIndex, - getIsSamePriceStateAndServerState, - queryResult, - }; -}; - -export default useMemberReportListInAction; diff --git a/client/src/hooks/useMembersStep.ts b/client/src/hooks/useMembersStep.ts new file mode 100644 index 000000000..1fe15d6d9 --- /dev/null +++ b/client/src/hooks/useMembersStep.ts @@ -0,0 +1,126 @@ +import {RefObject, useEffect, useRef, useState} from 'react'; +import {useNavigate} from 'react-router-dom'; + +import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; +import {Member} from 'types/serviceType'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import REGEXP from '@constants/regExp'; + +import useRequestPostMembers from './queries/member/useRequestPostMembers'; +import useRequestPostBill from './queries/bill/useRequestPostBill'; +import {BillStep} from './useAddBillFunnel'; + +interface Props { + billInfo: BillInfo; + setBillInfo: React.Dispatch>; + setStep: React.Dispatch>; + currentMembers: Member[]; +} + +const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => { + const [errorMessage, setErrorMessage] = useState(''); + const [nameInput, setNameInput] = useState(''); + const inputRef = useRef(null); + + const {postMembersAsync, isPending: isPendingPostMembers} = useRequestPostMembers(); + + const {postBill, isSuccess: isSuccessPostBill, isPending: isPendingPostBill} = useRequestPostBill(); + const navigate = useNavigate(); + const eventId = getEventIdByUrl(); + + const onNameInputChange = (value: string) => { + if (REGEXP.memberName.test(value)) { + setNameInput(value); + } + }; + + const handleNameInputChange = (event: React.ChangeEvent) => { + if (event.target.value.length > 4) { + setErrorMessage('이름은 4자까지 입력 가능해요'); + onNameInputChange(nameInput.slice(0, 4)); + } else { + setErrorMessage(''); + onNameInputChange(event.target.value); + } + }; + + const canAddMembers = nameInput && nameInput.length <= 4; + + const canSubmitMembers = billInfo.members.length !== 0; + + const setBillInfoMemberWithId = (name: string) => { + const existingMember = currentMembers.find(currentMember => currentMember.name === name); + if (existingMember) { + setBillInfo(prev => ({...prev, members: [...prev.members, {id: existingMember.id, name: name}]})); + } else { + setBillInfo(prev => ({...prev, members: [...prev.members, {id: -1, name: name}]})); + } + }; + + const handleNameInputEnter = (event: React.KeyboardEvent) => { + if (event.key === 'Enter' && canAddMembers && inputRef.current) { + event.preventDefault(); + if (!billInfo.members.map(({name}) => name).includes(nameInput)) { + setBillInfoMemberWithId(nameInput); + setNameInput(''); + inputRef.current.value = ''; + inputRef.current.blur(); + setTimeout(() => { + if (inputRef.current) inputRef.current?.focus(); + }, 10); + } + } + }; + + const handlePostBill = async () => { + if (billInfo.members.map(({id}) => id).includes(-1)) { + const newMembers = await postMembersAsync({ + members: billInfo.members + .filter(({id}) => id === -1) + .map(({name}) => ({ + name, + })), + }); + postBill({ + title: billInfo.title, + price: Number(billInfo.price.replace(',', '')), + memberIds: billInfo.members.map(member => + member.id === -1 ? newMembers.members.find(m => m.name === member.name)?.id || member.id : member.id, + ), + }); + } else { + postBill({ + title: billInfo.title, + price: Number(billInfo.price.replace(',', '')), + memberIds: billInfo.members.map(({id}) => id), + }); + } + }; + + useEffect(() => { + if (isSuccessPostBill) { + navigate(`/event/${eventId}/admin`); + } + }, [isSuccessPostBill]); + + const handlePrevStep = () => { + setStep('title'); + }; + + return { + errorMessage, + nameInput, + inputRef, + handleNameInputChange, + handleNameInputEnter, + isPendingPostBill, + isPendingPostMembers, + canSubmitMembers, + handlePostBill, + handlePrevStep, + }; +}; + +export default useMembersStep; diff --git a/client/src/hooks/useNavSwitch.tsx b/client/src/hooks/useNavSwitch.tsx deleted file mode 100644 index a622a7a30..000000000 --- a/client/src/hooks/useNavSwitch.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import {useEffect, useState} from 'react'; -import {useLocation, useNavigate} from 'react-router-dom'; - -const PATH_TABLE: Record = { - 홈: 'home', - 관리: 'admin', -}; - -const PATH_DISPLAY_TABLE: Record = { - home: '홈', - admin: '관리', -}; - -const useNavSwitch = () => { - const paths = ['홈', '관리']; - const location = useLocation(); - const navigate = useNavigate(); - - const pathArray = location.pathname.split('/'); - const basePath = pathArray.slice(0, -1).join('/'); - const lastPath = pathArray[pathArray.length - 1]; - - const [nav, setNav] = useState(PATH_DISPLAY_TABLE[lastPath]); - - useEffect(() => { - const isLogin = lastPath === 'login'; - setNav(isLogin ? '관리' : PATH_DISPLAY_TABLE[lastPath]); - }, [location]); - - const onChange = (displayName: string) => { - setNav(displayName); - navigate(`${basePath}/${PATH_TABLE[displayName]}`); - }; - - return { - nav, - paths, - onChange, - }; -}; - -export default useNavSwitch; diff --git a/client/src/hooks/usePriceStep.ts b/client/src/hooks/usePriceStep.ts new file mode 100644 index 000000000..181a44f3d --- /dev/null +++ b/client/src/hooks/usePriceStep.ts @@ -0,0 +1,27 @@ +import {useCallback} from 'react'; + +import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; + +import {BillStep} from './useAddBillFunnel'; + +interface Props { + setStep: React.Dispatch>; + setBillInfo: React.Dispatch>; +} + +const usePriceStep = ({setStep, setBillInfo}: Props) => { + const handleNumberKeyboardChange = useCallback( + (value: string) => { + setBillInfo(prev => ({...prev, price: value})); + }, + [setBillInfo], + ); + + const handleNextStep = () => { + setStep('title'); + }; + + return {handleNumberKeyboardChange, handleNextStep}; +}; + +export default usePriceStep; diff --git a/client/src/hooks/usePutAndDeleteBill.ts b/client/src/hooks/usePutAndDeleteBill.ts new file mode 100644 index 000000000..60c0ea358 --- /dev/null +++ b/client/src/hooks/usePutAndDeleteBill.ts @@ -0,0 +1,115 @@ +// import type {Bill, BillInputType, InputPair} from 'types/serviceType'; + +// import {useEffect, useState} from 'react'; + +// import {ValidateResult} from '@utils/validate/type'; + +// import {ERROR_MESSAGE} from '@constants/errorMessage'; + +// import usePutBillAction from './queries/'; +// import useDeleteBillAction from './queries/useRequestDeleteBill'; + +// const usePutAndDeleteBill = ( +// initialValue: InputPair, +// validateFunc: (inputPair: Bill) => ValidateResult, +// onClose: () => void, +// ) => { +// const [inputPair, setInputPair] = useState(initialValue); +// const [canSubmit, setCanSubmit] = useState(false); +// const [errorInfo, setErrorInfo] = useState>({title: false, price: false}); +// const [errorMessage, setErrorMessage] = useState(null); + +// const {mutateAsync: putBillAction} = usePutBillAction(); +// const {mutate: deleteBillAction} = useDeleteBillAction(); + +// // 현재 타겟의 event.target.value를 넣어주기 위해서 +// const getFieldValue = (field: BillInputType, value: string) => { +// if (field === 'title') { +// return {title: value, price: Number(inputPair.price)}; +// } else { +// return {title: inputPair.title, price: Number(value)}; +// } +// }; + +// // TODO: (@weadie) getFieldValue 를 리펙토링해야한다. + +// const handleInputChange = (field: BillInputType, event: React.ChangeEvent) => { +// const {value} = event.target; + +// if (value.length > 20) return; + +// const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue(field, value)); + +// setErrorMessage(errorMessage); + +// if (isValid) { +// // valid일 경우 에러메시지 nope, setValue, submit은 value가 비지 않았을 때 true를 설정 +// setInputPair(prevInputPair => { +// return { +// ...prevInputPair, +// [field]: value, +// }; +// }); +// setCanSubmit(value.length !== 0); +// } else { +// const {isValid: isValidName} = validateFunc(getFieldValue('title', inputPair.title)); +// const {isValid: isValidPrice} = validateFunc(getFieldValue('price', inputPair.price)); + +// setCanSubmit(isValidName && isValidPrice); +// // valid하지 않으면 event.target.value 덮어쓰기 +// event.target.value = inputPair[field]; +// } + +// if (field === 'title') { +// // 현재 field가 title일 때는 title의 errorInfo만 반영해줌 (blur에서도 errorInfo를 조작하기 때문) +// setErrorInfo(prev => ({title: errorInfo?.title ?? false, price: prev.price})); +// } else { +// setErrorInfo(prev => ({title: prev.title, price: errorInfo?.price ?? false})); +// } +// }; + +// const handleOnBlur = () => { +// const {isValid, errorMessage, errorInfo} = validateFunc({title: inputPair.title, price: Number(inputPair.price)}); + +// // blur시 값이 비었을 때 error state 반영 +// if (inputPair.price.length === 0 || inputPair.title.length === 0) { +// setErrorMessage(ERROR_MESSAGE.preventEmpty); +// setErrorInfo({title: inputPair.title.length === 0, price: inputPair.price.length === 0}); +// setCanSubmit(false); +// return; +// } + +// // 이외 blur시에 추가로 검증함 +// setErrorMessage(errorMessage); +// setCanSubmit(isValid); +// setErrorInfo(errorInfo ?? {title: false, price: false}); +// }; + +// const onSubmit = async (event: React.FormEvent, inputPair: InputPair, actionId: number) => { +// event.preventDefault(); + +// const {title, price} = inputPair; + +// await putBillAction({actionId, title, price: Number(price)}); + +// onClose(); +// }; + +// const onDelete = async (actionId: number) => { +// deleteBillAction({actionId}); +// onClose(); +// }; + +// return { +// inputPair, +// handleInputChange, +// handleOnBlur, +// onSubmit, +// onDelete, +// canSubmit, +// errorMessage, +// errorInfo, +// }; +// }; + +// export default usePutAndDeleteBill; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts deleted file mode 100644 index 6f1e4feaf..000000000 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ /dev/null @@ -1,113 +0,0 @@ -import type {Bill, BillInputType, InputPair} from 'types/serviceType'; - -import {useEffect, useState} from 'react'; - -import {ValidateResult} from '@utils/validate/type'; - -import {ERROR_MESSAGE} from '@constants/errorMessage'; - -import usePutBillAction from './queries/useRequestPutBillAction'; -import useDeleteBillAction from './queries/useRequestDeleteBillAction'; - -const usePutAndDeleteBillAction = ( - initialValue: InputPair, - validateFunc: (inputPair: Bill) => ValidateResult, - onClose: () => void, -) => { - const [inputPair, setInputPair] = useState(initialValue); - const [canSubmit, setCanSubmit] = useState(false); - const [errorInfo, setErrorInfo] = useState>({title: false, price: false}); - const [errorMessage, setErrorMessage] = useState(null); - - const {mutateAsync: putBillAction} = usePutBillAction(); - const {mutate: deleteBillAction} = useDeleteBillAction(); - - // 현재 타겟의 event.target.value를 넣어주기 위해서 - const getFieldValue = (field: BillInputType, value: string) => { - if (field === 'title') { - return {title: value, price: Number(inputPair.price)}; - } else { - return {title: inputPair.title, price: Number(value)}; - } - }; - - // TODO: (@weadie) getFieldValue 를 리펙토링해야한다. - - const handleInputChange = (field: BillInputType, event: React.ChangeEvent) => { - const {value} = event.target; - - const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue(field, value)); - - setErrorMessage(errorMessage); - - if (isValid) { - // valid일 경우 에러메시지 nope, setValue, submit은 value가 비지 않았을 때 true를 설정 - setInputPair(prevInputPair => { - return { - ...prevInputPair, - [field]: value, - }; - }); - setCanSubmit(value.length !== 0); - } else { - const {isValid: isValidName} = validateFunc(getFieldValue('title', inputPair.title)); - const {isValid: isValidPrice} = validateFunc(getFieldValue('price', inputPair.price)); - - setCanSubmit(isValidName && isValidPrice); - // valid하지 않으면 event.target.value 덮어쓰기 - event.target.value = inputPair[field]; - } - - if (field === 'title') { - // 현재 field가 title일 때는 title의 errorInfo만 반영해줌 (blur에서도 errorInfo를 조작하기 때문) - setErrorInfo(prev => ({title: errorInfo?.title ?? false, price: prev.price})); - } else { - setErrorInfo(prev => ({title: prev.title, price: errorInfo?.price ?? false})); - } - }; - - const handleOnBlur = () => { - const {isValid, errorMessage, errorInfo} = validateFunc({title: inputPair.title, price: Number(inputPair.price)}); - - // blur시 값이 비었을 때 error state 반영 - if (inputPair.price.length === 0 || inputPair.title.length === 0) { - setErrorMessage(ERROR_MESSAGE.preventEmpty); - setErrorInfo({title: inputPair.title.length === 0, price: inputPair.price.length === 0}); - setCanSubmit(false); - return; - } - - // 이외 blur시에 추가로 검증함 - setErrorMessage(errorMessage); - setCanSubmit(isValid); - setErrorInfo(errorInfo ?? {title: false, price: false}); - }; - - const onSubmit = async (event: React.FormEvent, inputPair: InputPair, actionId: number) => { - event.preventDefault(); - - const {title, price} = inputPair; - - await putBillAction({actionId, title, price: Number(price)}); - - onClose(); - }; - - const onDelete = async (actionId: number) => { - deleteBillAction({actionId}); - onClose(); - }; - - return { - inputPair, - handleInputChange, - handleOnBlur, - onSubmit, - onDelete, - canSubmit, - errorMessage, - errorInfo, - }; -}; - -export default usePutAndDeleteBillAction; diff --git a/client/src/hooks/useReportsPage.ts b/client/src/hooks/useReportsPage.ts new file mode 100644 index 000000000..87ab2c59f --- /dev/null +++ b/client/src/hooks/useReportsPage.ts @@ -0,0 +1,60 @@ +import {useState} from 'react'; +import {useOutletContext} from 'react-router-dom'; + +import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; + +import {isAndroid, isIOS} from '@utils/detectDevice'; + +import {ERROR_MESSAGE} from '@constants/errorMessage'; + +import {useSearchReports} from './useSearchReports'; +import toast from './useToast/toast'; + +const useReportsPage = () => { + const [memberName, setMemberName] = useState(''); + const {bankName, accountNumber} = useOutletContext(); + const {matchedReports, reports} = useSearchReports({memberName}); + + const changeName = ({target}: React.ChangeEvent) => { + setMemberName(target.value); + }; + + const onBankButtonClick = () => { + if (bankName.trim() === '' || accountNumber.trim() === '') { + toast.error(ERROR_MESSAGE.emptyBank, { + showingTime: 3000, + position: 'bottom', + }); + return; + } + + if (isAndroid()) { + const url = 'supertoss://'; + window.location.href = url; + return; + } + + if (isIOS()) { + const url = 'supertoss://send'; + window.location.href = url; + return; + } + }; + + const expenseListProp = matchedReports.map(member => ({ + ...member, + clipboardText: `${bankName} ${accountNumber} ${member.price}원`, + onBankButtonClick, + })); + + const isEmpty = reports.length <= 0; + + return { + isEmpty, + expenseListProp, + memberName, + changeName, + }; +}; + +export default useReportsPage; diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts deleted file mode 100644 index 09f227b8e..000000000 --- a/client/src/hooks/useSearchInMemberList.ts +++ /dev/null @@ -1,54 +0,0 @@ -import {useState} from 'react'; - -import useRequestGetCurrentInMemberList from './queries/useRequestGetCurrentInMemberList'; - -export type ReturnUseSearchInMemberList = { - currentInputIndex: number; - handleCurrentInputIndex: (inputIndex: number) => void; - filteredInMemberList: string[]; - searchCurrentInMember: (event: React.ChangeEvent) => void; - chooseMember: (inputIndex: number, name: string) => void; -}; - -const useSearchInMemberList = (handleChange: (index: number, value: string) => void): ReturnUseSearchInMemberList => { - const [currentInputIndex, setCurrentInputIndex] = useState(-1); - - // 서버에서 가져온 전체 리스트 - const {data} = useRequestGetCurrentInMemberList(); - const currentInMemberList = data?.memberNames ?? []; - - // 검색된 리스트 (따로 둔 이유는 검색 후 클릭했을 때 리스트를 비워주어야하기 때문) - const [filteredInMemberList, setFilteredInMemberList] = useState>([]); - - const filterMatchItems = (keyword: string) => { - if (keyword.trim() === '') return []; - - return currentInMemberList - .filter(member => member.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1) - .slice(0, 3); - }; - - const chooseMember = (inputIndex: number, name: string) => { - setFilteredInMemberList([]); - handleChange(inputIndex, name); - }; - - const searchCurrentInMember = (event: React.ChangeEvent) => { - const {value} = event.target; - setFilteredInMemberList(filterMatchItems(value)); - }; - - const handleCurrentInputIndex = (inputIndex: number) => { - setCurrentInputIndex(inputIndex); - }; - - return { - currentInputIndex, - handleCurrentInputIndex, - filteredInMemberList, - searchCurrentInMember, - chooseMember, - }; -}; - -export default useSearchInMemberList; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx deleted file mode 100644 index 90782cbdf..000000000 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import {renderHook, waitFor} from '@testing-library/react'; -import {MemoryRouter} from 'react-router-dom'; - -import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; -import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; -import {ToastProvider} from '@hooks/useToast/ToastProvider'; - -import reportListJson from '../../mocks/reportList.json'; - -import useSearchMemberReportList from './useSearchMemberReportList'; - -describe('useSearchMemberReportList', () => { - const initializeProvider = (name: string) => - renderHook(() => useSearchMemberReportList({name}), { - wrapper: ({children}) => ( - - - - {children} - - - - ), - }); - - it('빈 값을 검색한다면 검색 목록은 비어있다.', async () => { - const {result} = initializeProvider(''); - - await waitFor(() => expect(result.current.memberReportSearchList).toStrictEqual(reportListJson)); - }); - - it('검색어의 일부와 일치하는 이름이 있다면 해당 이름을 목록에 반환한다.', async () => { - const keyword = '소'; - const {result} = initializeProvider(keyword); - const expectedMemberReportSearchList = reportListJson.filter(memberReport => memberReport.name.includes(keyword)); - - await waitFor(() => { - expect(result.current.memberReportSearchList).toStrictEqual(expectedMemberReportSearchList); - }); - }); -}); diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx deleted file mode 100644 index 4a967e45c..000000000 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import useRequestGetMemberReportList from '@hooks/queries/useRequestGetMemberReportList'; - -type UseSearchMemberReportListParams = { - name: string; -}; - -const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { - const {data} = useRequestGetMemberReportList(); - const memberReportList = data ?? []; - - return { - memberReportSearchList: memberReportList.filter(memberReport => memberReport.name.includes(name)), - }; -}; - -export default useSearchMemberReportList; diff --git a/client/src/hooks/useSearchReports/index.ts b/client/src/hooks/useSearchReports/index.ts new file mode 100644 index 000000000..619af5493 --- /dev/null +++ b/client/src/hooks/useSearchReports/index.ts @@ -0,0 +1 @@ +export {default as useSearchReports} from './useSearchReports'; diff --git a/client/src/hooks/useSearchReports/useSearchReports.tsx b/client/src/hooks/useSearchReports/useSearchReports.tsx new file mode 100644 index 000000000..25ce95cca --- /dev/null +++ b/client/src/hooks/useSearchReports/useSearchReports.tsx @@ -0,0 +1,16 @@ +import useRequestGetReports from '@hooks/queries/report/useRequestGetReports'; + +type UseSearchReportsParams = { + memberName: string; +}; + +const useSearchReports = ({memberName}: UseSearchReportsParams) => { + const {reports} = useRequestGetReports(); + + return { + matchedReports: reports.filter(memberReport => memberReport.memberName.includes(memberName)), + reports, + }; +}; + +export default useSearchReports; diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx deleted file mode 100644 index 02241d3e3..000000000 --- a/client/src/hooks/useSetAllMemberList.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import {useEffect, useState} from 'react'; - -import {ValidateResult} from '@utils/validate/type'; -import {MemberChange} from '@apis/request/member'; - -import isArraysEqual from '@utils/isArraysEqual'; - -import useDeleteAllMemberList from './queries/useRequestDeleteAllMemberList'; -import usePutAllMemberList from './queries/useRequestPutAllMemberList'; -import useInput from './useInput'; - -interface UseSetAllMemberListProps { - validateFunc: (name: string) => ValidateResult; - allMemberList: string[]; - handleCloseAllMemberListModal: () => void; -} - -interface UseSetAllMemberListReturns { - editedAllMemberList: string[]; - canSubmit: boolean; - errorMessage: string; - errorIndexList: number[]; - handleNameChange: (index: number, event: React.ChangeEvent) => void; - handleClickDeleteButton: (index: number) => Promise; - handlePutAllMemberList: () => Promise; -} - -const useSetAllMemberList = ({ - validateFunc, - allMemberList, - handleCloseAllMemberListModal, -}: UseSetAllMemberListProps): UseSetAllMemberListReturns => { - const initialInputList = allMemberList.map((name, index) => ({index, value: name})); - const { - inputList, - errorMessage, - errorIndexList, - canSubmit, - handleChange, - setInputList: setEditedAllMemberList, - setCanSubmit, - } = useInput({validateFunc, initialInputList}); - - const [deleteInOriginal, setDeleteInOriginal] = useState(allMemberList); - const [deleteMemberList, setDeleteMemberList] = useState([]); - - const {mutateAsync: deleteAllMemberList} = useDeleteAllMemberList(); - const {mutate: putAllMemberList} = usePutAllMemberList(); - - const editedAllMemberList = inputList.map(input => input.value); - - useEffect(() => { - setCanSubmit(!isArraysEqual(editedAllMemberList, allMemberList)); - }, [editedAllMemberList]); - - const handleNameChange = (index: number, event: React.ChangeEvent) => { - const {value} = event.target; - - handleChange(index, value); - }; - - const handleClickDeleteButton = async (index: number) => { - const memberToDelete = editedAllMemberList[index]; - - setDeleteMemberList(prev => [...prev, memberToDelete]); - setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); - setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); - }; - - const handlePutAllMemberList = async () => { - // deleteMemberList가 비어있지 않은 경우에만 반복문 실행 (삭제 api 요청) - if (deleteMemberList.length > 0) { - for (const deleteMember of deleteMemberList) { - await deleteAllMemberList({memberName: deleteMember}); - } - } - - const editedMemberName: MemberChange[] = deleteInOriginal - .map((originalName, index) => { - if (editedAllMemberList[index] !== originalName) { - return {before: originalName, after: editedAllMemberList[index]}; - } - return null; // 조건에 맞지 않으면 null을 반환 - }) - .filter(item => item !== null); // null인 항목을 필터링하여 제거 - if (!isArraysEqual(editedAllMemberList, deleteInOriginal)) putAllMemberList({members: editedMemberName}); - handleCloseAllMemberListModal(); - }; - - return { - editedAllMemberList, - canSubmit, - errorMessage, - errorIndexList, - handleNameChange, - handleClickDeleteButton, - handlePutAllMemberList, - }; -}; -export default useSetAllMemberList; diff --git a/client/src/hooks/useSetBillInput.ts b/client/src/hooks/useSetBillInput.ts deleted file mode 100644 index a14b2a481..000000000 --- a/client/src/hooks/useSetBillInput.ts +++ /dev/null @@ -1,67 +0,0 @@ -import {useState} from 'react'; - -import validatePurchase from '@utils/validate/validatePurchase'; -import {Bill, BillInputType} from 'types/serviceType'; - -import useRequestPostBillList from './queries/useRequestPostBillList'; - -interface UseSetBillInputProps { - setIsAddEditableItem: React.Dispatch>; -} - -interface UseSetBillInputReturns { - billInput: Bill; - handleChangeBillInput: (field: BillInputType, event: React.ChangeEvent) => void; - handleBlurBillRequest: () => void; -} - -const useSetBillInput = ({setIsAddEditableItem}: UseSetBillInputProps): UseSetBillInputReturns => { - const initialInput = {title: '', price: 0}; - const [billInput, setBillInput] = useState(initialInput); - - const {mutate: postBillList} = useRequestPostBillList(); - - const handleChangeBillInput = (field: BillInputType, event: React.ChangeEvent) => { - const {value} = event.target; - const {isValid} = validatePurchase({ - ...billInput, - [field]: value, - }); - - if (isValid) { - setBillInput(prev => ({ - ...prev, - [field]: value, - })); - } - }; - - const handleBlurBillRequest = () => { - const isEmptyTitle = billInput.title.trim().length; - const isEmptyPrice = Number(billInput.price); - - // 두 input의 값이 모두 채워졌을 때 api 요청 - // api 요청을 하면 Input을 띄우지 않음 - if (isEmptyTitle && isEmptyPrice) { - postBillList( - {billList: [billInput]}, - { - onSuccess: () => { - setBillInput(initialInput); - setIsAddEditableItem(false); - }, - }, - ); - } else if (!isEmptyTitle && !isEmptyPrice) { - setIsAddEditableItem(false); - } - }; - - return { - billInput, - handleBlurBillRequest, - handleChangeBillInput, - }; -}; - -export default useSetBillInput; diff --git a/client/src/hooks/useSetEventNamePage.ts b/client/src/hooks/useSetEventNameStep.ts similarity index 71% rename from client/src/hooks/useSetEventNamePage.ts rename to client/src/hooks/useSetEventNameStep.ts index f5b5bce12..ae087434d 100644 --- a/client/src/hooks/useSetEventNamePage.ts +++ b/client/src/hooks/useSetEventNameStep.ts @@ -2,7 +2,9 @@ import {useState} from 'react'; import validateEventName from '@utils/validate/validateEventName'; -const useSetEventNamePage = () => { +export type UseSetEventNameStepReturnType = ReturnType; + +const useSetEventNameStep = () => { const [eventName, setEventName] = useState(''); const [errorMessage, setErrorMessage] = useState(null); const [canSubmit, setCanSubmit] = useState(false); @@ -11,14 +13,13 @@ const useSetEventNamePage = () => { const newValue = event.target.value; const validation = validateEventName(newValue); - setCanSubmit(newValue.length !== 0); - setErrorMessage(validation.errorMessage); - - if (validation.isValid) { - setEventName(newValue); + if (!validation.isValid) { + setErrorMessage(validation.errorMessage); } else { - event.target.value = eventName; + setErrorMessage(''); + setEventName(newValue); } + setCanSubmit(newValue.length !== 0); }; return { @@ -29,4 +30,4 @@ const useSetEventNamePage = () => { }; }; -export default useSetEventNamePage; +export default useSetEventNameStep; diff --git a/client/src/hooks/useSetEventPasswordPage.ts b/client/src/hooks/useSetEventPasswordPage.ts deleted file mode 100644 index 82ca72fb1..000000000 --- a/client/src/hooks/useSetEventPasswordPage.ts +++ /dev/null @@ -1,60 +0,0 @@ -import {useEffect, useState} from 'react'; -import {useLocation, useNavigate} from 'react-router-dom'; - -import validateEventPassword from '@utils/validate/validateEventPassword'; - -import {ROUTER_URLS} from '@constants/routerUrls'; -import RULE from '@constants/rule'; - -import usePostEvent from './queries/useRequestPostEvent'; - -const useSetEventPasswordPage = () => { - const [eventName, setEventName] = useState(''); - const [password, setPassword] = useState(''); - const [errorMessage, setErrorMessage] = useState(''); - const [canSubmit, setCanSubmit] = useState(false); - const navigate = useNavigate(); - const location = useLocation(); - const {mutate: postEvent, isPending: isPostEventPending} = usePostEvent(); - - useEffect(() => { - if (!location.state) { - navigate(ROUTER_URLS.main); - } else { - setEventName(location.state.eventName); - } - }, []); - - const submitPassword = async (event: React.FormEvent) => { - event.preventDefault(); - - postEvent( - {eventName, password: parseInt(password)}, - { - onSuccess: data => { - navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId: data.eventId})}`, { - replace: true, - }); - }, - }, - ); - }; - - const handleChange = (event: React.ChangeEvent) => { - const newValue = event.target.value; - const validation = validateEventPassword(newValue); - - setCanSubmit(newValue.length === RULE.maxEventPasswordLength); - - if (validation.isValid) { - setPassword(newValue); - setErrorMessage(''); - } else { - event.target.value = password; - setErrorMessage(validation.errorMessage ?? ''); - } - }; - - return {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending}; -}; -export default useSetEventPasswordPage; diff --git a/client/src/hooks/useSetEventPasswordStep.ts b/client/src/hooks/useSetEventPasswordStep.ts new file mode 100644 index 000000000..5705be855 --- /dev/null +++ b/client/src/hooks/useSetEventPasswordStep.ts @@ -0,0 +1,72 @@ +import {useState} from 'react'; +import {useNavigate} from 'react-router-dom'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; + +import RULE from '@constants/rule'; + +import useRequestPostEvent from './queries/event/useRequestPostEvent'; + +export type UseSetEventPasswordStepReturnType = ReturnType; + +const useSetEventPasswordStep = () => { + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + const {postEvent: requestPostEvent, isPostEventPending} = useRequestPostEvent(); + + const submitDataForPostEvent = async ({ + event, + eventName, + setEventToken, + }: { + event: React.FormEvent; + eventName: string; + setEventToken: (eventToken: string) => void; + }) => { + event.preventDefault(); + + await postEvent(eventName, setEventToken); + }; + + const getPasswordWithPad = () => { + return String(password).padStart(4, '0'); + }; + + const postEvent = async (eventName: string, updateEventToken: (eventToken: string) => void) => { + await requestPostEvent( + {eventName, password: getPasswordWithPad()}, + { + onSuccess: ({eventId}) => { + updateEventToken(eventId); + }, + }, + ); + }; + + const handleChange = (event: React.ChangeEvent) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + + if (validation.isValid) { + setPassword(newValue); + setErrorMessage(''); + } else { + event.target.value = password; + setErrorMessage(validation.errorMessage ?? ''); + } + }; + + return { + submitDataForPostEvent, + errorMessage, + handleChange, + canSubmit, + isPostEventPending, + password, + }; +}; + +export default useSetEventPasswordStep; diff --git a/client/src/hooks/useShareEvent.ts b/client/src/hooks/useShareEvent.ts new file mode 100644 index 000000000..86d185f48 --- /dev/null +++ b/client/src/hooks/useShareEvent.ts @@ -0,0 +1,47 @@ +import getEventIdByUrl from '@utils/getEventIdByUrl'; +import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; + +const useShareEvent = (eventName: string, isMobile: boolean) => { + const eventId = getEventIdByUrl(); + const url = getEventPageUrlByEnvironment(eventId, 'home'); + + const shareInfo = { + title: `[행동대장]\n${eventName}에 대한 정산을 시작할게요:)`, + text: '아래 링크에 접속해서 정산 내역을 확인해 주세요!', + url, + }; + + // 모바일이 아닌 기기는 단순 텍스트 복사 + // 모바일 기기에서는 카카오톡 공유를 사용 + const onShareButtonClick = () => { + if (!isMobile) return; + + kakaoShare(); + }; + + const kakaoShare = () => { + window.Kakao.Share.sendDefault({ + objectType: 'feed', + content: { + title: shareInfo.title, + description: shareInfo.text, + imageUrl: + 'https://wooteco-crew-wiki.s3.ap-northeast-2.amazonaws.com/%EC%9B%A8%EB%94%94%286%EA%B8%B0%29/g583lirp8yg.jpg', + link: { + mobileWebUrl: url, + webUrl: url, + }, + }, + buttonTitle: '정산 확인하기', + }); + }; + + const shareText = `${shareInfo.title}\n${shareInfo.text}\n${url}`; + + return { + shareText, + onShareButtonClick, + }; +}; + +export default useShareEvent; diff --git a/client/src/hooks/useTitleStep.ts b/client/src/hooks/useTitleStep.ts new file mode 100644 index 000000000..8ed5c787c --- /dev/null +++ b/client/src/hooks/useTitleStep.ts @@ -0,0 +1,64 @@ +import {useState} from 'react'; + +import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; + +import REGEXP from '@constants/regExp'; + +import {BillStep} from './useAddBillFunnel'; + +interface Props { + billInfo: BillInfo; + setBillInfo: React.Dispatch>; + setStep: React.Dispatch>; +} + +const useTitleStep = ({billInfo, setBillInfo, setStep}: Props) => { + const [errorMessage, setErrorMessage] = useState(''); + + const onTitleInputChange = (value: string) => { + if (REGEXP.billTitle.test(value)) { + setBillInfo(prev => ({...prev, title: value})); + } + }; + + const handleTitleInputChange = (event: React.ChangeEvent) => { + if (event.target.value.length > 12) { + setErrorMessage('지출내역은 12자까지 입력 가능해요'); + onTitleInputChange(billInfo.title.slice(0, 12)); + } else { + setErrorMessage(''); + onTitleInputChange(event.target.value); + } + }; + + const canSubmitTitleInput = billInfo.title && !errorMessage; + + const handleTitleInputEnter = (event: React.KeyboardEvent) => { + if (event.nativeEvent.isComposing) { + return; + } + if (event.key === 'Enter' && canSubmitTitleInput) { + event.preventDefault(); + setStep('members'); + } + }; + + const handleNextStep = () => { + setStep('members'); + }; + + const handlePrevStep = () => { + setStep('price'); + }; + + return { + errorMessage, + handleTitleInputChange, + handleTitleInputEnter, + canSubmitTitleInput, + handleNextStep, + handlePrevStep, + }; +}; + +export default useTitleStep; diff --git a/client/src/hooks/useToast/ToastProvider.tsx b/client/src/hooks/useToast/ToastProvider.tsx deleted file mode 100644 index be0d2ea15..000000000 --- a/client/src/hooks/useToast/ToastProvider.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import {createContext, useEffect, useState} from 'react'; - -import {ToastProps} from '../../components/Toast/Toast.type'; -import Toast from '../../components/Toast/Toast'; - -export const ToastContext = createContext(null); - -const DEFAULT_TIME = 3000; - -interface ToastContextProps { - showToast: (args: ShowToast) => void; -} - -type ShowToast = ToastProps & { - showingTime?: number; - isAlwaysOn?: boolean; -}; - -export const ToastProvider = ({children}: React.PropsWithChildren) => { - const [currentToast, setCurrentToast] = useState(null); - - const showToast = ({showingTime = DEFAULT_TIME, isAlwaysOn = false, ...toastProps}: ShowToast) => { - setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); - }; - - const closeToast = () => { - setCurrentToast(null); - }; - - useEffect(() => { - if (currentToast && !currentToast.isAlwaysOn) { - const timer = setTimeout(() => setCurrentToast(null), currentToast.showingTime); - - return () => clearTimeout(timer); - } - - return; - }, [currentToast]); - - return ( - - {currentToast && } - {children} - - ); -}; diff --git a/client/src/hooks/useToast/toast.ts b/client/src/hooks/useToast/toast.ts new file mode 100644 index 000000000..362227a62 --- /dev/null +++ b/client/src/hooks/useToast/toast.ts @@ -0,0 +1,19 @@ +import {ToastMessage, ToastOptions} from 'types/toastType'; + +import toastEventManager from './toastEventManager'; +import {TOAST_EVENT} from './toastEventManager.type'; + +const showToast = (message: ToastMessage, options: ToastOptions) => { + return toastEventManager.trigger(TOAST_EVENT.show, message, options); +}; + +// toast('안녕') 처럼도 사용할 수 있도록 +const toast = (message: ToastMessage, options: ToastOptions = {}) => { + return showToast(message, options); +}; + +toast.error = (message: ToastMessage, options: ToastOptions = {}) => showToast(message, options); +toast.confirm = (message: ToastMessage, options: ToastOptions = {}) => showToast(message, options); +toast.none = (message: ToastMessage, options: ToastOptions = {}) => showToast(message, options); + +export default toast; diff --git a/client/src/hooks/useToast/toastEventManager.ts b/client/src/hooks/useToast/toastEventManager.ts new file mode 100644 index 000000000..fc70d5af3 --- /dev/null +++ b/client/src/hooks/useToast/toastEventManager.ts @@ -0,0 +1,24 @@ +import {AddEventHandlerArgs, ToastEventCallbackMap} from './toastEventManager.type'; + +const toastEventManager = (() => { + const eventCallbackList = new Map(); + + return { + // eventType은 ToastEventCallbackMap 중 하나의 값을 받고 이 값에 따라 callback타입이 결정됩니다. + // 모티브는 addEventListener으로.. listener 인자에 적용되는 타입 narrowing방법을 흉내낸 것입니다. + addEventHandler({eventType, callback}: AddEventHandlerArgs) { + eventCallbackList.set(eventType, callback); + }, + + trigger(eventType: K, ...args: any) { + if (!eventCallbackList.has(eventType)) { + throw new Error(`토스트 이벤트 핸들러에 등록된 ${eventType} 이벤트가 없습니다. 이벤트 등록 후 호출해주세요.`); + } + + const callback = eventCallbackList.get(eventType); + callback(...args); + }, + }; +})(); + +export default toastEventManager; diff --git a/client/src/hooks/useToast/toastEventManager.type.ts b/client/src/hooks/useToast/toastEventManager.type.ts new file mode 100644 index 000000000..0d7603983 --- /dev/null +++ b/client/src/hooks/useToast/toastEventManager.type.ts @@ -0,0 +1,21 @@ +import {ToastMessage, ToastOptions} from 'types/toastType'; + +const TOAST_SHOW = 'TOAST_SHOW' as const; +const TOAST_CLOSE = 'TOAST_CLOSE' as const; + +export const TOAST_EVENT = { + show: TOAST_SHOW, + close: TOAST_CLOSE, +}; + +export type ToastEventType = typeof TOAST_SHOW | typeof TOAST_CLOSE; + +export type ToastEventCallbackMap = { + [TOAST_SHOW]: (message: ToastMessage, options: ToastOptions) => void; + [TOAST_CLOSE]: () => void; +}; + +export type AddEventHandlerArgs = { + eventType: K; + callback: ToastEventCallbackMap[K]; +}; diff --git a/client/src/hooks/useToast/useToast.test.tsx b/client/src/hooks/useToast/useToast.test.tsx index f790ba98e..e8c1bdd3d 100644 --- a/client/src/hooks/useToast/useToast.test.tsx +++ b/client/src/hooks/useToast/useToast.test.tsx @@ -1,20 +1,19 @@ import {render, renderHook, screen, waitFor} from '@testing-library/react'; import {act} from 'react'; -import {HDesignProvider} from 'haengdong-design'; -import {ToastProvider} from './ToastProvider'; // 위 코드에 해당하는 ToastProvider 경로 +import ToastContainer from '@components/Toast/ToastContainer'; + +import {HDesignProvider} from '@HDesign/index'; + import {useToast} from './useToast'; +import toast from './toast'; -const TOAST_CONFIG = { - message: 'Test Toast Message', -}; +const TOAST_MESSAGE = '테스트 메세지에요.'; // 테스트용 헬퍼 컴포넌트 const TestComponent = () => { - const {showToast} = useToast(); - const handleClick = () => { - showToast(TOAST_CONFIG); + toast(TOAST_MESSAGE); }; return ; @@ -23,9 +22,8 @@ const TestComponent = () => { const setup = () => render( - - - + + , ); @@ -39,18 +37,18 @@ describe('ToastProvider', () => { }); // 토스트 메시지가 나타나는지 확인 - expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); + expect(screen.getByText(TOAST_MESSAGE)).toBeInTheDocument(); // 1초 후에 토스트 메시지가 사라지는지 확인 await waitFor( () => { - expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); + expect(screen.queryByText(TOAST_MESSAGE)).not.toBeInTheDocument(); }, {timeout: 3100}, ); // 타임아웃을 3100ms로 설정하여 정확히 3초 후 확인 }); - it('토스트 닫기 버튼을 눌렀을 때 사라진다', async () => { + it('토스트를 누르면 사라진다', async () => { setup(); // 토스트를 띄우기 위해 버튼 클릭 @@ -59,7 +57,7 @@ describe('ToastProvider', () => { }); // 토스트 메시지가 나타나는지 확인 - expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); + expect(screen.getByText(TOAST_MESSAGE)).toBeInTheDocument(); // 토스트의 닫기 버튼을 클릭 act(() => { @@ -68,13 +66,7 @@ describe('ToastProvider', () => { // 닫기 버튼을 클릭한 후 토스트가 사라지는지 확인 await waitFor(() => { - expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); + expect(screen.queryByText(TOAST_MESSAGE)).not.toBeInTheDocument(); }); }); - - it('Provider없이 useToast 사용할 경우 에러를 던진다.', () => { - expect(() => { - const _ = renderHook(() => useToast()); - }).toThrow('useToast는 ToastProvider 내에서 사용되어야 합니다.'); - }); }); diff --git a/client/src/hooks/useToast/useToast.tsx b/client/src/hooks/useToast/useToast.tsx index 189847405..e47d99c50 100644 --- a/client/src/hooks/useToast/useToast.tsx +++ b/client/src/hooks/useToast/useToast.tsx @@ -1,13 +1,50 @@ -import {useContext} from 'react'; +/** @jsxImportSource @emotion/react */ +import {useEffect, useState} from 'react'; -import {ToastContext} from './ToastProvider'; +import {ToastMessage, ToastOptions, ToastArgs} from 'types/toastType'; + +import toastEventManager from './toastEventManager'; +import {TOAST_EVENT} from './toastEventManager.type'; + +const DEFAULT_TIME = 3000; + +type Toast = { + message: ToastMessage; + options: ToastOptions; +}; export const useToast = () => { - const context = useContext(ToastContext); + const [currentToast, setCurrentToast] = useState(null); + + const showToast = (message: ToastMessage, options: ToastOptions) => { + setCurrentToast({message, options}); + }; + + const closeToast = () => { + setCurrentToast(null); + }; + + const setAutoCloseTimer = () => { + if (!currentToast) return; + + const showingTime = currentToast.options.showingTime || DEFAULT_TIME; + const timer = setTimeout(() => setCurrentToast(null), showingTime); + + return () => clearTimeout(timer); + }; + + useEffect(() => { + if (currentToast?.options.isAutoClosed) setAutoCloseTimer(); + + return; + }, [currentToast]); - if (!context) { - throw new Error('useToast는 ToastProvider 내에서 사용되어야 합니다.'); - } + useEffect(() => { + toastEventManager.addEventHandler({eventType: TOAST_EVENT.show, callback: showToast}); + }, []); - return context; + return { + currentToast, + closeToast, + }; }; diff --git a/client/src/index.tsx b/client/src/index.tsx index 17f98655f..cb3fcb955 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -5,11 +5,6 @@ import * as Sentry from '@sentry/react'; import router from './router'; -// async function enableMocking() { -// const {worker} = await import('./mocks/browser'); -// return worker.start(); -// } - Sentry.init({ dsn: 'https://81685591a3234c689be8c48959b04c88@o4507739935997952.ingest.us.sentry.io/4507739943272448', integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()], @@ -23,6 +18,11 @@ Sentry.init({ }); // MSW 모킹을 사용하려면 아래 주석을 해제하고 save해주세요. +// async function enableMocking() { +// const {worker} = await import('./mocks/browser'); +// return worker.start(); +// } + // enableMocking().then(() => { ReactDOM.createRoot(document.getElementById('root')!).render( diff --git a/client/src/mocks/handlers.ts b/client/src/mocks/handlers.ts index 4189b2d66..d4347bc5b 100644 --- a/client/src/mocks/handlers.ts +++ b/client/src/mocks/handlers.ts @@ -1,15 +1,15 @@ import {authHandler} from './handlers/authHandlers'; import {eventHandler} from './handlers/eventHandlers'; import {reportHandlers} from './handlers/reportHandlers'; -import {stepListHandler} from './handlers/stepListHandler'; import {testHandler} from './handlers/testHandlers'; -import {memberReportInActionHandler} from './handlers/memberReportInActionHandlers'; +import {billHandler} from './handlers/billHandler'; +import {memberHandler} from './handlers/memberHandler'; export const handlers = [ ...authHandler, ...eventHandler, + ...billHandler, + ...memberHandler, ...testHandler, - ...stepListHandler, ...reportHandlers, - ...memberReportInActionHandler, ]; diff --git a/client/src/mocks/handlers/authHandlers.ts b/client/src/mocks/handlers/authHandlers.ts index 31532eea7..00000b1e8 100644 --- a/client/src/mocks/handlers/authHandlers.ts +++ b/client/src/mocks/handlers/authHandlers.ts @@ -1,100 +1,56 @@ -import {HttpResponse, http} from 'msw'; +import {http, HttpResponse} from 'msw'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {PASSWORD_LENGTH} from '@constants/password'; -import { - EXPIRED_TOKEN_FOR_TEST, - FORBIDDEN_TOKEN_FOR_TEST, - VALID_PASSWORD_FOR_TEST, - VALID_TOKEN_FOR_TEST, -} from '@mocks/validValueForTest'; - -type PostLoginParams = { - eventId: string; -}; - -type PostLoginRequestBody = { - password: string; -}; +import {MOCK_API_PREFIX} from '@mocks/mockEndpointPrefix'; export const authHandler = [ - http.post(`${TEMP_PREFIX}/:eventId/auth`, ({cookies}) => { - const token = cookies['eventToken']; - - if (token === VALID_TOKEN_FOR_TEST) { - return new HttpResponse(null, { - status: 200, - }); - } else if (token === EXPIRED_TOKEN_FOR_TEST) { - return HttpResponse.json( - { - errorCode: 'TOKEN_EXPIRED', - message: '만료된 토큰입니다.', - }, - {status: 401}, - ); - } else if (token === FORBIDDEN_TOKEN_FOR_TEST) { - return HttpResponse.json( - { - errorCode: 'FORBIDDEN', - message: '접근할 수 없는 행사입니다.', - }, - {status: 401}, - ); - } else if (token === undefined) { - return HttpResponse.json( - { - errorCode: 'TOKEN_NOT_FOUND', - message: '토큰이 존재하지 않습니다.', - }, - {status: 401}, - ); - } else { - return HttpResponse.json( - { - errorCode: 'TOKEN_INVALID', - message: '유효하지 않은 토큰입니다.', - }, - {status: 401}, - ); - } + // POST /api/eventId/auth (requestPostAuthentication) + http.post(`${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/auth`, () => { + return new HttpResponse(null, {status: 200}); }), - // TODO: (@weadie) any를 사용한 이유는.. any가 있는 위치가 이 handler함수의 responseBody타입인데, 아래처럼 return하는 것에 대한 예시가 공문에 없습니다. 함수를 까면 되겠지만 시간이 아깝고 알아낸다고 해서 이 responseBody 타입은 사실 중요한게 아니기 때문에 any로 대체하였습니다. - http.post( - `${TEMP_PREFIX}/:eventId/login`, - async ({request}) => { + // POST /api/eventId/login (requestPostToken) + http.post<{eventId: string}, {password: string}>( + `${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/login`, + async ({params, request}) => { + const {eventId} = params; const {password} = await request.json(); - if (password === String(VALID_PASSWORD_FOR_TEST)) { - return new HttpResponse(null, { - headers: { - 'Set-Cookie': 'eventToken=abc-123', - }, - }); - } else if (password.length < PASSWORD_LENGTH) { + if (!password) { return HttpResponse.json( { - errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', - message: `비밀번호는 ${PASSWORD_LENGTH}자리 숫자만 가능합니다.`, + errorCode: 'REQUEST_EMPTY', + message: '비밀번호는 공백일 수 없습니다.', }, - {status: 401}, + {status: 400}, ); - } else if (password === undefined) { + } + if (password.length !== PASSWORD_LENGTH) { return HttpResponse.json( { - errorCode: 'REQUEST_EMPTY', - message: '비밀번호는 공백일 수 없습니다.', + errorCode: 'PASSWORD_INVALID', + message: `비밀번호는 ${PASSWORD_LENGTH}자리여야 합니다.`, }, - {status: 401}, + {status: 400}, ); + } + + // 비밀번호가 1234인 경우만 성공으로 처리 + if (password === '1234') { + return new HttpResponse(null, { + status: 200, + headers: { + 'Set-Cookie': `eventToken=${eventId}-token`, + }, + }); } else { return HttpResponse.json( { - errorCode: 'PASSWORD_INVALID', - message: '비밀번호가 일치하지 않습니다.', + errorCode: 'PASSWORD_INCORRECT', + message: '비밀번호가 올바르지 않습니다.', }, {status: 401}, ); diff --git a/client/src/mocks/handlers/billHandler.ts b/client/src/mocks/handlers/billHandler.ts new file mode 100644 index 000000000..597ff3a1e --- /dev/null +++ b/client/src/mocks/handlers/billHandler.ts @@ -0,0 +1,115 @@ +import {http, HttpResponse, PathParams} from 'msw'; + +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; + +import {billData, billDetailsData} from '@mocks/sharedState'; + +import {MOCK_API_PREFIX} from './../mockEndpointPrefix'; + +interface BillDetailsData { + [key: string]: {billDetails: {id: number; memberName: string; price: string}[]}; +} + +export const billHandler = [ + // GET /api/eventId/bills + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/bills`, () => { + return HttpResponse.json(billData); + }), + + // GET /api/eventId/bills/billId/fixed + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/bills/:billId/fixed`, ({params}) => { + const {billId} = params; + const billDetails = (billDetailsData as unknown as BillDetailsData)[billId as keyof BillDetailsData]; + return HttpResponse.json(billDetails); + }), + + // POST /api/eventId/bills + http.post( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/bills`, + async ({request}) => { + try { + const {title, price, members} = await request.json(); + const newBill = {id: Date.now(), title, price, isFixed: false}; + + const lastStep = billData.steps[billData.steps.length - 1]; + const isSameMembers = JSON.stringify(lastStep.members.map(m => m.id).sort()) === JSON.stringify(members.sort()); + + if (isSameMembers) { + lastStep.bills.push(newBill); + } else { + billData.steps.push({ + bills: [newBill], + members: members.map(id => ({id, name: `Member ${id}`})), + }); + } + + (billDetailsData as unknown as BillDetailsData)[newBill.id.toString()] = { + billDetails: members.map((id, index) => ({ + id, + memberName: + billData.steps.flatMap(step => step.members).find(member => member.id === id)?.name || `Member ${id}`, + price: (Math.floor(price / members.length) + (index < price % members.length ? 1 : 0)).toString(), + })), + }; + + return HttpResponse.json({status: 200}); + } catch (error) { + return HttpResponse.json({message: 'Internal Server Error'}, {status: 500}); + } + }, + ), + + // DELETE /api/eventId/bills/billId + http.delete(`${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/bills/:billId`, ({params}) => { + const {billId} = params; + billData.steps.forEach(step => { + step.bills = step.bills.filter(bill => bill.id !== Number(billId)); + }); + delete (billDetailsData as unknown as BillDetailsData)[billId as keyof BillDetailsData]; + return HttpResponse.json({status: 200}); + }), + + // PUT /api/eventId/bills/billId + http.put( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/bills/:billId`, + async ({params, request}) => { + const {billId} = params; + const {title, price} = await request.json(); + + billData.steps.forEach(step => { + const billIndex = step.bills.findIndex(bill => bill.id === Number(billId)); + if (billIndex !== -1) { + step.bills[billIndex] = {...step.bills[billIndex], title, price}; + } + }); + + return HttpResponse.json({status: 200}); + }, + ), + + // PUT /api/eventId/bills/billId/fixed + http.put( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/bills/:billId/fixed`, + async ({params, request}) => { + const {billId} = params; + const {billDetails} = await request.json(); + + (billDetailsData as unknown as BillDetailsData)[billId as keyof BillDetailsData] = { + billDetails: billDetails.map(detail => ({ + id: detail.id, + memberName: 'Unknown', + price: detail.price.toString(), + })), + }; + + billData.steps.forEach(step => { + const billIndex = step.bills.findIndex(bill => bill.id === Number(billId)); + if (billIndex !== -1) { + step.bills[billIndex].isFixed = true; + } + }); + + return HttpResponse.json({status: 200}); + }, + ), +]; diff --git a/client/src/mocks/handlers/eventHandlers.ts b/client/src/mocks/handlers/eventHandlers.ts index 351993e16..1b06c5f9d 100644 --- a/client/src/mocks/handlers/eventHandlers.ts +++ b/client/src/mocks/handlers/eventHandlers.ts @@ -1,55 +1,64 @@ -import {HttpResponse, http} from 'msw'; +import type {EventId} from 'types/serviceType'; -import {RequestPostNewEvent, ResponsePostNewEvent} from '@apis/request/event'; +import {http, HttpResponse} from 'msw'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; - -import {PASSWORD_LENGTH} from '@constants/password'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {VALID_EVENT_NAME_LENGTH_IN_SERVER} from '@mocks/serverConstants'; - -type ErrorResponseBody = { - errorCode: string; - message: string; -}; +import {MOCK_API_PREFIX} from '@mocks/mockEndpointPrefix'; +import {eventData} from '@mocks/sharedState'; export const eventHandler = [ - http.post( - `${TEMP_PREFIX}`, + // POST /api/events (requestPostEvent) + http.post(`${MOCK_API_PREFIX}${USER_API_PREFIX}`, async ({request}) => { + const {eventName, password} = await request.json(); + + if ( + eventName.length < VALID_EVENT_NAME_LENGTH_IN_SERVER.min || + eventName.length > VALID_EVENT_NAME_LENGTH_IN_SERVER.max + ) { + return HttpResponse.json( + { + errorCode: 'EVENT_NAME_LENGTH_INVALID', + message: '행사 이름은 2자 이상 30자 이하만 입력 가능합니다.', + }, + {status: 400}, + ); + } + + if (password.length !== 4) { + return HttpResponse.json( + { + errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', + message: '비밀번호는 4자리 숫자만 가능합니다.', + }, + {status: 400}, + ); + } + + const eventId: EventId = {eventId: 'mock-event-id'}; + return HttpResponse.json(eventId, { + status: 201, + headers: { + 'Set-Cookie': 'eventToken=mock-event-token', + }, + }); + }), + + // GET /api/events/:eventId (requestGetEvent) + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId`, () => { + return HttpResponse.json(eventData); + }), + + // PATCH /api/admin/events/:eventId (requestPatchEvent) + http.patch( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId`, async ({request}) => { - const {eventName, password} = await request.json(); - - if (String(password).length < PASSWORD_LENGTH) { - return HttpResponse.json( - { - errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', - message: '비밀번호는 4자리 숫자만 가능합니다.', - }, - {status: 401}, - ); - } else if ( - eventName.length < VALID_EVENT_NAME_LENGTH_IN_SERVER.min || - eventName.length > VALID_EVENT_NAME_LENGTH_IN_SERVER.max - ) { - return HttpResponse.json( - { - errorCode: 'EVENT_NAME_LENGTH_INVALID', - message: `행사 이름은 2자 이상 30자 이하만 입력 가능합니다. 입력한 이름 길이 : ${eventName.length}`, - }, - {status: 401}, - ); - } else { - return HttpResponse.json( - { - eventId: 'eventId', - }, - { - headers: { - 'Set-Cookie': 'eventToken=abc-123', - }, - }, - ); - } + const updates = await request.json(); + + Object.assign(eventData, updates); + + return HttpResponse.json({status: 200}); }, ), ]; diff --git a/client/src/mocks/handlers/memberHandler.ts b/client/src/mocks/handlers/memberHandler.ts new file mode 100644 index 000000000..97233c8b5 --- /dev/null +++ b/client/src/mocks/handlers/memberHandler.ts @@ -0,0 +1,62 @@ +import {http, HttpResponse, PathParams} from 'msw'; + +import {AllMembers, Members} from 'types/serviceType'; + +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; + +import {MOCK_API_PREFIX} from '@mocks/mockEndpointPrefix'; +import {memberData} from '@mocks/sharedState'; + +export const memberHandler = [ + // POST /api/eventId/members (requestPostMember) + http.post( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/members`, + async ({request}) => { + const {members: newMembers} = await request.json(); + const addedMembers = newMembers.map((member, index) => ({ + id: memberData.members.length + index + 1, + name: member.name, + isDeposited: false, + })); + + memberData.members = [...memberData.members, ...addedMembers]; + + return HttpResponse.json({members: addedMembers}, {status: 201}); + }, + ), + + // DELETE /api/eventId/members/memberId (requestDeleteMember) + http.delete(`${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/members/:memberId`, ({params}) => { + const {memberId} = params; + memberData.members = memberData.members.filter(member => member.id !== Number(memberId)); + return HttpResponse.json({status: 200}); + }), + + // PUT /api/eventId/members (requestPutMember) + http.put( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/members`, + async ({request}) => { + const {members: updatedMembers} = await request.json(); + + memberData.members = memberData.members.map(member => { + const updatedMember = updatedMembers.find(m => m.id === member.id); + return updatedMember ? {...member, ...updatedMember} : member; + }); + + return HttpResponse.json({status: 200}); + }, + ), + + // GET /api/eventId/members/current (requestGetCurrentMember) + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/members/current`, () => { + const currentMembers: Members = { + members: memberData.members.map(({id, name}) => ({id, name})), + }; + return HttpResponse.json(currentMembers); + }), + + // GET /api/eventId/members (requestGetAllMember) + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/members`, () => { + return HttpResponse.json(memberData); + }), +]; diff --git a/client/src/mocks/handlers/memberReportInActionHandlers.ts b/client/src/mocks/handlers/memberReportInActionHandlers.ts deleted file mode 100644 index 45de357f1..000000000 --- a/client/src/mocks/handlers/memberReportInActionHandlers.ts +++ /dev/null @@ -1,49 +0,0 @@ -import {http, HttpResponse} from 'msw'; - -import {MemberReport} from 'types/serviceType'; - -import {TEMP_PREFIX} from '@apis/tempPrefix'; - -import memberReportInActionJson from '../memberReportListInAction.json'; - -let memberReportInActionMockData = memberReportInActionJson as MemberReport[]; - -type MemberReportListRequestParams = { - eventId: string; - actionId: string; -}; -type MemberReportListBody = {members: MemberReport[]}; - -export const memberReportInActionHandler = [ - http.get< - MemberReportListRequestParams, - MemberReportListBody, - any, - `${typeof TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed` - >(`${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, ({params}) => { - const {actionId} = params; - - if (Number(actionId) === 123) { - return HttpResponse.json({ - members: memberReportInActionMockData, - }); - } - - return HttpResponse.json({ - members: memberReportInActionMockData.slice(0, 2), - }); - }), - - http.put( - `${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, - async ({request}) => { - const {members} = await request.json(); - - memberReportInActionMockData = members; - - return HttpResponse.json({ - status: 200, - }); - }, - ), -]; diff --git a/client/src/mocks/handlers/reportHandlers.ts b/client/src/mocks/handlers/reportHandlers.ts index 6b256d7d3..5248fe82a 100644 --- a/client/src/mocks/handlers/reportHandlers.ts +++ b/client/src/mocks/handlers/reportHandlers.ts @@ -1,13 +1,13 @@ -import {HttpResponse, http} from 'msw'; +import {http, HttpResponse} from 'msw'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {USER_API_PREFIX} from '@apis/endpointPrefix'; -import reportListJson from '../reportList.json'; +import {MOCK_API_PREFIX} from '@mocks/mockEndpointPrefix'; +import {reportData} from '@mocks/sharedState'; export const reportHandlers = [ - http.get(`${TEMP_PREFIX}/:eventId/actions/reports`, () => { - return HttpResponse.json({ - reports: reportListJson, - }); + // GET /api/eventId/reports (requestGetMemberReport) + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/reports`, () => { + return HttpResponse.json(reportData); }), ]; diff --git a/client/src/mocks/handlers/stepListHandler.ts b/client/src/mocks/handlers/stepListHandler.ts deleted file mode 100644 index d79b7b0b4..000000000 --- a/client/src/mocks/handlers/stepListHandler.ts +++ /dev/null @@ -1,113 +0,0 @@ -import {HttpResponse, http} from 'msw'; - -import {Bill, MemberType, StepList} from 'types/serviceType'; - -import {TEMP_PREFIX} from '@apis/tempPrefix'; - -import stepListJson from '../stepList.json'; - -type StepListResponseBody = { - step: StepList; -}; - -type PostMemberListRequestBody = { - members: string[]; - status: MemberType; -}; - -type PostBillListRequestBody = { - actions: Bill[]; -}; - -let stepListMockData = stepListJson; - -export const stepListHandler = [ - http.get( - `${TEMP_PREFIX}/:eventId/actions`, - () => { - return HttpResponse.json({ - steps: stepListMockData, - }); - }, - ), - - http.get(`${TEMP_PREFIX}/:eventId/members`, () => { - return HttpResponse.json({ - memberNames: stepListMockData - .filter(({type}) => type !== 'BILL') - .map(({actions}) => actions.map(({name}) => name)) - .flat(), - }); - }), - - http.delete<{actionId: string}>(`${TEMP_PREFIX}/:eventId/member-actions/:actionId`, ({params}) => { - const {actionId} = params; - - if (parseInt(actionId) === 999) { - return HttpResponse.json( - { - errorCode: 'MEMBER_ACTION_STATUS_INVALID', - message: 'actionId는 999일 수 없습니다.(고의로 만든 에러임)', - }, - {status: 401}, - ); - } else { - return HttpResponse.json({ - status: 200, - }); - } - }), - - http.post( - `${TEMP_PREFIX}/:eventId/member-actions`, - async ({request}) => { - const {members, status} = await request.json(); - stepListMockData = [ - ...stepListJson, - { - type: status, - stepName: '영차영차', - members: status === 'IN' ? members : [], - actions: members.map(name => ({ - actionId: 999, - name, - price: 0, - sequence: 999, - isFixed: false, - })), - }, - ]; - - return HttpResponse.json({ - status: 200, - }); - }, - ), - - http.post( - `${TEMP_PREFIX}/:eventId/bill-actions`, - async ({request}) => { - const {actions} = await request.json(); - - stepListMockData = [ - ...stepListJson, - { - type: 'BILL', - stepName: '밥스카이', - members: [], - actions: actions.map(({title, price}) => ({ - actionId: 999, - name: title, - price, - sequence: 999, - isFixed: false, - })), - }, - ]; - - return HttpResponse.json({ - status: 200, - }); - }, - ), -]; diff --git a/client/src/mocks/imageFileMock.ts b/client/src/mocks/imageFileMock.ts new file mode 100644 index 000000000..b59aedd2d --- /dev/null +++ b/client/src/mocks/imageFileMock.ts @@ -0,0 +1,7 @@ +module.exports = { + process() { + return { + code: 'module.exports = "imageFileMock";', + }; + }, +}; diff --git a/client/src/mocks/invalidMemberStepList.json b/client/src/mocks/invalidMemberStepList.json deleted file mode 100644 index 33ca77e4c..000000000 --- a/client/src/mocks/invalidMemberStepList.json +++ /dev/null @@ -1,100 +0,0 @@ -[ - { - "type": "IN", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 999, - "name": "망쵸", - "price": null, - "sequence": 1, - "isFixed": false - }, - { - "actionId": 2, - "name": "백호", - "price": null, - "sequence": 2, - "isFixed": false - } - ] - }, - { - "type": "BILL", - "stepName": "1차", - "members": ["망쵸", "백호"], - "actions": [ - { - "actionId": 3, - "name": "감자탕", - "price": 10000, - "sequence": 3, - "isFixed": false - }, - { - "actionId": 4, - "name": "인생네컷", - "price": 10000, - "sequence": 4, - "isFixed": false - } - ] - }, - { - "type": "IN", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 5, - "name": "소하", - "price": null, - "sequence": 5, - "isFixed": false - }, - { - "actionId": 6, - "name": "웨디", - "price": null, - "sequence": 6, - "isFixed": false - } - ] - }, - { - "type": "BILL", - "stepName": "2차", - "members": ["소하", "웨디"], - "actions": [ - { - "actionId": 9, - "name": "노래방", - "price": 20000, - "sequence": 10, - "isFixed": false - } - ] - }, - { - "type": "OUT", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 7, - "name": "망쵸", - "price": null, - "sequence": 7, - "isFixed": false - }, - { - "actionId": 8, - "name": "백호", - "price": null, - "sequence": 8, - "isFixed": false - } - ] - } -] diff --git a/client/src/mocks/memberActionStepList.json b/client/src/mocks/memberActionStepList.json deleted file mode 100644 index 734db4a75..000000000 --- a/client/src/mocks/memberActionStepList.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "type": "IN", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 1, - "name": "망쵸", - "price": null, - "sequence": 1, - "isFixed": false - }, - { - "actionId": 2, - "name": "백호", - "price": null, - "sequence": 2, - "isFixed": false - } - ] - } -] diff --git a/client/src/mocks/memberReportListInAction.json b/client/src/mocks/memberReportListInAction.json deleted file mode 100644 index 2e24670cb..000000000 --- a/client/src/mocks/memberReportListInAction.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - {"name": "망쵸", "price": 25000, "isFixed": false}, - {"name": "이상", "price": 25000, "isFixed": false}, - {"name": "소하", "price": 25000, "isFixed": false}, - {"name": "쿠키", "price": 25000, "isFixed": false} -] diff --git a/client/src/mocks/memberReportSearchList.json b/client/src/mocks/memberReportSearchList.json deleted file mode 100644 index dfcb684b1..000000000 --- a/client/src/mocks/memberReportSearchList.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - {"name": "망쵸", "price": 1033200}, - {"name": "이상", "price": 10100}, - {"name": "소하", "price": 10000}, - {"name": "쿠키", "price": 100012}, - {"name": "토다리", "price": 1001230}, - {"name": "감자", "price": 1012300}, - {"name": "백호", "price": 10300}, - {"name": "웨디", "price": 1000} -] diff --git a/client/src/mocks/mockEndpointPrefix.ts b/client/src/mocks/mockEndpointPrefix.ts new file mode 100644 index 000000000..d02762e51 --- /dev/null +++ b/client/src/mocks/mockEndpointPrefix.ts @@ -0,0 +1,3 @@ +import {BASE_URL} from '@apis/baseUrl'; + +export const MOCK_API_PREFIX = typeof window !== 'undefined' ? `${BASE_URL.HD}` : ''; diff --git a/client/src/mocks/reportList.json b/client/src/mocks/reportList.json deleted file mode 100644 index a663eb9fd..000000000 --- a/client/src/mocks/reportList.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "name": "소하", - "price": 40000 - }, - { - "name": "감자", - "price": 20000 - }, - { - "name": "쿠키", - "price": 40000 - }, - { - "name": "토다리", - "price": 0 - } -] diff --git a/client/src/mocks/sharedState.ts b/client/src/mocks/sharedState.ts new file mode 100644 index 000000000..5f584092d --- /dev/null +++ b/client/src/mocks/sharedState.ts @@ -0,0 +1,143 @@ +export let eventData = { + eventName: '행동대장 야유회', + bankName: '', + accountNumber: '000000-01-121212', +}; + +export let memberData = { + members: [ + {id: 1, name: '망쵸', isDeposited: false}, + {id: 2, name: '백호', isDeposited: true}, + {id: 3, name: '감자', isDeposited: true}, + {id: 4, name: '이상', isDeposited: false}, + {id: 5, name: '소하', isDeposited: false}, + {id: 6, name: '웨디', isDeposited: false}, + {id: 7, name: '쿠키', isDeposited: false}, + ], +}; + +export let billData = { + steps: [ + { + bills: [ + {id: 1, title: '커피', price: 10000, isFixed: false}, + {id: 2, title: '인생네컷', price: 20000, isFixed: false}, + ], + members: [ + {id: 1, name: '망쵸'}, + {id: 2, name: '백호'}, + ], + }, + { + bills: [{id: 3, title: '맥주', price: 20000, isFixed: true}], + members: [ + {id: 1, name: '망쵸'}, + {id: 2, name: '백호'}, + {id: 3, name: '감자'}, + ], + }, + { + bills: [{id: 4, title: '뽕쟁이족', price: 70000, isFixed: false}], + members: [ + {id: 1, name: '망쵸'}, + {id: 2, name: '백호'}, + {id: 3, name: '감자'}, + {id: 4, name: '이상'}, + {id: 5, name: '소하'}, + {id: 6, name: '웨디'}, + {id: 7, name: '쿠키'}, + ], + }, + ], +}; + +export let billDetailsData = { + '1': { + billDetails: [ + { + id: 1, + memberName: '망쵸', + price: 5000, + isFixed: false, + }, + { + id: 2, + memberName: '백호', + price: 5000, + isFixed: false, + }, + ], + }, + '2': { + billDetails: [ + { + id: 1, + memberName: '망쵸', + price: 10000, + isFixed: false, + }, + { + id: 2, + memberName: '백호', + price: 10000, + isFixed: false, + }, + ], + }, + '3': { + billDetails: [ + { + id: 1, + memberName: '망쵸', + price: 5000, + isFixed: false, + }, + { + id: 2, + memberName: '백호', + price: 10000, + isFixed: true, + }, + { + id: 2, + memberName: '감자', + price: 5000, + isFixed: false, + }, + ], + }, + '4': { + billDetails: [ + {id: 1, memberName: '망쵸', price: 10000, isFixed: false}, + {id: 2, memberName: '백호', price: 10000, isFixed: false}, + {id: 3, memberName: '감자', price: 10000, isFixed: false}, + {id: 4, memberName: '이상', price: 10000, isFixed: false}, + {id: 5, memberName: '소하', price: 10000, isFixed: false}, + {id: 6, memberName: '웨디', price: 10000, isFixed: false}, + {id: 7, memberName: '쿠키', price: 10000, isFixed: false}, + ], + }, +}; + +export let reportData = { + reports: [ + { + memberId: 1, + memberName: '망쵸', + price: 20000, + isDeposited: false, + }, + { + memberId: 2, + memberName: '백호', + price: 25000, + isDeposited: true, + }, + { + memberId: 3, + memberName: '감자', + price: 5000, + isDeposited: true, + }, + ], +}; diff --git a/client/src/mocks/stepList.json b/client/src/mocks/stepList.json deleted file mode 100644 index 355692d58..000000000 --- a/client/src/mocks/stepList.json +++ /dev/null @@ -1,100 +0,0 @@ -[ - { - "type": "IN", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 1, - "name": "망쵸", - "price": null, - "sequence": 1, - "isFixed": false - }, - { - "actionId": 2, - "name": "백호", - "price": null, - "sequence": 2, - "isFixed": false - } - ] - }, - { - "type": "BILL", - "stepName": "1차", - "members": ["망쵸", "백호"], - "actions": [ - { - "actionId": 3, - "name": "감자탕", - "price": 10000, - "sequence": 3, - "isFixed": false - }, - { - "actionId": 4, - "name": "인생네컷", - "price": 10000, - "sequence": 4, - "isFixed": false - } - ] - }, - { - "type": "IN", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 5, - "name": "소하", - "price": null, - "sequence": 5, - "isFixed": false - }, - { - "actionId": 6, - "name": "웨디", - "price": null, - "sequence": 6, - "isFixed": false - } - ] - }, - { - "type": "BILL", - "stepName": "2차", - "members": ["소하", "웨디"], - "actions": [ - { - "actionId": 9, - "name": "노래방", - "price": 20000, - "sequence": 10, - "isFixed": false - } - ] - }, - { - "type": "OUT", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 7, - "name": "망쵸", - "price": null, - "sequence": 7, - "isFixed": false - }, - { - "actionId": 8, - "name": "백호", - "price": null, - "sequence": 8, - "isFixed": false - } - ] - } -] diff --git a/client/src/pages/AccountPage/Account.tsx b/client/src/pages/AccountPage/Account.tsx new file mode 100644 index 000000000..0490ead31 --- /dev/null +++ b/client/src/pages/AccountPage/Account.tsx @@ -0,0 +1,82 @@ +import {useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; + +import BankSelectModal from '@components/Modal/BankSelectModal/BankSelectModal'; + +import useAccount from '@hooks/useAccount'; + +import {FixedButton, Flex, FunnelLayout, LabelInput, MainLayout, Top, TopNav} from '@components/Design'; + +import getDeletedLastPath from '@utils/getDeletedLastPath'; + +const Account = () => { + const navigate = useNavigate(); + const location = useLocation(); + + const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false); + + const { + bankName, + accountNumber, + accountNumberErrorMessage, + canSubmit, + selectBank, + handleAccount, + handleAccountOnPaste, + enrollAccount, + } = useAccount(); + + const enrollAccountAndNavigateAdmin = async () => { + await enrollAccount(); + navigate(getDeletedLastPath(location.pathname)); + }; + + return ( + + + + + + + + + + + setIsBottomSheetOpen(true)} + /> + + {isBottomSheetOpen && ( + + )} + + + navigate(-1)}> + 확인 + + + ); +}; + +export default Account; diff --git a/client/src/pages/AddBillFunnel/AddBillFunnel.tsx b/client/src/pages/AddBillFunnel/AddBillFunnel.tsx new file mode 100644 index 000000000..acb13d698 --- /dev/null +++ b/client/src/pages/AddBillFunnel/AddBillFunnel.tsx @@ -0,0 +1,34 @@ +import {Member} from 'types/serviceType'; + +import useAddBillFunnel from '@hooks/useAddBillFunnel'; + +import {MainLayout, TopNav} from '@components/Design'; + +import PriceStep from './steps/PriceStep'; +import {TitleStep} from './steps/TitleStep'; +import MembersStep from './steps/MembersStep'; + +export interface BillInfo { + price: string; + title: string; + members: Member[]; +} + +const AddBillFunnel = () => { + const {step, setStep, billInfo, setBillInfo, currentMembers} = useAddBillFunnel(); + + return ( + + + + + {step === 'price' && } + {step === 'title' && } + {step === 'members' && ( + + )} + + ); +}; + +export default AddBillFunnel; diff --git a/client/src/pages/AddBillFunnel/steps/MembersStep.tsx b/client/src/pages/AddBillFunnel/steps/MembersStep.tsx new file mode 100644 index 000000000..fe4052d8e --- /dev/null +++ b/client/src/pages/AddBillFunnel/steps/MembersStep.tsx @@ -0,0 +1,104 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; +import ChipButton from '@components/Design/components/ChipButton/ChipButton'; +import {Member} from 'types/serviceType'; + +import useMembersStep from '@hooks/useMembersStep'; +import {BillStep} from '@hooks/useAddBillFunnel'; + +import {FixedButton, Flex, LabelInput, Text} from '@components/Design'; + +import {BillInfo} from '../AddBillFunnel'; + +interface Props { + billInfo: BillInfo; + setBillInfo: React.Dispatch>; + setStep: React.Dispatch>; + currentMembers: Member[]; +} + +const MembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => { + const { + errorMessage, + nameInput, + inputRef, + handleNameInputChange, + handleNameInputEnter, + isPendingPostBill, + isPendingPostMembers, + canSubmitMembers, + handlePostBill, + handlePrevStep, + } = useMembersStep({billInfo, setBillInfo, currentMembers, setStep}); + + return ( + <> +

    + + + + + +
    + + + 참여 인원 + + {`총 ${billInfo.members.length}명`} + +
    + {billInfo.members.map(member => ( + setBillInfo(prev => ({...prev, members: prev.members.filter(name => name !== member)}))} + /> + ))} +
    +
    +
    + + 추가완료 + + + ); +}; + +export default MembersStep; diff --git a/client/src/pages/AddBillFunnel/steps/PriceStep.tsx b/client/src/pages/AddBillFunnel/steps/PriceStep.tsx new file mode 100644 index 000000000..fea267860 --- /dev/null +++ b/client/src/pages/AddBillFunnel/steps/PriceStep.tsx @@ -0,0 +1,64 @@ +import {css} from '@emotion/react'; +import {useNavigate} from 'react-router-dom'; + +import AmountInput from '@components/AmountInput/AmountInput'; +import NumberKeyboard from '@components/Design/components/NumberKeyboard/NumberKeyboard'; +import Top from '@components/Design/components/Top/Top'; + +import usePriceStep from '@hooks/usePriceStep'; +import {BillStep} from '@hooks/useAddBillFunnel'; + +import {FixedButton} from '@components/Design'; + +import RULE from '@constants/rule'; + +import {BillInfo} from '../AddBillFunnel'; + +interface Props { + billInfo: BillInfo; + setBillInfo: React.Dispatch>; + setStep: React.Dispatch>; +} + +const PriceStep = ({billInfo, setBillInfo, setStep}: Props) => { + const navigate = useNavigate(); + const {handleNumberKeyboardChange, handleNextStep} = usePriceStep({setBillInfo, setStep}); + + return ( + <> +
    + + + + +
    +
    + +
    + navigate(-1)}> + 다음으로 + + + ); +}; + +export default PriceStep; diff --git a/client/src/pages/AddBillFunnel/steps/TitleStep.tsx b/client/src/pages/AddBillFunnel/steps/TitleStep.tsx new file mode 100644 index 000000000..eb910991f --- /dev/null +++ b/client/src/pages/AddBillFunnel/steps/TitleStep.tsx @@ -0,0 +1,63 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; + +import useTitleStep from '@hooks/useTitleStep'; +import {BillStep} from '@hooks/useAddBillFunnel'; + +import {FixedButton, LabelInput} from '@components/Design'; + +import {BillInfo} from '../AddBillFunnel'; + +interface Props { + billInfo: BillInfo; + setBillInfo: React.Dispatch>; + setStep: React.Dispatch>; +} + +export const TitleStep = ({billInfo, setBillInfo, setStep}: Props) => { + const { + errorMessage, + handleTitleInputChange, + handleTitleInputEnter, + canSubmitTitleInput, + handlePrevStep, + handleNextStep, + } = useTitleStep({ + billInfo, + setBillInfo, + setStep, + }); + + return ( + <> +
    + + + + + +
    + + 다음으로 + + + ); +}; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx deleted file mode 100644 index 066165d6a..000000000 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import {useLocation, useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; - -import {RunningDog} from '@components/Common/Logo'; - -import {ROUTER_URLS} from '@constants/routerUrls'; - -const CompleteCreateEventPage = () => { - const navigate = useNavigate(); - const location = useLocation(); - - const params = new URLSearchParams(location.search); - const eventId = params.get('eventId'); - - return ( - - - - <RunningDog /> - <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventId}/admin`)}>관리 페이지로 이동</FixedButton> - </MainLayout> - ); -}; - -export default CompleteCreateEventPage; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx new file mode 100644 index 000000000..34ee64661 --- /dev/null +++ b/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx @@ -0,0 +1,38 @@ +import {useNavigate} from 'react-router-dom'; +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; + +import {RunningDog} from '@components/Logo'; + +import {FixedButton} from '@HDesign/index'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +type CompleteCreateEventStepProps = { + eventToken: string; +}; + +const CompleteCreateEventStep = ({eventToken}: CompleteCreateEventStepProps) => { + const navigate = useNavigate(); + + return ( + <div + css={css` + display: flex; + flex-direction: column; + gap: 3rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text="행사가 생성되었어요!" emphasize={['행사가 생성되었어요!']} /> + <Top.Line text="관리 페이지에서 정산을 시작하세요" emphasize={['정산을 시작하세요']} /> + </Top> + <RunningDog /> + <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventToken}/admin`)}>관리 페이지로 이동</FixedButton> + </div> + ); +}; + +export default CompleteCreateEventStep; diff --git a/client/src/pages/CreateEventPage/CreateEventFunnel.tsx b/client/src/pages/CreateEventPage/CreateEventFunnel.tsx new file mode 100644 index 000000000..f21e62f23 --- /dev/null +++ b/client/src/pages/CreateEventPage/CreateEventFunnel.tsx @@ -0,0 +1,60 @@ +import {useNavigate} from 'react-router-dom'; + +import useFunnel from '@hooks/useFunnel'; +import useCreateEventData from '@hooks/useCreateEventData'; + +import {MainLayout, TopNav} from '@components/Design'; + +import SetEventNameStep from './SetEventNameStep'; +import SetEventPasswordStep from './SetEventPasswordStep'; +import CompleteCreateEventStep from './CompleteCreateEventStep'; + +type CreateEventStep = 'eventName' | 'eventPassword' | 'complete'; +const STEP_SEQUENCE: CreateEventStep[] = ['eventName', 'eventPassword', 'complete']; + +const CreateEventFunnel = () => { + const navigate = useNavigate(); + const {moveToNextStep, moveToPrevStep, Funnel, step} = useFunnel({ + defaultStep: 'eventName', + stepList: STEP_SEQUENCE, + }); + + const {eventNameProps, eventToken, setEventToken} = useCreateEventData(); + + const handleBack = () => { + if (step === STEP_SEQUENCE[0]) { + navigate('/'); + } else { + moveToPrevStep(); + } + }; + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + {step !== STEP_SEQUENCE[STEP_SEQUENCE.length - 1] && ( + <TopNav.Item displayName="뒤로가기" noEmphasis routePath="" onHandleRouteInFunnel={handleBack} /> + )} + </TopNav> + <Funnel step={step}> + <Funnel.Step name="eventName"> + <SetEventNameStep moveToNextStep={moveToNextStep} {...eventNameProps} /> + </Funnel.Step> + + <Funnel.Step name="eventPassword"> + <SetEventPasswordStep + moveToNextStep={moveToNextStep} + eventName={eventNameProps.eventName} + setEventToken={setEventToken} + /> + </Funnel.Step> + + <Funnel.Step name="complete"> + <CompleteCreateEventStep eventToken={eventToken} /> + </Funnel.Step> + </Funnel> + </MainLayout> + ); +}; + +export default CreateEventFunnel; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx deleted file mode 100644 index ad68327d2..000000000 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import {useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; -import {css} from '@emotion/react'; - -import useSetEventNamePage from '@hooks/useSetEventNamePage'; - -import {ROUTER_URLS} from '@constants/routerUrls'; - -const SetEventNamePage = () => { - const navigate = useNavigate(); - const {eventName, errorMessage, canSubmit, handleEventNameChange} = useSetEventNamePage(); - - const submitEventName = (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); - - navigate(ROUTER_URLS.eventCreatePassword, {state: {eventName}}); - }; - - return ( - <MainLayout backgroundColor="white"> - <TopNav> - <Back /> - </TopNav> - <Title title="행사 이름 입력" description="시작할 행사 이름을 입력해 주세요." /> - <form onSubmit={submitEventName} css={css({padding: '0 1rem'})}> - <LabelInput - labelText="행사 이름" - errorText={errorMessage ?? ''} - value={eventName} - type="text" - placeholder="행사 이름" - onChange={handleEventNameChange} - isError={!!errorMessage} - autoFocus - ></LabelInput> - <FixedButton disabled={!canSubmit}>다음</FixedButton> - </form> - </MainLayout> - ); -}; - -export default SetEventNamePage; diff --git a/client/src/pages/CreateEventPage/SetEventNameStep.tsx b/client/src/pages/CreateEventPage/SetEventNameStep.tsx new file mode 100644 index 000000000..924c4b79d --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventNameStep.tsx @@ -0,0 +1,56 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; + +import {UseSetEventNameStepReturnType} from '@hooks/useSetEventNameStep'; + +import {FixedButton, Flex, LabelInput} from '@HDesign/index'; + +type SetEventNamePageProps = UseSetEventNameStepReturnType & { + moveToNextStep: () => void; +}; + +const SetEventNameStep = ({ + eventName, + moveToNextStep, + errorMessage, + handleEventNameChange, + canSubmit, +}: SetEventNamePageProps) => { + const onSubmit = (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + + moveToNextStep(); + }; + + return ( + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text="정산을 시작하려는" /> + <Top.Line text="행사의 이름은 무엇인가요?" emphasize={['행사의 이름']} /> + </Top> + <form onSubmit={onSubmit}> + <LabelInput + labelText="행사 이름" + errorText={errorMessage ?? ''} + value={eventName} + type="text" + placeholder="행동대장 야유회" + onChange={handleEventNameChange} + isError={!!errorMessage} + autoFocus + /> + <FixedButton disabled={!canSubmit}>다음</FixedButton> + </form> + </div> + ); +}; + +export default SetEventNameStep; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx deleted file mode 100644 index 14fcdd75b..000000000 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; - -import useSetEventPasswordPage from '@hooks/useSetEventPasswordPage'; - -import RULE from '@constants/rule'; -import {PASSWORD_LENGTH} from '@constants/password'; - -const SetEventPasswordPage = () => { - const {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending} = - useSetEventPasswordPage(); - - return ( - <MainLayout backgroundColor="white"> - <TopNav> - <Back /> - </TopNav> - <Title - title="행사 비밀번호 설정" - description={`행사 관리에 필요한 ${PASSWORD_LENGTH} 자리의 숫자 비밀번호를 입력해 주세요.`} - /> - <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> - <LabelInput - labelText="비밀번호" - errorText={errorMessage} - value={password} - type="text" - maxLength={RULE.maxEventPasswordLength} - placeholder="비밀번호" - onChange={handleChange} - isError={!!errorMessage} - autoFocus - /> - <FixedButton variants={isPostEventPending ? 'loading' : 'primary'} disabled={!canSubmit}> - 행동 개시! - </FixedButton> - </form> - </MainLayout> - ); -}; - -export default SetEventPasswordPage; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx b/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx new file mode 100644 index 000000000..45370fd01 --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx @@ -0,0 +1,64 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; + +import useSetEventPasswordStep, {UseSetEventPasswordStepReturnType} from '@hooks/useSetEventPasswordStep'; + +import {FixedButton, LabelInput} from '@HDesign/index'; + +import RULE from '@constants/rule'; + +type SetEventPasswordPageProps = { + eventName: string; + moveToNextStep: () => void; + setEventToken: (eventToken: string) => void; +}; + +const SetEventPasswordStep = ({eventName, moveToNextStep, setEventToken}: SetEventPasswordPageProps) => { + const {submitDataForPostEvent, errorMessage, password, handleChange, isPostEventPending, canSubmit} = + useSetEventPasswordStep(); + + const submit = async (event: React.FormEvent<HTMLFormElement>) => { + await submitDataForPostEvent({event, eventName, setEventToken}); + + moveToNextStep(); + }; + + return ( + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line + text={`관리에 필요한 ${RULE.maxEventPasswordLength}자리 숫자`} + emphasize={[`${RULE.maxEventPasswordLength}자리 숫자`]} + /> + <Top.Line text="비밀번호는 무엇으로 할까요?" emphasize={['비밀번호']} /> + </Top> + <form onSubmit={submit}> + <LabelInput + labelText="비밀번호" + errorText={errorMessage} + value={password} + type="text" + maxLength={RULE.maxEventPasswordLength} + placeholder="1234" + onChange={handleChange} + isError={!!errorMessage} + autoFocus + /> + {/* 가상 키패드 적용 예정 */} + <FixedButton type="submit" variants={isPostEventPending ? 'loading' : 'primary'} disabled={!canSubmit}> + 행동 개시! + </FixedButton> + </form> + </div> + ); +}; + +export default SetEventPasswordStep; diff --git a/client/src/pages/CreateEventPage/index.ts b/client/src/pages/CreateEventPage/index.ts index 6d3d6c808..8d5867dc6 100644 --- a/client/src/pages/CreateEventPage/index.ts +++ b/client/src/pages/CreateEventPage/index.ts @@ -1,3 +1,3 @@ -export {default as SetEventNamePage} from './SetEventNamePage'; -export {default as SetEventPasswordPage} from './SetEventPasswordPage'; -export {default as CompleteCreateEventPage} from './CompleteCreateEventPage'; +export {default as SetEventNameStep} from './SetEventNameStep'; +export {default as SetEventPasswordStep} from './SetEventPasswordStep'; +export {default as CompleteCreateEventStep} from './CompleteCreateEventStep'; diff --git a/client/src/pages/EditBillPage/EditBillPage.tsx b/client/src/pages/EditBillPage/EditBillPage.tsx new file mode 100644 index 000000000..75a02d755 --- /dev/null +++ b/client/src/pages/EditBillPage/EditBillPage.tsx @@ -0,0 +1,96 @@ +import {css} from '@emotion/react'; + +import AmountInput from '@components/AmountInput/AmountInput'; +import BillDetails from '@components/BillDetails/BillDetails'; +import NumberKeyboardBottomSheet from '@components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet'; +import Top from '@components/Design/components/Top/Top'; + +import useEditBillPage from '@hooks/useEditBillPage'; + +import {FixedButton, Flex, MainLayout, TopNav} from '@components/Design'; + +const EditBillPage = () => { + const { + newBill, + newBillDetails, + billDetailsRef, + handleChangeBillTitle, + handleChangeBillPrice, + handleChangeBillDetails, + handleClickBillDetailInput, + handleClickDelete, + handleClickUpdate, + isPendingUpdate, + canSubmit, + keyboardInitialValue, + keyboardMaxPrice, + keyboardTargetId, + setKeyboardTargetId, + } = useEditBillPage(); + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <TopNav.Item displayName="뒤로가기" noEmphasis routePath="-1" /> + </TopNav> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Flex justifyContent="spaceBetween"> + <Top.EditableLine value={newBill.title} onChange={handleChangeBillTitle} /> + <Top.Line text="에서" /> + </Flex> + </Top> + <AmountInput + value={newBill.price.toLocaleString('ko-kr')} + onClick={() => handleClickBillDetailInput(0)} + underlined={true} + activated={keyboardTargetId === 0} + /> + + <BillDetails + ref={billDetailsRef} + billDetails={newBillDetails} + onClickInput={handleClickBillDetailInput} + activatedId={keyboardTargetId as number} + /> + </div> + {keyboardTargetId !== null && ( + <div + css={css` + height: 416px; + `} + content=" " + /> + )} + <FixedButton + disabled={!canSubmit} + onClick={handleClickUpdate} + onDeleteClick={handleClickDelete} + variants={isPendingUpdate() ? 'loading' : 'primary'} + > + 수정완료 + </FixedButton> + <NumberKeyboardBottomSheet + type="amount" + maxNumber={keyboardMaxPrice} + initialValue={keyboardInitialValue} + onChange={ + keyboardTargetId === 0 + ? handleChangeBillPrice + : (value: string) => handleChangeBillDetails({value, keyboardTargetId: keyboardTargetId ?? 0}) + } + isOpened={keyboardTargetId !== null} + onClose={() => setKeyboardTargetId(null)} + /> + </MainLayout> + ); +}; + +export default EditBillPage; diff --git a/client/src/pages/ErrorPage/ErrorPage.tsx b/client/src/pages/ErrorPage/ErrorPage.tsx index 31ef8c81f..92810e668 100644 --- a/client/src/pages/ErrorPage/ErrorPage.tsx +++ b/client/src/pages/ErrorPage/ErrorPage.tsx @@ -1,12 +1,13 @@ -import {MainLayout, Title} from 'haengdong-design'; +import Top from '@components/Design/components/Top/Top'; + +import {MainLayout} from '@HDesign/index'; const ErrorPage = () => { return ( <MainLayout> - <Title - title="알 수 없는 오류입니다." - description="오류가 난 상황에 대해 haengdongdj@gmail.com 로 연락주시면 소정의 상품을 드립니다." - /> + <Top> + <Top.Line text="알 수 없는 오류입니다." emphasize={['알 수 없는 오류입니다.']} /> + </Top> </MainLayout> ); }; diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts index cf6bb0042..830ec74a2 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts +++ b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts @@ -4,7 +4,8 @@ export const receiptStyle = () => css({ display: 'flex', flexDirection: 'column', - gap: '1rem', + gap: '0.5rem', + paddingInline: '1rem', paddingBottom: '2rem', }); diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 79deeac7a..c69170897 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -1,89 +1,59 @@ -import {useEffect, useState} from 'react'; -import {Title, FixedButton, ListButton, Button} from 'haengdong-design'; -import {useOutletContext} from 'react-router-dom'; +import {useEffect} from 'react'; +import {useNavigate, useOutletContext} from 'react-router-dom'; -import StepList from '@components/StepList/StepList'; -import {ModalBasedOnMemberCount, SetAllMemberListModal} from '@components/Modal/index'; -import useRequestGetAllMemberList from '@hooks/queries/useRequestGetAllMemberList'; -import useRequestPostAuthenticate from '@hooks/queries/useRequestPostAuthentication'; +import StepList from '@components/StepList/Steps'; +import useRequestPostAuthenticate from '@hooks/queries/auth/useRequestPostAuthentication'; +import useRequestGetSteps from '@hooks/queries/step/useRequestGetSteps'; import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; +import {Title, Button, Dropdown, DropdownButton} from '@HDesign/index'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + import {EventPageContextProps} from '../EventPageLayout'; -import {receiptStyle, titleAndListButtonContainerStyle, buttonGroupStyle} from './AdminPage.style'; +import {receiptStyle} from './AdminPage.style'; const AdminPage = () => { - const [isOpenFixedButtonBottomSheet, setIsOpenFixedButtonBottomSheet] = useState(false); - const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); - const [isAddEditableItem, setIsAddEditableItem] = useState(false); - - const {eventName} = useOutletContext<EventPageContextProps>(); - const {data: allMemberListData} = useRequestGetAllMemberList(); - const allMemberList = allMemberListData?.memberNames ?? []; + const navigate = useNavigate(); + const eventId = getEventIdByUrl(); + const {isAdmin, eventName} = useOutletContext<EventPageContextProps>(); const {totalExpenseAmount} = useTotalExpenseAmountStore(); - const {mutate: postAuthentication} = useRequestPostAuthenticate(); + const {steps} = useRequestGetSteps(); + const {postAuthenticate} = useRequestPostAuthenticate(); useEffect(() => { - postAuthentication(); - }, [postAuthentication]); + postAuthenticate(); + }, [postAuthenticate]); - const handleOpenAllMemberListButton = () => { - setIsOpenFixedButtonBottomSheet(prev => !prev); - setIsOpenAllMemberListButton(prev => !prev); + const navigateAccountInputPage = () => { + navigate(`/event/${eventId}/admin/edit`); }; - const getTitleDescriptionByInitialMemberSetting = () => { - return allMemberList.length > 0 - ? `지출 내역 및 인원 변동을 추가해 주세요. - 인원 변동을 기준으로 몇 차인지 나뉘어져요.` - : '“시작 인원 추가” 버튼을 눌러 행사의 시작부터 참여하는 사람들의 이름을 입력해 주세요.'; + const navigateEventMemberManage = () => { + navigate(`/event/${eventId}/admin/member`); }; return ( - <> - <div css={titleAndListButtonContainerStyle}> - <Title title={eventName} description={getTitleDescriptionByInitialMemberSetting()} price={totalExpenseAmount} /> - {allMemberList.length !== 0 && ( - <ListButton - prefix="전체 참여자" - suffix={`${allMemberList.length}명`} - onClick={handleOpenAllMemberListButton} - /> - )} - </div> - <section css={receiptStyle}> - <StepList isAddEditableItem={isAddEditableItem} setIsAddEditableItem={setIsAddEditableItem} /> - {allMemberList.length === 0 ? ( - <FixedButton children={'시작인원 추가하기'} onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} /> - ) : ( - <div css={buttonGroupStyle}> - <Button - size="medium" - variants="tertiary" - style={{width: '100%'}} - onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} - > - 인원 변동 추가 - </Button> - <Button size="medium" onClick={() => setIsAddEditableItem(true)} style={{width: '100%'}}> - 지출 내역 추가 - </Button> - </div> - )} - {isOpenFixedButtonBottomSheet && ( - <ModalBasedOnMemberCount - allMemberList={allMemberList} - setIsOpenBottomSheet={setIsOpenFixedButtonBottomSheet} - isOpenBottomSheet={isOpenFixedButtonBottomSheet} - isOpenAllMemberListButton={isOpenAllMemberListButton} - setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} - /> - )} - </section> - </> + <section css={receiptStyle}> + <Title + title={eventName} + amount={totalExpenseAmount} + dropdown={ + <Dropdown> + <DropdownButton text="전체 참여자 관리" onClick={navigateEventMemberManage} /> + <DropdownButton text="계좌번호 입력하기" onClick={navigateAccountInputPage} /> + </Dropdown> + } + /> + <StepList data={steps ?? []} isAdmin={isAdmin} /> + <Button size="medium" onClick={() => navigate(`/event/${eventId}/add-bill`)} style={{width: '100%'}}> + 지출내역 추가하기 + </Button> + </section> ); }; diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index 741dca3eb..03e189fc1 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -1,20 +1,33 @@ -import {FixedButton, LabelInput, Title} from 'haengdong-design'; +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; import useEventLogin from '@hooks/useEventLogin'; +import {FixedButton, LabelInput} from '@HDesign/index'; + import RULE from '@constants/rule'; -import {PASSWORD_LENGTH} from '@constants/password'; const EventLoginPage = () => { const {password, errorMessage, handleChange, canSubmit, submitPassword} = useEventLogin(); return ( - <> - <Title - title="행사 비밀번호 입력" - description={`관리를 위해선 비밀번호가 필요해요. 행사 생성 시 설정한 ${PASSWORD_LENGTH} 자리의 숫자 비밀번호를 입력해 주세요.`} - /> - <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line + text={`행사 생성 시 설정한 ${RULE.maxEventPasswordLength}자리`} + emphasize={[`${RULE.maxEventPasswordLength}자리`]} + /> + <Top.Line text="숫자 비밀번호를 입력해 주세요." emphasize={['비밀번호']} /> + </Top> + <form onSubmit={submitPassword}> <LabelInput labelText="비밀번호" errorText={errorMessage} @@ -28,7 +41,7 @@ const EventLoginPage = () => { ></LabelInput> <FixedButton disabled={!canSubmit}>관리 페이지로</FixedButton> </form> - </> + </div> ); }; diff --git a/client/src/pages/EventPage/AdminPage/EventMember.style.ts b/client/src/pages/EventPage/AdminPage/EventMember.style.ts new file mode 100644 index 000000000..f59f288bd --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/EventMember.style.ts @@ -0,0 +1,56 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@components/Design/theme/theme.type'; +import TYPOGRAPHY from '@components/Design/token/typography'; + +export const eventMemberStyle = () => + css({ + padding: '0 1rem', + }); + +export const memberList = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + padding: '0 0.5rem', + marginTop: '1rem', + height: 'inherit', + marginBottom: '100px', + }); + +export const noneReports = () => + css({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + height: 'inherit', + }); + +export const eventMember = () => + css({ + display: 'flex', + alignItems: 'center', + gap: '0.5rem', + padding: '0.5rem 0', + width: 'inherit', + justifyContent: 'space-between', + }); + +export const memberEditInput = (theme: Theme) => + css({ + input: { + width: '100%', + }, + width: '6.125rem', + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + borderBottom: `1px solid ${theme.colors.tertiary}`, + ...TYPOGRAPHY.bodyBold, + + '&:has(input:focus)': { + borderBottom: `1px solid ${theme.colors.primary}`, + }, + }); diff --git a/client/src/pages/EventPage/AdminPage/EventMember.tsx b/client/src/pages/EventPage/AdminPage/EventMember.tsx new file mode 100644 index 000000000..cdeaa8d40 --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/EventMember.tsx @@ -0,0 +1,94 @@ +/** @jsxImportSource @emotion/react */ +import {Report} from 'types/serviceType'; + +import useEventMember from '@hooks/useEventMember'; + +import {MainLayout, TopNav, Top, Amount, DepositToggle, Icon, IconButton, FixedButton, Text} from '@components/Design'; +import {useTheme} from '@components/Design'; + +import {eventMemberStyle, memberList, eventMember, memberEditInput, noneReports} from './EventMember.style'; + +const EventMember = () => { + const {reports, canSubmit, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus} = + useEventMember(); + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <TopNav.Item displayName="뒤로가기" noEmphasis routePath="-1" /> + </TopNav> + <section css={eventMemberStyle}> + <Top> + <Top.Line text="전체 참여자 관리" emphasize={['전체 참여자 관리']}></Top.Line> + </Top> + <div css={memberList}> + {reports.length === 0 ? ( + <div css={noneReports}> + <Text size="bodyBold">참여자가 존재하지 않아요!</Text> + <Text size="body" textColor="gray"> + 지출내역을 추가하면 참여자가 생성돼요. + </Text> + </div> + ) : ( + reports.map(member => { + return ( + <Member + key={member.memberId} + member={member} + changeMemberName={changeMemberName} + handleDeleteMember={handleDeleteMember} + toggleDepositStatus={toggleDepositStatus} + /> + ); + }) + )} + </div> + {reports.length === 0 ? ( + <></> + ) : ( + <FixedButton disabled={!canSubmit} onClick={updateMembersOnServer}> + 수정완료 + </FixedButton> + )} + </section> + </MainLayout> + ); +}; + +interface MemberProps { + member: Report; + changeMemberName: (memberId: number, newName: string) => void; + handleDeleteMember: (memberId: number) => void; + toggleDepositStatus: (memberId: number) => void; +} + +const Member = ({member, changeMemberName, handleDeleteMember, toggleDepositStatus}: MemberProps) => { + const {theme} = useTheme(); + + const handleChangeName = (e: React.ChangeEvent<HTMLInputElement>) => { + changeMemberName(member.memberId, e.target.value); + }; + + return ( + <div css={eventMember} id={`${member.memberId}`}> + <div css={memberEditInput(theme)}> + <input type="text" value={member.memberName} onChange={e => handleChangeName(e)} /> + <Icon iconType="pencilMini" /> + </div> + <div style={{display: 'flex', flexDirection: 'row', gap: '0.5rem'}}> + <Amount amount={member.price} /> + <DepositToggle isDeposit={member.isDeposited} onToggle={() => toggleDepositStatus(member.memberId)} /> + <IconButton + size="small" + variants="tertiary" + css={{width: '23px', height: '23px', borderRadius: '0.375rem'}} + onClick={() => handleDeleteMember(member.memberId)} + > + <Icon iconType="trashMini" /> + </IconButton> + </div> + </div> + ); +}; + +export default EventMember; diff --git a/client/src/pages/EventPage/EventPageFallback/BillEmptyFallback/index.tsx b/client/src/pages/EventPage/EventPageFallback/BillEmptyFallback/index.tsx new file mode 100644 index 000000000..4e8c0d7d7 --- /dev/null +++ b/client/src/pages/EventPage/EventPageFallback/BillEmptyFallback/index.tsx @@ -0,0 +1,16 @@ +import {Flex, Text} from '@components/Design'; + +import FALLBACK_TEXT from '../fallbackText'; + +const BillEmptyFallback = () => { + return ( + <Flex flexDirection="column" justifyContent="center" alignItems="center" gap="1.5rem" width="100%" height="20rem"> + <Text size="subTitle">{FALLBACK_TEXT.billEmptyTitle}</Text> + <Text size="body" style={{textAlign: 'center'}}> + {FALLBACK_TEXT.billEmptyHome} + </Text> + </Flex> + ); +}; + +export default BillEmptyFallback; diff --git a/client/src/pages/EventPage/EventPageFallback/fallbackText.ts b/client/src/pages/EventPage/EventPageFallback/fallbackText.ts new file mode 100644 index 000000000..6238264aa --- /dev/null +++ b/client/src/pages/EventPage/EventPageFallback/fallbackText.ts @@ -0,0 +1,7 @@ +const FALLBACK_TEXT = { + billEmptyTitle: '행사가 시작되지 않았어요', + billEmptyHome: `주최자가 아직 지출 내역을 +등록하지 않았어요.`, +} as const; + +export default FALLBACK_TEXT; diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 6f00c23f1..2fcf0d682 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,62 +1,39 @@ -import {MainLayout, TopNav, Switch, Button} from 'haengdong-design'; -import {Outlet, useMatch} from 'react-router-dom'; -import CopyToClipboard from 'react-copy-to-clipboard'; +import type {Event} from 'types/serviceType'; -import {useToast} from '@hooks/useToast/useToast'; -import useRequestGetEventName from '@hooks/queries/useRequestGetEventName'; +import {Outlet} from 'react-router-dom'; -import useNavSwitch from '@hooks/useNavSwitch'; +import useEventPageLayout from '@hooks/useEventPageLayout'; -import getEventIdByUrl from '@utils/getEventIdByUrl'; -import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; +import {ShareEventButton} from '@components/ShareEventButton'; -import {ROUTER_URLS} from '@constants/routerUrls'; +import {Flex, Icon, IconButton, MainLayout, TopNav} from '@HDesign/index'; -export type EventPageContextProps = { +export type EventPageContextProps = Event & { isAdmin: boolean; - eventName: string; }; const EventPageLayout = () => { - const {nav, paths, onChange} = useNavSwitch(); - const {data} = useRequestGetEventName(); - const eventName = data?.eventName ?? ''; - const eventId = getEventIdByUrl(); - - const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; - const isLoginPage = useMatch(ROUTER_URLS.eventLogin) !== null; + const {isAdmin, isLoginPage, eventOutline} = useEventPageLayout(); const outletContext: EventPageContextProps = { isAdmin, - eventName, + ...eventOutline, }; - const {showToast} = useToast(); - const url = getEventPageUrlByEnvironment(eventId, 'home'); - return ( <MainLayout backgroundColor="gray"> - <TopNav> - <Switch value={nav} values={paths} onChange={onChange} /> - {!isLoginPage && ( - <CopyToClipboard - text={`[행동대장]\n"${eventName}"에 대한 정산을 시작할게요:)\n아래 링크에 접속해서 정산 내역을 확인해 주세요!\n${url}`} - onCopy={() => - showToast({ - showingTime: 3000, - message: '링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', - type: 'confirm', - position: 'bottom', - bottom: '8rem', - }) - } - > - <Button size="small" variants="secondary"> - 정산 초대하기 - </Button> - </CopyToClipboard> - )} - </TopNav> + <Flex justifyContent="spaceBetween" alignItems="center"> + <TopNav> + <TopNav.Item routePath="/"> + <IconButton variants="none"> + <Icon iconType="heundeut" /> + </IconButton> + </TopNav.Item> + <TopNav.Item displayName="홈" routePath="/home" /> + <TopNav.Item displayName="관리" routePath="/admin" /> + </TopNav> + {!isLoginPage && <ShareEventButton eventOutline={eventOutline} />} + </Flex> <Outlet context={outletContext} /> </MainLayout> ); diff --git a/client/src/pages/EventPage/HomePage/HomePage.style.ts b/client/src/pages/EventPage/HomePage/HomePage.style.ts new file mode 100644 index 000000000..d02747cb2 --- /dev/null +++ b/client/src/pages/EventPage/HomePage/HomePage.style.ts @@ -0,0 +1,9 @@ +import {css} from '@emotion/react'; + +export const receiptStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + paddingInline: '1rem', + paddingBottom: '2rem', +}); diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx index 72fc77cb9..1876327bf 100644 --- a/client/src/pages/EventPage/HomePage/HomePage.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -1,23 +1,28 @@ -import {Tab, Tabs, Title} from 'haengdong-design'; +import type {EventPageContextProps} from '../EventPageLayout'; + import {useOutletContext} from 'react-router-dom'; -import MemberReportList from '@components/MemberReportList/MemberReportList'; -import StepList from '@components/StepList/StepList'; +import StepList from '@components/StepList/Steps'; +import useRequestGetSteps from '@hooks/queries/step/useRequestGetSteps'; +import Reports from '@components/Reports/Reports'; import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; -import {EventPageContextProps} from '../EventPageLayout'; +import {Tab, Tabs, Title} from '@HDesign/index'; + +import {receiptStyle} from './HomePage.style'; const HomePage = () => { - const {eventName} = useOutletContext<EventPageContextProps>(); + const {isAdmin, eventName} = useOutletContext<EventPageContextProps>(); + const {steps} = useRequestGetSteps(); const {totalExpenseAmount} = useTotalExpenseAmountStore(); return ( - <div style={{paddingBottom: '2rem'}}> - <Title title={eventName} price={totalExpenseAmount} /> - <Tabs tabsContainerStyle={{gap: '1rem'}}> - <Tab label="전체 지출 내역" content={<StepList />} /> - <Tab label="참여자 별 내역" content={<MemberReportList />} /> + <div css={receiptStyle}> + <Title title={eventName} amount={totalExpenseAmount} /> + <Tabs> + <Tab label="참여자 별 정산" content={<Reports />} /> + <Tab label="전체 지출 내역" content={<StepList data={steps ?? []} isAdmin={isAdmin} />} /> </Tabs> </div> ); diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx index d3a1cd079..50cae98b8 100644 --- a/client/src/pages/MainPage/MainPage.tsx +++ b/client/src/pages/MainPage/MainPage.tsx @@ -1,11 +1,11 @@ -import {MainLayout} from 'haengdong-design'; +import {Flex, MainLayout} from '@HDesign/index'; import Nav from './Nav/Nav'; import MainSection from './Section/MainSection'; import DescriptionSection from './Section/DescriptionSection'; import AddBillSection from './Section/AddBillSection'; import AddMemberSection from './Section/AddMemberSection'; -import MemberReportSection from './Section/MemberReportSection'; +import ReportSection from './Section/ReportSection'; const MainPage = () => { return ( @@ -15,7 +15,7 @@ const MainPage = () => { <DescriptionSection /> <AddBillSection /> <AddMemberSection /> - <MemberReportSection /> + <ReportSection /> </MainLayout> ); }; diff --git a/client/src/pages/MainPage/Nav/Nav.style.ts b/client/src/pages/MainPage/Nav/Nav.style.ts index 58cf1cb86..89589e825 100644 --- a/client/src/pages/MainPage/Nav/Nav.style.ts +++ b/client/src/pages/MainPage/Nav/Nav.style.ts @@ -1,19 +1,22 @@ import {css} from '@emotion/react'; -export const navStyle = css({ - position: 'fixed', - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - padding: '1rem', +import {Theme} from '@components/Design/theme/theme.type'; - top: '0', - width: '100%', - maxWidth: '768px', - zIndex: '20', - height: '4rem', - backgroundColor: 'white', -}); +export const navStyle = (theme: Theme) => + css({ + position: 'fixed', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '1rem', + + top: '0', + width: '100%', + maxWidth: '768px', + zIndex: theme.zIndex.navBackgroundColor, + height: '4rem', + backgroundColor: 'white', + }); export const logoStyle = css({ display: 'flex', diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx index ec4d745c9..2ca0cfb4d 100644 --- a/client/src/pages/MainPage/Nav/Nav.tsx +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -1,23 +1,32 @@ -import {Button, Flex, Text} from 'haengdong-design'; import {useNavigate} from 'react-router-dom'; -import Heundeut from '@assets/image/heundeut.svg'; +import {useTheme} from '@theme/HDesignProvider'; -import {ROUTER_URLS} from '@constants/routerUrls'; +import {Button, Flex, Text, Icon, TopNav, IconButton} from '@HDesign/index'; -import {logoStyle, navStyle} from './Nav.style'; +import {ROUTER_URLS} from '@constants/routerUrls'; const Nav = () => { + const {theme} = useTheme(); const navigate = useNavigate(); return ( - <header css={navStyle}> - <Flex gap="0.5rem"> - <Heundeut /> - <div css={logoStyle}> + <header style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', height: '37px'}}> + <TopNav> + <TopNav.Item routePath="/"> + <IconButton variants="none"> + <Icon iconType="heundeut" /> + </IconButton> + </TopNav.Item> + <TopNav.Item routePath="/"> <Text size="subTitle">행동대장</Text> - </div> - </Flex> - <Button size="medium" variants="tertiary" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + </TopNav.Item> + </TopNav> + <Button + size="medium" + variants="tertiary" + onClick={() => navigate(ROUTER_URLS.createEvent)} + style={{marginRight: '1rem'}} + > 정산 시작하기 </Button> </header> diff --git a/client/src/pages/MainPage/Section/AddBillSection.tsx b/client/src/pages/MainPage/Section/AddBillSection.tsx index ecf7dd90d..ca2fe1f34 100644 --- a/client/src/pages/MainPage/Section/AddBillSection.tsx +++ b/client/src/pages/MainPage/Section/AddBillSection.tsx @@ -1,8 +1,9 @@ import {css} from '@emotion/react'; -import {Text} from 'haengdong-design'; import AddBillMockup from '@assets/image/addBillMockup.svg'; +import {Text} from '@HDesign/index'; + const AddBillSection = () => { return ( <div diff --git a/client/src/pages/MainPage/Section/AddMemberSection.tsx b/client/src/pages/MainPage/Section/AddMemberSection.tsx index ae6e7d1fc..a7ff92539 100644 --- a/client/src/pages/MainPage/Section/AddMemberSection.tsx +++ b/client/src/pages/MainPage/Section/AddMemberSection.tsx @@ -1,9 +1,10 @@ import {css} from '@emotion/react'; -import {Text} from 'haengdong-design'; -import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; import AddMemberMockup from '@assets/image/addMemberMockup.svg'; +import {Text} from '@HDesign/index'; +import {useTheme} from '@HDesign/index'; + const AddMemberSection = () => { const {theme} = useTheme(); return ( diff --git a/client/src/pages/MainPage/Section/DescriptionSection.tsx b/client/src/pages/MainPage/Section/DescriptionSection.tsx index 193cfe465..f53e88cf9 100644 --- a/client/src/pages/MainPage/Section/DescriptionSection.tsx +++ b/client/src/pages/MainPage/Section/DescriptionSection.tsx @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Text} from 'haengdong-design'; -import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; + +import {Text, useTheme} from '@HDesign/index'; const DescriptionSection = () => { const {theme} = useTheme(); diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx index 4bbeb7340..3be031978 100644 --- a/client/src/pages/MainPage/Section/MainSection.tsx +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -1,14 +1,17 @@ import {css, keyframes} from '@emotion/react'; -import {Button, Text} from 'haengdong-design'; import {useNavigate} from 'react-router-dom'; -import {StandingDog} from '@components/Common/Logo'; import ChevronDown from '@assets/image/chevronDownLarge.svg'; +import {StandingDog} from '@components/Logo'; + +import {Button, Text} from '@HDesign/index'; + import {ROUTER_URLS} from '@constants/routerUrls'; const MainSection = () => { const navigate = useNavigate(); + return ( <div css={css({ @@ -38,7 +41,7 @@ const MainSection = () => { <Text css={animateWithDelay(1)} style={{textAlign: 'center'}} size="title">{`행동대장을 통해 간편하게 정산하세요 `}</Text> - <Button css={animateWithDelay(2)} size="large" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + <Button css={animateWithDelay(2)} size="large" onClick={() => navigate(ROUTER_URLS.createEvent)}> 정산 시작하기 </Button> </div> diff --git a/client/src/pages/MainPage/Section/MemberReportSection.tsx b/client/src/pages/MainPage/Section/ReportSection.tsx similarity index 86% rename from client/src/pages/MainPage/Section/MemberReportSection.tsx rename to client/src/pages/MainPage/Section/ReportSection.tsx index 69871e1c9..452365ea2 100644 --- a/client/src/pages/MainPage/Section/MemberReportSection.tsx +++ b/client/src/pages/MainPage/Section/ReportSection.tsx @@ -1,9 +1,10 @@ import {css} from '@emotion/react'; -import {Text} from 'haengdong-design'; import MemberReportMockup from '@assets/image/memberReportMockup.svg'; -const MemberReportSection = () => { +import {Text} from '@HDesign/index'; + +const ReportSection = () => { return ( <div css={css({ @@ -28,4 +29,4 @@ const MemberReportSection = () => { ); }; -export default MemberReportSection; +export default ReportSection; diff --git a/client/src/router.tsx b/client/src/router.tsx index 51162c775..735b09786 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -4,8 +4,12 @@ import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; +import AddBillFunnel from '@pages/AddBillFunnel/AddBillFunnel'; +import CreateEventFunnel from '@pages/CreateEventPage/CreateEventFunnel'; +import EventMember from '@pages/EventPage/AdminPage/EventMember'; +import EditBillPage from '@pages/EditBillPage/EditBillPage'; +import Account from '@pages/AccountPage/Account'; -import {CompleteCreateEventPage, SetEventNamePage, SetEventPasswordPage} from '@pages/CreateEventPage'; import {MainPage} from '@pages/MainPage'; import {EventPage} from '@pages/EventPage'; @@ -24,16 +28,9 @@ const router = createBrowserRouter([ element: <MainPage />, }, { - path: ROUTER_URLS.eventCreateName, - element: <SetEventNamePage />, - }, - { - path: ROUTER_URLS.eventCreatePassword, - element: <SetEventPasswordPage />, - }, - { - path: ROUTER_URLS.eventCreateComplete, - element: <CompleteCreateEventPage />, + path: ROUTER_URLS.createEvent, + + element: <CreateEventFunnel />, }, { path: ROUTER_URLS.event, @@ -47,6 +44,22 @@ const router = createBrowserRouter([ }, ], }, + { + path: ROUTER_URLS.addBill, + element: <AddBillFunnel />, + }, + { + path: ROUTER_URLS.member, + element: <EventMember />, + }, + { + path: ROUTER_URLS.editBill, + element: <EditBillPage />, + }, + { + path: ROUTER_URLS.eventEdit, + element: <Account />, + }, { path: '*', element: <ErrorPage />, diff --git a/client/src/store/stepListStore.ts b/client/src/store/stepListStore.ts deleted file mode 100644 index 07f3b107f..000000000 --- a/client/src/store/stepListStore.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {create} from 'zustand'; - -import {ConvertedAction} from 'types/serviceType'; - -type State = { - stepList: ConvertedAction[]; -}; - -type Action = { - updateStepList: (stepList: State['stepList']) => void; -}; - -export const useStepListStore = create<State & Action>(set => ({ - stepList: [], - updateStepList: stepList => set(() => ({stepList})), -})); diff --git a/client/src/store/stepsStore.ts b/client/src/store/stepsStore.ts new file mode 100644 index 000000000..e89adf392 --- /dev/null +++ b/client/src/store/stepsStore.ts @@ -0,0 +1,16 @@ +import {create} from 'zustand'; + +import {Steps} from 'types/serviceType'; + +type State = { + steps: Steps[]; +}; + +type Action = { + updateSteps: (stepList: State['steps']) => void; +}; + +export const useBillsStore = create<State & Action>(set => ({ + steps: [], + updateSteps: steps => set(() => ({steps})), +})); diff --git a/client/src/store/totalExpenseAmountStore.ts b/client/src/store/totalExpenseAmountStore.ts index e9ebcf52a..cce46575e 100644 --- a/client/src/store/totalExpenseAmountStore.ts +++ b/client/src/store/totalExpenseAmountStore.ts @@ -1,6 +1,6 @@ import {create} from 'zustand'; -import {BillStep, MemberStep} from 'types/serviceType'; +import {Step as StepType} from 'types/serviceType'; import {getTotalExpenseAmount} from '@utils/caculateExpense'; @@ -9,10 +9,10 @@ type State = { }; type Action = { - updateTotalExpenseAmount: (stepList: (MemberStep | BillStep)[]) => void; + updateTotalExpenseAmount: (steps: StepType[]) => void; }; export const useTotalExpenseAmountStore = create<State & Action>(set => ({ totalExpenseAmount: 0, - updateTotalExpenseAmount: stepList => set({totalExpenseAmount: getTotalExpenseAmount(stepList)}), + updateTotalExpenseAmount: (steps: StepType[]) => set({totalExpenseAmount: getTotalExpenseAmount(steps)}), })); diff --git a/client/src/types/fetchErrorType.ts b/client/src/types/fetchErrorType.ts deleted file mode 100644 index 19fe8ee6f..000000000 --- a/client/src/types/fetchErrorType.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; - -import {Method} from '@apis/fetcher'; - -export type FetchErrorType = Error & { - requestBody: string; - status: number; - endpoint: string; - errorInfo: ErrorInfo; - method: Method; -}; diff --git a/client/src/types/kakao.d.ts b/client/src/types/kakao.d.ts new file mode 100644 index 000000000..4d72a9833 --- /dev/null +++ b/client/src/types/kakao.d.ts @@ -0,0 +1,38 @@ +declare global { + interface Window { + Kakao: typeof Kakao; + } +} + +namespace Kakao { + function init(appKey: string): void; + function isInitialized(): boolean; + + namespace Share { + function cleanup(): void; + function sendDefault(params: sendDefaultParams): void; + + interface sendDefaultParams { + objectType: 'feed'; + content: { + title: string; + imageUrl: string; + imageWidth?: number; + imageHeight?: number; + description: string; + link: { + mobileWebUrl: string; + webUrl: string; + }; + }; + buttonTitle?: string; + buttons?: { + title: string; + link: { + webUrl: string; + mobileWebUrl: string; + }; + }[]; + } + } +} diff --git a/client/src/types/serviceType.ts b/client/src/types/serviceType.ts index 0467995f1..a2ecca3aa 100644 --- a/client/src/types/serviceType.ts +++ b/client/src/types/serviceType.ts @@ -1,80 +1,67 @@ -export type MemberType = 'IN' | 'OUT'; +// ******************************************************************* +// ******************** UX 개선 이후 변경된 부분들 24.09.19 **************** +// ******************************************************************* -export type InOutType = '늦참' | '탈주'; +export interface Steps { + steps: Step[]; +} -export type MemberReport = { - name: string; - price: number; -}; +export interface Step { + bills: Bill[]; + members: Member[]; +} -export type MemberReportInAction = MemberReport & { - isFixed: boolean; -}; - -export type Bill = { +export interface Bill { + id: number; title: string; price: number; -}; - -type StepBase = { - members: string[]; -}; - -export type MemberStep = StepBase & { - type: MemberType; - stepName: null; - actions: MemberAction[]; -}; - -export type BillStep = StepBase & { - type: 'BILL'; - stepName: string; - actions: BillAction[]; -}; - -// (@weadie) 준 데이터 형식에서 steps를 빼내 flat하게 사용중. 일관성있게 하는게 좋긴 하나 사용시 번거로움이 있을 거라고 판단. -export type StepList = { - steps: (MemberStep | BillStep)[]; -}; - -export type Action = { - actionId: number; - name: string; - price: number | null; - sequence: number; isFixed: boolean; -}; +} -export type BillAction = Omit<Action, 'price'> & { +export interface BillDetail { + id: number; + memberName: string; price: number; -}; - -export type MemberAction = Omit<Action, 'price'> & { - price: null; -}; - -export type Member = { - name: string; - status: MemberType; -}; - -export type ActionType = 'IN' | 'OUT' | 'BILL'; + isFixed: boolean; +} -// export type StepList = { -// actions: Action[]; -// }; +export interface BillDetails { + members: BillDetail[]; +} -export type ConvertedAction = { - actionId: number; +export interface Member { + id: number; name: string; - price: string | null; - sequence: number; - type: ActionType; -}; - -export type InputPair = Omit<Bill, 'price'> & { - price: string; - index: number; -}; +} + +export interface Members { + members: Member[]; +} + +export interface MemberWithDeposited extends Member { + isDeposited: boolean; +} + +export interface AllMembers { + members: MemberWithDeposited[]; +} +export interface EventId { + eventId: string; +} + +export interface Event { + eventName: string; + bankName: string; + accountNumber: string; +} + +export interface Report { + memberId: number; + memberName: string; + isDeposited: boolean; + price: number; +} -export type BillInputType = 'title' | 'price'; +export interface Reports { + reports: Report[]; +} diff --git a/client/src/types/toastType.ts b/client/src/types/toastType.ts new file mode 100644 index 000000000..d81a20572 --- /dev/null +++ b/client/src/types/toastType.ts @@ -0,0 +1,20 @@ +import {Theme} from '@components/Design/theme/theme.type'; + +export type ToastPosition = 'bottom' | 'top'; + +export type ToastOptions = { + showingTime?: number; + isAutoClosed?: boolean; + isCloseOnClick?: boolean; + position?: ToastPosition; + bottom?: string; + top?: string; + theme?: Theme; +}; + +export type ToastMessage = string; + +export type ToastArgs = { + message: ToastMessage; + options: ToastOptions; +}; diff --git a/client/src/utils/NetworkStateCatcher.tsx b/client/src/utils/NetworkStateCatcher.tsx new file mode 100644 index 000000000..1a8158ec8 --- /dev/null +++ b/client/src/utils/NetworkStateCatcher.tsx @@ -0,0 +1,39 @@ +import {useEffect} from 'react'; + +import {useToast} from '@hooks/useToast/useToast'; +import toast from '@hooks/useToast/toast'; + +const NetworkStateCatcher = () => { + const handleNetworkOnline = () => { + // closeToast(); + }; + + const handleNetworkOffline = () => { + // TODO: (@weadie) 토스트 높이는 z-index 이슈가 해결되면 반영할 예정입니다. + toast.error('네트워크 연결 상태를 확인해주세요.', { + isAutoClosed: false, + position: 'bottom', + bottom: '6rem', + }); + }; + + const addNetworkStateEventListener = () => { + window.addEventListener('online', handleNetworkOnline); + window.addEventListener('offline', handleNetworkOffline); + }; + + const removeNetworkStateEventListener = () => { + window.removeEventListener('online', handleNetworkOnline); + window.removeEventListener('offline', handleNetworkOffline); + }; + + useEffect(() => { + addNetworkStateEventListener(); + + return removeNetworkStateEventListener; + }, []); + + return null; +}; + +export default NetworkStateCatcher; diff --git a/client/src/utils/caculateExpense.ts b/client/src/utils/caculateExpense.ts index 8b41af8c3..2ee8c2fa5 100644 --- a/client/src/utils/caculateExpense.ts +++ b/client/src/utils/caculateExpense.ts @@ -1,14 +1,8 @@ -import {BillAction, BillStep, MemberStep} from 'types/serviceType'; +import {Step} from 'types/serviceType'; -export const calculateStepExpense = (actions: BillAction[]) => { - return actions.reduce((sum, {price}) => sum + price, 0); -}; - -export const getTotalExpenseAmount = (stepList: (MemberStep | BillStep)[]) => { - return stepList.reduce((sum, {type, actions}) => { - if (type === 'BILL') { - return sum + calculateStepExpense(actions); - } - return sum; +export const getTotalExpenseAmount = (steps: Step[]) => { + return steps.reduce((total, step) => { + const stepTotal = step.bills.reduce((sum, bill) => sum + bill.price, 0); + return total + stepTotal; }, 0); }; diff --git a/client/src/utils/captureError.ts b/client/src/utils/captureError.ts index 67a30ac99..2c445cf82 100644 --- a/client/src/utils/captureError.ts +++ b/client/src/utils/captureError.ts @@ -1,49 +1,53 @@ -import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; +import RequestError from '@errors/RequestError'; import sendLogToSentry from './sendLogToSentry'; -export const captureError = async (error: Error, errorInfo: ErrorInfo) => { +export const captureError = async (error: Error) => { // prod 환경에서만 Sentry capture 실행 if (process.env.NODE_ENV !== 'production') return; - switch (errorInfo?.errorCode) { - case 'INTERNAL_SERVER_ERROR': - sendLogToSentry({error, errorInfo, level: 'fatal'}); - break; + if (error instanceof RequestError) { + switch (error.errorCode) { + case 'INTERNAL_SERVER_ERROR': + sendLogToSentry({error, level: 'fatal'}); + break; - case 'FORBIDDEN': - sendLogToSentry({error, errorInfo}); + case 'FORBIDDEN': + sendLogToSentry({error}); - break; + break; - case 'TOKEN_INVALID': - sendLogToSentry({error, errorInfo}); + case 'TOKEN_INVALID': + sendLogToSentry({error}); - break; + break; - case 'TOKEN_EXPIRED': - sendLogToSentry({error, errorInfo}); + case 'TOKEN_EXPIRED': + sendLogToSentry({error}); - break; + break; - case 'TOKEN_NOT_FOUND': - sendLogToSentry({error, errorInfo}); + case 'TOKEN_NOT_FOUND': + sendLogToSentry({error}); - break; + break; - // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 - case 'PASSWORD_INVALID': - sendLogToSentry({error, errorInfo, level: 'debug'}); + // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 + case 'PASSWORD_INVALID': + sendLogToSentry({error, level: 'debug'}); - break; + break; - // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 - case 'BILL_ACTION_PRICE_INVALID': - sendLogToSentry({error, errorInfo, level: 'debug'}); - break; + // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 + case 'BILL_ACTION_PRICE_INVALID': + sendLogToSentry({error, level: 'debug'}); + break; - default: - sendLogToSentry({error, errorInfo, level: 'fatal'}); - break; + default: + sendLogToSentry({error, level: 'fatal'}); + break; + } + } else { + sendLogToSentry({error, level: 'fatal'}); } }; diff --git a/client/src/utils/detectDevice.ts b/client/src/utils/detectDevice.ts new file mode 100644 index 000000000..2b1df2ea9 --- /dev/null +++ b/client/src/utils/detectDevice.ts @@ -0,0 +1,20 @@ +export const isMobileDevice = () => { + const userAgent = window.navigator.userAgent; + const mobileRegex = [/Android/i, /iPhone/i, /iPad/i, /iPod/i, /BlackBerry/i, /Windows Phone/i]; + + return mobileRegex.some(mobile => userAgent.match(mobile)); +}; + +export const isIOS = () => { + const userAgent = window.navigator.userAgent; + const iosRegex = [/iPhone/i, /iPad/i, /iPod/i]; + + return iosRegex.some(device => userAgent.match(device)); +}; + +export const isAndroid = () => { + const userAgent = window.navigator.userAgent; + const androidRegex = [/Android/i, /BlackBerry/i, /Windows Phone/i]; + + return androidRegex.some(device => userAgent.match(device)); +}; diff --git a/client/src/utils/getDeletedLastPath.ts b/client/src/utils/getDeletedLastPath.ts new file mode 100644 index 000000000..f2edfb154 --- /dev/null +++ b/client/src/utils/getDeletedLastPath.ts @@ -0,0 +1,7 @@ +const getDeletedLastPath = (url: string) => { + const urlParts = url.split('/'); + urlParts.pop(); + return urlParts.join('/'); +}; + +export default getDeletedLastPath; diff --git a/client/src/utils/groupActions.ts b/client/src/utils/groupActions.ts deleted file mode 100644 index a6347167d..000000000 --- a/client/src/utils/groupActions.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {BillStep, ConvertedAction, MemberStep} from 'types/serviceType'; - -import stepListToAction from './stepListToActions'; - -const groupActions = (stepList: (BillStep | MemberStep)[]) => { - const actions = stepListToAction(stepList); - const groupedActions: ConvertedAction[][] = []; - - let group: ConvertedAction[] = []; - - actions.forEach((action, index) => { - if (group.length === 0 || group[group.length - 1].type === action.type) { - group.push(action); - } else { - groupedActions.push(group); - group = []; - } - - if (index === actions.length - 1) { - groupedActions.push(group); - } - }); - - return groupedActions; -}; - -export default groupActions; diff --git a/client/src/utils/isRequestError.ts b/client/src/utils/isRequestError.ts new file mode 100644 index 000000000..98dfc90f5 --- /dev/null +++ b/client/src/utils/isRequestError.ts @@ -0,0 +1,7 @@ +import RequestError from '@errors/RequestError'; + +const isRequestError = (error: Error) => { + return error instanceof RequestError; +}; + +export default isRequestError; diff --git a/client/src/utils/sendLogToSentry.ts b/client/src/utils/sendLogToSentry.ts index 22d736b6c..e7aec9286 100644 --- a/client/src/utils/sendLogToSentry.ts +++ b/client/src/utils/sendLogToSentry.ts @@ -1,10 +1,6 @@ import * as Sentry from '@sentry/react'; -import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; - -import {UNKNOWN_ERROR} from '@constants/errorMessage'; - -import FetchError from '../errors/FetchError'; +import RequestError from '../errors/RequestError'; /** * level은 아래와 같은 용도에 맞게 지정해줍니다. @@ -21,44 +17,34 @@ type SentryLevel = 'fatal' | 'error' | 'warning' | 'info' | 'debug' | 'log'; type SendLogToSentry = { level?: SentryLevel; error: Error; - errorInfo: ErrorInfo; }; -const sendLogToSentry = ({level = 'error', error, errorInfo}: SendLogToSentry) => { +const sendLogToSentry = ({level = 'error', error}: SendLogToSentry) => { Sentry.withScope(scope => { - const {errorCode, message} = errorInfo; scope.setLevel(level); - scope.setTag('environment', process.env.NODE_ENV); - - if (error instanceof FetchError) { + if (error instanceof RequestError) { + const {errorCode, message} = error; scope.setTags({ endpoint: error.endpoint, url: window.location.href, - errorCode, errorMessage: message, status: error.status, - // requestBody: JSON.stringify(error.requestBody), - method: error.method, - }); - - Sentry.captureMessage(`${errorCode}`); - } else if (error instanceof Error) { - scope.setTags({ - url: window.location.href, errorCode, - errorMessage: message, + requestBody: JSON.stringify(error.requestBody), + method: error.method, }); - Sentry.captureMessage(`${errorCode}`); } else { + const {name, message} = error; + scope.setTags({ url: window.location.href, - errorCode, - message: UNKNOWN_ERROR, - name: UNKNOWN_ERROR, + name, + message, }); - Sentry.captureMessage(`${errorCode}`); + + Sentry.captureMessage(`${name}`); } }); }; diff --git a/client/src/utils/stepListToActions.ts b/client/src/utils/stepListToActions.ts deleted file mode 100644 index 5fe1bb3a7..000000000 --- a/client/src/utils/stepListToActions.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {BillStep, ConvertedAction, MemberStep} from 'types/serviceType'; - -const stepListToAction = (stepList: (BillStep | MemberStep)[]) => { - // (@todari) test용이라 임시로 any 사용할게용... - // Action을 사용하려고 하는데 serviceType의 기존 Action이랑 겹쳐서요~~~ - const actions: ConvertedAction[] = []; - - stepList.forEach(step => { - step.actions.forEach(action => { - actions.push({ - actionId: action.actionId, - name: action.name, - price: action.price ? action.price.toLocaleString() : null, - sequence: action.sequence, - type: step.type, - }); - }); - }); - - return actions; -}; - -export default stepListToAction; diff --git a/client/src/utils/validate/validateAccountNumber.ts b/client/src/utils/validate/validateAccountNumber.ts new file mode 100644 index 000000000..fb100a22b --- /dev/null +++ b/client/src/utils/validate/validateAccountNumber.ts @@ -0,0 +1,23 @@ +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import REGEXP from '@constants/regExp'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateAccountNumber = (accountNumber: string): ValidateResult => { + const isValidateType = () => { + return REGEXP.accountNumber.test(accountNumber); + }; + + const isValidateLength = () => { + return accountNumber.length >= RULE.minAccountNumberLength && accountNumber.length <= RULE.maxAccountNumberLength; + }; + + if (isValidateType() && isValidateLength()) { + return {isValid: true, errorMessage: null}; + } + + return {isValid: false, errorMessage: ERROR_MESSAGE.invalidAccountNumber}; +}; + +export default validateAccountNumber; diff --git a/client/src/utils/validate/validateMemberReportInAction.ts b/client/src/utils/validate/validateBillDetails.ts similarity index 85% rename from client/src/utils/validate/validateMemberReportInAction.ts rename to client/src/utils/validate/validateBillDetails.ts index b4e6c2a9a..a77a154a5 100644 --- a/client/src/utils/validate/validateMemberReportInAction.ts +++ b/client/src/utils/validate/validateBillDetails.ts @@ -3,7 +3,7 @@ import RULE from '@constants/rule'; import {ValidateResult} from './type'; -const validateMemberReportInAction = (price: string, totalPrice: number): ValidateResult => { +const validateBillDetails = (price: string, totalPrice: number): ValidateResult => { let errorMessage = null; const numberTypePrice = Number(price); @@ -30,4 +30,4 @@ const validateMemberReportInAction = (price: string, totalPrice: number): Valida return {isValid: false, errorMessage: errorMessage || ERROR_MESSAGE.invalidInput}; }; -export default validateMemberReportInAction; +export default validateBillDetails; diff --git a/client/src/utils/validate/validateEventName.ts b/client/src/utils/validate/validateEventName.ts index 93f4ecef1..1c88fd4b3 100644 --- a/client/src/utils/validate/validateEventName.ts +++ b/client/src/utils/validate/validateEventName.ts @@ -7,6 +7,7 @@ const validateEventName = (name: string): ValidateResult => { if (name.length > RULE.maxEventNameLength) { return {isValid: false, errorMessage: ERROR_MESSAGE.eventName}; } + return {isValid: true, errorMessage: null}; }; diff --git a/client/src/utils/validate/validateMemberName.ts b/client/src/utils/validate/validateMemberName.ts index bb87122a2..b23ca74f2 100644 --- a/client/src/utils/validate/validateMemberName.ts +++ b/client/src/utils/validate/validateMemberName.ts @@ -16,15 +16,7 @@ const validateMemberName = (name: string): ValidateResult => { return true; }; - const validateEmpty = () => { - if (!name.trim().length) { - errorMessage = ERROR_MESSAGE.preventEmpty; - return false; - } - return true; - }; - - if (validateOnlyString() && validateLength() && validateEmpty()) { + if (validateOnlyString() && validateLength()) { return {isValid: true, errorMessage: null}; } diff --git a/client/src/utils/validate/validatePurchase.ts b/client/src/utils/validate/validatePurchase.ts deleted file mode 100644 index 9915ce8b7..000000000 --- a/client/src/utils/validate/validatePurchase.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type {Bill} from 'types/serviceType'; - -import {ERROR_MESSAGE} from '@constants/errorMessage'; -import RULE from '@constants/rule'; -import REGEXP from '@constants/regExp'; - -import {ValidateResult} from './type'; - -const validatePurchase = (inputPair: Bill): ValidateResult => { - const {title, price} = inputPair; - let errorMessage: string | null = null; - - const errorInfo = { - price: false, - title: false, - }; - - const validatePrice = () => { - if (price > RULE.maxPrice) { - errorMessage = ERROR_MESSAGE.purchasePrice; - errorInfo.price = true; - return false; - } - - errorInfo.price = false; - return true; - }; - - const validateTitle = () => { - if (!REGEXP.purchaseTitle.test(title)) { - errorMessage = ERROR_MESSAGE.purchaseTitle; - errorInfo.title = true; - return false; - } - - errorInfo.title = false; - return true; - }; - - if (validatePrice() && validateTitle()) { - return {isValid: true, errorMessage: null}; - } - - return {isValid: false, errorMessage, errorInfo}; -}; - -export default validatePurchase; diff --git a/client/tsconfig.json b/client/tsconfig.json index 84c7c054a..f68912ec3 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -44,7 +44,15 @@ "@mocks/*": ["mocks/*"], "@pages/*": ["pages/*"], "@utils/*": ["utils/*"], - "@errors/*": ["errors/*"] + "@errors/*": ["errors/*"], + + "@HDesign/*": ["components/Design/*"], + "@HDcomponents/*": ["components/Design/components/*"], + "@token/*": ["components/Design/token/*"], + "@layouts/*": ["components/Design/layouts/*"], + "@type/*": ["components/Design/type/*"], + "@theme/*": ["components/Design/theme/*"], + "@HDutils/*": ["components/Design/utils/*"] }, "outDir": "./dist" }, diff --git a/client/webpack.common.mjs b/client/webpack.common.mjs index 160baf0ca..90879f2f9 100644 --- a/client/webpack.common.mjs +++ b/client/webpack.common.mjs @@ -22,6 +22,13 @@ export default { '@pages': path.resolve(__dirname, 'src/pages/'), '@utils': path.resolve(__dirname, 'src/utils/'), '@errors': path.resolve(__dirname, 'src/errors/'), + '@HDesign': path.resolve(__dirname, 'src/components/Design/'), + '@HDcomponents': path.resolve(__dirname, 'src/components/Design/components/'), + '@HDutils': path.resolve(__dirname, 'src/components/Design/utils/'), + '@token': path.resolve(__dirname, 'src/components/Design/token/'), + '@theme': path.resolve(__dirname, 'src/components/Design/theme/'), + '@layouts': path.resolve(__dirname, 'src/components/Design/layouts/'), + '@type': path.resolve(__dirname, 'src/components/Design/type/'), }, }, module: { @@ -39,6 +46,10 @@ export default { }, ], }, + { + test: /\.png$/i, + loader: 'file-loader', + }, ], }, plugins: [ diff --git a/server/.gitignore b/server/.gitignore deleted file mode 100644 index 671ee930b..000000000 --- a/server/.gitignore +++ /dev/null @@ -1,244 +0,0 @@ -# Created by https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux -# Edit at https://www.toptal.com/developers/gitignore?templates=java,intellij,gradle,macos,windows,linux - -### Intellij ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### Intellij Patch ### -# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 - -# *.iml -# modules.xml -# .idea/misc.xml -# *.ipr - -# Sonarlint plugin -# https://plugins.jetbrains.com/plugin/7973-sonarlint -.idea/**/sonarlint/ - -# SonarQube Plugin -# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin -.idea/**/sonarIssues.xml - -# Markdown Navigator plugin -# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced -.idea/**/markdown-navigator.xml -.idea/**/markdown-navigator-enh.xml -.idea/**/markdown-navigator/ - -# Cache file creation bug -# See https://youtrack.jetbrains.com/issue/JBR-2257 -.idea/$CACHE_FILE$ - -# CodeStream plugin -# https://plugins.jetbrains.com/plugin/12206-codestream -.idea/codestream.xml - -# Azure Toolkit for IntelliJ plugin -# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij -.idea/**/azureSettings.xml - -### Java ### -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* - -### Linux ### -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -### macOS ### -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### macOS Patch ### -# iCloud generated files -*.icloud - -### Windows ### -# Windows thumbnail cache files -Thumbs.db -Thumbs.db:encryptable -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -### Gradle ### -.gradle -**/build/ -!src/**/build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Avoid ignore Gradle wrappper properties -!gradle-wrapper.properties - -# Cache of project -.gradletasknamecache - -# Eclipse Gradle plugin generated files -# Eclipse Core -.project -# JDT-specific (Eclipse Java Development Tools) -.classpath - -### Gradle Patch ### -# Java heap dump -*.hprof - -# End of https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux diff --git a/server/Dockerfile b/server/Dockerfile deleted file mode 100644 index df2cf44e0..000000000 --- a/server/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM openjdk:17-jdk-slim - -WORKDIR /app - -COPY /build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar - -EXPOSE 8080 -ENTRYPOINT ["java"] -CMD ["-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE}", "-Duser.timezone=Asia/Seoul", "-jar", "haengdong-0.0.1-SNAPSHOT.jar"] diff --git a/server/build.gradle b/server/build.gradle deleted file mode 100644 index 4229de130..000000000 --- a/server/build.gradle +++ /dev/null @@ -1,86 +0,0 @@ -plugins { - id 'java' - id 'org.springframework.boot' version '3.3.1' - id 'io.spring.dependency-management' version '1.1.5' - id 'org.asciidoctor.jvm.convert' version '3.3.2' -} - -group = 'server' -version = '0.0.1-SNAPSHOT' - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } -} - -configurations { - compileOnly { - extendsFrom annotationProcessor - } - asciidoctorExt -} - -repositories { - mavenCentral() -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-actuator' - - implementation 'io.jsonwebtoken:jjwt:0.9.1' - implementation 'javax.xml.bind:jaxb-api:2.3.1' - - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' - - runtimeOnly 'com.h2database:h2' - runtimeOnly 'com.mysql:mysql-connector-j' - - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - - asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' - testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' -} - -ext { - snippetsDir = file('build/generated-snippets') -} - -test { - useJUnitPlatform() - outputs.dir snippetsDir -} - -asciidoctor { - inputs.dir snippetsDir - configurations 'asciidoctorExt' - baseDirFollowsSourceFile() - dependsOn test -} - -tasks.resolveMainClassName { - dependsOn 'copyApiDocuments' -} - -tasks.register('copyApiDocuments', Copy) { - dependsOn asciidoctor - from file("build/docs/asciidoc") - into file("build/resources/main/static/docs") -} - -bootJar { - dependsOn copyApiDocuments -} - -jar { - enabled = false -} - -build { - dependsOn copyApiDocuments -} diff --git a/server/docs/24-08-04-erd.sql b/server/docs/24-08-04-erd.sql deleted file mode 100644 index ae2fbc4a5..000000000 --- a/server/docs/24-08-04-erd.sql +++ /dev/null @@ -1,65 +0,0 @@ --- Create tables -CREATE TABLE action -( - event_id BIGINT, - id BIGINT AUTO_INCREMENT, - sequence BIGINT, - PRIMARY KEY (id) -); - -CREATE TABLE bill_action -( - action_id BIGINT UNIQUE, - id BIGINT AUTO_INCREMENT, - price BIGINT, - title VARCHAR(30), - PRIMARY KEY (id) -); - -CREATE TABLE event -( - id BIGINT AUTO_INCREMENT, - name VARCHAR(255), - token VARCHAR(255), - PRIMARY KEY (id) -); - -CREATE TABLE event_step -( - event_id BIGINT, - id BIGINT AUTO_INCREMENT, - sequence BIGINT, - name VARCHAR(255), - PRIMARY KEY (id) -); - -CREATE TABLE member_action -( - action_id BIGINT UNIQUE, - id BIGINT AUTO_INCREMENT, - member_group_id BIGINT, - member_name VARCHAR(255), - status ENUM('IN', 'OUT'), - PRIMARY KEY (id) -); - --- Add foreign key constraints -ALTER TABLE action - ADD CONSTRAINT FKgf0qmub9va1xbe44nehny31yw - FOREIGN KEY (event_id) - REFERENCES event (id); - -ALTER TABLE bill_action - ADD CONSTRAINT FK54tx517tp0ry6453olkply4us - FOREIGN KEY (action_id) - REFERENCES action (id); - -ALTER TABLE event_step - ADD CONSTRAINT FKe3rkib91cvl0x5w9wqkshmn81 - FOREIGN KEY (event_id) - REFERENCES event (id); - -ALTER TABLE member_action - ADD CONSTRAINT FK5jna51dn8fs2ir52l4uwn517u - FOREIGN KEY (action_id) - REFERENCES action (id); diff --git a/server/docs/24-08-04-erd.svg b/server/docs/24-08-04-erd.svg deleted file mode 100644 index 5a4bac225..000000000 --- a/server/docs/24-08-04-erd.svg +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Do not edit this file with editors other than draw.io --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1993px" height="1581px" viewBox="-0.5 -0.5 1993 1581" content="<mxfile host="app.diagrams.net" modified="2024-07-25T04:17:06.208Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" etag="gR5VLfYLO6MRu5dHcV28" version="24.7.3" type="github"> <diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1"> <mxGraphModel dx="2380" dy="2150" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> <root> <mxCell id="WIyWlLk6GJQsqaUBKTNV-0" /> <mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" /> <mxCell id="8gZzuRhjrYuwNxX9kY4q-98" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-442" y="-590" width="1992" height="1580" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-47" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=ERone;startFill=0;endArrow=ERzeroToMany;endFill=0;dashed=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-0" target="8gZzuRhjrYuwNxX9kY4q-37" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=ERone;startFill=0;endArrow=ERzeroToMany;endFill=0;dashed=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-0" target="8gZzuRhjrYuwNxX9kY4q-56" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-0" value="Event" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="40" y="40" width="280" height="120" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-1" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-2" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-3" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-137" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-7" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-8" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-9" value="token" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-138" value="varchar(20)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-4" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-5" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-6" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-139" value="varchar(255)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-37" value="Event_Step" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="40" y="240" width="280" height="150" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-38" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-39" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-40" value="event_step_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-143" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-41" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-42" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-43" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-144" value="varchar(30)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-44" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-45" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-46" value="sequence" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-145" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-48" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-49" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-50" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-146" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-77" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;startArrow=ERone;startFill=0;endArrow=ERone;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-56" target="8gZzuRhjrYuwNxX9kY4q-67" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-91" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;startArrow=ERone;startFill=0;endArrow=ERone;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-56" target="8gZzuRhjrYuwNxX9kY4q-81" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-56" value="Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="414" y="40" width="280" height="120" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-57" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-58" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-59" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-140" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-60" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-61" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-62" value="sequence" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-141" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-63" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-64" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-65" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-142" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-67" value="Bill_Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="414" y="240" width="280" height="150" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-68" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-69" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-70" value="bill_action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-147" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-71" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-72" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-73" value="title" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-148" value="varchar(30)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-78" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-79" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-80" value="price" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-149" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-74" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-75" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-76" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-150" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-81" value="Member_Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="790" y="40" width="280" height="180" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-82" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-83" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-84" value="member_action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-151" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-85" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-86" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-87" value="member_name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-152" value="varchar(20)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-92" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-93" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-94" value="status" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-153" value="varchar(10)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-95" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-96" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-97" value="member_group_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-154" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-88" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="150" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-89" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-90" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-155" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> </root> </mxGraphModel> </diagram> </mxfile> " resource="https://app.diagrams.net/?src=about#Hkunsanglee%2Fcafekiosk-study%2Fmain%2Fsrc%2Fmain%2Fresources%2Fexample2.svg#%7B%22pageId%22%3A%22C5RBs43oDa-KdzZeNtuy%22%7D"><defs/><g><g data-cell-id="WIyWlLk6GJQsqaUBKTNV-0"><g data-cell-id="WIyWlLk6GJQsqaUBKTNV-1"><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-98"><g><rect x="0" y="0" width="1992" height="1580" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-47"><g><path d="M 622 750 L 622 814.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 626 754 L 618 754" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="622" cy="818" rx="3" ry="3" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 626 830 L 622 822 L 618 830 M 622 822 L 622 830" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-66"><g><path d="M 762 690 L 840.5 690" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 766 686 L 766 694" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="844" cy="690" rx="3" ry="3" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 856 686 L 848 690 L 856 694 M 848 690 L 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-0"><g><path d="M 482 660 L 482 630 L 762 630 L 762 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 482 660 L 482 750 L 762 750 L 762 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 482 660 L 762 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 512 660 L 512 690 L 512 720 L 512 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 632 660 L 632 690 L 632 720 L 632 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 622px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Event</div></div></div></foreignObject><text x="622" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Event</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-1"><g><path d="M 482 660 M 762 660 M 762 690 L 482 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-2"><g><rect x="482" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 660 M 512 660 M 512 690 M 482 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="497" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-3"><g><rect x="512" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 660 M 632 660 M 632 690 M 512 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="520" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-137"><g><rect x="632" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 660 M 762 660 M 762 690 M 632 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-7"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-8"><g><rect x="482" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 690 M 512 690 M 512 720 M 482 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-9"><g><rect x="512" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 690 M 632 690 M 632 720 M 512 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">token</div></div></div></foreignObject><text x="520" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">token</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-138"><g><rect x="632" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 690 M 762 690 M 762 720 M 632 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(20)</div></div></div></foreignObject><text x="640" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(20)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-4"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-5"><g><rect x="482" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 720 M 512 720 M 512 750 M 482 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-6"><g><rect x="512" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 720 M 632 720 M 632 750 M 512 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">name</div></div></div></foreignObject><text x="520" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-139"><g><rect x="632" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 720 M 762 720 M 762 750 M 632 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(255)</div></div></div></foreignObject><text x="640" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(255)</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-37"><g><path d="M 482 860 L 482 830 L 762 830 L 762 860" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 482 860 L 482 980 L 762 980 L 762 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 482 860 L 762 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 512 860 L 512 890 L 512 920 L 512 950 L 512 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 632 860 L 632 890 L 632 920 L 632 950 L 632 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 845px; margin-left: 622px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Event_Step</div></div></div></foreignObject><text x="622" y="849" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Event_Step</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-38"><g><path d="M 482 860 M 762 860 M 762 890 L 482 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-39"><g><rect x="482" y="860" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 860 M 512 860 M 512 890 M 482 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 875px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="497" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-40"><g><rect x="512" y="860" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 860 M 632 860 M 632 890 M 512 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 875px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">event_step_id</div></div></div></foreignObject><text x="520" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">event_step_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-143"><g><rect x="632" y="860" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 860 M 762 860 M 762 890 M 632 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 875px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-41"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-42"><g><rect x="482" y="890" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 890 M 512 890 M 512 920 M 482 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-43"><g><rect x="512" y="890" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 890 M 632 890 M 632 920 M 512 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 905px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">name</div></div></div></foreignObject><text x="520" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-144"><g><rect x="632" y="890" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 890 M 762 890 M 762 920 M 632 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 905px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(30)</div></div></div></foreignObject><text x="640" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(30)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-44"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-45"><g><rect x="482" y="920" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 920 M 512 920 M 512 950 M 482 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-46"><g><rect x="512" y="920" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 920 M 632 920 M 632 950 M 512 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 935px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">sequence</div></div></div></foreignObject><text x="520" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">sequence</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-145"><g><rect x="632" y="920" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 920 M 762 920 M 762 950 M 632 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 935px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-48"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-49"><g><rect x="482" y="950" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 950 M 512 950 M 512 980 M 482 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 965px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="497" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-50"><g><rect x="512" y="950" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 950 M 632 950 M 632 980 M 512 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 965px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="520" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-146"><g><rect x="632" y="950" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 950 M 762 950 M 762 980 M 632 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 965px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-77"><g><path d="M 996 750 L 996 830" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 1000 754 L 992 754" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 992 826 L 1000 826" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-91"><g><path d="M 1136 690 L 1184 690 L 1184 720 L 1232 720" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 1140 686 L 1140 694" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1228 724 L 1228 716" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-56"><g><path d="M 856 660 L 856 630 L 1136 630 L 1136 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 856 660 L 856 750 L 1136 750 L 1136 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 856 660 L 1136 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 886 660 L 886 690 L 886 720 L 886 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1006 660 L 1006 690 L 1006 720 L 1006 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 996px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Action</div></div></div></foreignObject><text x="996" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-57"><g><path d="M 856 660 M 1136 660 M 1136 690 L 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-58"><g><rect x="856" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 660 M 886 660 M 886 690 M 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="871" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-59"><g><rect x="886" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 660 M 1006 660 M 1006 690 M 886 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="894" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-140"><g><rect x="1006" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 660 M 1136 660 M 1136 690 M 1006 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-60"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-61"><g><rect x="856" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 690 M 886 690 M 886 720 M 856 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-62"><g><rect x="886" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 690 M 1006 690 M 1006 720 M 886 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">sequence</div></div></div></foreignObject><text x="894" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">sequence</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-141"><g><rect x="1006" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 690 M 1136 690 M 1136 720 M 1006 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-63"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-64"><g><rect x="856" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 720 M 886 720 M 886 750 M 856 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 735px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="871" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-65"><g><rect x="886" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 720 M 1006 720 M 1006 750 M 886 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="894" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-142"><g><rect x="1006" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 720 M 1136 720 M 1136 750 M 1006 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-67"><g><path d="M 856 860 L 856 830 L 1136 830 L 1136 860" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 856 860 L 856 980 L 1136 980 L 1136 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 856 860 L 1136 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 886 860 L 886 890 L 886 920 L 886 950 L 886 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1006 860 L 1006 890 L 1006 920 L 1006 950 L 1006 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 845px; margin-left: 996px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Bill_Action</div></div></div></foreignObject><text x="996" y="849" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Bill_Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-68"><g><path d="M 856 860 M 1136 860 M 1136 890 L 856 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-69"><g><rect x="856" y="860" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 860 M 886 860 M 886 890 M 856 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 875px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="871" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-70"><g><rect x="886" y="860" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 860 M 1006 860 M 1006 890 M 886 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 875px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bill_action_id</div></div></div></foreignObject><text x="894" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bill_action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-147"><g><rect x="1006" y="860" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 860 M 1136 860 M 1136 890 M 1006 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 875px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-71"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-72"><g><rect x="856" y="890" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 890 M 886 890 M 886 920 M 856 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-73"><g><rect x="886" y="890" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 890 M 1006 890 M 1006 920 M 886 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 905px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">title</div></div></div></foreignObject><text x="894" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">title</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-148"><g><rect x="1006" y="890" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 890 M 1136 890 M 1136 920 M 1006 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 905px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(30)</div></div></div></foreignObject><text x="1014" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(30)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-78"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-79"><g><rect x="856" y="920" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 920 M 886 920 M 886 950 M 856 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-80"><g><rect x="886" y="920" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 920 M 1006 920 M 1006 950 M 886 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 935px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">price</div></div></div></foreignObject><text x="894" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">price</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-149"><g><rect x="1006" y="920" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 920 M 1136 920 M 1136 950 M 1006 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 935px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-74"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-75"><g><rect x="856" y="950" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 950 M 886 950 M 886 980 M 856 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 965px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="871" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-76"><g><rect x="886" y="950" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 950 M 1006 950 M 1006 980 M 886 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 965px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="894" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-150"><g><rect x="1006" y="950" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 950 M 1136 950 M 1136 980 M 1006 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 965px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-81"><g><path d="M 1232 660 L 1232 630 L 1512 630 L 1512 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1232 660 L 1232 810 L 1512 810 L 1512 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1232 660 L 1512 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1262 660 L 1262 690 L 1262 720 L 1262 750 L 1262 780 L 1262 810" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1382 660 L 1382 690 L 1382 720 L 1382 750 L 1382 780 L 1382 810" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 1372px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Member_Action</div></div></div></foreignObject><text x="1372" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Member_Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-82"><g><path d="M 1232 660 M 1512 660 M 1512 690 L 1232 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-83"><g><rect x="1232" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 660 M 1262 660 M 1262 690 M 1232 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 1233px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="1247" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-84"><g><rect x="1262" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 660 M 1382 660 M 1382 690 M 1262 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">member_action_id</div></div></div></foreignObject><text x="1270" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">member_action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-151"><g><rect x="1382" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 660 M 1512 660 M 1512 690 M 1382 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-85"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-86"><g><rect x="1232" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 690 M 1262 690 M 1262 720 M 1232 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-87"><g><rect x="1262" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 690 M 1382 690 M 1382 720 M 1262 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">member_name</div></div></div></foreignObject><text x="1270" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">member_name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-152"><g><rect x="1382" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 690 M 1512 690 M 1512 720 M 1382 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(20)</div></div></div></foreignObject><text x="1390" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(20)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-92"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-93"><g><rect x="1232" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 720 M 1262 720 M 1262 750 M 1232 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-94"><g><rect x="1262" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 720 M 1382 720 M 1382 750 M 1262 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">status</div></div></div></foreignObject><text x="1270" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">status</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-153"><g><rect x="1382" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 720 M 1512 720 M 1512 750 M 1382 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(10)</div></div></div></foreignObject><text x="1390" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(10)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-95"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-96"><g><rect x="1232" y="750" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 750 M 1262 750 M 1262 780 M 1232 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-97"><g><rect x="1262" y="750" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 750 M 1382 750 M 1382 780 M 1262 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 765px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">member_group_id</div></div></div></foreignObject><text x="1270" y="769" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">member_group_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-154"><g><rect x="1382" y="750" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 750 M 1512 750 M 1512 780 M 1382 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 765px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="769" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-88"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-89"><g><rect x="1232" y="780" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 780 M 1262 780 M 1262 810 M 1232 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 795px; margin-left: 1233px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="1247" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-90"><g><rect x="1262" y="780" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 780 M 1382 780 M 1382 810 M 1262 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 795px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="1270" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-155"><g><rect x="1382" y="780" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 780 M 1512 780 M 1512 810 M 1382 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 795px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g></g></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file diff --git a/server/gradle/wrapper/gradle-wrapper.jar b/server/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e6441136f3d4ba8a0da8d277868979cfbc8ad796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 UfUyy3EX0IC28@JalTrWuAK7&_a{vGU diff --git a/server/gradle/wrapper/gradle-wrapper.properties b/server/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index a4413138c..000000000 --- a/server/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/server/gradlew b/server/gradlew deleted file mode 100644 index b740cf133..000000000 --- a/server/gradlew +++ /dev/null @@ -1,249 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/server/gradlew.bat b/server/gradlew.bat deleted file mode 100644 index 25da30dbd..000000000 --- a/server/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/server/settings.gradle b/server/settings.gradle deleted file mode 100644 index dbbee46fb..000000000 --- a/server/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'haengdong' diff --git a/server/src/docs/asciidoc/billAction.adoc b/server/src/docs/asciidoc/billAction.adoc deleted file mode 100644 index dfd7e26db..000000000 --- a/server/src/docs/asciidoc/billAction.adoc +++ /dev/null @@ -1,121 +0,0 @@ -== 지출 액션 - -=== 지출 액션 생성 - -operation::createBillActions[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"REQUEST_EMPTY", - "message":"지출 금액은 비어 있으면 안됩니다." - }, - { - "code":"REQUEST_EMPTY", - "message":"지출 내역은 비어 있으면 안됩니다." - }, - { - "code":"BILL_ACTION_TITLE_INVALID", - "message":"앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다." - }, - { - "code":"BILL_ACTION_PRICE_INVALID", - "message":"지출 금액은 10,000,000 이하의 자연수여야 합니다." - }, - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- - -=== 지출 액션 수정 - -operation::updateBillAction[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"REQUEST_EMPTY", - "message":"지출 내역 제목은 공백일 수 없습니다." - }, - { - "code":"REQUEST_EMPTY", - "message":"지출 금액은 공백일 수 없습니다." - }, - { - "code":"BILL_ACTION_TITLE_INVALID", - "message":"앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다." - }, - { - "code":"BILL_ACTION_PRICE_INVALID", - "message":"지출 금액은 %,d 이하의 자연수여야 합니다." - }, - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"BILL_ACTION_NOT_FOUND", - "message":"존재하지 않는 지출 액션입니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- - -=== 지출 액션 삭제 - -operation::deleteBillAction[snippets="path-parameters,http-request,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- diff --git a/server/src/docs/asciidoc/billActionDetail.adoc b/server/src/docs/asciidoc/billActionDetail.adoc deleted file mode 100644 index a8f19f21b..000000000 --- a/server/src/docs/asciidoc/billActionDetail.adoc +++ /dev/null @@ -1,93 +0,0 @@ -== 지출 상세 - -=== 지출 상세 조회 - -operation::findBillActionDetailsTest[snippets="path-parameters,http-request,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code": "EVENT_NOT_FOUND", - "message": "존재하지 않는 행사입니다." - }, - { - "code": "BILL_ACTION_NOT_FOUND", - "message": "존재하지 않는 지출 액션입니다." - }, - { - "code": "BILL_ACTION_DETAIL_NOT_FOUND", - "message": "존재하지 않는 참여자 지출입니다." - }, - { - "code": "TOKEN_NOT_FOUND", - "message": "토큰이 존재하지 않습니다." - }, - { - "code": "TOKEN_EXPIRED", - "message": "만료된 토큰입니다." - }, - { - "code": "TOKEN_INVALID", - "message": "유효하지 않은 토큰입니다." - }, - { - "code": "FORBIDDEN", - "message": "접근할 수 없는 행사입니다." - } -] ----- - -=== 지출 상세 수정 - -operation::updateBillActionDetailsTest[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code": "REQUEST_EMPTY", - "message": "멤버 이름은 공백일 수 없습니다." - }, - { - "code": "REQUEST_EMPTY", - "message": "지출 금액은 공백일 수 없습니다." - }, - { - "code": "EVENT_NOT_FOUND", - "message": "존재하지 않는 행사입니다." - }, - { - "code": "BILL_ACTION_NOT_FOUND", - "message": "존재하지 않는 지출 액션입니다." - }, - { - "code": "BILL_ACTION_DETAIL_NOT_FOUND", - "message": "존재하지 않는 참여자 지출입니다." - }, - { - "code": "BILL_ACTION_PRICE_NOT_MATCHED", - "message": "지출 총액이 일치하지 않습니다." - }, - { - "code": "TOKEN_NOT_FOUND", - "message": "토큰이 존재하지 않습니다." - }, - { - "code": "TOKEN_EXPIRED", - "message": "만료된 토큰입니다." - }, - { - "code": "TOKEN_INVALID", - "message": "유효하지 않은 토큰입니다." - }, - { - "code": "FORBIDDEN", - "message": "접근할 수 없는 행사입니다." - } -] ----- diff --git a/server/src/docs/asciidoc/event.adoc b/server/src/docs/asciidoc/event.adoc deleted file mode 100644 index 72511b91b..000000000 --- a/server/src/docs/asciidoc/event.adoc +++ /dev/null @@ -1,205 +0,0 @@ -== 행사 - -=== 행사 생성 - -operation::createEvent[snippets="http-request,request-body,request-fields,response-body,response-fields,http-response,response-cookies"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"REQUEST_EMPTY", - "message":"행사 이름은 공백일 수 없습니다." - }, - { - "code":"EVENT_NAME_LENGTH_INVALID", - "message":"행사 이름은 2자 이상 30자 이하만 입력 가능합니다. 입력한 이름 길이 : 21" - }, - { - "code":"EVENT_NAME_MULTIPLE_BLANK", - "message":"행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : 공백 문자" - }, - { - "code":"EVENT_PASSWORD_INVALID", - "message":"비밀번호는 4자리 숫자만 가능합니다." - } -] ----- - -=== 행사 관리자 로그인 - -operation::eventLogin[snippets="path-parameters,http-request,request-body,request-fields,http-response,response-cookies"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"REQUEST_EMPTY", - "message":"비밀번호는 공백일 수 없습니다." - }, - { - "code":"PASSWORD_INVALID", - "message":"비밀번호가 일치하지 않습니다." - } -] ----- - -=== 행사 정보 조회 - -operation::getEvent[snippets="path-parameters,http-request,response-body,response-fields,http-response"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - } -] ----- - -=== 행사 전체 참여자 목록 조회 - -operation::findAllEventMember[snippets="path-parameters,http-request,response-body,response-fields,http-response,response-fields"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - } -] ----- - -=== 행사 전체 액션 이력 조회 - -operation::findActions[snippets="path-parameters,http-request,http-response,response-fields"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - } -] ----- - -=== 행사 참여자 이름 변경 - -operation::updateEventMemberName[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - - { - "code":"MEMBER_NAME_CHANGE_DUPLICATE", - "message":"중복된 참여 인원 이름 변경 요청이 존재합니다." - }, - { - "code":"MEMBER_NOT_EXIST", - "message":"현재 참여하고 있지 않는 인원이 존재합니다." - }, - { - "code":"REQUEST_EMPTY", - "message":"멤버 이름은 공백일 수 없습니다." - }, - { - "code":"MEMBER_NAME_LENGTH_INVALID", - "message":"멤버 이름은 1자 이상 4자 이하만 입력 가능합니다." - }, - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"MEMBER_NAME_DUPLICATE", - "message":"중복된 행사 참여 인원 이름이 존재합니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"만료된 토큰입니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- - -=== 행사 참여자 삭제 (특정 참여자의 모든 참여자 액션 삭제) - -operation::deleteAllMemberActionByName[snippets="path-parameters,http-request,http-response,request-cookies"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- - -=== 행사 어드민 권한 확인 - -operation::authenticateEvent[snippets="http-request,http-response,request-cookies"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code": "EVENT_NOT_FOUND", - "message": "존재하지 않는 행사입니다." - }, - { - "code": "TOKEN_NOT_FOUND", - "message": "토큰이 존재하지 않습니다." - }, - { - "code": "TOKEN_EXPIRED", - "message": "만료된 토큰입니다." - }, - { - "code": "TOKEN_INVALID", - "message": "유효하지 않은 토큰입니다." - }, - { - "code": "FORBIDDEN", - "message": "접근할 수 없는 행사입니다." - } -] ----- diff --git a/server/src/docs/asciidoc/index.adoc b/server/src/docs/asciidoc/index.adoc deleted file mode 100644 index 8e1bcd2d0..000000000 --- a/server/src/docs/asciidoc/index.adoc +++ /dev/null @@ -1,15 +0,0 @@ -ifndef::snippets[] -:snippets: ../../build/generated-snippets -endif::[] -= 행동대장 -:source-highlighter: highlightjs :hardbreaks: -:toc: left :doctype: book :icons: font :toc-title: 전체 API 목록 :toclevels: 2 :sectlinks: -:sectnums: -:sectnumlevels: 2 - - -include::{docdir}/event.adoc[] -include::{docdir}/memberBillReport.adoc[] -include::{docdir}/memberAction.adoc[] -include::{docdir}/billAction.adoc[] -include::{docdir}/billActionDetail.adoc[] diff --git a/server/src/docs/asciidoc/memberAction.adoc b/server/src/docs/asciidoc/memberAction.adoc deleted file mode 100644 index 897102c8d..000000000 --- a/server/src/docs/asciidoc/memberAction.adoc +++ /dev/null @@ -1,100 +0,0 @@ -== 참여자 액션 - -=== 참여자 액션 생성 - -operation::createMemberAction[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"REQUEST_EMPTY", - "message":"멤버 액션은 공백일 수 없습니다." - }, - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"MEMBER_ACTION_STATUS_INVALID", - "message":"멤버 액션은 IN, OUT만 가능합니다. 입력한 멤버 액션: I_N" - }, - { - "code":"MEMBER_ALREADY_EXIST", - "message":"현재 참여하고 있는 인원이 존재합니다." - }, - { - "code":"MEMBER_NOT_EXIST", - "message":"현재 참여하고 있지 않는 인원이 존재합니다." - }, - { - "code":"MEMBER_NAME_DUPLICATE", - "message":"중복된 이름이 존재합니다. 입력된 이름: 이상, 이상, 감자, 백호" - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- - -=== 현재 행사에 참여 중인 (탈주 가능한) 참여자 목록 조회 - -operation::getCurrentMembers[snippets="path-parameters,http-request,http-response,response-fields"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - } -] ----- - -=== 참여자 액션 삭제 - -operation::deleteMemberAction[snippets="path-parameters,http-request,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"ACTION_NOT_FOUND", - "message":"존재하지 않는 액션입니다." - }, - { - "code":"MEMBER_ACTION_NOT_FOUND", - "message":"존재하지 않는 멤버 액션입니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- diff --git a/server/src/docs/asciidoc/memberBillReport.adoc b/server/src/docs/asciidoc/memberBillReport.adoc deleted file mode 100644 index 18bd7d3ef..000000000 --- a/server/src/docs/asciidoc/memberBillReport.adoc +++ /dev/null @@ -1,17 +0,0 @@ -== 정산 - -=== 참여자별 정산 결과 조회 - -operation::getMemberBillReports[snippets="path-parameters,http-request,response-body,response-fields,http-response,http-request"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - } -] ----- diff --git a/server/src/main/java/server/haengdong/HaengdongApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java deleted file mode 100644 index 4a84c6120..000000000 --- a/server/src/main/java/server/haengdong/HaengdongApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@Slf4j -@SpringBootApplication -public class HaengdongApplication { - - public static void main(String[] args) { - SpringApplication.run(HaengdongApplication.class, args); - } - -} diff --git a/server/src/main/java/server/haengdong/application/ActionService.java b/server/src/main/java/server/haengdong/application/ActionService.java deleted file mode 100644 index bcf5e8b55..000000000 --- a/server/src/main/java/server/haengdong/application/ActionService.java +++ /dev/null @@ -1,39 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberBillReport; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class ActionService { - - private final BillActionRepository billActionRepository; - private final MemberActionRepository memberActionRepository; - private final EventRepository eventRepository; - - public List<MemberBillReportAppResponse> getMemberBillReports(String token) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - List<BillAction> billActions = billActionRepository.findByAction_Event(event); - List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event); - - MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); - - return memberBillReport.getReports().entrySet().stream() - .map(entry -> new MemberBillReportAppResponse(entry.getKey(), entry.getValue())) - .toList(); - } -} diff --git a/server/src/main/java/server/haengdong/application/AuthService.java b/server/src/main/java/server/haengdong/application/AuthService.java deleted file mode 100644 index d9352ad53..000000000 --- a/server/src/main/java/server/haengdong/application/AuthService.java +++ /dev/null @@ -1,41 +0,0 @@ -package server.haengdong.application; - - -import java.util.Map; -import server.haengdong.domain.TokenProvider; -import server.haengdong.exception.AuthenticationException; -import server.haengdong.exception.HaengdongErrorCode; - -public class AuthService { - - private static final String TOKEN_NAME = "eventToken"; - private static final String CLAIM_SUB = "sub"; - - private final TokenProvider tokenProvider; - - public AuthService(TokenProvider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - public String createToken(String eventId) { - Map<String, Object> payload = Map.of(CLAIM_SUB, eventId); - - return tokenProvider.createToken(payload); - } - - public String findEventIdByToken(String token) { - validateToken(token); - Map<String, Object> payload = tokenProvider.getPayload(token); - return (String) payload.get(CLAIM_SUB); - } - - private void validateToken(String token) { - if (!tokenProvider.validateToken(token)) { - throw new AuthenticationException(HaengdongErrorCode.TOKEN_INVALID); - } - } - - public String getTokenName() { - return TOKEN_NAME; - } -} diff --git a/server/src/main/java/server/haengdong/application/BillActionDetailService.java b/server/src/main/java/server/haengdong/application/BillActionDetailService.java deleted file mode 100644 index 55d39aac0..000000000 --- a/server/src/main/java/server/haengdong/application/BillActionDetailService.java +++ /dev/null @@ -1,76 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.BillActionDetailUpdateAppRequest; -import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; -import server.haengdong.application.response.BillActionDetailsAppResponse; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetail; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class BillActionDetailService { - - private final BillActionRepository billActionRepository; - - public BillActionDetailsAppResponse findBillActionDetails(String token, Long actionId) { - BillAction billAction = billActionRepository.findByAction_Id(actionId) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); - validateToken(token, billAction); - - List<BillActionDetail> billActionDetails = billAction.getBillActionDetails(); - return BillActionDetailsAppResponse.of(billActionDetails); - } - - @Transactional - public void updateBillActionDetails(String token, Long actionId, BillActionDetailsUpdateAppRequest request) { - BillAction billAction = billActionRepository.findByAction_Id(actionId) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); - - List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests = request.billActionDetailUpdateAppRequests(); - - validateToken(token, billAction); - validateTotalPrice(billActionDetailUpdateAppRequests, billAction); - - List<BillActionDetail> billActionDetails = billAction.getBillActionDetails(); - - for (BillActionDetailUpdateAppRequest updateRequest : billActionDetailUpdateAppRequests) { - BillActionDetail detailToUpdate = billActionDetails.stream() - .filter(detail -> detail.isSameName(updateRequest.name())) - .findFirst() - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_DETAIL_NOT_FOUND)); - - detailToUpdate.updatePrice(updateRequest.price()); - detailToUpdate.updateIsFixed(updateRequest.isFixed()); - } - } - - private void validateToken(String token, BillAction billAction) { - Event event = billAction.getEvent(); - if (event.isTokenMismatch(token)) { - throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND); - } - } - - private void validateTotalPrice(List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests, - BillAction billAction) { - Long requestsPriceSum = calculateUpdatePriceSum(billActionDetailUpdateAppRequests); - if (!billAction.isSamePrice(requestsPriceSum)) { - throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_PRICE_NOT_MATCHED); - } - } - - private Long calculateUpdatePriceSum(List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests) { - return billActionDetailUpdateAppRequests.stream() - .map(BillActionDetailUpdateAppRequest::price) - .reduce(0L, Long::sum); - } -} diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java deleted file mode 100644 index dae36a2e7..000000000 --- a/server/src/main/java/server/haengdong/application/BillActionService.java +++ /dev/null @@ -1,80 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.BillActionAppRequest; -import server.haengdong.application.request.BillActionUpdateAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class BillActionService { - - private final BillActionRepository billActionRepository; - private final MemberActionRepository memberActionRepository; - private final ActionRepository actionRepository; - private final EventRepository eventRepository; - - @Transactional - public void saveAllBillAction(String eventToken, List<BillActionAppRequest> requests) { - Event event = getEvent(eventToken); - Action action = createStartAction(event); - List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); - CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); - - for (BillActionAppRequest request : requests) { - BillAction billAction = request.toBillAction(action, currentMembers); - billActionRepository.save(billAction); - action = action.next(); - } - } - - private Action createStartAction(Event event) { - return actionRepository.findLastByEvent(event) - .map(Action::next) - .orElse(Action.createFirst(event)); - } - - @Transactional - public void updateBillAction(String token, Long actionId, BillActionUpdateAppRequest request) { - BillAction billAction = billActionRepository.findByAction_Id(actionId) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); - - validateToken(token, billAction); - - billAction.update(request.title(), request.price()); - } - - private void validateToken(String token, BillAction billAction) { - Event event = billAction.getEvent(); - if (event.isTokenMismatch(token)) { - throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND); - } - } - - @Transactional - public void deleteBillAction(String token, Long actionId) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - - billActionRepository.deleteByAction_EventAndActionId(event, actionId); - } - - private Event getEvent(String eventToken) { - return eventRepository.findByToken(eventToken) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - } -} diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java deleted file mode 100644 index 1aaddd0f9..000000000 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ /dev/null @@ -1,170 +0,0 @@ -package server.haengdong.application; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Set; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.request.EventLoginAppRequest; -import server.haengdong.application.request.MemberNameUpdateAppRequest; -import server.haengdong.application.request.MemberNamesUpdateAppRequest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.application.response.MembersAppResponse; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetailRepository; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.event.EventTokenProvider; -import server.haengdong.exception.AuthenticationException; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class EventService { - - private final EventRepository eventRepository; - private final EventTokenProvider eventTokenProvider; - private final BillActionRepository billActionRepository; - private final MemberActionRepository memberActionRepository; - private final BillActionDetailRepository billActionDetailRepository; - - - @Transactional - public EventAppResponse saveEvent(EventAppRequest request) { - String token = eventTokenProvider.createToken(); - Event event = request.toEvent(token); - eventRepository.save(event); - - return EventAppResponse.of(event); - } - - public EventDetailAppResponse findEvent(String token) { - Event event = getEvent(token); - - return EventDetailAppResponse.of(event); - } - - public List<ActionAppResponse> findActions(String token) { - Event event = getEvent(token); - - List<BillAction> billActions = billActionRepository.findByAction_Event(event).stream() - .sorted(Comparator.comparing(BillAction::getSequence)).toList(); - List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event).stream() - .sorted(Comparator.comparing(MemberAction::getSequence)).toList(); - - return getActionAppResponses(billActions, memberActions); - } - - private List<ActionAppResponse> getActionAppResponses( - List<BillAction> billActions, - List<MemberAction> memberActions - ) { - int billActionIndex = 0; - int memberActionIndex = 0; - List<ActionAppResponse> actionAppResponses = new ArrayList<>(); - - while (billActionIndex < billActions.size() && memberActionIndex < memberActions.size()) { - BillAction billAction = billActions.get(billActionIndex); - MemberAction memberAction = memberActions.get(memberActionIndex); - if (billAction.getSequence() < memberAction.getSequence()) { - actionAppResponses.add(ActionAppResponse.of(billAction)); - billActionIndex++; - } else { - actionAppResponses.add(ActionAppResponse.of(memberAction)); - memberActionIndex++; - } - } - while (billActionIndex < billActions.size()) { - BillAction billAction = billActions.get(billActionIndex++); - actionAppResponses.add(ActionAppResponse.of(billAction)); - } - while (memberActionIndex < memberActions.size()) { - MemberAction memberAction = memberActions.get(memberActionIndex++); - actionAppResponses.add(ActionAppResponse.of(memberAction)); - } - - return actionAppResponses; - } - - public MembersAppResponse findAllMembers(String token) { - Event event = getEvent(token); - - List<String> memberNames = memberActionRepository.findAllUniqueMemberByEvent(event); - - return new MembersAppResponse(memberNames); - } - - @Transactional - public void updateMember(String token, MemberNamesUpdateAppRequest request) { - Event event = getEvent(token); - List<MemberNameUpdateAppRequest> members = request.members(); - - validateBeforeNames(members, event); - validateAfterNames(members, event); - - members.forEach(member -> updateMemberName(event, member.before(), member.after())); - } - - private void validateBeforeNames(List<MemberNameUpdateAppRequest> members, Event event) { - List<String> beforeNames = members.stream() - .map(MemberNameUpdateAppRequest::before) - .toList(); - if (beforeNames.size() != Set.copyOf(beforeNames).size()) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); - } - beforeNames.forEach(beforeName -> validateBeforeMemberNameExist(event, beforeName)); - } - - private void validateBeforeMemberNameExist(Event event, String beforeName) { - boolean isMemberNameExist = memberActionRepository.existsByAction_EventAndMemberName(event, beforeName); - if (!isMemberNameExist) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NOT_EXIST); - } - } - - private void validateAfterNames(List<MemberNameUpdateAppRequest> members, Event event) { - List<String> afterNames = members.stream() - .map(MemberNameUpdateAppRequest::after) - .toList(); - if (afterNames.size() != Set.copyOf(afterNames).size()) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); - } - afterNames.forEach(afterName -> validateAfterMemberNameNotExist(event, afterName)); - } - - private void validateAfterMemberNameNotExist(Event event, String afterName) { - boolean isMemberNameExist = memberActionRepository.existsByAction_EventAndMemberName(event, afterName); - if (isMemberNameExist) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE); - } - } - - private void updateMemberName(Event event, String beforeName, String afterName) { - memberActionRepository.findAllByAction_EventAndMemberName(event, beforeName) - .forEach(memberAction -> memberAction.updateMemberName(afterName)); - billActionDetailRepository.findAllByBillAction_Action_EventAndMemberName(event, beforeName) - .forEach(billActionDetail -> billActionDetail.updateMemberName(afterName)); - } - - public void validatePassword(EventLoginAppRequest request) throws HaengdongException { - Event event = getEvent(request.token()); - if (event.isPasswordMismatch(request.password())) { - throw new AuthenticationException(HaengdongErrorCode.PASSWORD_INVALID); - } - } - - private Event getEvent(String token) { - return eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - } -} diff --git a/server/src/main/java/server/haengdong/application/MemberActionFactory.java b/server/src/main/java/server/haengdong/application/MemberActionFactory.java deleted file mode 100644 index c0a171642..000000000 --- a/server/src/main/java/server/haengdong/application/MemberActionFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -package server.haengdong.application; - -import java.util.ArrayList; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.action.MemberGroupIdProvider; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Component -public class MemberActionFactory { - - private final MemberGroupIdProvider memberGroupIdProvider; - - public List<MemberAction> createMemberActions( - MemberActionsSaveAppRequest request, - CurrentMembers currentMembers, - Action action - ) { - validateMemberNames(request); - validateActions(request, currentMembers); - - Long memberGroupId = memberGroupIdProvider.createGroupId(); - List<MemberAction> createdMemberActions = new ArrayList<>(); - List<MemberActionSaveAppRequest> actions = request.actions(); - for (MemberActionSaveAppRequest appRequest : actions) { - MemberAction memberAction = appRequest.toMemberAction(action, memberGroupId); - createdMemberActions.add(memberAction); - action = action.next(); - } - - return createdMemberActions; - } - - private void validateMemberNames(MemberActionsSaveAppRequest request) { - List<String> memberNames = request.actions().stream() - .map(MemberActionSaveAppRequest::name) - .toList(); - - long uniqueCount = memberNames.stream().distinct().count(); - if (uniqueCount != memberNames.size()) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE); - } - } - - private void validateActions(MemberActionsSaveAppRequest request, CurrentMembers currentMembers) { - List<MemberActionSaveAppRequest> actions = request.actions(); - - for (MemberActionSaveAppRequest action : actions) { - MemberActionStatus memberActionStatus = MemberActionStatus.of(action.status()); - currentMembers.validate(action.name(), memberActionStatus); - } - } -} diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java deleted file mode 100644 index 245de8cef..000000000 --- a/server/src/main/java/server/haengdong/application/MemberActionService.java +++ /dev/null @@ -1,100 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class MemberActionService { - - private final MemberActionFactory memberActionFactory; - private final MemberActionRepository memberActionRepository; - private final EventRepository eventRepository; - private final ActionRepository actionRepository; - private final BillActionRepository billActionRepository; - - @Transactional - public void saveMemberAction(String token, MemberActionsSaveAppRequest request) { - Event event = findEvent(token); - - List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); - CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); - Action action = createStartAction(event); - List<MemberAction> memberActions = memberActionFactory.createMemberActions(request, currentMembers, action); - memberActionRepository.saveAll(memberActions); - } - - private Action createStartAction(Event event) { - return actionRepository.findLastByEvent(event) - .map(Action::next) - .orElse(Action.createFirst(event)); - } - - public List<CurrentMemberAppResponse> getCurrentMembers(String token) { - Event event = findEvent(token); - List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); - CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); - - return currentMembers.getMembers() - .stream() - .map(CurrentMemberAppResponse::new) - .toList(); - } - - private Event findEvent(String token) { - return eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - } - - @Transactional - public void deleteMember(String token, String memberName) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - - memberActionRepository.deleteAllByEventAndMemberName(event, memberName); - - List<BillAction> billActions = billActionRepository.findByAction_Event(event); - billActions.forEach(billAction -> resetBillAction(event, billAction)); - } - - @Transactional - public void deleteMemberAction(String token, Long actionId) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - Action action = actionRepository.findByIdAndEvent(actionId, event) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.ACTION_NOT_FOUND)); - MemberAction memberAction = memberActionRepository.findByAction(action) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.MEMBER_ACTION_NOT_FOUND)); - - memberActionRepository.deleteAllByMemberNameAndMinSequence(memberAction.getMemberName(), - memberAction.getSequence()); - - List<BillAction> billActions = billActionRepository.findByEventAndGreaterThanSequence(event, - action.getSequence()); - billActions.forEach(billAction -> resetBillAction(event, billAction)); - } - - private void resetBillAction(Event event, BillAction billAction) { - List<MemberAction> memberActions = memberActionRepository.findByEventAndSequence(event, - billAction.getSequence()); - CurrentMembers currentMembers = CurrentMembers.of(memberActions); - - billAction.resetBillActionDetails(currentMembers); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java deleted file mode 100644 index 21eb17d4a..000000000 --- a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.CurrentMembers; - -public record BillActionAppRequest( - String title, - Long price -) { - - public BillAction toBillAction(Action action, CurrentMembers currentMembers) { - return BillAction.create(action, title, price, currentMembers); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java deleted file mode 100644 index e514aee81..000000000 --- a/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java +++ /dev/null @@ -1,8 +0,0 @@ -package server.haengdong.application.request; - -public record BillActionDetailUpdateAppRequest( - String name, - Long price, - boolean isFixed -) { -} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java deleted file mode 100644 index 1fe19798e..000000000 --- a/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java +++ /dev/null @@ -1,8 +0,0 @@ -package server.haengdong.application.request; - -import java.util.List; - -public record BillActionDetailsUpdateAppRequest( - List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests -) { -} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java deleted file mode 100644 index a90e3dd42..000000000 --- a/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package server.haengdong.application.request; - -public record BillActionUpdateAppRequest( - String title, - Long price -) { -} diff --git a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java deleted file mode 100644 index 20ec16d88..000000000 --- a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.event.Event; - -public record EventAppRequest(String name, String password) { - - public Event toEvent(String token) { - return new Event(name, password, token); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java deleted file mode 100644 index 947b5ef39..000000000 --- a/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java +++ /dev/null @@ -1,4 +0,0 @@ -package server.haengdong.application.request; - -public record EventLoginAppRequest(String token, String password) { -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java deleted file mode 100644 index f7f8d8fc2..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java +++ /dev/null @@ -1,12 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; - -public record MemberActionSaveAppRequest(String name, String status) { - - public MemberAction toMemberAction(Action action, Long memberGroupId) { - return new MemberAction(action, name, MemberActionStatus.of(status), memberGroupId); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java deleted file mode 100644 index 650b908df..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package server.haengdong.application.request; - -import java.util.List; - -public record MemberActionsSaveAppRequest(List<MemberActionSaveAppRequest> actions) { -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java deleted file mode 100644 index d629d3a02..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package server.haengdong.application.request; - -public record MemberNameUpdateAppRequest( - String before, - String after -) { -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java deleted file mode 100644 index cd0c00544..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java +++ /dev/null @@ -1,8 +0,0 @@ -package server.haengdong.application.request; - -import java.util.List; - -public record MemberNamesUpdateAppRequest( - List<MemberNameUpdateAppRequest> members -) { -} diff --git a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java deleted file mode 100644 index 0c2c12611..000000000 --- a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java +++ /dev/null @@ -1,61 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; - -public record ActionAppResponse( - Long actionId, - String name, - Long price, - Long sequence, - boolean isFixed, - ActionType actionType -) { - - public ActionAppResponse(Long actionId, String name, Long price, Long sequence, ActionType actionType) { - this(actionId, name, price, sequence, false, actionType); - } - - public static ActionAppResponse of(BillAction billAction) { - return new ActionAppResponse( - billAction.getAction().getId(), - billAction.getTitle(), - billAction.getPrice(), - billAction.getSequence(), - billAction.isFixed(), - ActionAppResponse.ActionType.BILL - ); - } - - public static ActionAppResponse of(MemberAction memberAction) { - MemberActionStatus status = memberAction.getStatus(); - - return new ActionAppResponse( - memberAction.getAction().getId(), - memberAction.getMemberName(), - null, - memberAction.getSequence(), - false, - ActionAppResponse.ActionType.of(status) - ); - } - - public String actionTypeName() { - return actionType.name(); - } - - public enum ActionType { - BILL, - IN, - OUT, - ; - - private static ActionType of(MemberActionStatus memberActionStatus) { - if (MemberActionStatus.IN == memberActionStatus) { - return IN; - } - return OUT; - } - } -} diff --git a/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java deleted file mode 100644 index 3efc7ac9d..000000000 --- a/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.action.BillActionDetail; - -public record BillActionDetailAppResponse( - String name, - Long price, - boolean isFixed -) { - - public static BillActionDetailAppResponse of(BillActionDetail billActionDetail) { - return new BillActionDetailAppResponse( - billActionDetail.getMemberName(), - billActionDetail.getPrice(), - billActionDetail.isFixed() - ); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java b/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java deleted file mode 100644 index 061f07816..000000000 --- a/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.application.response; - -import java.util.List; -import java.util.stream.Collectors; -import server.haengdong.domain.action.BillActionDetail; - -public record BillActionDetailsAppResponse(List<BillActionDetailAppResponse> billActionDetailAppResponses) { - - public static BillActionDetailsAppResponse of(List<BillActionDetail> billActionDetails) { - return billActionDetails.stream() - .map(BillActionDetailAppResponse::of) - .collect(Collectors.collectingAndThen(Collectors.toList(), BillActionDetailsAppResponse::new)); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java deleted file mode 100644 index 6c682d3e9..000000000 --- a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.action.MemberAction; - -public record CurrentMemberAppResponse(String name) { - - public static CurrentMemberAppResponse of(MemberAction memberAction) { - return new CurrentMemberAppResponse(memberAction.getMemberName()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java deleted file mode 100644 index f331d0011..000000000 --- a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.event.Event; - -public record EventAppResponse(String token) { - - public static EventAppResponse of(Event event) { - return new EventAppResponse(event.getToken()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java deleted file mode 100644 index 6e38826d4..000000000 --- a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.event.Event; - -public record EventDetailAppResponse(String eventName) { - - public static EventDetailAppResponse of(Event event) { - return new EventDetailAppResponse(event.getName()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java deleted file mode 100644 index 21b6cef56..000000000 --- a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java +++ /dev/null @@ -1,4 +0,0 @@ -package server.haengdong.application.response; - -public record MemberBillReportAppResponse(String name, Long price) { -} diff --git a/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java b/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java deleted file mode 100644 index be8378b37..000000000 --- a/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java +++ /dev/null @@ -1,8 +0,0 @@ -package server.haengdong.application.response; - -import java.util.List; - -public record MembersAppResponse( - List<String> memberNames -) { -} diff --git a/server/src/main/java/server/haengdong/config/AdminInterceptor.java b/server/src/main/java/server/haengdong/config/AdminInterceptor.java deleted file mode 100644 index a0542ed46..000000000 --- a/server/src/main/java/server/haengdong/config/AdminInterceptor.java +++ /dev/null @@ -1,51 +0,0 @@ -package server.haengdong.config; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpMethod; -import org.springframework.web.servlet.HandlerInterceptor; -import server.haengdong.application.AuthService; -import server.haengdong.exception.AuthenticationException; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.infrastructure.auth.AuthenticationExtractor; - -@Slf4j -public class AdminInterceptor implements HandlerInterceptor { - - private final AuthService authService; - private final AuthenticationExtractor authenticationExtractor; - - public AdminInterceptor(AuthService authService, AuthenticationExtractor authenticationExtractor) { - this.authService = authService; - this.authenticationExtractor = authenticationExtractor; - } - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { - String requestURI = request.getRequestURI(); - - if (requestURI.endsWith("/login")) { - return true; // 요청을 계속 진행하도록 허용 - } - - HttpMethod method = HttpMethod.valueOf(request.getMethod()); - if (HttpMethod.GET.equals(method) || HttpMethod.OPTIONS.equals(method)) { - return true; - } - - validateToken(request); - - return true; - } - - private void validateToken(HttpServletRequest request) { - String token = authenticationExtractor.extract(request, authService.getTokenName()); - String tokenEventId = authService.findEventIdByToken(token); - String eventId = request.getRequestURI().split("/")[3]; - if (!tokenEventId.equals(eventId)) { - log.warn("[행사 접근 불가] Cookie EventId = {}, URL EventId = {}", tokenEventId, eventId); - throw new AuthenticationException(HaengdongErrorCode.FORBIDDEN); - } - } -} diff --git a/server/src/main/java/server/haengdong/config/RequestServletFilter.java b/server/src/main/java/server/haengdong/config/RequestServletFilter.java deleted file mode 100644 index b1afdb6f8..000000000 --- a/server/src/main/java/server/haengdong/config/RequestServletFilter.java +++ /dev/null @@ -1,23 +0,0 @@ -package server.haengdong.config; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import java.io.IOException; -import org.springframework.stereotype.Component; -import org.springframework.web.util.ContentCachingRequestWrapper; - -@Component -public class RequestServletFilter implements Filter { - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper((HttpServletRequest) request); - - chain.doFilter(wrappedRequest, response); - } -} diff --git a/server/src/main/java/server/haengdong/config/WebMvcConfig.java b/server/src/main/java/server/haengdong/config/WebMvcConfig.java deleted file mode 100644 index d1caa176f..000000000 --- a/server/src/main/java/server/haengdong/config/WebMvcConfig.java +++ /dev/null @@ -1,66 +0,0 @@ -package server.haengdong.config; - -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import server.haengdong.application.AuthService; -import server.haengdong.domain.TokenProvider; -import server.haengdong.infrastructure.auth.AuthenticationExtractor; -import server.haengdong.infrastructure.auth.JwtTokenProvider; -import server.haengdong.infrastructure.auth.TokenProperties; - -@RequiredArgsConstructor -@EnableConfigurationProperties(TokenProperties.class) -@Configuration -public class WebMvcConfig implements WebMvcConfigurer { - - private final TokenProperties tokenProperties; - - @Value("${cors.max-age}") - private Long maxAge; - - @Value("${cors.allowed-origins}") - private String[] allowedOrigins; - - @Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOrigins(allowedOrigins) - .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") - .allowedHeaders("*") - .allowCredentials(true) - .maxAge(maxAge); - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(adminInterceptor()) - .addPathPatterns("/api/**") - .excludePathPatterns("/api/events"); - } - - @Bean - public AdminInterceptor adminInterceptor() { - return new AdminInterceptor(authService(), authenticationExtractor()); - } - - @Bean - public AuthService authService() { - return new AuthService(tokenProvider()); - } - - @Bean - public TokenProvider tokenProvider() { - return new JwtTokenProvider(tokenProperties); - } - - @Bean - public AuthenticationExtractor authenticationExtractor() { - return new AuthenticationExtractor(); - } -} diff --git a/server/src/main/java/server/haengdong/domain/TokenProvider.java b/server/src/main/java/server/haengdong/domain/TokenProvider.java deleted file mode 100644 index 28e7956c3..000000000 --- a/server/src/main/java/server/haengdong/domain/TokenProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package server.haengdong.domain; - -import java.util.Map; - -public interface TokenProvider { - - String createToken(Map<String, Object> payload); - - Map<String, Object> getPayload(String token); - - boolean validateToken(String token); -} diff --git a/server/src/main/java/server/haengdong/domain/action/Action.java b/server/src/main/java/server/haengdong/domain/action/Action.java deleted file mode 100644 index 11f91fc38..000000000 --- a/server/src/main/java/server/haengdong/domain/action/Action.java +++ /dev/null @@ -1,42 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.domain.event.Event; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Action { - - private static final long FIRST_SEQUENCE = 1L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private Event event; - - private Long sequence; - - public Action(Event event, Long sequence) { - this.event = event; - this.sequence = sequence; - } - - public static Action createFirst(Event event) { - return new Action(event, FIRST_SEQUENCE); - } - - public Action next() { - return new Action(event, sequence + 1); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java deleted file mode 100644 index 2fde0ffa6..000000000 --- a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface ActionRepository extends JpaRepository<Action, Long> { - - @Query(""" - SELECT a - FROM Action a - WHERE a.event = :event - ORDER BY a.sequence DESC - LIMIT 1 - """) - Optional<Action> findLastByEvent(@Param("event") Event event); - - Optional<Action> findByIdAndEvent(Long id, Event event); -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java deleted file mode 100644 index 943b40ce5..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillAction.java +++ /dev/null @@ -1,156 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.OneToMany; -import jakarta.persistence.OneToOne; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.domain.event.Event; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class BillAction implements Comparable<BillAction> { - - public static final int MIN_TITLE_LENGTH = 1; - public static final int MAX_TITLE_LENGTH = 30; - public static final long MIN_PRICE = 1L; - public static final long MAX_PRICE = 10_000_000L; - private static final long DEFAULT_PRICE = 0L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) - private Action action; - - @Column(length = MAX_TITLE_LENGTH) - private String title; - - private Long price; - - @OneToMany(mappedBy = "billAction", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) - private List<BillActionDetail> billActionDetails = new ArrayList<>(); - - public BillAction(Action action, String title, Long price) { - validateTitle(title); - validatePrice(price); - this.action = action; - this.title = title.trim(); - this.price = price; - } - - private void validateTitle(String title) { - int titleLength = title.trim().length(); - if (titleLength < MIN_TITLE_LENGTH || titleLength > MAX_TITLE_LENGTH) { - throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_TITLE_INVALID); - } - } - - private void validatePrice(Long price) { - if (price < MIN_PRICE || price > MAX_PRICE) { - throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_PRICE_INVALID); - } - } - - public static BillAction create(Action action, String title, Long price, CurrentMembers currentMembers) { - BillAction billAction = new BillAction(action, title, price); - billAction.resetBillActionDetails(currentMembers); - return billAction; - } - - public void resetBillActionDetails(CurrentMembers currentMembers) { - this.billActionDetails.clear(); - Iterator<Long> priceIterator = distributePrice(currentMembers.size()).iterator(); - - for (String member : currentMembers.getMembers()) { - BillActionDetail billActionDetail = new BillActionDetail(this, member, priceIterator.next(), false); - this.billActionDetails.add(billActionDetail); - } - } - - private void resetBillActionDetails() { - Iterator<Long> priceIterator = distributePrice(billActionDetails.size()).iterator(); - - billActionDetails.forEach(billActionDetail -> { - billActionDetail.updatePrice(priceIterator.next()); - billActionDetail.updateIsFixed(false); - }); - } - - private List<Long> distributePrice(int memberCount) { - if (memberCount == 0) { - return new ArrayList<>(); - } - long eachPrice = price / memberCount; - long remainder = price % memberCount; - - List<Long> results = Stream.generate(() -> eachPrice) - .limit(memberCount - 1) - .collect(Collectors.toList()); - results.add(eachPrice + remainder); - return results; - } - - public void update(String title, Long price) { - validateTitle(title); - validatePrice(price); - this.title = title.trim(); - this.price = price; - resetBillActionDetails(); - } - - public void addDetails(List<BillActionDetail> billActionDetails) { - billActionDetails.forEach(this::addDetail); - } - - private void addDetail(BillActionDetail billActionDetail) { - this.billActionDetails.add(billActionDetail); - billActionDetail.setBillAction(this); - } - - public boolean isFixed() { - return billActionDetails.stream() - .anyMatch(BillActionDetail::isFixed); - } - - public boolean isSamePrice(Long price) { - return this.price.equals(price); - } - - public Long findPriceByMemberName(String memberName) { - return billActionDetails.stream() - .filter(billActionDetail -> billActionDetail.hasMemberName(memberName)) - .map(BillActionDetail::getPrice) - .findFirst() - .orElse(DEFAULT_PRICE); - } - - public Long getSequence() { - return action.getSequence(); - } - - public Event getEvent() { - return action.getEvent(); - } - - @Override - public int compareTo(BillAction o) { - return Long.compare(this.getSequence(), o.getSequence()); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java deleted file mode 100644 index ffdfe04a3..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java +++ /dev/null @@ -1,61 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class BillActionDetail { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private BillAction billAction; - - private String memberName; - - private Long price; - - private boolean isFixed; - - public BillActionDetail(BillAction billAction, String memberName, Long price, boolean isFixed) { - this.billAction = billAction; - this.memberName = memberName; - this.price = price; - this.isFixed = isFixed; - } - - public void updatePrice(Long price) { - this.price = price; - } - - public void updateIsFixed(boolean isFixed) { - this.isFixed = isFixed; - } - - public void updateMemberName(String name) { - this.memberName = name; - } - - public boolean hasMemberName(String memberName) { - return this.memberName.equals(memberName); - } - - public boolean isSameName(String memberName) { - return this.memberName.equals(memberName); - } - - public void setBillAction(BillAction billAction) { - this.billAction = billAction; - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java deleted file mode 100644 index 05de55304..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.List; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface BillActionDetailRepository extends JpaRepository<BillActionDetail, Long> { - - @Query(""" - select bd - from BillActionDetail bd - where bd.billAction = :billAction - """) - List<BillActionDetail> findAllByBillAction(BillAction billAction); - - List<BillActionDetail> findAllByBillAction_Action_EventAndMemberName(Event event, String memberName); -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java deleted file mode 100644 index 817a63bf8..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.List; -import java.util.Optional; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface BillActionRepository extends JpaRepository<BillAction, Long> { - - @EntityGraph(attributePaths = {"action"}) - List<BillAction> findByAction_Event(Event event); - - void deleteByAction_EventAndActionId(Event event, Long actionId); - - Optional<BillAction> findByAction_Id(Long actionId); - - @Query(""" - select ba - from BillAction ba - where ba.action.event = :event and ba.action.sequence > :sequence - """) - List<BillAction> findByEventAndGreaterThanSequence(Event event, Long sequence); -} diff --git a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java deleted file mode 100644 index ba380aae5..000000000 --- a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java +++ /dev/null @@ -1,81 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -public class CurrentMembers { - - private final Set<String> members; - - public CurrentMembers() { - this(new HashSet<>()); - } - - protected CurrentMembers(Set<String> members) { - this.members = members; - } - - public static CurrentMembers of(List<MemberAction> memberActions) { - List<MemberAction> sortedMemberActions = getSortedMemberActions(memberActions); - Set<String> members = new HashSet<>(); - for (MemberAction memberAction : sortedMemberActions) { - String member = memberAction.getMemberName(); - if (memberAction.isSameStatus(MemberActionStatus.IN)) { - members.add(member); - continue; - } - members.remove(member); - } - - return new CurrentMembers(members); - } - - private static List<MemberAction> getSortedMemberActions(List<MemberAction> memberActions) { - return memberActions.stream() - .sorted(Comparator.comparing(MemberAction::getSequence)) - .toList(); - } - - public CurrentMembers addMemberAction(MemberAction memberAction) { - String memberName = memberAction.getMemberName(); - - Set<String> currentMembers = new HashSet<>(members); - - if (memberAction.isIn()) { - currentMembers.add(memberName); - } else { - currentMembers.remove(memberName); - } - return new CurrentMembers(currentMembers); - } - - public void validate(String memberName, MemberActionStatus memberActionStatus) { - if (memberActionStatus == MemberActionStatus.IN && members.contains(memberName)) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_ALREADY_EXIST); - } - if (memberActionStatus == MemberActionStatus.OUT && !members.contains(memberName)) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NOT_EXIST); - } - } - - public boolean isEmpty() { - return members.isEmpty(); - } - - public boolean isNotEmpty() { - return !members.isEmpty(); - } - - public int size() { - return members.size(); - } - - public Set<String> getMembers() { - return Collections.unmodifiableSet(members); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberAction.java b/server/src/main/java/server/haengdong/domain/action/MemberAction.java deleted file mode 100644 index 3faf65bde..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberAction.java +++ /dev/null @@ -1,76 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.OneToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class MemberAction implements Comparable<MemberAction> { - - public static final int MIN_NAME_LENGTH = 1; - public static final int MAX_NAME_LENGTH = 4; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) - private Action action; - - private String memberName; - - @Enumerated(EnumType.STRING) - private MemberActionStatus status; - - private Long memberGroupId; - - public MemberAction(Action action, String memberName, MemberActionStatus status, Long memberGroupId) { - validateMemberName(memberName); - this.action = action; - this.memberName = memberName; - this.status = status; - this.memberGroupId = memberGroupId; - } - - private void validateMemberName(String memberName) { - int memberLength = memberName.length(); - if (memberLength < MIN_NAME_LENGTH || memberLength > MAX_NAME_LENGTH) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_LENGTH_INVALID); - } - } - - public void updateMemberName(String memberName) { - validateMemberName(memberName); - this.memberName = memberName; - } - - public boolean isIn() { - return status == MemberActionStatus.IN; - } - - public boolean isSameStatus(MemberActionStatus memberActionStatus) { - return status == memberActionStatus; - } - - public Long getSequence() { - return action.getSequence(); - } - - @Override - public int compareTo(MemberAction o) { - return Long.compare(this.getSequence(), o.getSequence()); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java deleted file mode 100644 index 324ff9797..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java +++ /dev/null @@ -1,53 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.List; -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface MemberActionRepository extends JpaRepository<MemberAction, Long> { - - @Query("select m from MemberAction m join fetch m.action where m.action.event = :event") - List<MemberAction> findAllByEvent(@Param("event") Event event); - - @Query(""" - select distinct m.memberName - from MemberAction m - where m.action.event = :event - """) - List<String> findAllUniqueMemberByEvent(Event event); - - @Modifying - @Query(""" - delete - from MemberAction m - where m.memberName = :memberName and m.action.event = :event - """) - void deleteAllByEventAndMemberName(Event event, String memberName); - - Optional<MemberAction> findByAction(Action action); - - @Modifying - @Query(""" - delete - from MemberAction m - where m.memberName = :memberName and m.action.sequence >= :sequence - """) - void deleteAllByMemberNameAndMinSequence(String memberName, Long sequence); - - List<MemberAction> findAllByAction_EventAndMemberName(Event event, String memberName); - - boolean existsByAction_EventAndMemberName(Event event, String updatedMemberName); - - @Query(""" - select ma - from MemberAction ma - where ma.action.event = :event and ma.action.sequence < :sequence - """) - List<MemberAction> findByEventAndSequence(Event event, Long sequence); -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java deleted file mode 100644 index 76c5a66d4..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Arrays; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -public enum MemberActionStatus { - IN, - OUT, - ; - - public static MemberActionStatus of(String status) { - return Arrays.stream(MemberActionStatus.values()) - .filter(s -> s.name().equals(status)) - .findFirst() - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.MEMBER_ACTION_STATUS_INVALID, - String.format(HaengdongErrorCode.MEMBER_ACTION_STATUS_INVALID.getMessage(), status))); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java deleted file mode 100644 index 7a707b9d8..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java +++ /dev/null @@ -1,75 +0,0 @@ -package server.haengdong.domain.action; - -import static java.util.stream.Collectors.toMap; - -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.function.Function; -import lombok.Getter; - -@Getter -public class MemberBillReport { - - private final Map<String, Long> reports; - - private MemberBillReport(Map<String, Long> reports) { - this.reports = reports; - } - - public static MemberBillReport createByActions(List<BillAction> billActions, List<MemberAction> memberActions) { - PriorityQueue<BillAction> sortedBillActions = new PriorityQueue<>(billActions); - PriorityQueue<MemberAction> sortedMemberActions = new PriorityQueue<>(memberActions); - - Map<String, Long> memberBillReports = initReports(memberActions); - CurrentMembers currentMembers = new CurrentMembers(); - while (!sortedBillActions.isEmpty() && !sortedMemberActions.isEmpty()) { - if (isMemberActionTurn(sortedMemberActions, sortedBillActions)) { - MemberAction memberAction = sortedMemberActions.poll(); - currentMembers = currentMembers.addMemberAction(memberAction); - continue; - } - addBillAction(sortedBillActions, currentMembers, memberBillReports); - } - - while (!sortedBillActions.isEmpty()) { - addBillAction(sortedBillActions, currentMembers, memberBillReports); - } - - return new MemberBillReport(memberBillReports); - } - - private static Map<String, Long> initReports(List<MemberAction> memberActions) { - return memberActions.stream() - .map(MemberAction::getMemberName) - .distinct() - .collect(toMap(Function.identity(), i -> 0L)); - } - - private static boolean isMemberActionTurn( - PriorityQueue<MemberAction> memberActions, - PriorityQueue<BillAction> billActions - ) { - MemberAction memberAction = memberActions.peek(); - BillAction billAction = billActions.peek(); - - return memberAction.getSequence() < billAction.getSequence(); - } - - private static void addBillAction( - PriorityQueue<BillAction> sortedBillActions, - CurrentMembers currentMembers, - Map<String, Long> memberBillReports - ) { - BillAction billAction = sortedBillActions.poll(); - if (currentMembers.isEmpty()) { - return; - } - - for (String currentMember : currentMembers.getMembers()) { - Long currentPrice = billAction.findPriceByMemberName(currentMember); - Long price = memberBillReports.get(currentMember) + currentPrice; - memberBillReports.put(currentMember, price); - } - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java deleted file mode 100644 index 9e32bd733..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java +++ /dev/null @@ -1,11 +0,0 @@ -package server.haengdong.domain.action; - -import org.springframework.stereotype.Component; - -@Component -public class MemberGroupIdProvider { - - public Long createGroupId() { - return System.currentTimeMillis(); - } -} diff --git a/server/src/main/java/server/haengdong/domain/event/Event.java b/server/src/main/java/server/haengdong/domain/event/Event.java deleted file mode 100644 index bb5d53dbc..000000000 --- a/server/src/main/java/server/haengdong/domain/event/Event.java +++ /dev/null @@ -1,70 +0,0 @@ -package server.haengdong.domain.event; - -import jakarta.persistence.AttributeOverride; -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Event { - - public static final int MIN_NAME_LENGTH = 1; - public static final int MAX_NAME_LENGTH = 20; - private static final String SPACES = " "; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String name; - - @Embedded - @AttributeOverride(name = "value", column = @Column(name = "password")) - private Password password; - - private String token; - - public Event(String name, String password, String token) { - validateName(name); - this.name = name; - this.password = new Password(password); - this.token = token; - } - - private void validateName(String name) { - int nameLength = name.trim().length(); - if (nameLength < MIN_NAME_LENGTH || MAX_NAME_LENGTH < nameLength) { - throw new HaengdongException(HaengdongErrorCode.EVENT_NAME_LENGTH_INVALID, - String.format("행사 이름은 %d자 이상 %d자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", - MIN_NAME_LENGTH, - MAX_NAME_LENGTH, - name.length())); - } - if (isBlankContinuous(name)) { - throw new HaengdongException(HaengdongErrorCode.EVENT_NAME_CONSECUTIVE_SPACES, - String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", name)); - } - } - - private boolean isBlankContinuous(String name) { - return name.contains(SPACES); - } - - public boolean isTokenMismatch(String token) { - return !this.token.equals(token); - } - - public boolean isPasswordMismatch(String rawPassword) { - return !password.matches(rawPassword); - } -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventRepository.java b/server/src/main/java/server/haengdong/domain/event/EventRepository.java deleted file mode 100644 index 09526125e..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package server.haengdong.domain.event; - -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface EventRepository extends JpaRepository<Event, Long> { - - Optional<Event> findByToken(String token); -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventStep.java b/server/src/main/java/server/haengdong/domain/event/EventStep.java deleted file mode 100644 index 297abdb66..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventStep.java +++ /dev/null @@ -1,28 +0,0 @@ -package server.haengdong.domain.event; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class EventStep { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private Event event; - - private String name; - - private Long sequence; -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java deleted file mode 100644 index 6450f0dcf..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package server.haengdong.domain.event; - -import java.util.UUID; -import org.springframework.stereotype.Component; - -@Component -public class EventTokenProvider { - - public String createToken() { - return UUID.randomUUID().toString(); - } -} diff --git a/server/src/main/java/server/haengdong/domain/event/Password.java b/server/src/main/java/server/haengdong/domain/event/Password.java deleted file mode 100644 index 375849dbf..000000000 --- a/server/src/main/java/server/haengdong/domain/event/Password.java +++ /dev/null @@ -1,52 +0,0 @@ -package server.haengdong.domain.event; - -import jakarta.persistence.Embeddable; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Base64; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -@Embeddable -public class Password { - - public static final int PASSWORD_LENGTH = 4; - private static final Pattern PASSWORD_PATTERN = Pattern.compile(String.format("^\\d{%d}$", PASSWORD_LENGTH)); - private static final String HASH_ALGORITHM = "SHA-256"; - - private String value; - - public Password(String password) { - validatePassword(password); - this.value = encode(password); - } - - private void validatePassword(String password) { - Matcher matcher = PASSWORD_PATTERN.matcher(password); - if (!matcher.matches()) { - throw new HaengdongException(HaengdongErrorCode.EVENT_PASSWORD_FORMAT_INVALID); - } - } - - private String encode(String rawPassword) { - try { - MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM); - byte[] hashedPassword = digest.digest(rawPassword.getBytes()); - return Base64.getEncoder().encodeToString(hashedPassword); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("해시 알고리즘이 존재하지 않습니다."); - } - } - - public boolean matches(String rawPassword) { - String hashedPassword = encode(rawPassword); - return value.equals(hashedPassword); - } -} diff --git a/server/src/main/java/server/haengdong/exception/AuthenticationException.java b/server/src/main/java/server/haengdong/exception/AuthenticationException.java deleted file mode 100644 index 2efcb16e7..000000000 --- a/server/src/main/java/server/haengdong/exception/AuthenticationException.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.exception; - -import lombok.Getter; - -@Getter -public class AuthenticationException extends RuntimeException { - - private final HaengdongErrorCode errorCode; - private final String message; - - public AuthenticationException(HaengdongErrorCode errorCode) { - this(errorCode, errorCode.getMessage()); - } - - public AuthenticationException(HaengdongErrorCode errorCode, String message) { - this.errorCode = errorCode; - this.message = message; - } -} diff --git a/server/src/main/java/server/haengdong/exception/ErrorResponse.java b/server/src/main/java/server/haengdong/exception/ErrorResponse.java deleted file mode 100644 index d0a2b01a0..000000000 --- a/server/src/main/java/server/haengdong/exception/ErrorResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.exception; - -public record ErrorResponse( - HaengdongErrorCode errorCode, - String message -) { - - public static ErrorResponse of(HaengdongErrorCode errorCode) { - return new ErrorResponse(errorCode, errorCode.getMessage()); - } - - public static ErrorResponse of(HaengdongErrorCode errorCode, String message) { - return new ErrorResponse(errorCode, message); - } -} diff --git a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java deleted file mode 100644 index 0cee7cb4c..000000000 --- a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java +++ /dev/null @@ -1,90 +0,0 @@ -package server.haengdong.exception; - -import jakarta.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.servlet.resource.NoResourceFoundException; - -@Slf4j -@RestControllerAdvice -public class GlobalExceptionHandler { - - private static final String LOG_FORMAT = """ - \n\t{ - "RequestURI": "{} {}", - "RequestBody": {}, - "ErrorMessage": "{}" - \t} - """; - - @ExceptionHandler(AuthenticationException.class) - public ResponseEntity<ErrorResponse> authenticationException(HttpServletRequest req, AuthenticationException e) { - log.warn(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED) - .body(ErrorResponse.of(e.getErrorCode())); - } - - @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - public ResponseEntity<ErrorResponse> noResourceException(HttpRequestMethodNotSupportedException e) { - log.warn(e.getMessage(), e); - return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.REQUEST_METHOD_NOT_SUPPORTED)); - } - - @ExceptionHandler(NoResourceFoundException.class) - public ResponseEntity<ErrorResponse> noResourceException(NoResourceFoundException e) { - log.warn(e.getMessage(), e); - return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.NO_RESOURCE_REQUEST)); - } - - @ExceptionHandler(HttpMessageNotReadableException.class) - public ResponseEntity<ErrorResponse> httpMessageNotReadableException(HttpMessageNotReadableException e) { - log.warn(e.getMessage(), e); - return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.MESSAGE_NOT_READABLE)); - } - - @ExceptionHandler(MethodArgumentNotValidException.class) - public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - log.warn(e.getMessage(), e); - String errorMessage = e.getFieldErrors().stream() - .map(error -> error.getField() + " " + error.getDefaultMessage()) - .collect(Collectors.joining(", ")); - - return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.REQUEST_EMPTY, errorMessage)); - } - - @ExceptionHandler(HaengdongException.class) - public ResponseEntity<ErrorResponse> haengdongException(HttpServletRequest req, HaengdongException e) { - log.warn(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); - return ResponseEntity.badRequest() - .body(ErrorResponse.of(e.getErrorCode())); - } - - @ExceptionHandler(Exception.class) - public ResponseEntity<ErrorResponse> handleException(HttpServletRequest req, Exception e) { - log.error(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); - return ResponseEntity.internalServerError() - .body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR)); - } - - private String getRequestBody(HttpServletRequest req) { - try (BufferedReader reader = req.getReader()) { - return reader.lines().collect(Collectors.joining(System.lineSeparator() + "\t")); - } catch (IOException e) { - log.error("Failed to read request body", e); - return ""; - } - } -} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java deleted file mode 100644 index 475d16c11..000000000 --- a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java +++ /dev/null @@ -1,69 +0,0 @@ -package server.haengdong.exception; - -import lombok.Getter; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.Password; - -@Getter -public enum HaengdongErrorCode { - - /* Domain */ - - EVENT_NOT_FOUND("존재하지 않는 행사입니다."), - EVENT_NAME_LENGTH_INVALID(String.format("행사 이름은 %d자 이상 %d자 이하만 입력 가능합니다.", - Event.MIN_NAME_LENGTH, - Event.MAX_NAME_LENGTH)), - EVENT_NAME_CONSECUTIVE_SPACES("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s"), - EVENT_PASSWORD_FORMAT_INVALID(String.format("비밀번호는 %d자리 숫자만 가능합니다.", Password.PASSWORD_LENGTH)), - - ACTION_NOT_FOUND("존재하지 않는 액션입니다."), - - MEMBER_NAME_LENGTH_INVALID(String.format("멤버 이름은 %d자 이상 %d자 이하만 입력 가능합니다.", - MemberAction.MIN_NAME_LENGTH, - MemberAction.MAX_NAME_LENGTH)), - MEMBER_NAME_DUPLICATE("중복된 행사 참여 인원 이름이 존재합니다."), - MEMBER_NOT_EXIST("현재 참여하고 있지 않는 인원이 존재합니다."), - MEMBER_ALREADY_EXIST("현재 참여하고 있는 인원이 존재합니다."), - MEMBER_NAME_CHANGE_DUPLICATE("중복된 참여 인원 이름 변경 요청이 존재합니다."), - - MEMBER_ACTION_NOT_FOUND("존재하지 않는 멤버 액션입니다."), - MEMBER_ACTION_STATUS_INVALID("멤버 액션은 IN, OUT만 가능합니다. 입력한 멤버 액션: %s"), - - BILL_ACTION_NOT_FOUND("존재하지 않는 지출 액션입니다."), - BILL_ACTION_TITLE_INVALID(String.format("앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다.", - BillAction.MIN_TITLE_LENGTH, - BillAction.MAX_TITLE_LENGTH)), - BILL_ACTION_PRICE_INVALID(String.format("지출 금액은 %,d 이하의 자연수여야 합니다.", BillAction.MAX_PRICE)), - BILL_ACTION_DETAIL_NOT_FOUND("존재하지 않는 참여자 지출입니다."), - BILL_ACTION_PRICE_NOT_MATCHED("지출 총액이 일치하지 않습니다."), - - /* Authentication */ - - PASSWORD_INVALID("비밀번호가 일치하지 않습니다."), - - TOKEN_NOT_FOUND("토큰이 존재하지 않습니다."), - TOKEN_EXPIRED("만료된 토큰입니다."), - TOKEN_INVALID("유효하지 않은 토큰입니다."), - - FORBIDDEN("접근할 수 없는 행사입니다."), - - /* Request Validation */ - - REQUEST_EMPTY("입력 값은 공백일 수 없습니다.") - - /* System */, - - MESSAGE_NOT_READABLE("읽을 수 없는 요청입니다."), - REQUEST_METHOD_NOT_SUPPORTED("지원하지 않는 요청 메서드입니다."), - NO_RESOURCE_REQUEST("존재하지 않는 자원입니다."), - INTERNAL_SERVER_ERROR("서버 내부에서 에러가 발생했습니다."), - ; - - private final String message; - - HaengdongErrorCode(String message) { - this.message = message; - } -} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongException.java b/server/src/main/java/server/haengdong/exception/HaengdongException.java deleted file mode 100644 index b86fe4ffc..000000000 --- a/server/src/main/java/server/haengdong/exception/HaengdongException.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.exception; - -import lombok.Getter; - -@Getter -public class HaengdongException extends RuntimeException { - - private final HaengdongErrorCode errorCode; - private final String message; - - public HaengdongException(HaengdongErrorCode errorCode) { - this(errorCode, errorCode.getMessage()); - } - - public HaengdongException(HaengdongErrorCode errorCode, String message) { - this.errorCode = errorCode; - this.message = message; - } -} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java b/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java deleted file mode 100644 index 4972de48a..000000000 --- a/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java +++ /dev/null @@ -1,23 +0,0 @@ -package server.haengdong.infrastructure.auth; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import java.util.Arrays; -import server.haengdong.exception.AuthenticationException; -import server.haengdong.exception.HaengdongErrorCode; - -public class AuthenticationExtractor { - - public String extract(HttpServletRequest request, String cookieName) { - Cookie[] cookies = request.getCookies(); - if (cookies == null) { - throw new AuthenticationException(HaengdongErrorCode.TOKEN_NOT_FOUND); - } - - return Arrays.stream(cookies) - .filter(cookie -> cookieName.equals(cookie.getName())) - .findFirst() - .orElseThrow(() -> new AuthenticationException(HaengdongErrorCode.TOKEN_NOT_FOUND)) - .getValue(); - } -} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java b/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java deleted file mode 100644 index 18f867601..000000000 --- a/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.infrastructure.auth; - -import java.time.Duration; -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties("cookie") -public record CookieProperties( - boolean httpOnly, - boolean secure, - String domain, - String path, - String sameSite, - Duration maxAge -) { -} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java b/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java deleted file mode 100644 index df9ec6a81..000000000 --- a/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -package server.haengdong.infrastructure.auth; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.JwtException; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import server.haengdong.domain.TokenProvider; - -public class JwtTokenProvider implements TokenProvider { - - private final TokenProperties tokenProperties; - - public JwtTokenProvider(TokenProperties tokenProperties) { - this.tokenProperties = tokenProperties; - } - - @Override - public String createToken(Map<String, Object> payload) { - Claims claims = Jwts.claims(new HashMap<>(payload)); - Date now = new Date(); - Date validity = new Date(now.getTime() + tokenProperties.expireLength()); - - return Jwts.builder() - .setClaims(claims) - .setIssuedAt(now) - .setExpiration(validity) - .signWith(SignatureAlgorithm.HS256, tokenProperties.secretKey()) - .compact(); - } - - @Override - public Map<String, Object> getPayload(String token) { - return Jwts.parser() - .setSigningKey(tokenProperties.secretKey()) - .parseClaimsJws(token) - .getBody(); - } - - @Override - public boolean validateToken(String token) { - try { - Jws<Claims> claims = Jwts.parser().setSigningKey(tokenProperties.secretKey()).parseClaimsJws(token); - - return !claims.getBody().getExpiration().before(new Date()); - } catch (JwtException | IllegalArgumentException e) { - return false; - } - } -} - diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java b/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java deleted file mode 100644 index 11dedcdbf..000000000 --- a/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java +++ /dev/null @@ -1,7 +0,0 @@ -package server.haengdong.infrastructure.auth; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties("security.jwt.token") -public record TokenProperties(String secretKey, Long expireLength) { -} diff --git a/server/src/main/java/server/haengdong/presentation/ActionController.java b/server/src/main/java/server/haengdong/presentation/ActionController.java deleted file mode 100644 index 657cb567e..000000000 --- a/server/src/main/java/server/haengdong/presentation/ActionController.java +++ /dev/null @@ -1,26 +0,0 @@ -package server.haengdong.presentation; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.ActionService; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.presentation.response.MemberBillReportsResponse; - -@RequiredArgsConstructor -@RestController -public class ActionController { - - private final ActionService actionService; - - @GetMapping("/api/events/{eventId}/actions/reports") - public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVariable("eventId") String token) { - List<MemberBillReportAppResponse> memberBillReports = actionService.getMemberBillReports(token); - - return ResponseEntity.ok() - .body(MemberBillReportsResponse.of(memberBillReports)); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionController.java b/server/src/main/java/server/haengdong/presentation/BillActionController.java deleted file mode 100644 index 56e99337d..000000000 --- a/server/src/main/java/server/haengdong/presentation/BillActionController.java +++ /dev/null @@ -1,55 +0,0 @@ -package server.haengdong.presentation; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.BillActionService; -import server.haengdong.presentation.request.BillActionUpdateRequest; -import server.haengdong.presentation.request.BillActionsSaveRequest; - -@RequiredArgsConstructor -@RestController -public class BillActionController { - - private final BillActionService billActionService; - - @PostMapping("/api/events/{eventId}/bill-actions") - public ResponseEntity<Void> saveAllBillAction( - @PathVariable("eventId") String token, - @Valid @RequestBody BillActionsSaveRequest request - ) { - billActionService.saveAllBillAction(token, request.toAppRequests()); - - return ResponseEntity.ok() - .build(); - } - - @PutMapping("/api/events/{eventId}/bill-actions/{actionId}") - public ResponseEntity<Void> updateBillAction( - @PathVariable("eventId") String token, - @PathVariable("actionId") Long actionId, - @Valid @RequestBody BillActionUpdateRequest request - ) { - billActionService.updateBillAction(token, actionId, request.toAppResponse()); - - return ResponseEntity.ok() - .build(); - } - - @DeleteMapping("/api/events/{eventId}/bill-actions/{actionId}") - public ResponseEntity<Void> deleteBillAction( - @PathVariable("eventId") String token, - @PathVariable("actionId") Long actionId - ) { - billActionService.deleteBillAction(token, actionId); - - return ResponseEntity.ok() - .build(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java b/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java deleted file mode 100644 index 5602e6777..000000000 --- a/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java +++ /dev/null @@ -1,42 +0,0 @@ -package server.haengdong.presentation; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.BillActionDetailService; -import server.haengdong.application.response.BillActionDetailsAppResponse; -import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; -import server.haengdong.presentation.response.BillActionDetailsResponse; - -@RequiredArgsConstructor -@RestController -public class BillActionDetailController { - - private final BillActionDetailService billActionDetailService; - - @GetMapping("/api/events/{eventId}/bill-actions/{actionId}/fixed") - public ResponseEntity<BillActionDetailsResponse> findBillActionDetails( - @PathVariable("eventId") String token, - @PathVariable("actionId") Long actionId - ) { - BillActionDetailsAppResponse appResponse = billActionDetailService.findBillActionDetails(token, actionId); - - return ResponseEntity.ok(BillActionDetailsResponse.of(appResponse)); - } - - @PutMapping("/api/events/{eventId}/bill-actions/{actionId}/fixed") - public ResponseEntity<Void> updateBillActionDetails( - @PathVariable("eventId") String token, - @PathVariable("actionId") Long actionId, - @Valid @RequestBody BillActionDetailsUpdateRequest request - ) { - billActionDetailService.updateBillActionDetails(token, actionId, request.toAppRequest()); - - return ResponseEntity.ok().build(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java deleted file mode 100644 index 34261042f..000000000 --- a/server/src/main/java/server/haengdong/presentation/EventController.java +++ /dev/null @@ -1,120 +0,0 @@ -package server.haengdong.presentation; - -import jakarta.validation.Valid; -import java.util.List; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseCookie; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.AuthService; -import server.haengdong.application.EventService; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.infrastructure.auth.CookieProperties; -import server.haengdong.presentation.request.EventLoginRequest; -import server.haengdong.presentation.request.EventSaveRequest; -import server.haengdong.presentation.request.MemberNamesUpdateRequest; -import server.haengdong.presentation.response.ActionsResponse; -import server.haengdong.presentation.response.EventDetailResponse; -import server.haengdong.presentation.response.EventResponse; -import server.haengdong.presentation.response.MembersResponse; -import server.haengdong.presentation.response.StepsResponse; - -@Slf4j -@RequiredArgsConstructor -@EnableConfigurationProperties(CookieProperties.class) -@RestController -public class EventController { - - private final EventService eventService; - private final AuthService authService; - private final CookieProperties cookieProperties; - - @PostMapping("/api/events") - public ResponseEntity<EventResponse> saveEvent(@Valid @RequestBody EventSaveRequest request) { - EventResponse eventResponse = EventResponse.of(eventService.saveEvent(request.toAppRequest())); - - String jwtToken = authService.createToken(eventResponse.eventId()); - - ResponseCookie responseCookie = createResponseCookie(jwtToken); - return ResponseEntity.ok() - .header(HttpHeaders.SET_COOKIE, responseCookie.toString()) - .body(eventResponse); - } - - @GetMapping("/api/events/{eventId}") - public ResponseEntity<EventDetailResponse> findEvent(@PathVariable("eventId") String token) { - EventDetailResponse eventDetailResponse = EventDetailResponse.of(eventService.findEvent(token)); - - return ResponseEntity.ok(eventDetailResponse); - } - - @GetMapping("/api/events/{eventId}/actions") - public ResponseEntity<StepsResponse> findActions(@PathVariable("eventId") String token) { - StepsResponse stepsResponse = StepsResponse.of(eventService.findActions(token)); - - return ResponseEntity.ok(stepsResponse); - } - - @GetMapping("/api/events/{eventId}/actions/v2") - public ResponseEntity<ActionsResponse> findActions2(@PathVariable("eventId") String token) { - List<ActionAppResponse> actions = eventService.findActions(token); - ActionsResponse actionsResponse = ActionsResponse.of(actions); - - return ResponseEntity.ok(actionsResponse); - } - - @GetMapping("/api/events/{eventId}/members") - public ResponseEntity<MembersResponse> findAllMembers(@PathVariable("eventId") String token) { - MembersResponse response = MembersResponse.of(eventService.findAllMembers(token)); - - return ResponseEntity.ok(response); - } - - @PutMapping("/api/events/{eventId}/members/nameChange") - public ResponseEntity<Void> updateMember( - @PathVariable("eventId") String token, - @Valid @RequestBody MemberNamesUpdateRequest request - ) { - eventService.updateMember(token, request.toAppRequest()); - - return ResponseEntity.ok().build(); - } - - @PostMapping("/api/events/{eventId}/login") - public ResponseEntity<Void> loginEvent( - @PathVariable("eventId") String token, - @Valid @RequestBody EventLoginRequest request - ) { - eventService.validatePassword(request.toAppRequest(token)); - String jwtToken = authService.createToken(token); - - ResponseCookie responseCookie = createResponseCookie(jwtToken); - return ResponseEntity.ok() - .header(HttpHeaders.SET_COOKIE, responseCookie.toString()) - .build(); - } - - @PostMapping("/api/events/{eventId}/auth") - public ResponseEntity<Void> authenticate(@PathVariable("eventId") String token) { - return ResponseEntity.ok().build(); - } - - private ResponseCookie createResponseCookie(String token) { - return ResponseCookie.from(authService.getTokenName(), token) - .httpOnly(cookieProperties.httpOnly()) - .secure(cookieProperties.secure()) - .domain(cookieProperties.domain()) - .path(cookieProperties.path()) - .sameSite(cookieProperties.sameSite()) - .maxAge(cookieProperties.maxAge()) - .build(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/MemberActionController.java b/server/src/main/java/server/haengdong/presentation/MemberActionController.java deleted file mode 100644 index 1703245f7..000000000 --- a/server/src/main/java/server/haengdong/presentation/MemberActionController.java +++ /dev/null @@ -1,60 +0,0 @@ -package server.haengdong.presentation; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.MemberActionService; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.request.MemberActionsSaveRequest; -import server.haengdong.presentation.response.CurrentMembersResponse; - -@RequiredArgsConstructor -@RestController -public class MemberActionController { - - private final MemberActionService memberActionService; - - @PostMapping("/api/events/{eventId}/member-actions") - public ResponseEntity<Void> saveMemberAction( - @PathVariable("eventId") String token, - @RequestBody MemberActionsSaveRequest request - ) { - memberActionService.saveMemberAction(token, request.toAppRequest()); - - return ResponseEntity.ok().build(); - } - - @GetMapping("/api/events/{eventId}/members/current") - public ResponseEntity<CurrentMembersResponse> getCurrentMembers(@PathVariable("eventId") String token) { - List<CurrentMemberAppResponse> currentMembers = memberActionService.getCurrentMembers(token); - - return ResponseEntity.ok() - .body(CurrentMembersResponse.of(currentMembers)); - } - - @DeleteMapping("/api/events/{eventId}/members/{memberName}") - public ResponseEntity<Void> deleteMember( - @PathVariable("eventId") String token, - @PathVariable("memberName") String memberName - ) { - memberActionService.deleteMember(token, memberName); - - return ResponseEntity.ok().build(); - } - - @DeleteMapping("/api/events/{eventId}/member-actions/{actionId}") - public ResponseEntity<Void> deleteMemberAction( - @PathVariable("eventId") String token, - @PathVariable("actionId") Long actionId - ) { - memberActionService.deleteMemberAction(token, actionId); - - return ResponseEntity.ok().build(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java deleted file mode 100644 index 21c4bd60f..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java +++ /dev/null @@ -1,21 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import server.haengdong.application.request.BillActionDetailUpdateAppRequest; - -public record BillActionDetailUpdateRequest( - - @NotBlank(message = "맴버 이름은 공백일 수 없습니다.") - String name, - - @NotNull(message = "지출 금액은 공백일 수 없습니다.") - Long price, - - @NotNull(message = "지출 금액은 공백일 수 없습니다.") - boolean isFixed -) { - public BillActionDetailUpdateAppRequest toAppRequest() { - return new BillActionDetailUpdateAppRequest(this.name, this.price, this.isFixed); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java deleted file mode 100644 index fafbb8fd7..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java +++ /dev/null @@ -1,16 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import java.util.List; -import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; - -public record BillActionDetailsUpdateRequest( - @Valid @NotEmpty List<BillActionDetailUpdateRequest> members -) { - public BillActionDetailsUpdateAppRequest toAppRequest() { - return new BillActionDetailsUpdateAppRequest(members.stream() - .map(BillActionDetailUpdateRequest::toAppRequest) - .toList()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java deleted file mode 100644 index a47ff8316..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import server.haengdong.application.request.BillActionAppRequest; - -public record BillActionSaveRequest( - - @NotBlank(message = "지출 내역 제목은 공백일 수 없습니다.") - String title, - - @NotNull(message = "지출 금액은 공백일 수 없습니다.") - Long price -) { - - public BillActionAppRequest toAppRequest() { - return new BillActionAppRequest(title, price); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java deleted file mode 100644 index 680006816..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import server.haengdong.application.request.BillActionUpdateAppRequest; - -public record BillActionUpdateRequest( - - @NotBlank(message = "지출 내역 제목은 공백일 수 없습니다.") - String title, - - @NotNull(message = "지출 금액은 공백일 수 없습니다.") - Long price -) { - public BillActionUpdateAppRequest toAppResponse() { - return new BillActionUpdateAppRequest(title, price); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java deleted file mode 100644 index 6727d4cf1..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import java.util.List; -import server.haengdong.application.request.BillActionAppRequest; - -public record BillActionsSaveRequest( - - @Valid @NotEmpty List<BillActionSaveRequest> actions -) { - - public List<BillActionAppRequest> toAppRequests() { - return actions.stream() - .map(BillActionSaveRequest::toAppRequest) - .toList(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java deleted file mode 100644 index a1286e903..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import server.haengdong.application.request.EventLoginAppRequest; - -public record EventLoginRequest( - - @NotBlank(message = "비밀번호는 공백일 수 없습니다.") - String password -) { - public EventLoginAppRequest toAppRequest(String token) { - return new EventLoginAppRequest(token, password); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java deleted file mode 100644 index 6bd7cd006..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import server.haengdong.application.request.EventAppRequest; - -public record EventSaveRequest( - - @NotBlank(message = "행사 이름은 공백일 수 없습니다.") - String eventName, - - @NotBlank(message = "비밀번호는 공백일 수 없습니다.") - String password -) { - - public EventAppRequest toAppRequest() { - return new EventAppRequest(eventName, password); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java deleted file mode 100644 index 41e95cc3c..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java +++ /dev/null @@ -1,25 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import java.util.List; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; - -public record MemberActionsSaveRequest( - - @NotEmpty - List<String> members, - - @NotBlank(message = "멤버 액션은 공백일 수 없습니다.") - String status -) { - - public MemberActionsSaveAppRequest toAppRequest() { - List<MemberActionSaveAppRequest> appRequests = members.stream() - .map(name -> new MemberActionSaveAppRequest(name, status)) - .toList(); - - return new MemberActionsSaveAppRequest(appRequests); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java deleted file mode 100644 index 3cd2294ca..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import server.haengdong.application.request.MemberNameUpdateAppRequest; - -public record MemberNameUpdateRequest( - - @NotBlank(message = "멤버 이름은 공백일 수 없습니다.") - String before, - - @NotBlank(message = "멤버 이름은 공백일 수 없습니다.") - String after -) { - - public MemberNameUpdateAppRequest toAppRequest() { - return new MemberNameUpdateAppRequest(before, after); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java deleted file mode 100644 index 872aa55de..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import java.util.List; -import server.haengdong.application.request.MemberNamesUpdateAppRequest; - -public record MemberNamesUpdateRequest( - @Valid @NotEmpty List<MemberNameUpdateRequest> members -) { - - public MemberNamesUpdateAppRequest toAppRequest() { - return new MemberNamesUpdateAppRequest(members.stream() - .map(MemberNameUpdateRequest::toAppRequest) - .toList()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java deleted file mode 100644 index ea26ea769..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java +++ /dev/null @@ -1,26 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.ActionAppResponse; - -public record ActionResponse( - Long actionId, - String name, - Long price, - Long sequence, - boolean isFixed -) { - - public ActionResponse(Long actionId, String name, Long price, Long sequence) { - this(actionId, name, price, sequence, false); - } - - public static ActionResponse of(ActionAppResponse actionAppResponse) { - return new ActionResponse( - actionAppResponse.actionId(), - actionAppResponse.name(), - actionAppResponse.price(), - actionAppResponse.sequence(), - actionAppResponse.isFixed() - ); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java deleted file mode 100644 index ea46c5bd9..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java +++ /dev/null @@ -1,22 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.ActionAppResponse; - -public record ActionResponse2( - Long actionId, - String name, - Long price, - Long sequence, - String type -) { - - public static ActionResponse2 of(ActionAppResponse actionAppResponse) { - return new ActionResponse2( - actionAppResponse.actionId(), - actionAppResponse.name(), - actionAppResponse.price(), - actionAppResponse.sequence(), - actionAppResponse.actionType().name() - ); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java deleted file mode 100644 index c8ae780e3..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.ActionAppResponse; - -public record ActionsResponse( - List<ActionResponse2> actions -) { - public static ActionsResponse of(List<ActionAppResponse> actions) { - return new ActionsResponse(actions.stream() - .map(ActionResponse2::of) - .toList()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java deleted file mode 100644 index 10f71b82e..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.BillActionDetailAppResponse; - -public record BillActionDetailResponse( - String name, - Long price, - boolean isFixed -) { - - public static BillActionDetailResponse of(BillActionDetailAppResponse billActionDetailAppResponse) { - return new BillActionDetailResponse( - billActionDetailAppResponse.name(), - billActionDetailAppResponse.price(), - billActionDetailAppResponse.isFixed() - ); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java deleted file mode 100644 index 182e76db6..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import java.util.stream.Collectors; -import server.haengdong.application.response.BillActionDetailsAppResponse; - -public record BillActionDetailsResponse( - List<BillActionDetailResponse> members -) { - - public static BillActionDetailsResponse of(BillActionDetailsAppResponse billActionDetailsAppResponse) { - return billActionDetailsAppResponse.billActionDetailAppResponses().stream() - .map(BillActionDetailResponse::of) - .collect(Collectors.collectingAndThen(Collectors.toList(), BillActionDetailsResponse::new)); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java deleted file mode 100644 index 289cca4fa..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.CurrentMemberAppResponse; - -public record CurrentMembersResponse(List<String> memberNames) { - - public static CurrentMembersResponse of(List<CurrentMemberAppResponse> currentMembers) { - List<String> responses = currentMembers.stream() - .map(CurrentMemberAppResponse::name) - .toList(); - - return new CurrentMembersResponse(responses); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java deleted file mode 100644 index c18694393..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.EventDetailAppResponse; - -public record EventDetailResponse(String eventName) { - - public static EventDetailResponse of(EventDetailAppResponse response) { - return new EventDetailResponse(response.eventName()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java deleted file mode 100644 index 506f5e814..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.EventAppResponse; - -public record EventResponse(String eventId) { - - public static EventResponse of(EventAppResponse eventAppResponse) { - return new EventResponse(eventAppResponse.token()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java deleted file mode 100644 index 0ea409202..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.MemberBillReportAppResponse; - -public record MemberBillReportResponse(String name, Long price) { - - public static MemberBillReportResponse of(MemberBillReportAppResponse memberBillReportAppResponse) { - return new MemberBillReportResponse(memberBillReportAppResponse.name(), memberBillReportAppResponse.price()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java deleted file mode 100644 index d350c4009..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.MemberBillReportAppResponse; - -public record MemberBillReportsResponse(List<MemberBillReportResponse> reports) { - - public static MemberBillReportsResponse of(List<MemberBillReportAppResponse> memberBillReports) { - List<MemberBillReportResponse> reports = memberBillReports.stream() - .map(MemberBillReportResponse::of) - .toList(); - - return new MemberBillReportsResponse(reports); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java deleted file mode 100644 index 0947d9e02..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.MembersAppResponse; - -public record MembersResponse( - List<String> memberNames -) { - - public static MembersResponse of(MembersAppResponse response) { - return new MembersResponse(response.memberNames()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java deleted file mode 100644 index 55dd62c58..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.ArrayList; -import java.util.List; -import server.haengdong.application.response.ActionAppResponse; - -public record StepResponse( - String stepName, - String type, - List<String> members, - List<ActionResponse> actions -) { - public static StepResponse of(String stepName, List<String> members, List<ActionAppResponse> actions) { - return new StepResponse( - stepName, - actions.get(0).actionTypeName(), - new ArrayList<>(members), - toActionsResponse(actions) - ); - } - - private static List<ActionResponse> toActionsResponse(List<ActionAppResponse> actions) { - return actions.stream() - .map(ActionResponse::of) - .toList(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java deleted file mode 100644 index 5f7573d67..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java +++ /dev/null @@ -1,56 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.ArrayList; -import java.util.List; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.ActionAppResponse.ActionType; - -public record StepsResponse(List<StepResponse> steps) { - - public static StepsResponse of(List<ActionAppResponse> actions) { - List<StepResponse> steps = new ArrayList<>(); - List<String> currentMembers = new ArrayList<>(); - List<List<ActionAppResponse>> groups = createGroups(actions); - - int billStepCount = 0; - for (List<ActionAppResponse> group : groups) { - changeCurrentMembers(group, currentMembers); - if (group.get(0).actionType() == ActionType.BILL) { - billStepCount++; - } - StepResponse stepResponse = StepResponse.of(billStepCount + "차", currentMembers, group); - steps.add(stepResponse); - } - return new StepsResponse(steps); - } - - private static List<List<ActionAppResponse>> createGroups(List<ActionAppResponse> actions) { - List<List<ActionAppResponse>> groups = new ArrayList<>(); - - for (ActionAppResponse action : actions) { - if (groups.isEmpty() || isActionTypeChange(action, groups)) { - groups.add(new ArrayList<>()); - } - groups.get(groups.size() - 1).add(action); - } - - return groups; - } - - private static boolean isActionTypeChange(ActionAppResponse action, List<List<ActionAppResponse>> groups) { - List<ActionAppResponse> currentGroup = groups.get(groups.size() - 1); - return currentGroup.get(0).actionType() != action.actionType(); - } - - private static void changeCurrentMembers(List<ActionAppResponse> group, List<String> currentMembers) { - for (ActionAppResponse action : group) { - if (action.actionType() == ActionType.IN) { - currentMembers.add(action.name()); - continue; - } - if (action.actionType() == ActionType.OUT) { - currentMembers.remove(action.name()); - } - } - } -} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml deleted file mode 100644 index 2ae503547..000000000 --- a/server/src/main/resources/application.yml +++ /dev/null @@ -1,66 +0,0 @@ -spring: - datasource: - driver-class-name: org.h2.Driver - url: jdbc:h2:mem:database - username: sa - password: - - h2: - console: - enabled: true - path: /h2-console - - jpa: - hibernate: - ddl-auto: create - properties: - hibernate: - format_sql: true - jdbc.time_zone: Asia/Seoul - show-sql: true - -cors: - max-age: 3600 - allowed-origins: http://localhost:3000, https://haengdong.pro, https://dev.haengdong.pro, https://app.haengdong.pro - -security: - jwt: - token: - secret-key: skdmeejEKJdkDjklDlkj123DKLJ3kDkeDkDKQMEOD1D90D8dE - expire-length: 604800000 # 1주일 - -cookie: - http-only: false - secure: false - path: / - same-site: none - max-age: 7D - -management: - endpoints: - web: - exposure: - include: health, metrics, logfile - -server: - servlet: - encoding: - charset: UTF-8 - enabled: true - force: true - ---- - -spring: - config: - import: classpath:config/application-prod.yml - activate: - on-profile: prod - ---- - -spring: - config: - import: classpath:config/application-dev.yml - activate: - on-profile: dev diff --git a/server/src/main/resources/config b/server/src/main/resources/config deleted file mode 160000 index fa4270674..000000000 --- a/server/src/main/resources/config +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fa42706743e6eb3f4fd8c34618614eff8ae94b3d diff --git a/server/src/main/resources/logback-spring.xml b/server/src/main/resources/logback-spring.xml deleted file mode 100644 index 283b966a3..000000000 --- a/server/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,97 +0,0 @@ -<configuration> - <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> - <encoder> - <!-- 콘솔에 로그 출력 형식 --> - <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> - - <appender name="ERROR-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <filter class="ch.qos.logback.classic.filter.LevelFilter"> - <level>ERROR</level> - <onMatch>ACCEPT</onMatch> - <onMismatch>DENY</onMismatch> - </filter> - <file>logs/spring-boot-application-error.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <fileNamePattern>logs/spring-boot-application-error.%d{yyyy-MM-dd}.log</fileNamePattern> - <maxHistory>30</maxHistory> - </rollingPolicy> - <encoder> - <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> - <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> - - <appender name="WARN-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <filter class="ch.qos.logback.classic.filter.LevelFilter"> - <level>WARN</level> - <onMatch>ACCEPT</onMatch> - <onMismatch>DENY</onMismatch> - </filter> - <file>logs/spring-boot-application-warn.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <fileNamePattern>logs/spring-boot-application-warn.%d{yyyy-MM-dd}.log</fileNamePattern> - <maxHistory>30</maxHistory> - </rollingPolicy> - <encoder> - <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> - <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> - - <appender name="INFO-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <filter class="ch.qos.logback.classic.filter.LevelFilter"> - <level>INFO</level> - <onMatch>ACCEPT</onMatch> - <onMismatch>DENY</onMismatch> - </filter> - <file>logs/spring-boot-application-info.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <fileNamePattern>logs/spring-boot-application-info.%d{yyyy-MM-dd}.log</fileNamePattern> - <maxHistory>30</maxHistory> - </rollingPolicy> - <encoder> - <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> - <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> - - <appender name="DEBUG-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <filter class="ch.qos.logback.classic.filter.LevelFilter"> - <level>DEBUG</level> - <onMatch>ACCEPT</onMatch> - <onMismatch>DENY</onMismatch> - </filter> - <file>logs/spring-boot-application-debug.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <fileNamePattern>logs/spring-boot-application-debug.%d{yyyy-MM-dd}.log</fileNamePattern> - <maxHistory>30</maxHistory> - </rollingPolicy> - <encoder> - <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> - <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> - - <springProfile name="default"> - <root level="INFO"> - <appender-ref ref="CONSOLE"/> - </root> - </springProfile> - - <springProfile name="dev"> - <root level="INFO"> - <appender-ref ref="ERROR-ROLLING"/> - <appender-ref ref="WARN-ROLLING"/> - <appender-ref ref="INFO-ROLLING"/> - <appender-ref ref="DEBUG-ROLLING"/> - </root> - </springProfile> - - <springProfile name="prod"> - <root level="ERROR"> - <appender-ref ref="ERROR-ROLLING"/> - </root> - </springProfile> -</configuration> diff --git a/server/src/test/java/server/haengdong/application/ActionServiceTest.java b/server/src/test/java/server/haengdong/application/ActionServiceTest.java deleted file mode 100644 index ee979b278..000000000 --- a/server/src/test/java/server/haengdong/application/ActionServiceTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; -import static server.haengdong.support.fixture.Fixture.BILL_ACTION; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetail; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class ActionServiceTest extends ServiceTestSupport { - - @Autowired - private ActionService actionService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private MemberActionRepository memberActionRepository; - - @DisplayName("참여자별 정산 현황을 조회한다.") - @Test - void getMemberBillReports() { - Event event = Fixture.EVENT1; - Event savedEvent = eventRepository.save(event); - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(savedEvent, 1L), "소하", IN, 1L), - new MemberAction(new Action(savedEvent, 2L), "감자", IN, 1L), - new MemberAction(new Action(savedEvent, 3L), "쿠키", IN, 1L), - new MemberAction(new Action(savedEvent, 5L), "감자", OUT, 2L) - ); - List<BillAction> billActions = List.of( - new BillAction(new Action(savedEvent, 4L), "뽕족", 60_000L), - new BillAction(new Action(savedEvent, 7L), "인생네컷", 20_000L) - ); - billActions.get(0).addDetails( - List.of( - new BillActionDetail(BILL_ACTION, "소하", 10_000L, false), - new BillActionDetail(BILL_ACTION, "감자", 40_000L, true), - new BillActionDetail(BILL_ACTION, "쿠키", 10_000L, false) - ) - ); - billActions.get(1).addDetails( - List.of( - new BillActionDetail(BILL_ACTION, "소하", 5_000L, true), - new BillActionDetail(BILL_ACTION, "쿠키", 15_000L, true) - ) - ); - memberActionRepository.saveAll(memberActions); - billActionRepository.saveAll(billActions); - - List<MemberBillReportAppResponse> responses = actionService.getMemberBillReports(event.getToken()); - - assertThat(responses) - .hasSize(3) - .extracting(MemberBillReportAppResponse::name, MemberBillReportAppResponse::price) - .containsExactlyInAnyOrder( - tuple("감자", 40_000L), - tuple("쿠키", 25_000L), - tuple("소하", 15_000L) - ); - } - - @DisplayName("존재하지 않는 이벤트의 참여자별 정산 현황을 조회하는 경우 예외가 발생한다.") - @Test - void getMemberBillReports1() { - assertThatThrownBy(() -> actionService.getMemberBillReports("invalid token")) - .isInstanceOf(HaengdongException.class) - .hasMessage(HaengdongErrorCode.EVENT_NOT_FOUND.getMessage()); - } -} diff --git a/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java deleted file mode 100644 index 7074ce846..000000000 --- a/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.tuple; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import server.haengdong.application.request.BillActionDetailUpdateAppRequest; -import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; -import server.haengdong.application.response.BillActionDetailAppResponse; -import server.haengdong.application.response.BillActionDetailsAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetail; -import server.haengdong.domain.action.BillActionDetailRepository; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class BillActionDetailServiceTest extends ServiceTestSupport { - - @Autowired - private BillActionDetailService billActionDetailService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private BillActionDetailRepository billActionDetailRepository; - - @DisplayName("참여자별 지출 금액을 조회한다.") - @Test - void findBillActionDetailsTest() { - Event event1 = Fixture.EVENT1; - eventRepository.save(event1); - Action action = new Action(event1, 1L); - BillAction billAction = new BillAction(action, "뽕족", 10000L); - billActionRepository.save(billAction); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "토다리", 6000L, true); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "쿠키", 4000L, true); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); - - BillActionDetailsAppResponse response = billActionDetailService.findBillActionDetails( - event1.getToken(), action.getId()); - - assertThat(response.billActionDetailAppResponses()).hasSize(2) - .extracting(BillActionDetailAppResponse::name, BillActionDetailAppResponse::price) - .containsExactly( - tuple("토다리", 6000L), - tuple("쿠키", 4000L) - ); - } - - @DisplayName("지출 금액 수정 요청의 총합이 지출 금액과 일치하지 않으면 예외가 발생한다.") - @Test - void updateBillActionDetailsTest1() { - Event event1 = Fixture.EVENT1; - eventRepository.save(event1); - Action action = new Action(event1, 1L); - BillAction billAction = new BillAction(action, "뽕족", 10000L); - billActionRepository.save(billAction); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "토다리", 5000L, false); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "쿠키", 5000L, false); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); - - BillActionDetailsUpdateAppRequest request = new BillActionDetailsUpdateAppRequest(List.of( - new BillActionDetailUpdateAppRequest("토다리", 3000L, true), - new BillActionDetailUpdateAppRequest("쿠키", 4000L, true) - )); - assertThatCode( - () -> billActionDetailService.updateBillActionDetails(event1.getToken(), action.getId(), request)) - .isInstanceOf(HaengdongException.class) - .hasMessage("지출 총액이 일치하지 않습니다."); - } - - @DisplayName("지출 고정 금액을 수정한다.") - @Test - void updateBillActionDetailsTest2() { - Event event1 = Fixture.EVENT1; - eventRepository.save(event1); - Action action = new Action(event1, 1L); - BillAction billAction = new BillAction(action, "뽕족", 10000L); - billActionRepository.save(billAction); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "토다리", 5000L, false); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "쿠키", 5000L, false); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); - - BillActionDetailsUpdateAppRequest request = new BillActionDetailsUpdateAppRequest(List.of( - new BillActionDetailUpdateAppRequest("토다리", 3000L, true), - new BillActionDetailUpdateAppRequest("쿠키", 7000L, true) - )); - billActionDetailService.updateBillActionDetails(event1.getToken(), action.getId(), request); - - List<BillActionDetail> results = billActionDetailRepository.findAll(); - - assertThat(results).hasSize(2) - .extracting(BillActionDetail::getMemberName, BillActionDetail::getPrice) - .containsExactly( - tuple("토다리", 3000L), - tuple("쿠키", 7000L) - ); - } -} diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java deleted file mode 100644 index 39e52f80c..000000000 --- a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java +++ /dev/null @@ -1,229 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; -import static org.junit.jupiter.api.Assertions.assertAll; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import server.haengdong.application.request.BillActionAppRequest; -import server.haengdong.application.request.BillActionUpdateAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetail; -import server.haengdong.domain.action.BillActionDetailRepository; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class BillActionServiceTest extends ServiceTestSupport { - - @Autowired - private BillActionService billActionService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private BillActionDetailRepository billActionDetailRepository; - - @Autowired - private MemberActionRepository memberActionRepository; - - @DisplayName("지출 내역을 생성한다.") - @Test - void saveAllBillAction() { - Event event = Fixture.EVENT1; - Event savedEvent = eventRepository.save(event); - Action action1 = new Action(event, 1L); - Action action2 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "백호", MemberActionStatus.IN, 1L); - MemberAction memberAction2 = new MemberAction(action2, "망쵸", MemberActionStatus.IN, 2L); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); - - List<BillActionAppRequest> requests = List.of( - new BillActionAppRequest("뽕족", 10_000L), - new BillActionAppRequest("인생맥주", 15_000L) - ); - - billActionService.saveAllBillAction(event.getToken(), requests); - - List<BillAction> actions = billActionRepository.findByAction_Event(savedEvent); - - assertThat(actions).extracting(BillAction::getTitle, BillAction::getPrice, BillAction::getSequence) - .containsExactlyInAnyOrder( - tuple("뽕족", 10_000L, 3L), - tuple("인생맥주", 15_000L, 4L) - ); - } - - @DisplayName("지출 내역을 생성하면 지출 상세 내역이 생성된다.") - @Test - void saveAllBillActionTest1() { - Event event = Fixture.EVENT1; - Event savedEvent = eventRepository.save(event); - Action action1 = new Action(event, 1L); - Action action2 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "백호", MemberActionStatus.IN, 1L); - MemberAction memberAction2 = new MemberAction(action2, "망쵸", MemberActionStatus.IN, 2L); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); - - List<BillActionAppRequest> request = List.of( - new BillActionAppRequest("뽕족", 10_000L), - new BillActionAppRequest("인생맥주", 15_000L) - ); - - billActionService.saveAllBillAction(event.getToken(), request); - - List<BillActionDetail> billActionDetails = billActionDetailRepository.findAll(); - - assertThat(billActionDetails) - .hasSize(4) - .extracting("memberName", "price") - .containsExactlyInAnyOrder( - tuple("백호", 5_000L), - tuple("망쵸", 5_000L), - tuple("백호", 7_500L), - tuple("망쵸", 7_500L) - ); - } - - @DisplayName("이벤트가 존재하지 않으면 지출 내역을 생성할 수 없다.") - @Test - void saveAllBillAction1() { - List<BillActionAppRequest> requests = List.of( - new BillActionAppRequest("뽕족", 10_000L), - new BillActionAppRequest("인생맥주", 15_000L) - ); - - assertThatThrownBy(() -> billActionService.saveAllBillAction("token", requests)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("지출 액션을 수정한다.") - @Test - void updateBillAction() { - Event event = Fixture.EVENT1; - Event savedEvent = eventRepository.save(event); - Action action = Action.createFirst(savedEvent); - BillAction billAction = new BillAction(action, "뽕족", 10_000L); - BillAction savedBillAction = billActionRepository.save(billAction); - - Long actionId = savedBillAction.getAction().getId(); - BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("인생맥주", 20_000L); - - billActionService.updateBillAction(event.getToken(), actionId, request); - - BillAction updatedBillAction = billActionRepository.findById(savedBillAction.getId()).get(); - - assertAll( - () -> assertThat(updatedBillAction.getTitle()).isEqualTo("인생맥주"), - () -> assertThat(updatedBillAction.getPrice()).isEqualTo(20_000L) - ); - } - - @DisplayName("행사에 속하지 않은 지출 액션은 수정할 수 없다.") - @Test - void updateBillAction1() { - Event event1 = Fixture.EVENT1; - Event event2 = Fixture.EVENT2; - Event savedEvent1 = eventRepository.save(event1); - Event savedEvent2 = eventRepository.save(event2); - Action action1 = Action.createFirst(savedEvent1); - Action action2 = Action.createFirst(savedEvent2); - BillAction billAction1 = new BillAction(action1, "뽕족", 10_000L); - BillAction billAction2 = new BillAction(action2, "뽕족", 10_000L); - BillAction savedBillAction1 = billActionRepository.save(billAction1); - billActionRepository.save(billAction2); - - Long actionId = savedBillAction1.getAction().getId(); - BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("인생맥주", 20_000L); - - assertThatThrownBy(() -> billActionService.updateBillAction(event2.getToken(), actionId, request)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("지출 내역 금액을 변경하면 지출 디테일이 초기화 된다.") - @Test - void updateBillAction2() { - Event event = Fixture.EVENT1; - Event savedEvent = eventRepository.save(event); - Action action = Action.createFirst(savedEvent); - BillAction billAction = new BillAction(action, "뽕족", 10_000L); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "감자", 3000L, true); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "고구마", 2000L, true); - BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "당근", 3000L, true); - BillActionDetail billActionDetail4 = new BillActionDetail(billAction, "양파", 2000L, true); - billAction.addDetails(List.of(billActionDetail1, billActionDetail2, billActionDetail3, billActionDetail4)); - BillAction savedBillAction = billActionRepository.save(billAction); - - Long actionId = savedBillAction.getAction().getId(); - BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("인생맥주", 20_000L); - - billActionService.updateBillAction(event.getToken(), actionId, request); - - BillAction updatedBillAction = billActionRepository.findById(savedBillAction.getId()).get(); - List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(updatedBillAction); - - assertThat(billActionDetails).hasSize(4) - .extracting("memberName", "price") - .containsExactlyInAnyOrder( - tuple("감자", 5000L), - tuple("고구마", 5000L), - tuple("당근", 5000L), - tuple("양파", 5000L) - ); - } - - @DisplayName("지출 내역을 삭제한다.") - @Test - void deleteBillAction() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - BillAction billAction = new BillAction(new Action(event, 1L), "커피", 50_900L); - billActionRepository.save(billAction); - Long actionId = billAction.getAction().getId(); - - billActionService.deleteBillAction(event.getToken(), actionId); - - assertThat(billActionRepository.findById(billAction.getId())).isEmpty(); - } - - @DisplayName("지출 내역을 삭제하면 지출 상세도 삭제된다.") - @Test - void deleteBillActionTest1() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "백호", MemberActionStatus.IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "망쵸", MemberActionStatus.IN, 2L); - BillAction billAction = new BillAction(new Action(event, 3L), "커피", 50_900L); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "백호", 25_450L, false); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "망쵸", 25_450L, false); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); - billActionRepository.save(billAction); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); - Long actionId = billAction.getAction().getId(); - - billActionService.deleteBillAction(event.getToken(), actionId); - - assertThat(billActionDetailRepository.findAll()).isEmpty(); - } - - @DisplayName("지출 내역 삭제 시 행사가 존재하지 않으면 예외가 발생한다.") - @Test - void deleteBillAction1() { - assertThatThrownBy(() -> billActionService.deleteBillAction("소하망쵸", 1L)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java deleted file mode 100644 index 407fa1457..000000000 --- a/server/src/test/java/server/haengdong/application/EventServiceTest.java +++ /dev/null @@ -1,231 +0,0 @@ -package server.haengdong.application; - - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.BDDMockito.given; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.request.MemberNameUpdateAppRequest; -import server.haengdong.application.request.MemberNamesUpdateAppRequest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.application.response.MembersAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.event.EventTokenProvider; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class EventServiceTest extends ServiceTestSupport { - - @Autowired - private EventService eventService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private MemberActionRepository memberActionRepository; - - @MockBean - private EventTokenProvider eventTokenProvider; - - @DisplayName("행사를 생성한다") - @Test - void saveEventTest() { - EventAppRequest request = new EventAppRequest("test", "1234"); - given(eventTokenProvider.createToken()).willReturn("TOKEN"); - - EventAppResponse response = eventService.saveEvent(request); - - assertThat(response.token()).isEqualTo("TOKEN"); - } - - @DisplayName("토큰으로 행사를 조회한다.") - @Test - void findEventTest() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - - EventDetailAppResponse eventDetailAppResponse = eventService.findEvent(event.getToken()); - - assertThat(eventDetailAppResponse.eventName()).isEqualTo(event.getName()); - } - - @DisplayName("행사에 속한 모든 액션을 조회한다.") - @Test - void findActionsTest() { - Event event = Fixture.EVENT1; - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", IN, 1L); - Action action1 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "쿠키", IN, 1L); - Action action2 = new Action(event, 3L); - BillAction billAction = new BillAction(action2, "뽕나무쟁이족발", 30000L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction, memberAction1)); - billActionRepository.save(billAction); - - List<ActionAppResponse> actionAppResponses = eventService.findActions(event.getToken()); - - assertThat(actionAppResponses).hasSize(3) - .extracting(ActionAppResponse::actionId, - ActionAppResponse::name, - ActionAppResponse::price, - ActionAppResponse::sequence, - ActionAppResponse::actionTypeName) - .containsExactly( - tuple(1L, "토다리", null, 1L, "IN"), - tuple(2L, "쿠키", null, 2L, "IN"), - tuple(3L, "뽕나무쟁이족발", 30000L, 3L, "BILL") - ); - } - - @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") - @Test - void findAllMembersTest() { - Event event = Fixture.EVENT1; - Action action1 = new Action(event, 1L); - Action action2 = new Action(event, 2L); - Action action3 = new Action(event, 3L); - Action action4 = new Action(event, 4L); - BillAction billAction = new BillAction(action3, "뽕나무쟁이족발", 30000L); - MemberAction memberAction1 = new MemberAction(action1, "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(action2, "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(action4, "쿠키", OUT, 1L); - eventRepository.save(event); - billActionRepository.save(billAction); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); - - MembersAppResponse membersAppResponse = eventService.findAllMembers(event.getToken()); - - assertThat(membersAppResponse.memberNames()).containsExactlyInAnyOrder("토다리", "쿠키"); - } - - @DisplayName("행사 참여 인원들의 이름을 변경한다.") - @Test - void updateMember() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); - MemberAction memberAction4 = new MemberAction(new Action(event, 4L), "쿠키", OUT, 3L); - MemberAction memberAction5 = new MemberAction(new Action(event, 5L), "쿠키", IN, 4L); - MemberAction memberAction6 = new MemberAction(new Action(event, 6L), "쿠키", OUT, 5L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of( - memberAction1, memberAction2, memberAction3, memberAction4, memberAction5, memberAction6 - )); - - eventService.updateMember(event.getToken(), new MemberNamesUpdateAppRequest(List.of( - new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), - new MemberNameUpdateAppRequest("토다리", "토쟁이") - ))); - - List<MemberAction> foundMemberActions = memberActionRepository.findAllByEvent(event); - assertThat(foundMemberActions) - .extracting(MemberAction::getId, MemberAction::getMemberName) - .contains( - tuple(memberAction1.getId(), "토쟁이"), - tuple(memberAction2.getId(), "쿡쿡"), - tuple(memberAction3.getId(), "웨디"), - tuple(memberAction4.getId(), "쿡쿡"), - tuple(memberAction5.getId(), "쿡쿡"), - tuple(memberAction6.getId(), "쿡쿡") - ); - } - - @DisplayName("이미 존재하는 인원의 이름으로 변경할 수 없다.") - @Test - void updateMember1() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); - - MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( - new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), - new MemberNameUpdateAppRequest("웨디", "토다리") - )); - - assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("존재하지 않는 인원은 변경할 수 없다.") - @Test - void updateMember2() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); - - MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( - new MemberNameUpdateAppRequest("쿡쿡", "토쟁이"), - new MemberNameUpdateAppRequest("웨디", "말복") - )); - - assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("변경 전 참여 인원 이름이 중복될 수 없다.") - @Test - void updateMember3() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); - - MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( - new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), - new MemberNameUpdateAppRequest("쿠키", "토쟁이") - )); - - assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("변경 후 참여 인원 이름이 중복될 수 없다.") - @Test - void updateMember4() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); - - MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( - new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), - new MemberNameUpdateAppRequest("토다리", "쿡쿡") - )); - - assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java deleted file mode 100644 index c04f06026..000000000 --- a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java +++ /dev/null @@ -1,223 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class MemberActionFactoryTest extends ServiceTestSupport { - - @Autowired - private MemberActionFactory memberActionFactory; - - @Autowired - private MemberActionRepository memberActionRepository; - - @Autowired - private EventRepository eventRepository; - - @DisplayName("이전 멤버 액션이 시퀀스 기준으로 정렬되지 않은 상태에서 새로운 멤버 액션 요청을 검증한다.") - @Test - void createMemberActionsTest() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action1 = new Action(event, 1L); - Action action2 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); - MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - - List<MemberAction> unorderedMemberActions = List.of(memberAction2, memberAction1); - CurrentMembers currentMembers = CurrentMembers.of(unorderedMemberActions); - Action startAction = new Action(event, 3L); - - assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("인원 변동 액션을 생성한다.") - @Test - void createMemberActionsTest1() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest memberActionsSaveAppRequest = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - Action startAction = new Action(event, 2L); - - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - List<MemberAction> memberActions = memberActionFactory.createMemberActions(memberActionsSaveAppRequest, - currentMembers, startAction - ); - - assertThat(memberActions).hasSize(1) - .extracting(MemberAction::getAction, MemberAction::getMemberName, MemberAction::getStatus) - .containsExactly( - tuple(startAction, "토다리", MemberActionStatus.OUT) - ); - } - - @DisplayName("현재 행사에 참여 중인 경우에 퇴장할 수 있다.") - @Test - void createMemberActionsTest2() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") - @Test - void createMemberActionsTest3() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action1 = new Action(event, 1L); - MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction1); - Action action2 = new Action(event, 2L); - MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); - memberActionRepository.save(memberAction2); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "IN"))); - Action startAction = new Action(event, 3L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction1, memberAction2)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장한 적 없는 경우에 입장할 수 있다.") - @Test - void createMemberActionsTest4() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") - @Test - void createMemberActionTest5() { - Event event = eventRepository.save(Fixture.EVENT1); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "OUT"))); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of()); - - assertThatCode( - () -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("행사에 이미 참여 중인 경우 다시 입장할 수 없다.") - @Test - void createMemberActionTest6() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 동시에 여러 번 입장할 수 없다.") - @Test - void createMemberActionTest7() { - Event event = eventRepository.save(Fixture.EVENT1); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of( - new MemberActionSaveAppRequest("쿠키", "IN"), - new MemberActionSaveAppRequest("쿠키", "IN") - )); - Action startAction = new Action(event, 1L); - CurrentMembers currentMembers = CurrentMembers.of(List.of()); - - assertThatCode( - () -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 동시에 여러 번 퇴장할 수 없다.") - @Test - void createMemberActionTest8() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of( - new MemberActionSaveAppRequest("쿠키", "OUT"), - new MemberActionSaveAppRequest("쿠키", "OUT") - )); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 입장과 퇴장을 동시에 할 수 없다.") - @Test - void createMemberActionTest9() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of( - new MemberActionSaveAppRequest("쿠키", "IN"), - new MemberActionSaveAppRequest("쿠키", "OUT") - )); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java deleted file mode 100644 index b6d29444c..000000000 --- a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java +++ /dev/null @@ -1,251 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.groups.Tuple.tuple; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetail; -import server.haengdong.domain.action.BillActionDetailRepository; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class MemberActionServiceTest extends ServiceTestSupport { - - @Autowired - private MemberActionService memberActionService; - - @Autowired - private MemberActionRepository memberActionRepository; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private BillActionDetailRepository billActionDetailRepository; - - @DisplayName("현재 행사에 참여하고 있는 경우에 나갈 수 있다.") - @Test - void saveMemberActionTest() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "망쵸", IN, 1L); - memberActionRepository.save(memberAction); - - assertThatCode(() -> memberActionService.saveMemberAction(event.getToken(), new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("망쵸", "OUT"))))) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") - @Test - void saveMemberActionTest1() { - Event event = eventRepository.save(Fixture.EVENT1); - Action actionOne = new Action(event, 1L); - MemberAction memberActionOne = new MemberAction(actionOne, "망쵸", IN, 1L); - memberActionRepository.save(memberActionOne); - - Action actionTwo = new Action(event, 2L); - MemberAction memberActionTwo = new MemberAction(actionTwo, "망쵸", OUT, 1L); - memberActionRepository.save(memberActionTwo); - - assertThatCode(() -> memberActionService.saveMemberAction(event.getToken(), new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("망쵸", "IN"))))) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") - @Test - void saveMemberActionTest2() { - MemberActionsSaveAppRequest appRequest = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("TOKEN", "OUT"))); - - assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", appRequest)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("이벤트가 없으면 현재 참여 인원을 조회할 수 없다.") - @Test - void getCurrentMembers() { - assertThatThrownBy(() -> memberActionService.getCurrentMembers("token")) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("행사의 전체 참여자 중에서 특정 참여자의 맴버 액션을 전부 삭제한다.") - @Test - void deleteMember() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "참여자", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "토다리", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "쿠키", IN, 1L); - MemberAction memberAction4 = new MemberAction(new Action(event, 4L), "소하", IN, 1L); - MemberAction memberAction5 = new MemberAction(new Action(event, 5L), "웨디", IN, 1L); - MemberAction memberAction6 = new MemberAction(new Action(event, 6L), "참여자", OUT, 1L); - memberActionRepository.saveAll( - List.of(memberAction1, memberAction2, memberAction3, memberAction4, memberAction5, memberAction6)); - - Event event2 = Fixture.EVENT2; - eventRepository.save(event2); - Action action2 = Action.createFirst(event2); - MemberAction anotherMemberAction = new MemberAction(action2, "참여자", IN, 1L); - memberActionRepository.save(anotherMemberAction); - - memberActionService.deleteMember(event.getToken(), "참여자"); - - List<MemberAction> memberActions = memberActionRepository.findAll(); - - assertThat(memberActions).hasSize(5) - .extracting("memberName", "status") - .containsExactly( - tuple("토다리", IN), - tuple("쿠키", IN), - tuple("소하", IN), - tuple("웨디", IN), - tuple("참여자", IN) - ); - } - - @DisplayName("이벤트에 속한 멤버을 삭제하면 전체 지출 내역 디테일이 초기화된다.") - @Test - void deleteMember1() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "토다리", IN, 1L); - Action targetAction = new Action(event, 2L); - MemberAction memberAction2 = createMemberAction(targetAction, "토다리", OUT, 2L); - MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "쿠키", IN, 3L); - MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "웨디", IN, 4L); - MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "감자", IN, 5L); - memberActionRepository.saveAll( - List.of(memberAction1, - memberAction2, - memberAction3, - memberAction4, - memberAction5 - ) - ); - BillAction billAction = new BillAction(new Action(event, 6L), "뽕족", 100_000L); - billActionRepository.save(billAction); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "쿠키", 40_000L, true); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "웨디", 30_000L, false); - BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "감자", 30_000L, false); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2, billActionDetail3)); - List<BillActionDetail> allByBillAction = billActionDetailRepository.findAllByBillAction(billAction); - System.out.println("allByBillAction = " + allByBillAction.isEmpty()); - - memberActionService.deleteMember(event.getToken(), "쿠키"); - - List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(billAction); - - assertThat(billActionDetails).hasSize(2) - .extracting("memberName", "price") - .containsExactlyInAnyOrder( - tuple("웨디", 50_000L), - tuple("감자", 50_000L) - ); - } - - @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.") - @Test - void deleteMemberAction() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "토다리", IN, 1L); - Action targetAction = new Action(event, 2L); - MemberAction memberAction2 = createMemberAction(targetAction, "토다리", OUT, 2L); - MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "쿠키", IN, 3L); - MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "웨디", IN, 4L); - MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "토다리", IN, 5L); - MemberAction memberAction6 = createMemberAction(new Action(event, 6L), "토다리", OUT, 6L); - MemberAction memberAction7 = createMemberAction(new Action(event, 7L), "쿠키", OUT, 7L); - memberActionRepository.saveAll( - List.of(memberAction1, - memberAction2, - memberAction3, - memberAction4, - memberAction5, - memberAction6, - memberAction7) - ); - - memberActionService.deleteMemberAction(event.getToken(), targetAction.getId()); - List<MemberAction> memberActions = memberActionRepository.findAll(); - - assertThat(memberActions).hasSize(4) - .extracting("id", "memberName", "status") - .containsExactly( - tuple(memberAction1.getId(), "토다리", IN), - tuple(memberAction3.getId(), "쿠키", IN), - tuple(memberAction4.getId(), "웨디", IN), - tuple(memberAction7.getId(), "쿠키", OUT) - ); - } - - @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후 지출 내역 디테일이 초기화된다.") - @Test - void deleteMemberAction1() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "토다리", IN, 1L); - Action targetAction = new Action(event, 2L); - MemberAction memberAction2 = createMemberAction(targetAction, "토다리", OUT, 2L); - MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "쿠키", IN, 3L); - MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "웨디", IN, 4L); - MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "감자", IN, 5L); - memberActionRepository.saveAll( - List.of(memberAction1, - memberAction2, - memberAction3, - memberAction4, - memberAction5 - ) - ); - BillAction billAction = new BillAction(new Action(event, 6L), "뽕족", 100_000L); - billActionRepository.save(billAction); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "쿠키", 40_000L, true); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "웨디", 30_000L, false); - BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "감자", 30_000L, false); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2, billActionDetail3)); - - memberActionService.deleteMemberAction(event.getToken(), targetAction.getId()); - List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(billAction); - - assertThat(billActionDetails).hasSize(4) - .extracting("memberName", "price") - .containsExactlyInAnyOrder( - tuple("토다리", 25_000L), - tuple("쿠키", 25_000L), - tuple("웨디", 25_000L), - tuple("감자", 25_000L) - ); - } - - private MemberAction createMemberAction( - Action action, - String memberName, - MemberActionStatus memberActionStatus, - long memberGroupId - ) { - return new MemberAction(action, memberName, memberActionStatus, memberGroupId); - } -} diff --git a/server/src/test/java/server/haengdong/application/ServiceTestSupport.java b/server/src/test/java/server/haengdong/application/ServiceTestSupport.java deleted file mode 100644 index b0e2db0a6..000000000 --- a/server/src/test/java/server/haengdong/application/ServiceTestSupport.java +++ /dev/null @@ -1,11 +0,0 @@ -package server.haengdong.application; - -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import server.haengdong.support.extension.DatabaseCleanerExtension; - -@ExtendWith(DatabaseCleanerExtension.class) -@SpringBootTest(webEnvironment= WebEnvironment.NONE) -abstract class ServiceTestSupport { -} diff --git a/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java deleted file mode 100644 index 39c2d0bb8..000000000 --- a/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package server.haengdong.docs; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import server.haengdong.application.ActionService; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.presentation.ActionController; - -class ActionControllerDocsTest extends RestDocsSupport { - - private final ActionService actionService = mock(ActionService.class); - - @Override - protected Object initController() { - return new ActionController(actionService); - } - - @DisplayName("참여자별 정산 현황을 조회한다.") - @Test - void getMemberBillReports() throws Exception { - List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( - new MemberBillReportAppResponse("소하", 20_000L), new MemberBillReportAppResponse("토다리", 200_000L)); - - given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/actions/reports", "망쵸토큰") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("소하"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("토다리"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))) - .andDo( - document("getMemberBillReports", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("reports").type(JsonFieldType.ARRAY).description("전체 정산 현황 목록"), - fieldWithPath("reports[0].name").type(JsonFieldType.STRING) - .description("참여자 이름"), - fieldWithPath("reports[0].price").type(JsonFieldType.NUMBER) - .description("참여자 정산 금액") - )) - ); - } -} diff --git a/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java deleted file mode 100644 index 7ed6fe6c4..000000000 --- a/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java +++ /dev/null @@ -1,128 +0,0 @@ -package server.haengdong.docs; - -import static org.mockito.Mockito.mock; -import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; -import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import server.haengdong.application.BillActionService; -import server.haengdong.presentation.BillActionController; -import server.haengdong.presentation.request.BillActionSaveRequest; -import server.haengdong.presentation.request.BillActionUpdateRequest; -import server.haengdong.presentation.request.BillActionsSaveRequest; - -class BillActionControllerDocsTest extends RestDocsSupport { - - private final BillActionService billActionService = mock(BillActionService.class); - - @Override - protected Object initController() { - return new BillActionController(billActionService); - } - - @DisplayName("지출 내역을 생성한다.") - @Test - void saveAllBillAction() throws Exception { - BillActionsSaveRequest request = new BillActionsSaveRequest( - List.of( - new BillActionSaveRequest("뽕족", 10_000L), - new BillActionSaveRequest("인생맥주", 10_000L) - ) - ); - String requestBody = objectMapper.writeValueAsString(request); - String eventId = "쿠키토큰"; - - mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) - .contentType(MediaType.APPLICATION_JSON) - .cookie(EVENT_COOKIE) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo(document("createBillActions", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ), - requestFields( - fieldWithPath("actions").description("생성할 지출 액션 목록"), - fieldWithPath("actions[0].title").description("생성할 지출 액션의 제목"), - fieldWithPath("actions[0].price").description("생성할 지출 액션의 금액") - ) - )); - } - - @DisplayName("지출 액션을 수정한다.") - @Test - void updateBillAction() throws Exception { - BillActionUpdateRequest request = new BillActionUpdateRequest("뽕족", 10_000L); - - String requestBody = objectMapper.writeValueAsString(request); - String eventId = "웨디토큰"; - - mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1L) - .cookie(EVENT_COOKIE) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo(document("updateBillAction", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("actionId").description("지출 액션 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ), - requestFields( - fieldWithPath("title").description("수정할 지출 액션의 제목"), - fieldWithPath("price").description("수정할 지출 액션의 금액") - ) - )); - } - - @DisplayName("지출 내역을 삭제한다.") - @Test - void deleteBillAction() throws Exception { - String eventId = "토다리토큰"; - - mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1) - .cookie(EVENT_COOKIE) - ) - .andDo(print()) - .andExpect(status().isOk()) - .andDo(document("deleteBillAction", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("actionId").description("지출 액션 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ) - )); - } -} diff --git a/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java deleted file mode 100644 index f492195f3..000000000 --- a/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java +++ /dev/null @@ -1,127 +0,0 @@ -package server.haengdong.docs; - -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; -import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; -import server.haengdong.application.BillActionDetailService; -import server.haengdong.application.response.BillActionDetailAppResponse; -import server.haengdong.application.response.BillActionDetailsAppResponse; -import server.haengdong.presentation.BillActionDetailController; -import server.haengdong.presentation.request.BillActionDetailUpdateRequest; -import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; - -public class BillActionDetailControllerDocsTest extends RestDocsSupport { - - private final BillActionDetailService billActionDetailService = mock(BillActionDetailService.class); - - @Override - protected Object initController() { - return new BillActionDetailController(billActionDetailService); - } - - @DisplayName("참여자별 지출 금액을 조회한다.") - @Test - void findBillActionDetailsTest() throws Exception { - BillActionDetailsAppResponse appResponse = new BillActionDetailsAppResponse( - List.of(new BillActionDetailAppResponse("토다리", 1000L, false))); - given(billActionDetailService.findBillActionDetails(anyString(), anyLong())) - .willReturn(appResponse); - - mockMvc.perform(get("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) - .cookie(EVENT_COOKIE)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.members").isArray()) - .andExpect(jsonPath("$.members[0].name").value("토다리")) - .andExpect(jsonPath("$.members[0].price").value(1000L)) - .andExpect(jsonPath("$.members[0].isFixed").value(false)) - .andDo( - document("findBillActionDetailsTest", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("actionId").description("액션 ID") - ), requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ), responseFields( - fieldWithPath("members").type(JsonFieldType.ARRAY) - .description("전체 정산 수정 요청 목록"), - fieldWithPath("members[0].name").type(JsonFieldType.STRING) - .description("참여자 이름"), - fieldWithPath("members[0].price").type(JsonFieldType.NUMBER) - .description("참여자 정산 금액"), - fieldWithPath("members[0].isFixed").type(JsonFieldType.BOOLEAN) - .description("참여자 정산 금액 수정 여부") - ) - ) - ); - } - - @DisplayName("참여자별 지출 금액을 수정한다.") - @Test - void updateBillActionDetailsTest() throws Exception { - List<BillActionDetailUpdateRequest> billActionDetailUpdateRequests = List.of( - new BillActionDetailUpdateRequest("소하", 10000L, true), - new BillActionDetailUpdateRequest("웨디", 20000L, true) - ); - BillActionDetailsUpdateRequest request = new BillActionDetailsUpdateRequest( - billActionDetailUpdateRequests); - - String json = objectMapper.writeValueAsString(request); - - mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) - .cookie(EVENT_COOKIE) - .contentType(MediaType.APPLICATION_JSON) - .content(json)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo( - document("updateBillActionDetailsTest", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("actionId").description("액션 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ), - requestFields( - fieldWithPath("members").type(JsonFieldType.ARRAY) - .description("전체 정산 수정 요청 목록"), - fieldWithPath("members[0].name").type(JsonFieldType.STRING) - .description("참여자 이름"), - fieldWithPath("members[0].price").type(JsonFieldType.NUMBER) - .description("참여자 정산 금액"), - fieldWithPath("members[0].isFixed").type(JsonFieldType.BOOLEAN) - .description("참여자 정산 금액 수정 여부") - ) - ) - ); - } -} diff --git a/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java deleted file mode 100644 index 88de2a3a6..000000000 --- a/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java +++ /dev/null @@ -1,381 +0,0 @@ -package server.haengdong.docs; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; -import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; -import static org.springframework.restdocs.cookies.CookieDocumentation.responseCookies; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; - -import java.time.Duration; -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; -import server.haengdong.application.AuthService; -import server.haengdong.application.EventService; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.ActionAppResponse.ActionType; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.application.response.MembersAppResponse; -import server.haengdong.infrastructure.auth.CookieProperties; -import server.haengdong.presentation.EventController; -import server.haengdong.presentation.request.EventLoginRequest; -import server.haengdong.presentation.request.EventSaveRequest; -import server.haengdong.presentation.request.MemberNameUpdateRequest; -import server.haengdong.presentation.request.MemberNamesUpdateRequest; - -public class EventControllerDocsTest extends RestDocsSupport { - - private final EventService eventService = mock(EventService.class); - private final AuthService authService = mock(AuthService.class); - private final CookieProperties cookieProperties = new CookieProperties( - true, true, "domain", "path", "none", Duration.ofDays(7) - ); - - @Override - protected Object initController() { - return new EventController(eventService, authService, cookieProperties); - } - - @DisplayName("이벤트를 생성한다.") - @Test - void saveEvent() throws Exception { - EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리", "0987"); - String requestBody = objectMapper.writeValueAsString(eventSaveRequest); - String eventId = "쿠키 토큰"; - EventAppResponse eventAppResponse = new EventAppResponse(eventId); - given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); - given(authService.createToken(eventId)).willReturn("jwtToken"); - given(authService.getTokenName()).willReturn("eventToken"); - - mockMvc.perform(post("/api/events") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(cookie().value("eventToken", "jwtToken")) - .andExpect(jsonPath("$.eventId").value("쿠키 토큰")) - .andDo( - document("createEvent", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - requestFields( - fieldWithPath("eventName").type(JsonFieldType.STRING).description("행사 이름"), - fieldWithPath("password").type(JsonFieldType.STRING).description("행사 비밀 번호") - ), - responseFields( - fieldWithPath("eventId").type(JsonFieldType.STRING) - .description("행사 ID") - ), - responseCookies( - cookieWithName("eventToken").description("행사 관리자용 토큰") - ) - ) - ); - } - - @DisplayName("토큰으로 행사를 조회한다.") - @Test - void findEventTest() throws Exception { - String eventId = "망쵸토큰"; - EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("행동대장 회식"); - given(eventService.findEvent(eventId)).willReturn(eventDetailAppResponse); - - mockMvc.perform(get("/api/events/{eventId}", eventId)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.eventName").value("행동대장 회식")) - .andDo( - document("getEvent", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("eventName").type(JsonFieldType.STRING).description("행사 이름") - ) - ) - ); - } - - @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") - @Test - void findAllMembersTest() throws Exception { - MembersAppResponse memberAppResponse = new MembersAppResponse(List.of("토다리", "쿠키")); - given(eventService.findAllMembers(anyString())).willReturn(memberAppResponse); - - mockMvc.perform(get("/api/events/{eventId}/members", "TOKEN")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.memberNames").isArray()) - .andExpect(jsonPath("$.memberNames[0]").value("토다리")) - .andExpect(jsonPath("$.memberNames[1]").value("쿠키")) - .andDo( - document("findAllEventMember", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("memberNames").type(JsonFieldType.ARRAY) - .description("행사 참여자 목록") - ) - ) - ); - } - - @DisplayName("행사 참여 인원의 이름을 수정한다.") - @Test - void updateMember() throws Exception { - String token = "TOKEN"; - MemberNamesUpdateRequest memberNameUpdateRequest = new MemberNamesUpdateRequest(List.of( - new MemberNameUpdateRequest("토다링", "토쟁이"), - new MemberNameUpdateRequest("감자", "고구마") - )); - - String requestBody = objectMapper.writeValueAsString(memberNameUpdateRequest); - - mockMvc.perform(put("/api/events/{eventId}/members/nameChange", token) - .cookie(EVENT_COOKIE) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo( - document("updateEventMemberName", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ), - requestFields( - fieldWithPath("members").type(JsonFieldType.ARRAY).description("수정할 참여자 목록"), - fieldWithPath("members[].before").type(JsonFieldType.STRING) - .description("수정 전 참여자 이름"), - fieldWithPath("members[].after").type(JsonFieldType.STRING) - .description("수정 후 참여자 이름") - ) - ) - ); - } - - @DisplayName("행사 어드민이 로그인한다.") - @Test - void loginEvent() throws Exception { - String token = "TOKEN"; - EventLoginRequest eventLoginRequest = new EventLoginRequest("1234"); - String requestBody = objectMapper.writeValueAsString(eventLoginRequest); - given(authService.createToken(token)).willReturn("jwtToken"); - given(authService.getTokenName()).willReturn("eventToken"); - - mockMvc.perform(post("/api/events/{eventId}/login", token) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(cookie().value("eventToken", "jwtToken")) - .andExpect(status().isOk()) - .andDo( - document("eventLogin", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - requestFields( - fieldWithPath("password").type(JsonFieldType.STRING) - .description("행사 비밀 번호") - ), - responseCookies( - cookieWithName("eventToken").description("행사 관리자용 토큰") - ) - ) - ); - } - - @DisplayName("행사 전체 액션 이력 조회") - @Test - void findActions() throws Exception { - String token = "TOKEN"; - List<ActionAppResponse> actionAppResponses = List.of( - new ActionAppResponse(1L, "망쵸", null, 1L, ActionType.IN), - new ActionAppResponse(2L, "족발", 100L, 2L, ActionType.BILL), - new ActionAppResponse(3L, "인생네컷", 1000L, 3L, ActionType.BILL), - new ActionAppResponse(4L, "망쵸", null, 4L, ActionType.OUT) - ); - given(eventService.findActions(token)).willReturn(actionAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/actions", token) - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.steps[0].type").value(equalTo("IN"))) - .andExpect(jsonPath("$.steps[0].stepName").value(equalTo("0차"))) - .andExpect(jsonPath("$.steps[0].members[0]").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.steps[0].actions[0].actionId").value(equalTo(1))) - .andExpect(jsonPath("$.steps[0].actions[0].name").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.steps[0].actions[0].price").value(equalTo(null))) - .andExpect(jsonPath("$.steps[0].actions[0].sequence").value(equalTo(1))) - - .andExpect(jsonPath("$.steps[1].type").value(equalTo("BILL"))) - .andExpect(jsonPath("$.steps[1].stepName").value(equalTo("1차"))) - .andExpect(jsonPath("$.steps[1].members[0]").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.steps[1].actions[0].actionId").value(equalTo(2))) - .andExpect(jsonPath("$.steps[1].actions[0].name").value(equalTo("족발"))) - .andExpect(jsonPath("$.steps[1].actions[0].price").value(equalTo(100))) - .andExpect(jsonPath("$.steps[1].actions[0].sequence").value(equalTo(2))) - - .andExpect(jsonPath("$.steps[1].actions[1].actionId").value(equalTo(3))) - .andExpect(jsonPath("$.steps[1].actions[1].name").value(equalTo("인생네컷"))) - .andExpect(jsonPath("$.steps[1].actions[1].price").value(equalTo(1000))) - .andExpect(jsonPath("$.steps[1].actions[1].sequence").value(equalTo(3))) - - .andExpect(jsonPath("$.steps[2].type").value(equalTo("OUT"))) - .andExpect(jsonPath("$.steps[2].stepName").value(equalTo("1차"))) - .andExpect(jsonPath("$.steps[2].actions[0].actionId").value(equalTo(4))) - .andExpect(jsonPath("$.steps[2].actions[0].name").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.steps[2].actions[0].price").value(equalTo(null))) - .andExpect(jsonPath("$.steps[2].actions[0].sequence").value(equalTo(4))) - - .andDo( - document("findActions", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("steps[].stepName").type(JsonFieldType.STRING) - .description("스탭 이름"), - fieldWithPath("steps[].type").type(JsonFieldType.STRING) - .description("액션 유형 [BILL, IN, OUT]"), - fieldWithPath("steps[].members").type(JsonFieldType.ARRAY) - .description("해당 step에 참여한 참여자 목록"), - fieldWithPath("steps[].actions[].actionId").type(JsonFieldType.NUMBER) - .description("액션 ID"), - fieldWithPath("steps[].actions[].name").type(JsonFieldType.STRING) - .description("참여자 액션일 경우 참여자 이름, 지출 액션일 경우 지출 내역 이름"), - fieldWithPath("steps[].actions[].price").type(JsonFieldType.NUMBER).optional() - .description("참여자 액션일 경우 null, 지출 액션일 경우 지출 금액"), - fieldWithPath("steps[].actions[].sequence").type(JsonFieldType.NUMBER) - .description("액션 순서"), - fieldWithPath("steps[].actions[].isFixed").type(JsonFieldType.BOOLEAN) - .description("지출 내역의 멤버별 고정 지출 금액 생성 여부") - ) - ) - ); - } - - @DisplayName("행사 전체 액션 이력 조회 v2") - @Test - void findActions2() throws Exception { - String token = "TOKEN"; - List<ActionAppResponse> actionAppResponses = List.of( - new ActionAppResponse(1L, "망쵸", null, 1L, ActionType.IN), - new ActionAppResponse(2L, "족발", 100L, 2L, ActionType.BILL), - new ActionAppResponse(3L, "인생네컷", 1000L, 3L, ActionType.BILL), - new ActionAppResponse(4L, "망쵸", null, 4L, ActionType.OUT) - ); - given(eventService.findActions(token)).willReturn(actionAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/actions/v2", token) - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.actions[0].actionId").value(equalTo(1))) - .andExpect(jsonPath("$.actions[0].name").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.actions[0].price").value(equalTo(null))) - .andExpect(jsonPath("$.actions[0].sequence").value(equalTo(1))) - .andExpect(jsonPath("$.actions[0].type").value(equalTo("IN"))) - - .andExpect(jsonPath("$.actions[1].actionId").value(equalTo(2))) - .andExpect(jsonPath("$.actions[1].name").value(equalTo("족발"))) - .andExpect(jsonPath("$.actions[1].price").value(equalTo(100))) - .andExpect(jsonPath("$.actions[1].sequence").value(equalTo(2))) - .andExpect(jsonPath("$.actions[1].type").value(equalTo("BILL"))) - - .andExpect(jsonPath("$.actions[2].actionId").value(equalTo(3))) - .andExpect(jsonPath("$.actions[2].name").value(equalTo("인생네컷"))) - .andExpect(jsonPath("$.actions[2].price").value(equalTo(1000))) - .andExpect(jsonPath("$.actions[2].sequence").value(equalTo(3))) - .andExpect(jsonPath("$.actions[2].type").value(equalTo("BILL"))) - - .andExpect(jsonPath("$.actions[3].actionId").value(equalTo(4))) - .andExpect(jsonPath("$.actions[3].name").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.actions[3].price").value(equalTo(null))) - .andExpect(jsonPath("$.actions[3].sequence").value(equalTo(4))) - .andExpect(jsonPath("$.actions[3].type").value(equalTo("OUT"))) - - .andDo( - document("findActions", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("actions[].actionId").type(JsonFieldType.NUMBER) - .description("액션 ID"), - fieldWithPath("actions[].name").type(JsonFieldType.STRING) - .description("참여자 액션일 경우 참여자 이름, 지출 액션일 경우 지출 내역 이름"), - fieldWithPath("actions[].price").type(JsonFieldType.NUMBER).optional() - .description("참여자 액션일 경우 null, 지출 액션일 경우 지출 금액"), - fieldWithPath("actions[].sequence").type(JsonFieldType.NUMBER) - .description("액션 순서"), - fieldWithPath("actions[].type").type(JsonFieldType.STRING) - .description("액션 타입") - ) - ) - ); - } - - @DisplayName("행사 어드민 권한을 확인한다.") - @Test - void authenticateTest() throws Exception { - String token = "TOKEN"; - mockMvc.perform(post("/api/events/{eventId}/auth", token) - .cookie(EVENT_COOKIE)) - .andDo(print()) - .andExpect(status().isOk()) - - .andDo( - document("authenticateEvent", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰").optional() - ) - ) - ); - } -} diff --git a/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java deleted file mode 100644 index afd766c8f..000000000 --- a/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java +++ /dev/null @@ -1,157 +0,0 @@ -package server.haengdong.docs; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; -import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; -import server.haengdong.application.MemberActionService; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.MemberActionController; -import server.haengdong.presentation.request.MemberActionsSaveRequest; - -public class MemberActionControllerDocsTest extends RestDocsSupport { - - private final MemberActionService memberActionService = mock(MemberActionService.class); - - @Override - protected Object initController() { - return new MemberActionController(memberActionService); - } - - @DisplayName("참여자 행동을 추가한다.") - @Test - void saveMemberActionTest() throws Exception { - MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( - List.of("웨디", "소하", "토다리", "쿠키"), "IN"); - - String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); - - mockMvc.perform(post("/api/events/{eventId}/member-actions", "망쵸토큰") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody) - .cookie(EVENT_COOKIE)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo( - document("createMemberAction", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - requestCookies( - cookieWithName("eventToken").description("토큰 토큰") - ), - requestFields( - fieldWithPath("members").type(JsonFieldType.ARRAY) - .description("액션 대상 참여자 목록"), - fieldWithPath("status").type(JsonFieldType.STRING) - .description("참여자 액션 상태 [IN(늦참), OUT(탈주)]") - ) - ) - ); - } - - @DisplayName("현재 참여 인원을 조회합니다.") - @Test - void getCurrentMembers() throws Exception { - List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( - new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); - - given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/members/current", "망쵸토큰") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.memberNames[0]").value(equalTo("소하"))) - .andExpect(jsonPath("$.memberNames[1]").value(equalTo("토다리"))) - .andDo( - document("getCurrentMembers", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("memberNames").type(JsonFieldType.ARRAY) - .description("현재 탈주 가능한 참여 인원 이름 목록") - ) - ) - ); - } - - @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.") - @Test - void deleteMemberAction() throws Exception { - String eventId = "망쵸토큰"; - Long actionId = 2L; - - mockMvc.perform(delete("/api/events/{eventId}/member-actions/{actionId}", eventId, actionId) - .cookie(EVENT_COOKIE)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo( - document("deleteMemberAction", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("actionId").description("액션 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자용 토큰") - ) - ) - ); - } - - @DisplayName("행사의 전체 참여자 중에서 특정 참여자의 맴버 액션을 전부 삭제한다.") - @Test - void deleteMember() throws Exception { - String eventId = "망쵸토큰"; - String memberName = "행동대장"; - - mockMvc.perform(delete("/api/events/{eventId}/members/{memberName}", eventId, memberName) - .cookie(EVENT_COOKIE)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo( - document("deleteAllMemberActionByName", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("memberName").description("행사 참여자 이름") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자용 토큰") - ) - ) - ); - } -} diff --git a/server/src/test/java/server/haengdong/docs/RestDocsSupport.java b/server/src/test/java/server/haengdong/docs/RestDocsSupport.java deleted file mode 100644 index 3e6901ba8..000000000 --- a/server/src/test/java/server/haengdong/docs/RestDocsSupport.java +++ /dev/null @@ -1,28 +0,0 @@ -package server.haengdong.docs; - -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.restdocs.RestDocumentationContextProvider; -import org.springframework.restdocs.RestDocumentationExtension; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; - -@ExtendWith({RestDocumentationExtension.class}) -abstract class RestDocsSupport { - - protected MockMvc mockMvc; - - protected ObjectMapper objectMapper = new ObjectMapper(); - - @BeforeEach - void setUp(RestDocumentationContextProvider restDocumentation) { - this.mockMvc = MockMvcBuilders.standaloneSetup(initController()) - .apply(documentationConfiguration(restDocumentation)) - .build(); - } - - protected abstract Object initController(); -} diff --git a/server/src/test/java/server/haengdong/domain/action/ActionTest.java b/server/src/test/java/server/haengdong/domain/action/ActionTest.java deleted file mode 100644 index 6ff25479c..000000000 --- a/server/src/test/java/server/haengdong/domain/action/ActionTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; -import server.haengdong.support.fixture.Fixture; - -class ActionTest { - - @DisplayName("액션의 초기 순서번호는 1이다.") - @Test - void createFirst() { - Event event = Fixture.EVENT1; - Action action = Action.createFirst(event); - - assertThat(action.getSequence()).isOne(); - } - - @DisplayName("현재 액션의 다음 액션의 순서는 1만큼 증가한다.") - @Test - void next() { - Event event = Fixture.EVENT1; - Action action = new Action(event, 2L); - - Action nextAction = action.next(); - - assertThat(nextAction.getSequence()).isEqualTo(3L); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java deleted file mode 100644 index ba1ab36f2..000000000 --- a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; -import static server.haengdong.support.fixture.Fixture.BILL_ACTION; -import static server.haengdong.support.fixture.Fixture.EVENT1; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import server.haengdong.domain.event.Event; -import server.haengdong.exception.HaengdongException; - -class BillActionTest { - - @DisplayName("지출 내역 제목의 앞뒤 공백을 제거한 길이가 1 ~ 30자가 아니면 지출을 생성할 수 없다.") - @ParameterizedTest - @ValueSource(strings = {"", " ", "1234567890123456789012345678901"}) - void validateTitle(String title) { - Event event = EVENT1; - Action action = new Action(event, 1L); - Long price = 100L; - - assertThatThrownBy(() -> new BillAction(action, title, price)) - .isInstanceOf(HaengdongException.class) - .hasMessage("앞뒤 공백을 제거한 지출 내역 제목은 1 ~ 30자여야 합니다."); - } - - @DisplayName("금액이 10,000,000 이하의 자연수가 아니면 지출을 생성할 수 없다.") - @ParameterizedTest - @ValueSource(longs = {0, 10_000_001, 20_000_000}) - void validatePrice(long price) { - Event event = EVENT1; - Action action = new Action(event, 1L); - String title = "title"; - - assertThatThrownBy(() -> new BillAction(action, title, price)) - .isInstanceOf(HaengdongException.class) - .hasMessage("지출 금액은 10,000,000 이하의 자연수여야 합니다."); - } - - @DisplayName("지출 내역을 올바르게 생성한다.") - @Test - void createBillAction() { - Event event = EVENT1; - Action action = new Action(event, 1L); - String title = "title"; - Long price = 1_000L; - - BillAction billAction = new BillAction(action, title, price); - - assertAll( - () -> assertThat(billAction.getAction()).isEqualTo(action), - () -> assertThat(billAction.getTitle()).isEqualTo(title), - () -> assertThat(billAction.getPrice()).isEqualTo(price) - ); - } - - @DisplayName("지출 액션에 멤버별 고정 금액이 설정되어 있는지 확인한다.") - @Test - void isFixed1() { - BillAction fixedBillAction = new BillAction(new Action(EVENT1, 1L), "인생네컷", 2_000L); - - List<BillActionDetail> unfixedBillActionDetails = List.of( - new BillActionDetail(BILL_ACTION, "감자", 1_000L, false), - new BillActionDetail(BILL_ACTION, "고구마", 1_000L, false) - ); - fixedBillAction.addDetails(unfixedBillActionDetails); - - assertThat(fixedBillAction.isFixed()).isEqualTo(false); - } - - @DisplayName("지출 액션에 멤버별 고정 금액이 설정되어 있는지 확인한다.") - @Test - void isFixed2() { - BillAction fixedBillAction = new BillAction(new Action(EVENT1, 1L), "인생네컷", 5_000L); - - List<BillActionDetail> unfixedBillActionDetails = List.of( - new BillActionDetail(BILL_ACTION, "감자", 4_000L, true), - new BillActionDetail(BILL_ACTION, "고구마", 1_000L, true) - ); - fixedBillAction.addDetails(unfixedBillActionDetails); - - assertThat(fixedBillAction.isFixed()).isEqualTo(true); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java deleted file mode 100644 index 93148abd3..000000000 --- a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import java.util.Set; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class CurrentMembersTest { - - @DisplayName("인원 변동 이력으로 현재 참여 인원을 계산한다.") - @Test - void of() { - Event event = Fixture.EVENT1; - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(event, 1L), "망쵸", IN, 1L), - new MemberAction(new Action(event, 2L), "백호", IN, 1L), - new MemberAction(new Action(event, 3L), "백호", OUT, 1L), - new MemberAction(new Action(event, 4L), "웨디", IN, 1L) - ); - - CurrentMembers currentMembers = CurrentMembers.of(memberActions); - - assertThat(currentMembers.getMembers()) - .containsExactlyInAnyOrder("망쵸", "웨디"); - } - - @DisplayName("인원 변동 액션의 상태가 IN이면 현재 인원에 추가한다.") - @Test - void addMemberAction1() { - CurrentMembers currentMembers = new CurrentMembers(); - Event event = Fixture.EVENT1; - MemberAction memberAction = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); - - CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction); - Set<String> members = addedCurrentMembers.getMembers(); - - assertThat(members).hasSize(1) - .containsExactly("웨디"); - } - - @DisplayName("인원 변동 액션의 상태가 OUT이면 현재 인원에서 제외한다.") - @Test - void addMemberAction2() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); - CurrentMembers currentMembers = new CurrentMembers().addMemberAction(memberAction1); - MemberAction memberAction2 = new MemberAction(new Action(event, 1L), "웨디", OUT, 1L); - - CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction2); - - assertThat(addedCurrentMembers.getMembers()).hasSize(0); - } - - @DisplayName("현재 참여중인 인원은 나갈 수 있다.") - @Test - void validate1() { - CurrentMembers currentMembers = new CurrentMembers(Set.of("토다리")); - - assertThatCode(() -> currentMembers.validate("토다리", OUT)) - .doesNotThrowAnyException(); - } - - @DisplayName("현재 참여중이지 않은 인원은 들어올 수 있다.") - @Test - void validate2() { - CurrentMembers currentMembers = new CurrentMembers(Set.of("쿠키")); - - assertThatCode(() -> currentMembers.validate("토다리", IN)) - .doesNotThrowAnyException(); - } - - @DisplayName("현재 참여중인 인원은 들어올 수 없다.") - @Test - void validate3() { - CurrentMembers currentMembers = new CurrentMembers(Set.of("토다리")); - - assertThatCode(() -> currentMembers.validate("토다리", IN)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("현재 참여중이지 않은 인원은 나갈 수 없다.") - @Test - void validate4() { - CurrentMembers currentMembers = new CurrentMembers(Set.of("쿠키")); - - assertThatCode(() -> currentMembers.validate("토다리", OUT)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java deleted file mode 100644 index 02070a537..000000000 --- a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; -import static server.haengdong.support.fixture.Fixture.BILL_ACTION; - -import java.util.List; -import java.util.Map; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; -import server.haengdong.support.fixture.Fixture; - -class MemberBillReportTest { - - @DisplayName("액션 목록으로 참가자 정산 리포트를 생성한다.") - @Test - void createByActions() { - Event event = Fixture.EVENT1; - List<BillAction> billActions = List.of( - new BillAction(new Action(event, 4L), "뽕족", 60_000L), - new BillAction(new Action(event, 7L), "인생네컷", 20_000L) - ); - billActions.get(0).addDetails( - List.of( - new BillActionDetail(BILL_ACTION, "소하", 10_000L, false), - new BillActionDetail(BILL_ACTION, "감자", 40_000L, true), - new BillActionDetail(BILL_ACTION, "쿠키", 10_000L, false) - ) - ); - billActions.get(1).addDetails( - List.of( - new BillActionDetail(BILL_ACTION, "소하", 5_000L, true), - new BillActionDetail(BILL_ACTION, "쿠키", 15_000L, true) - ) - ); - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(event, 1L), "소하", IN, 1L), - new MemberAction(new Action(event, 2L), "감자", IN, 1L), - new MemberAction(new Action(event, 3L), "쿠키", IN, 1L), - new MemberAction(new Action(event, 5L), "감자", OUT, 2L) - ); - - MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); - - assertThat(memberBillReport.getReports()) - .containsAllEntriesOf( - Map.of( - "감자", 40_000L, - "쿠키", 25_000L, - "소하", 15_000L - ) - ); - } -} diff --git a/server/src/test/java/server/haengdong/domain/event/EventTest.java b/server/src/test/java/server/haengdong/domain/event/EventTest.java deleted file mode 100644 index 12c0c0569..000000000 --- a/server/src/test/java/server/haengdong/domain/event/EventTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package server.haengdong.domain.event; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import server.haengdong.exception.HaengdongException; - -class EventTest { - - @DisplayName("공백 문자가 연속되지 않고, 이름이 2자 이상 20자 이하인 행사를 생성하면 예외가 발생하지 않는다.") - @ParameterizedTest - @ValueSource(strings = {"12", "12345678901234567890", "공 백", " 공백", "공백 ", " 공 백 "}) - void createSuccessTest(String eventName) { - assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) - .doesNotThrowAnyException(); - } - - @DisplayName("공백 문자가 연속되면 예외가 발생한다.") - @ParameterizedTest - @ValueSource(strings = {" 공백", "공백 ", "공백 연속", "공 백"}) - void createFailTest1(String eventName) { - assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) - .isInstanceOf(HaengdongException.class) - .hasMessage(String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", eventName)); - } - - @DisplayName("이름이 1자 미만이거나 20자 초과인 경우 예외가 발생한다.") - @ParameterizedTest - @ValueSource(strings = {"", " ", "123456789012345678901"}) - void createFilTest2(String eventName) { - assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) - .isInstanceOf(HaengdongException.class) - .hasMessage(String.format("행사 이름은 1자 이상 20자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", eventName.length())); - } - - @DisplayName("비밀번호는 4자리 숫자 입니다.") - @ParameterizedTest - @ValueSource(strings = {"1", "12", "123", "12345", "adgd"}) - void validatePassword(String password) { - assertThatCode(() -> new Event("이름", password, "TEST_TOKEN")) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("비밀번호가 다른지 검증한다.") - @Test - void isNotSamePassword() { - String rawPassword = "1234"; - Event event = new Event("이름", rawPassword, "TEST_TOKEN"); - - assertThat(event.isPasswordMismatch(rawPassword)).isFalse(); - } - - @DisplayName("비밀번호가 다른지 검증한다.") - @Test - void isNotSamePassword1() { - String rawPassword = "1234"; - Event event = new Event("이름", "5678", "TEST_TOKEN"); - - assertThat(event.isPasswordMismatch(rawPassword)).isTrue(); - } -} diff --git a/server/src/test/java/server/haengdong/domain/event/PasswordTest.java b/server/src/test/java/server/haengdong/domain/event/PasswordTest.java deleted file mode 100644 index c504d3aa2..000000000 --- a/server/src/test/java/server/haengdong/domain/event/PasswordTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.domain.event; - -import static org.assertj.core.api.Assertions.assertThatCode; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import server.haengdong.exception.HaengdongException; - -class PasswordTest { - - @DisplayName("비밀번호는 4자리 숫자 입니다.") - @ParameterizedTest - @ValueSource(strings = {"1", "12", "123", "12345", "adgd"}) - void validatePassword(String rawPassword) { - assertThatCode(() -> new Password(rawPassword)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java deleted file mode 100644 index 1de5889b5..000000000 --- a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package server.haengdong.presentation; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import server.haengdong.application.response.MemberBillReportAppResponse; - -class ActionControllerTest extends ControllerTestSupport { - - @DisplayName("참여자별 정산 현황을 조회한다.") - @Test - void getMemberBillReports() throws Exception { - List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( - new MemberBillReportAppResponse("소하", 20_000L), new MemberBillReportAppResponse("토다리", 200_000L)); - - given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/actions/reports", "망쵸토큰") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("소하"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("토다리"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java deleted file mode 100644 index 4420e369c..000000000 --- a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package server.haengdong.presentation; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doThrow; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; -import server.haengdong.presentation.request.BillActionSaveRequest; -import server.haengdong.presentation.request.BillActionUpdateRequest; -import server.haengdong.presentation.request.BillActionsSaveRequest; - -class BillActionControllerTest extends ControllerTestSupport { - - @DisplayName("지출 내역을 생성한다.") - @Test - void saveAllBillAction() throws Exception { - BillActionsSaveRequest request = new BillActionsSaveRequest( - List.of( - new BillActionSaveRequest("뽕족", 10_000L), - new BillActionSaveRequest("인생맥주", 10_000L) - ) - ); - String requestBody = objectMapper.writeValueAsString(request); - String eventId = "쿠키토큰"; - - mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("title이 비어 있는 경우 지출 내역을 생성할 수 없다.") - @Test - void saveAllBillAction1() throws Exception { - BillActionsSaveRequest request = new BillActionsSaveRequest( - List.of( - new BillActionSaveRequest("", 10_000L), - new BillActionSaveRequest("인생맥주", 10_000L) - ) - ); - String requestBody = objectMapper.writeValueAsString(request); - String eventId = "소하토큰"; - - mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isBadRequest()); - } - - @DisplayName("지출 액션을 수정한다.") - @Test - void updateBillAction() throws Exception { - BillActionUpdateRequest request = new BillActionUpdateRequest("뽕족", 10_000L); - - String requestBody = objectMapper.writeValueAsString(request); - String eventId = "웨디토큰"; - - mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("지출 내역을 삭제한다.") - @Test - void deleteBillAction() throws Exception { - String eventId = "토다리토큰"; - - mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("존재하지 않는 행사에 대한 지출 내역을 삭제할 수 없다.") - @Test - void deleteBillAction1() throws Exception { - String eventId = "이상해토큰"; - doThrow(new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)) - .when(billActionService).deleteBillAction(any(String.class), any(Long.class)); - - mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1)) - .andDo(print()) - .andExpect(status().isBadRequest()); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java deleted file mode 100644 index 6b595ee27..000000000 --- a/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package server.haengdong.presentation; - -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import server.haengdong.application.response.BillActionDetailAppResponse; -import server.haengdong.application.response.BillActionDetailsAppResponse; -import server.haengdong.presentation.request.BillActionDetailUpdateRequest; -import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; - -class BillActionDetailControllerTest extends ControllerTestSupport { - - @DisplayName("참여자별 지출 금액을 조회한다.") - @Test - void findBillActionDetails() throws Exception { - BillActionDetailsAppResponse appResponse = new BillActionDetailsAppResponse( - List.of(new BillActionDetailAppResponse("토다리", 1000L, false))); - given(billActionDetailService.findBillActionDetails(anyString(), anyLong())) - .willReturn(appResponse); - - mockMvc.perform(get("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.members").isArray()) - .andExpect(jsonPath("$.members[0].name").value("토다리")) - .andExpect(jsonPath("$.members[0].price").value(1000L)); - } - - @DisplayName("참여자별 지출 금액을 수정한다.") - @Test - void updateBillActionDetailsTest() throws Exception { - List<BillActionDetailUpdateRequest> billActionDetailUpdateRequests = List.of( - new BillActionDetailUpdateRequest("소하", 10000L, true), - new BillActionDetailUpdateRequest("웨디", 20000L, true) - ); - BillActionDetailsUpdateRequest request = new BillActionDetailsUpdateRequest( - billActionDetailUpdateRequests); - - String json = objectMapper.writeValueAsString(request); - - mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(json)) - .andDo(print()) - .andExpect(status().isOk()); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java b/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java deleted file mode 100644 index 46489b1a5..000000000 --- a/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java +++ /dev/null @@ -1,53 +0,0 @@ -package server.haengdong.presentation; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.FilterType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import server.haengdong.application.ActionService; -import server.haengdong.application.AuthService; -import server.haengdong.application.BillActionDetailService; -import server.haengdong.application.BillActionService; -import server.haengdong.application.EventService; -import server.haengdong.application.MemberActionService; - -@WebMvcTest( - controllers = { - EventController.class, - ActionController.class, - BillActionController.class, - MemberActionController.class, - BillActionDetailController.class - }, - excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {WebMvcConfigurer.class})} -) -abstract class ControllerTestSupport { - - @Autowired - protected MockMvc mockMvc; - - @Autowired - protected ObjectMapper objectMapper; - - @MockBean - protected EventService eventService; - - @MockBean - protected AuthService authService; - - @MockBean - protected ActionService actionService; - - @MockBean - protected MemberActionService memberActionService; - - @MockBean - protected BillActionService billActionService; - - @MockBean - protected BillActionDetailService billActionDetailService; -} diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java deleted file mode 100644 index fcfe48d01..000000000 --- a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package server.haengdong.presentation; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.application.response.MembersAppResponse; -import server.haengdong.presentation.request.EventLoginRequest; -import server.haengdong.presentation.request.EventSaveRequest; -import server.haengdong.presentation.request.MemberNameUpdateRequest; -import server.haengdong.presentation.request.MemberNamesUpdateRequest; - - -class EventControllerTest extends ControllerTestSupport { - - @DisplayName("이벤트를 생성한다.") - @Test - void saveEvent() throws Exception { - EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리", "0987"); - String requestBody = objectMapper.writeValueAsString(eventSaveRequest); - String eventId = "망쵸토큰"; - EventAppResponse eventAppResponse = new EventAppResponse(eventId); - given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); - given(authService.createToken(eventId)).willReturn("jwtToken"); - given(authService.getTokenName()).willReturn("eventToken"); - - mockMvc.perform(post("/api/events") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(cookie().value("eventToken", "jwtToken")) - .andExpect(jsonPath("$.eventId").value("망쵸토큰")); - } - - @DisplayName("토큰으로 행사를 조회한다.") - @Test - void findEventTest() throws Exception { - String eventId = "망쵸토큰"; - EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("행동대장 회식"); - given(eventService.findEvent(eventId)).willReturn(eventDetailAppResponse); - - mockMvc.perform(get("/api/events/{eventId}", eventId)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.eventName").value("행동대장 회식")); - } - - @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") - @Test - void findAllMembersTest() throws Exception { - MembersAppResponse memberAppResponse = new MembersAppResponse(List.of("토다리", "쿠키")); - given(eventService.findAllMembers(anyString())).willReturn(memberAppResponse); - - mockMvc.perform(get("/api/events/{eventId}/members", "TOKEN")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.memberNames").isArray()) - .andExpect(jsonPath("$.memberNames[0]").value("토다리")) - .andExpect(jsonPath("$.memberNames[1]").value("쿠키")); - } - - @DisplayName("행사 참여 인원의 이름을 수정한다.") - @Test - void updateMember() throws Exception { - String token = "TOKEN"; - MemberNamesUpdateRequest memberNameUpdateRequest = new MemberNamesUpdateRequest(List.of( - new MemberNameUpdateRequest("토다링", "토쟁이"), - new MemberNameUpdateRequest("감자", "고구마") - )); - - String requestBody = objectMapper.writeValueAsString(memberNameUpdateRequest); - - mockMvc.perform(put("/api/events/{eventId}/members/nameChange", token) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("행사 어드민이 로그인한다.") - @Test - void loginEvent() throws Exception { - String token = "TOKEN"; - EventLoginRequest eventLoginRequest = new EventLoginRequest("1234"); - String requestBody = objectMapper.writeValueAsString(eventLoginRequest); - given(authService.createToken(token)).willReturn("jwtToken"); - given(authService.getTokenName()).willReturn("eventToken"); - - mockMvc.perform(post("/api/events/{eventId}/login", token) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(cookie().value("eventToken", "jwtToken")) - .andExpect(status().isOk()); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java deleted file mode 100644 index f50c70a17..000000000 --- a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package server.haengdong.presentation; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.request.MemberActionsSaveRequest; - -class MemberActionControllerTest extends ControllerTestSupport { - - @DisplayName("참여자 행동을 추가한다.") - @Test - void saveMemberActionTest() throws Exception { - MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( - List.of("웨디", "소하", "토다리", "쿠키"), "IN"); - - String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); - - mockMvc.perform(post("/api/events/{eventId}/member-actions", "망쵸토큰") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("현재 참여 인원을 조회합니다.") - @Test - void getCurrentMembers() throws Exception { - List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( - new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); - - given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/members/current", "망쵸토큰") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.memberNames[0]").value(equalTo("소하"))) - .andExpect(jsonPath("$.memberNames[1]").value(equalTo("토다리"))); - } - - @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.") - @Test - void deleteMemberAction() throws Exception { - String eventId = "망쵸토큰"; - Long actionId = 2L; - - mockMvc.perform(delete("/api/events/{eventId}/member-actions/{actionId}", eventId, actionId)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("행사의 전체 참여자 중에서 특정 참여자의 맴버 액션을 전부 삭제한다.") - @Test - void deleteMember() throws Exception { - String eventId = "망쵸토큰"; - String memberName = "행동대장"; - - mockMvc.perform(delete("/api/events/{eventId}/members/{memberName}", eventId, memberName)) - .andDo(print()) - .andExpect(status().isOk()); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java b/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java deleted file mode 100644 index 051fcae0f..000000000 --- a/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package server.haengdong.presentation.response; - - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.ActionAppResponse.ActionType; - -class StepsResponseTest { - - @DisplayName("이웃한 같은 타입의 액션들을 그룹화 하여 응답객체를 생성한다.") - @Test - void of() { - List<ActionAppResponse> actions = List.of( - new ActionAppResponse(1L, "망쵸", null, 1L, ActionType.IN), - new ActionAppResponse(2L, "백호", null, 2L, ActionType.IN), - new ActionAppResponse(3L, "감자탕", 10_000L, 3L, ActionType.BILL), - new ActionAppResponse(4L, "인생네컷", 10_000L, 4L, ActionType.BILL), - new ActionAppResponse(5L, "소하", null, 5L, ActionType.IN), - new ActionAppResponse(6L, "웨디", null, 6L, ActionType.IN), - new ActionAppResponse(7L, "망쵸", null, 7L, ActionType.OUT), - new ActionAppResponse(8L, "백호", null, 8L, ActionType.OUT), - new ActionAppResponse(9L, "노래방", 20_000L, 9L, ActionType.BILL) - ); - - StepsResponse stepsResponse = StepsResponse.of(actions); - - StepsResponse expected = new StepsResponse( - List.of( - new StepResponse("0차", "IN", List.of("망쵸", "백호"), List.of( - new ActionResponse(1L, "망쵸", null, 1L), - new ActionResponse(2L, "백호", null, 2L) - )), - new StepResponse("1차", "BILL", List.of("망쵸", "백호"), List.of( - new ActionResponse(3L, "감자탕", 10_000L, 3L), - new ActionResponse(4L, "인생네컷", 10_000L, 4L) - )), - new StepResponse("1차", "IN", List.of("망쵸", "백호", "소하", "웨디"), List.of( - new ActionResponse(5L, "소하", null, 5L), - new ActionResponse(6L, "웨디", null, 6L) - )), - new StepResponse("1차", "OUT", List.of("소하", "웨디"), List.of( - new ActionResponse(7L, "망쵸", null, 7L), - new ActionResponse(8L, "백호", null, 8L) - )), - new StepResponse("2차", "BILL", List.of("소하", "웨디"), List.of( - new ActionResponse(9L, "노래방", 20_000L, 9L) - )) - ) - ); - assertThat(stepsResponse).isEqualTo(expected); - } - - @DisplayName("액션이 없으면 빈 스탭들이 만들어진다.") - @Test - void ofEmpty() { - StepsResponse stepsResponse = StepsResponse.of(List.of()); - assertThat(stepsResponse.steps()).isEmpty(); - } -} diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java deleted file mode 100644 index 346e81d2d..000000000 --- a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java +++ /dev/null @@ -1,52 +0,0 @@ -package server.haengdong.support.extension; - -import jakarta.annotation.PostConstruct; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import java.util.List; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -@Component -class DatabaseCleaner { - - private static final String REFERENTIAL_FORMAT = "set referential_integrity %b;"; - private static final String TRUNCATE_FORMAT = "truncate table %s restart identity;"; - - @PersistenceContext - private EntityManager em; - private String truncateTablesQuery; - - @PostConstruct - public void createTruncateQuery() { - List<String> tableNames = getTableNames(); - StringBuilder stringBuilder = new StringBuilder(); - - for (String tableName : tableNames) { - String truncateQuery = String.format(TRUNCATE_FORMAT, tableName); - stringBuilder.append(truncateQuery); - } - truncateTablesQuery = stringBuilder.toString(); - } - - private List<String> getTableNames() { - String sql = """ - select table_name - from information_schema.tables - where table_schema = 'PUBLIC' - """; - return em.createNativeQuery(sql).getResultList(); - } - - @Transactional - public void clear() { - em.clear(); - truncate(); - } - - private void truncate() { - em.createNativeQuery(String.format(REFERENTIAL_FORMAT, false)).executeUpdate(); - em.createNativeQuery(truncateTablesQuery).executeUpdate(); - em.createNativeQuery(String.format(REFERENTIAL_FORMAT, true)).executeUpdate(); - } -} diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java deleted file mode 100644 index 653ecadb3..000000000 --- a/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.support.extension; - -import org.junit.jupiter.api.extension.AfterEachCallback; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -public class DatabaseCleanerExtension implements AfterEachCallback { - - @Override - public void afterEach(ExtensionContext context) { - DatabaseCleaner databaseCleaner = getDataCleaner(context); - databaseCleaner.clear(); - } - - private DatabaseCleaner getDataCleaner(ExtensionContext extensionContext) { - return SpringExtension.getApplicationContext(extensionContext) - .getBean(DatabaseCleaner.class); - } -} diff --git a/server/src/test/java/server/haengdong/support/fixture/Fixture.java b/server/src/test/java/server/haengdong/support/fixture/Fixture.java deleted file mode 100644 index 6844915d9..000000000 --- a/server/src/test/java/server/haengdong/support/fixture/Fixture.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.support.fixture; - -import jakarta.servlet.http.Cookie; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.event.Event; - -public class Fixture { - - public static final Event EVENT1 = new Event("쿠키", "1234", "TOKEN1"); - public static final Event EVENT2 = new Event("웨디", "1234", "TOKEN2"); - public static final Cookie EVENT_COOKIE = new Cookie("eventToken", "토큰토큰"); - public static final Action ACTION = new Action(EVENT1, 1L); - public static final BillAction BILL_ACTION = new BillAction(ACTION, "뽕족", 30_000L); -}

    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 z