From 3dcc196b0de76349040d39a566d45c2a1cf00f52 Mon Sep 17 00:00:00 2001 From: Inseo Hwang Date: Sat, 18 Nov 2023 03:51:53 +0900 Subject: [PATCH] =?UTF-8?q?Release=200.10.0:=20=ED=94=84=EB=A1=9C=ED=95=84?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B0=9C=EB=B0=9C=20(#84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Feat: 모바일 병동 입장 UI 개발 (DUT-528) (#71) * Fix: 랜딩페이지 이미지, height 수정 * Feat: 신청근무 UI 리펙토링, 개발 * Feat: 웹 신청근무 수락/거절 기능 개발 * Refactor: 이벤트 최적화, 최신 기능 이벤트 반영 * Release 0.4.0: 신청근무 수락, 거절 추가 / 이벤트 최적화 * Feat: 웹 성능 최적화 (#73) * Feat: Code splitting, dynamic import (React.lazy) * Feat: Font Opt * Feat: png to webp * Release 0.5.0: 웹 성능 최적화 * Feat: 간호사 연동 관리 기능 개발 (#75) * Feat: 랜딩 수정 * Feat: 로딩 기능 추가, 회원가입 절차 수정 등 (#DUT-648 / #77) * Release 0.7.0: 로딩 기능 추가, 회원가입 절차 수정 * Feat: 튜토리얼 기능 개발 (#79) * Feat: 오버레이 가이드 기능 개발 * HOTFIX: FaultLayer z-index 수정 * Feat: 튜토리얼 개발 * Release 0.8.0: 튜토리얼 기능 개발 * Fix: workflow 비활성화 * Fix: 근무형태 탭에서 근무 설정 변경 불가 * Fix: 튜토리얼 폰트 사이즈 수정 * Feat: 병동 생성 시 근무 유형 classification * Release 0.8.2 * Feat: Apple 로그인 추가, 로그인 UI 개편 * Release 0.9.0: 애플 로그인 추가 * Fix: 간호사 수정 모달 개선 * Fix: 용어 수정 * Feat: 병동 코드 표시 * Feat: 게시하기 추가, 구분 UI 수정 * Fix: 간호사 관리 페이지 UI 안정성 수정 * Release 0.9.2: UI 안정화 * Feat: 자동완성 기능 개발, 붙여넣기 기능 안정화 * Feat: 프로필 페이지 개발 * Release 0.10.0: 프로필 페이지 개발 --- package.json | 3 +- pnpm-lock.yaml | 510 +++++++++++++++++- src/components/NavigationBar/index.tsx | 7 +- src/hooks/account/useEditAccount.ts | 78 +++ src/hooks/auth/useAuth/index.ts | 8 +- src/hooks/shift/useCreateShift/indes.ts | 117 ++++ src/hooks/shift/useEditShift/index.ts | 144 ++--- src/hooks/ward/useEditWard/index.ts | 4 + src/libs/api/account.ts | 12 +- src/libs/api/nurse.ts | 1 + src/libs/api/ward.ts | 4 + src/libs/constant/path.ts | 2 +- .../components/NurseEditModal.tsx | 1 + .../MemberPage/components/NurseEditDrawer.tsx | 1 + src/pages/ProfilePage/index.tsx | 290 ++++++++++ .../RegisterPage/components/RegisterNurse.tsx | 10 +- src/pages/Router.tsx | 2 + 17 files changed, 1049 insertions(+), 145 deletions(-) create mode 100644 src/hooks/account/useEditAccount.ts create mode 100644 src/hooks/shift/useCreateShift/indes.ts create mode 100644 src/pages/ProfilePage/index.tsx diff --git a/package.json b/package.json index 4127720d..1a7236a7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "dutying-web", "private": true, - "version": "0.9.8", + "version": "0.10.0", "type": "module", "scripts": { "dev": "vite", @@ -25,6 +25,7 @@ "history": "^5.3.0", "immer": "^10.0.2", "lodash-es": "^4.17.21", + "puppeteer": "^21.5.2", "qs": "^6.11.2", "react": "^18.2.0", "react-beautiful-dnd": "^13.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4783fb24..8790ae6d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ dependencies: lodash-es: specifier: ^4.17.21 version: 4.17.21 + puppeteer: + specifier: ^21.5.2 + version: 21.5.2(typescript@5.1.6) qs: specifier: ^6.11.2 version: 6.11.2 @@ -809,6 +812,22 @@ packages: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: true + /@puppeteer/browsers@1.8.0: + resolution: {integrity: sha512-TkRHIV6k2D8OlUe8RtG+5jgOF/H98Myx0M6AOafC8DdNVOFiBSFa5cpRDtpm8LXOa9sVwe0+e6Q3FC56X/DZfg==} + engines: {node: '>=16.3.0'} + hasBin: true + dependencies: + debug: 4.3.4(supports-color@5.5.0) + extract-zip: 2.0.1 + progress: 2.0.3 + proxy-agent: 6.3.1 + tar-fs: 3.0.4 + unbzip2-stream: 1.4.3 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + dev: false + /@remix-run/router@1.7.2: resolution: {integrity: sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==} engines: {node: '>=14'} @@ -1198,6 +1217,10 @@ packages: engines: {node: '>= 10'} dev: true + /@tootallnate/quickjs-emscripten@0.23.0: + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + dev: false + /@trysound/sax@0.2.0: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -1267,7 +1290,6 @@ packages: /@types/node@20.4.2: resolution: {integrity: sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==} - dev: true /@types/prop-types@15.7.5: resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} @@ -1343,6 +1365,14 @@ packages: '@types/yargs-parser': 21.0.0 dev: true + /@types/yauzl@2.10.3: + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + requiresBuild: true + dependencies: + '@types/node': 20.4.2 + dev: false + optional: true + /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.45.0)(typescript@5.1.6): resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1570,6 +1600,15 @@ packages: - supports-color dev: true + /agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} + dependencies: + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + dev: false + /aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} @@ -1601,7 +1640,6 @@ packages: /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - dev: true /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} @@ -1619,7 +1657,6 @@ packages: engines: {node: '>=8'} dependencies: color-convert: 2.0.1 - dev: true /ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} @@ -1678,7 +1715,6 @@ packages: /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true /aria-query@5.1.3: resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} @@ -1761,6 +1797,13 @@ packages: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: true + /ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + dependencies: + tslib: 2.6.0 + dev: false + /astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} @@ -1804,6 +1847,10 @@ packages: - debug dev: false + /b4a@1.6.4: + resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} + dev: false + /babel-plugin-styled-components@2.1.4(@babel/core@7.22.9)(styled-components@5.3.11): resolution: {integrity: sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==} peerDependencies: @@ -1833,6 +1880,11 @@ packages: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} dev: false + /basic-ftp@5.0.3: + resolution: {integrity: sha512-QHX8HLlncOLpy54mh+k/sWIFd0ThmRqwe9ZjELybGZK+tZ8rUb9VO0saKJUROTbE+KhzDUT7xziGpGrW8Kmd+g==} + engines: {node: '>=10.0.0'} + dev: false + /big-integer@1.6.51: resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} engines: {node: '>=0.6'} @@ -1939,7 +1991,6 @@ packages: /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: true /camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} @@ -2025,6 +2076,16 @@ packages: fsevents: 2.3.2 dev: true + /chromium-bidi@0.4.33(devtools-protocol@0.0.1203626): + resolution: {integrity: sha512-IxoFM5WGQOIAd95qrSXzJUv4eXIrh+RvU3rwwqIiwYuvfE7U/Llj4fejbsJnjJMUYCuGtVQsY2gv7oGl4aTNSQ==} + peerDependencies: + devtools-protocol: '*' + dependencies: + devtools-protocol: 0.0.1203626 + mitt: 3.0.1 + urlpattern-polyfill: 9.0.0 + dev: false + /ci-info@3.8.0: resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} engines: {node: '>=8'} @@ -2062,6 +2123,15 @@ packages: string-width: 5.1.2 dev: true + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + /clsx@1.2.1: resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} engines: {node: '>=6'} @@ -2077,14 +2147,12 @@ packages: engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 - dev: true /color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true /colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -2173,6 +2241,22 @@ packages: path-type: 4.0.0 dev: true + /cosmiconfig@8.3.6(typescript@5.1.6): + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + typescript: 5.1.6 + dev: false + /crc-32@1.2.2: resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} engines: {node: '>=0.8'} @@ -2187,6 +2271,14 @@ packages: readable-stream: 3.6.2 dev: false + /cross-fetch@4.0.0: + resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -2278,6 +2370,11 @@ packages: engines: {node: '>=4'} dev: true + /data-uri-to-buffer@6.0.1: + resolution: {integrity: sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==} + engines: {node: '>= 14'} + dev: false + /data-urls@4.0.0: resolution: {integrity: sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==} engines: {node: '>=14'} @@ -2361,6 +2458,15 @@ packages: object-keys: 1.1.1 dev: true + /degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + dev: false + /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -2370,6 +2476,10 @@ packages: engines: {node: '>=6'} dev: true + /devtools-protocol@0.0.1203626: + resolution: {integrity: sha512-nEzHZteIUZfGCZtTiS1fRpC8UZmsfD1SiyPvaUNvS13dvKf666OAm8YTi0+Ca3n1nLEyu49Cy4+dPWpaHFJk9g==} + dev: false + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: true @@ -2464,7 +2574,6 @@ packages: /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} @@ -2485,7 +2594,6 @@ packages: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: is-arrayish: 0.2.1 - dev: true /es-abstract@1.22.1: resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==} @@ -2618,6 +2726,18 @@ packages: engines: {node: '>=10'} dev: true + /escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + dev: false + /eslint-config-prettier@8.8.0(eslint@8.45.0): resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} hasBin: true @@ -2772,6 +2892,12 @@ packages: eslint-visitor-keys: 3.4.1 dev: true + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: false + /esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} @@ -2794,12 +2920,10 @@ packages: /estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - dev: true /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - dev: true /exceljs@4.3.0: resolution: {integrity: sha512-hTAeo5b5TPvf8Z02I2sKIT4kSfCnOO2bCxYX8ABqODCdAjppI3gI9VYiGCQQYVcBaBSKlFDMKlAQRqC+kV9O8w==} @@ -2843,6 +2967,20 @@ packages: jest-util: 29.6.1 dev: true + /extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + dependencies: + debug: 4.3.4(supports-color@5.5.0) + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + dev: false + /fast-csv@4.3.6: resolution: {integrity: sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw==} engines: {node: '>=10.0.0'} @@ -2859,6 +2997,10 @@ packages: resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} dev: true + /fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + dev: false + /fast-glob@3.3.0: resolution: {integrity: sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==} engines: {node: '>=8.6.0'} @@ -2884,6 +3026,12 @@ packages: reusify: 1.0.4 dev: true + /fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + dependencies: + pend: 1.2.0 + dev: false + /fflate@0.7.4: resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==} dev: true @@ -2954,6 +3102,15 @@ packages: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} dev: false + /fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: false + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -2996,6 +3153,11 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: false + /get-func-name@2.0.0: resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} dev: true @@ -3008,6 +3170,13 @@ packages: has-proto: 1.0.1 has-symbols: 1.0.3 + /get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + dependencies: + pump: 3.0.0 + dev: false + /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -3021,6 +3190,18 @@ packages: get-intrinsic: 1.2.1 dev: true + /get-uri@6.0.2: + resolution: {integrity: sha512-5KLucCJobh8vBY1K07EFV4+cPZH3mrV9YeAruUseCQKHB58SGjjT2l9/eA9LD082IiuMjSlFJEcdJ27TXvbZNw==} + engines: {node: '>= 14'} + dependencies: + basic-ftp: 5.0.3 + data-uri-to-buffer: 6.0.1 + debug: 4.3.4(supports-color@5.5.0) + fs-extra: 8.1.0 + transitivePeerDependencies: + - supports-color + dev: false + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -3192,6 +3373,16 @@ packages: - supports-color dev: true + /http-proxy-agent@7.0.0: + resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + dev: false + /https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -3202,6 +3393,16 @@ packages: - supports-color dev: true + /https-proxy-agent@7.0.2: + resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + dev: false + /human-signals@4.3.1: resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} engines: {node: '>=14.18.0'} @@ -3237,7 +3438,6 @@ packages: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} @@ -3267,6 +3467,14 @@ packages: side-channel: 1.0.4 dev: true + /ip@1.1.8: + resolution: {integrity: sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==} + dev: false + + /ip@2.0.0: + resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} + dev: false + /is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -3285,7 +3493,6 @@ packages: /is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true /is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} @@ -3334,7 +3541,6 @@ packages: /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - dev: true /is-fullwidth-code-point@4.0.0: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} @@ -3526,7 +3732,6 @@ packages: hasBin: true dependencies: argparse: 2.0.1 - dev: true /jsdom@22.1.0: resolution: {integrity: sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==} @@ -3573,7 +3778,6 @@ packages: /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -3592,6 +3796,12 @@ packages: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} dev: true + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: false + /jsx-ast-utils@3.3.4: resolution: {integrity: sha512-fX2TVdCViod6HwKEtSWGHs57oFhVfCMwieb9PuRDgjDPh5XeqJiHFFFJCHxU5cnTc3Bu/GRL+kPiFmw8XWOfKw==} engines: {node: '>=4.0'} @@ -3639,7 +3849,6 @@ packages: /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true /lint-staged@13.2.3: resolution: {integrity: sha512-zVVEXLuQIhr1Y7R7YAWx4TZLdvuzk7DnmrsTNL0fax6Z3jrpFcas+vKbzxhhvp6TA55m1SQuWkpzI1qbfDZbAg==} @@ -3806,6 +4015,11 @@ packages: yallist: 4.0.0 dev: true + /lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + dev: false + /lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -3894,6 +4108,14 @@ packages: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: false + /mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + dev: false + + /mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + dev: false + /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -3940,6 +4162,11 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true + /netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + dev: false + /no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: @@ -3947,6 +4174,18 @@ packages: tslib: 2.6.0 dev: true + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + /node-releases@2.0.13: resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} @@ -4104,6 +4343,31 @@ packages: aggregate-error: 3.1.0 dev: true + /pac-proxy-agent@7.0.1: + resolution: {integrity: sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==} + engines: {node: '>= 14'} + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.0 + debug: 4.3.4(supports-color@5.5.0) + get-uri: 6.0.2 + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + pac-resolver: 7.0.0 + socks-proxy-agent: 8.0.2 + transitivePeerDependencies: + - supports-color + dev: false + + /pac-resolver@7.0.0: + resolution: {integrity: sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg==} + engines: {node: '>= 14'} + dependencies: + degenerator: 5.0.1 + ip: 1.1.8 + netmask: 2.0.2 + dev: false + /pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} dev: false @@ -4113,7 +4377,6 @@ packages: engines: {node: '>=6'} dependencies: callsites: 3.1.0 - dev: true /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} @@ -4123,7 +4386,6 @@ packages: error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - dev: true /parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} @@ -4157,7 +4419,6 @@ packages: /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true /pathe@1.1.1: resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} @@ -4167,6 +4428,10 @@ packages: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} dev: true + /pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + dev: false + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -4362,6 +4627,11 @@ packages: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: false + /progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + dev: false + /prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} dependencies: @@ -4373,6 +4643,22 @@ packages: resolution: {integrity: sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==} dev: false + /proxy-agent@6.3.1: + resolution: {integrity: sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4(supports-color@5.5.0) + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + lru-cache: 7.18.3 + pac-proxy-agent: 7.0.1 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.2 + transitivePeerDependencies: + - supports-color + dev: false + /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} dev: false @@ -4381,11 +4667,51 @@ packages: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: true + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} dev: true + /puppeteer-core@21.5.2: + resolution: {integrity: sha512-v4T0cWnujSKs+iEfmb8ccd7u4/x8oblEyKqplqKnJ582Kw8PewYAWvkH4qUWhitN3O2q9RF7dzkvjyK5HbzjLA==} + engines: {node: '>=16.13.2'} + dependencies: + '@puppeteer/browsers': 1.8.0 + chromium-bidi: 0.4.33(devtools-protocol@0.0.1203626) + cross-fetch: 4.0.0 + debug: 4.3.4(supports-color@5.5.0) + devtools-protocol: 0.0.1203626 + ws: 8.14.2 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + dev: false + + /puppeteer@21.5.2(typescript@5.1.6): + resolution: {integrity: sha512-BaAGJOq8Fl6/cck6obmwaNLksuY0Bg/lIahCLhJPGXBFUD2mCffypa4A592MaWnDcye7eaHmSK9yot0pxctY8A==} + engines: {node: '>=16.13.2'} + requiresBuild: true + dependencies: + '@puppeteer/browsers': 1.8.0 + cosmiconfig: 8.3.6(typescript@5.1.6) + puppeteer-core: 21.5.2 + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - typescript + - utf-8-validate + dev: false + /qs@6.11.2: resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} engines: {node: '>=0.6'} @@ -4401,6 +4727,10 @@ packages: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true + /queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + dev: false + /raf-schd@4.0.3: resolution: {integrity: sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==} dev: false @@ -4683,6 +5013,11 @@ packages: resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==} dev: false + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: false + /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: true @@ -4690,7 +5025,6 @@ packages: /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: true /resolve@1.22.2: resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} @@ -4900,6 +5234,11 @@ packages: is-fullwidth-code-point: 4.0.0 dev: true + /smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + dev: false + /snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} dependencies: @@ -4907,11 +5246,37 @@ packages: tslib: 2.6.0 dev: true + /socks-proxy-agent@8.0.2: + resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4(supports-color@5.5.0) + socks: 2.7.1 + transitivePeerDependencies: + - supports-color + dev: false + + /socks@2.7.1: + resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} + engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} + dependencies: + ip: 2.0.0 + smart-buffer: 4.2.0 + dev: false + /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} dev: true + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dev: false + optional: true + /stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -4934,6 +5299,13 @@ packages: internal-slot: 1.0.5 dev: true + /streamx@2.15.5: + resolution: {integrity: sha512-9thPGMkKC2GctCzyCUjME3yR03x2xNo0GPKGkRw2UMYN+gqWa9uqpyNWhmsNCutU5zHmkUum0LsCRQTXUgUCAg==} + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + dev: false + /string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -4946,7 +5318,6 @@ packages: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: true /string-width@5.1.2: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} @@ -5012,7 +5383,6 @@ packages: engines: {node: '>=8'} dependencies: ansi-regex: 5.0.1 - dev: true /strip-ansi@7.1.0: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} @@ -5172,6 +5542,14 @@ packages: - ts-node dev: true + /tar-fs@3.0.4: + resolution: {integrity: sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==} + dependencies: + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 3.1.6 + dev: false + /tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} @@ -5183,6 +5561,14 @@ packages: readable-stream: 3.6.2 dev: false + /tar-stream@3.1.6: + resolution: {integrity: sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==} + dependencies: + b4a: 1.6.4 + fast-fifo: 1.3.2 + streamx: 2.15.5 + dev: false + /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true @@ -5202,7 +5588,6 @@ packages: /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true /time-zone@1.0.0: resolution: {integrity: sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==} @@ -5268,6 +5653,10 @@ packages: url-parse: 1.5.10 dev: true + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + /tr46@4.1.1: resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} engines: {node: '>=14'} @@ -5306,7 +5695,6 @@ packages: /tslib@2.6.0: resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} - dev: true /tsutils@3.21.0(typescript@5.1.6): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} @@ -5387,7 +5775,6 @@ packages: resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} engines: {node: '>=14.17'} hasBin: true - dev: true /ufo@1.1.2: resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} @@ -5402,6 +5789,18 @@ packages: which-boxed-primitive: 1.0.2 dev: true + /unbzip2-stream@1.4.3: + resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} + dependencies: + buffer: 5.7.1 + through: 2.3.8 + dev: false + + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: false + /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} @@ -5445,6 +5844,10 @@ packages: requires-port: 1.0.0 dev: true + /urlpattern-polyfill@9.0.0: + resolution: {integrity: sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==} + dev: false + /use-memo-one@1.1.3(react@18.2.0): resolution: {integrity: sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==} peerDependencies: @@ -5623,6 +6026,10 @@ packages: xml-name-validator: 4.0.0 dev: true + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} @@ -5653,6 +6060,13 @@ packages: webidl-conversions: 7.0.0 dev: true + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: @@ -5716,7 +6130,6 @@ packages: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -5734,6 +6147,19 @@ packages: optional: true dev: true + /ws@8.14.2: + resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} + 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 + dev: false + /xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} @@ -5742,6 +6168,11 @@ packages: /xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: false + /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -5754,6 +6185,31 @@ packages: engines: {node: '>= 14'} dev: true + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: false + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: false + + /yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + dev: false + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} diff --git a/src/components/NavigationBar/index.tsx b/src/components/NavigationBar/index.tsx index c2c9d1e4..632b8416 100644 --- a/src/components/NavigationBar/index.tsx +++ b/src/components/NavigationBar/index.tsx @@ -5,6 +5,7 @@ import { events, sendEvent } from 'analytics'; import useAuth from '@hooks/auth/useAuth'; import useTutorial from '@hooks/ui/useTutorial'; import ROUTE from '@libs/constant/path'; +import { useNavigate } from 'react-router'; interface Props { isFold: boolean; @@ -19,6 +20,7 @@ const NavigationBar = ({ isFold, setIsFold }: Props) => { const { actions: { setMakeTutorial, setMemberTutorial, setRequestTutorial }, } = useTutorial(); + const navigate = useNavigate(); const handleResetTutorial = () => { console.log(window.location.pathname); @@ -73,7 +75,10 @@ const NavigationBar = ({ isFold, setIsFold }: Props) => {
가이드
-
+
navigate(ROUTE.PROFILE)} + > { + const { + state: { accountMe }, + actions: { handleGetAccountMe, handleLogout }, + } = useAuth(); + const { + queryKey: { getWardQueryKey }, + } = useEditWard(); + const { setLoading } = useLoading(); + const queryClient = useQueryClient(); + + const handleEditProfile = async (nurse: Nurse, profileImage: string) => { + if (!accountMe) return; + try { + setLoading(true); + updateNurse(nurse.nurseId, nurse); + await editAccount(accountMe.accountId, { + name: nurse.name, + profileImgBase64: profileImage, + }); + await queryClient.invalidateQueries(getWardQueryKey); + await handleGetAccountMe(); + } catch (e) { + console.error(e); + toast.error('프로필 업데이트에 실패했습니다..'); + } finally { + setLoading(false); + } + }; + + const quitWard = async () => { + if (!accountMe || !accountMe.wardId) return; + if (!confirm('정말 병동을 나가시겠습니까?')) return; + try { + setLoading(true); + await quitWardApi(accountMe.wardId); + await eidtAccountStatus(accountMe.accountId, 'WARD_SELECT_PENDING'); + await handleGetAccountMe(); + } catch (e) { + console.error(e); + toast.error('병동 나가기에 실패했습니다..'); + } finally { + setLoading(false); + } + }; + + const deleteAccount = async () => { + if (!accountMe) return; + if (!confirm('정말 탈퇴하시겠습니까?')) return; + try { + setLoading(true); + deleteAccountApi(accountMe.accountId); + handleLogout(); + } catch (e) { + console.error(e); + toast.error('계정 삭제에 실패했습니다..'); + } finally { + setLoading(false); + } + }; + + return { quitWard, handleEditProfile, deleteAccount }; +}; + +export default useEditAccount; diff --git a/src/hooks/auth/useAuth/index.ts b/src/hooks/auth/useAuth/index.ts index d0d07549..aeaf2a69 100644 --- a/src/hooks/auth/useAuth/index.ts +++ b/src/hooks/auth/useAuth/index.ts @@ -2,7 +2,7 @@ import { shallow } from 'zustand/shallow'; import useAuthStore from './store'; import axiosInstance from '@libs/api/client'; import { demoStart, getAccountMe } from '@libs/api/auth'; -import { useNavigate } from 'react-router'; +import { useLocation, useNavigate } from 'react-router'; import ROUTE from '@libs/constant/path'; import useInitStore from '@hooks/useInitStore'; import useEditShiftStore from '@hooks/shift/useEditShift/store'; @@ -36,6 +36,7 @@ const useAuth = (activeEffect = false) => { ], shallow ); + const { pathname } = useLocation(); const { setLoading } = useLoading(); const initStore = useInitStore(); const { initState: initEditShiftStore } = useEditShiftStore(); @@ -47,6 +48,7 @@ const useAuth = (activeEffect = false) => { const handleLogout = async () => { initStore(); sendEvent(events.auth.logut); + if (pathname !== ROUTE.ROOT) navigate(ROUTE.ROOT); }; const handleLogin = (accessToken: string, nextPageUrl?: string) => { @@ -83,7 +85,9 @@ const useAuth = (activeEffect = false) => { useEffect(() => { if (_loaded && activeEffect) { - handleGetAccountMe(); + if (demoStartDate && new Date(demoStartDate).getTime() + 3540000 - new Date().getTime() <= 0) + handleLogout(); + else handleGetAccountMe(); } }, [activeEffect, accessToken, _loaded]); diff --git a/src/hooks/shift/useCreateShift/indes.ts b/src/hooks/shift/useCreateShift/indes.ts new file mode 100644 index 00000000..2b04849e --- /dev/null +++ b/src/hooks/shift/useCreateShift/indes.ts @@ -0,0 +1,117 @@ +import useLoading from '@hooks/ui/useLoading'; +import useEditShift from '../useEditShift'; +import { match } from 'ts-pattern'; +import axiosInstance from '@libs/api/client'; +import { useQueryClient } from '@tanstack/react-query'; +import useAuth from '@hooks/auth/useAuth'; +import { updateShifts } from '@libs/api/shift'; +import toast from 'react-hot-toast'; + +function useCreateShift() { + const { setLoading } = useLoading(); + const { + queryKey: { shiftQueryKey }, + state: { year, month, shift, wardShiftTypeMap }, + } = useEditShift(); + const { + state: { wardId }, + } = useAuth(); + + const queryClient = useQueryClient(); + + const autoCompleteShift = async () => { + if (!shift || !wardShiftTypeMap || !wardId) return; + if ( + !confirm( + '근무표를 자동으로 채우시겠습니까?\n신청 근무를 최대한 반영한 채 채워집니다.\n총 2분~3분이 소요됩니다!' + ) + ) + return; + setLoading(true); + + try { + const duty = ( + await axiosInstance.post( + 'https://ml.dutying.net/duty/make', + { + names: shift.divisionShiftNurses + .flatMap((x) => x) + .map((row) => ({ + name: row.shiftNurse.name, + prev: ['0'].concat( + row.lastWardShiftList.map((shiftId) => { + return shiftId + ? match(wardShiftTypeMap.get(shiftId)?.shortName) + .with('D', () => '1') + .with('E', () => '2') + .with('N', () => '3') + .with('O', () => '4') + .otherwise(() => '0') + : '0'; + }) + ), + request: row.wardShiftList.map((shiftId) => { + return shiftId + ? match(wardShiftTypeMap.get(shiftId)?.shortName) + .with('D', () => '1') + .with('E', () => '2') + .with('N', () => '3') + .with('O', () => '4') + .otherwise(() => '0') + : '0'; + }), + })), + }, + { + withCredentials: false, + } + ) + ).data; + + if (!duty || !shift || !wardShiftTypeMap) return; + const flatNurses = shift.divisionShiftNurses.flatMap((x) => x); + const updateShiftPromises: Promise[] = []; + for (let i = 0; i < duty.length; i++) { + const wardShiftsDTO = []; + for (let j = 0; j < duty[i].length; j++) { + const row = flatNurses[i]; + const wardShiftType = + shift.wardShiftTypes.find((x) => { + return ( + x.shortName === + match(duty[i][j]) + .with('D', () => 'D') + .with('E', () => 'E') + .with('N', () => 'N') + .with('-', () => 'O') + .otherwise(() => null) + ); + }) || null; + if (!row || j + 1 > shift.days.length) continue; + + wardShiftsDTO.push({ + shiftNurseId: row.shiftNurse.shiftNurseId, + date: `${year}-${month.toString().padStart(2, '0')}-${(j + 1) + .toString() + .padStart(2, '0')}`, + wardShiftTypeId: wardShiftType === null ? null : wardShiftType.wardShiftTypeId, + }); + } + updateShiftPromises.push(updateShifts(wardId, wardShiftsDTO)); + } + await Promise.all(updateShiftPromises); + await queryClient.invalidateQueries(shiftQueryKey); + } catch (e) { + console.error(e); + toast.error('근무표 생성에 실패했습니다..'); + } finally { + setLoading(false); + } + }; + + return { + autoCompleteShift, + }; +} + +export default useCreateShift; diff --git a/src/hooks/shift/useEditShift/index.ts b/src/hooks/shift/useEditShift/index.ts index 4ed890bd..6c6a501c 100644 --- a/src/hooks/shift/useEditShift/index.ts +++ b/src/hooks/shift/useEditShift/index.ts @@ -19,6 +19,7 @@ import { import { getShiftTeams } from '@libs/api/shiftTeam'; import useAuth from '@hooks/auth/useAuth'; import useLoading from '@hooks/ui/useLoading'; +import toast from 'react-hot-toast'; const useEditShift = (activeEffect = false) => { const [ @@ -207,85 +208,6 @@ const useEditShift = (activeEffect = false) => { } ); - const { mutate: mutateShifts } = useMutation( - ({ wardId, wardShiftsDTO }: { wardId: number; wardShiftsDTO: WardShiftsDTO }) => - updateShifts(wardId, wardShiftsDTO), - { - onMutate: async ({ wardShiftsDTO }) => { - await queryClient.cancelQueries(['shift']); - const oldShift = queryClient.getQueryData(shiftQueryKey); - const oldEditHistory = editHistory; - const oldFocus = focus; - - if (!oldShift || !wardShiftTypeMap) return; - - const editList = wardShiftsDTO.map((eidtShift) => { - const nurse = findNurse(oldShift, eidtShift.shiftNurseId)!; - const focus = { - shiftNurseName: nurse.name, - shiftNurseId: nurse.shiftNurseId, - day: parseInt(eidtShift.date.split('-')[2]) - 1, - }; - const oldShiftTypeId = oldShift.divisionShiftNurses - .flatMap((x) => x) - .find((x) => x.shiftNurse.shiftNurseId === eidtShift.shiftNurseId)!.wardShiftList[ - focus.day - ]; - - return { - nurseName: nurse.name, - focus, - prevShiftType: - oldShiftTypeId !== null ? wardShiftTypeMap.get(oldShiftTypeId) || null : null, - nextShiftType: - eidtShift.wardShiftTypeId !== null - ? wardShiftTypeMap.get(eidtShift.wardShiftTypeId) || null - : null, - dateString: new Date().toLocaleString(), - }; - }); - - setState( - 'editHistory', - produce(oldEditHistory, (draft) => { - const histories = draft.get(year + ',' + month + ',' + currentShiftTeam!.shiftTeamId); - if (histories) { - histories.history = histories.history - .slice(0, histories.current + 1) - .concat(editList); - histories.current = histories.history.length - 1; - } else { - draft.set(year + ',' + month + ',' + currentShiftTeam!.shiftTeamId, { - current: editList.length - 1, - history: editList, - }); - } - }) - ); - - queryClient.setQueryData( - shiftQueryKey, - produce(oldShift, (draft) => { - wardShiftsDTO.forEach((wardShift) => { - draft.divisionShiftNurses - .flatMap((x) => x) - .find((x) => x.shiftNurse.shiftNurseId === wardShift.shiftNurseId)!.wardShiftList[ - parseInt(wardShift.date.split('-')[2]) - 1 - ] = wardShift.wardShiftTypeId; - }); - }) - ); - - return { oldShift, oldEditHistory, oldFocus }; - }, - onError: (_, __, context) => { - if (context === undefined || context.oldShift === undefined) return; - queryClient.setQueryData(shiftQueryKey, context.oldShift); - setState('editHistory', context.oldEditHistory); - }, - } - ); - const { mutate: mutateShiftsAndHistory } = useMutation( ({ wardId, @@ -505,36 +427,44 @@ const useEditShift = (activeEffect = false) => { const pasteShift = async () => { if (!wardId || !shift || !focus || !wardShiftTypeMap) return; - const shiftNameTable = (await navigator.clipboard.readText()) - .replace(/\r/g, '') - .split('\n') - .map((x) => x.split('\t')); - const wardShiftsDTO = []; - const flatNurses = shift.divisionShiftNurses.flatMap((x) => x); - const startNurseIndex = flatNurses.findIndex( - (x) => x.shiftNurse.shiftNurseId === focus.shiftNurseId - ); - for (let i = 0; i < shiftNameTable.length; i++) { - for (let j = 0; j < shiftNameTable[i].length; j++) { - const row = flatNurses[startNurseIndex + i]; - const wardShiftType = shift.wardShiftTypes.find((x) => { - return x.shortName === shiftNameTable[i][j]; - }); - if (!wardShiftType || !row || focus.day + j + 1 > shift.days.length) continue; - - wardShiftsDTO.push({ - shiftNurseId: row.shiftNurse.shiftNurseId, - date: `${year}-${month.toString().padStart(2, '0')}-${(focus.day + j + 1) - .toString() - .padStart(2, '0')}`, - wardShiftTypeId: wardShiftType.wardShiftTypeId, - }); + setLoading(true); + try { + const shiftNameTable = (await navigator.clipboard.readText()) + .replace(/\r/g, '') + .split('\n') + .map((x) => x.split('\t')); + const updateShiftPromises: Promise[] = []; + const flatNurses = shift.divisionShiftNurses.flatMap((x) => x); + const startNurseIndex = flatNurses.findIndex( + (x) => x.shiftNurse.shiftNurseId === focus.shiftNurseId + ); + for (let i = 0; i < shiftNameTable.length; i++) { + const wardShiftsDTO = []; + for (let j = 0; j < shiftNameTable[i].length; j++) { + const row = flatNurses[startNurseIndex + i]; + const wardShiftType = shift.wardShiftTypes.find((x) => { + return x.shortName === shiftNameTable[i][j]; + }); + if (!wardShiftType || !row || focus.day + j + 1 > shift.days.length) continue; + + wardShiftsDTO.push({ + shiftNurseId: row.shiftNurse.shiftNurseId, + date: `${year}-${month.toString().padStart(2, '0')}-${(focus.day + j + 1) + .toString() + .padStart(2, '0')}`, + wardShiftTypeId: wardShiftType.wardShiftTypeId, + }); + } + updateShiftPromises.push(updateShifts(wardId, wardShiftsDTO)); } + await Promise.all(updateShiftPromises); + await queryClient.invalidateQueries(shiftQueryKey); + } catch (e) { + console.error(e); + toast.error('붙여넣기에 실패했습니다..'); + } finally { + setLoading(false); } - mutateShifts({ - wardId, - wardShiftsDTO, - }); }; const handleKeyDown = useCallback( diff --git a/src/hooks/ward/useEditWard/index.ts b/src/hooks/ward/useEditWard/index.ts index 1a24ff29..d0116c63 100644 --- a/src/hooks/ward/useEditWard/index.ts +++ b/src/hooks/ward/useEditWard/index.ts @@ -164,6 +164,10 @@ const useEditWard = () => { }; return { + queryKey: { + getWardQueryKey, + getWardWaitingNursesQueryKey, + }, state: { ward, watingNurses, diff --git a/src/libs/api/account.ts b/src/libs/api/account.ts index f14fbfef..87bab9bb 100644 --- a/src/libs/api/account.ts +++ b/src/libs/api/account.ts @@ -19,4 +19,14 @@ const initAccount = async (accountId: number, name: string, profileImgBase64: st (await axiosInstance.patch(`/accounts/${accountId}/init`, { name, profileImgBase64 })) .data; -export { getAccount, getAccountMeWaiting, editAccount, eidtAccountStatus, initAccount }; +const deleteAccount = async (accountId: number) => + (await axiosInstance.delete(`/accounts/${accountId}`)).data; + +export { + getAccount, + getAccountMeWaiting, + editAccount, + eidtAccountStatus, + initAccount, + deleteAccount, +}; diff --git a/src/libs/api/nurse.ts b/src/libs/api/nurse.ts index c4db9fe4..10929253 100644 --- a/src/libs/api/nurse.ts +++ b/src/libs/api/nurse.ts @@ -10,6 +10,7 @@ const createAccountNurse = async (accountId: number, createNurse: CreateNurseDTO await axiosInstance.post(`/nurses?accountId=${accountId}`, { ...createNurse, phoneNum: createNurse.phoneNum.replace(/-+/g, ''), + employmentDate: createNurse.employmentDate.replace(/-/g, ''), }) ).data; diff --git a/src/libs/api/ward.ts b/src/libs/api/ward.ts index 6bb49b4b..508751c1 100644 --- a/src/libs/api/ward.ts +++ b/src/libs/api/ward.ts @@ -63,6 +63,9 @@ const approveWatingNurses = async (wardId: number, waitingNurseId: number, shift const deleteWatingNurses = async (wardId: number, nurseId: number) => (await axiosInstance.delete(`/wards/${wardId}/waiting-nurses?nurseId=${nurseId}`)).data; +const quitWard = async (wardId: number) => + (await axiosInstance.delete(`/wards/${wardId}/quit`)).data; + export { getWardConstraint, updateWardConstraint, @@ -75,4 +78,5 @@ export { connectWatingNurses, approveWatingNurses, deleteWatingNurses, + quitWard, }; diff --git a/src/libs/constant/path.ts b/src/libs/constant/path.ts index f1c1655d..4014f12b 100644 --- a/src/libs/constant/path.ts +++ b/src/libs/constant/path.ts @@ -7,10 +7,10 @@ const ROUTE = { REFRESH: '/refresh', REDIRECT: '/oauth2/redirect', ONBOARDING: '/onboarding', - HOME: '/home', MAKE: '/make', REQUEST: '/request', MEMBER: '/member', + PROFILE: '/profile', }; export default ROUTE; diff --git a/src/pages/MakeShiftPage/components/NurseEditModal.tsx b/src/pages/MakeShiftPage/components/NurseEditModal.tsx index f4b6a3fe..f1d0e8f7 100644 --- a/src/pages/MakeShiftPage/components/NurseEditModal.tsx +++ b/src/pages/MakeShiftPage/components/NurseEditModal.tsx @@ -90,6 +90,7 @@ function NurseEditModal() { { handleChange('employmentDate', e.target.value); sendEvent(events.makePage.editNurseModal.changeNurseEmploymentDate); diff --git a/src/pages/MemberPage/components/NurseEditDrawer.tsx b/src/pages/MemberPage/components/NurseEditDrawer.tsx index 813e2adf..edd00765 100644 --- a/src/pages/MemberPage/components/NurseEditDrawer.tsx +++ b/src/pages/MemberPage/components/NurseEditDrawer.tsx @@ -87,6 +87,7 @@ function NurseEditDrawer() { { handleChange('employmentDate', e.target.value); sendEvent(events.memberPage.editNurseDrawer.changeNurseEmploymentDate); diff --git a/src/pages/ProfilePage/index.tsx b/src/pages/ProfilePage/index.tsx new file mode 100644 index 00000000..2b8b2f44 --- /dev/null +++ b/src/pages/ProfilePage/index.tsx @@ -0,0 +1,290 @@ +import { CameraIcon, CheckedIcon, RandomIcon, UncheckedIcon } from '@assets/svg'; +import TextField from '@components/TextField'; +import Button from '@components/Button'; +import Select from '@components/Select'; +import { profileImages } from '@assets/profileImage'; +import { ChangeEvent, useEffect, useRef, useState } from 'react'; +import imageCompression from 'browser-image-compression'; +import useAuth from '@hooks/auth/useAuth'; +import useEditShiftTeam from '@hooks/ward/useEditShiftTeam'; +import useEditAccount from '@hooks/account/useEditAccount'; + +function ProfilePage() { + const { + state: { shiftTeams, selectedNurse }, + actions: { selectNurse }, + } = useEditShiftTeam(); + const { + state: { accountMe }, + actions: { handleLogout }, + } = useAuth(); + const { handleEditProfile, deleteAccount, quitWard } = useEditAccount(); + + const [writeNurse, setWriteNurse] = useState(null); + const [profileImage, setProfileImage] = useState( + profileImages[Math.floor(Math.random() * 30)] + ); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const handleChange = (key: keyof Nurse, value: any) => { + if (!writeNurse) return; + setWriteNurse({ ...writeNurse, [key]: value }); + }; + + const save = () => { + writeNurse && profileImage && handleEditProfile(writeNurse, profileImage); + }; + + useEffect(() => { + if (shiftTeams && accountMe) + selectNurse( + shiftTeams.flatMap((x) => x.nurses).find((x) => x.accountId === accountMe.accountId) + ?.nurseId || null + ); + }, [accountMe, shiftTeams]); + + useEffect(() => { + console.log(selectedNurse, accountMe); + if (selectedNurse && accountMe && selectedNurse?.accountId === accountMe?.accountId) { + setWriteNurse(selectedNurse); + setProfileImage(accountMe.profileImgBase64); + } + }, [selectedNurse, accountMe]); + + const handleRandomProfileImage = () => { + setProfileImage(profileImages[Math.floor(Math.random() * 30)]); + }; + + const imageInputRef = useRef(null); + + const handleUploadImgae = () => { + imageInputRef.current && imageInputRef.current.click(); + }; + + const handleChangeImage = async (e: ChangeEvent) => { + if (!e.target.files || e.target.files.length < 1) return; + const options = { + maxSizeMB: 1, + maxWidthOrHeight: 1920, + useWebWorker: true, + }; + try { + const compressedFile = await imageCompression(e.target.files[0], options); + const base64Image = await convertBase64(compressedFile); + setProfileImage(base64Image.replace(/data.*;base64,/, '')); + } catch (error) { + console.log(error); + } + }; + + const convertBase64 = (file: File): Promise => { + return new Promise((resolve, reject) => { + const fileReader = new FileReader(); + fileReader.readAsDataURL(file); + fileReader.onload = () => { + resolve(fileReader.result as string); + }; + fileReader.onerror = (error) => { + reject(error); + }; + }); + }; + + return ( +
+
+

프로필 설정

+ +
+
+
+
프로필 이미지
+
+ +
+
+
+ +

랜덤 변경

+
+
+ +

사진 등록

+ +
+
+
+
+
+ + handleChange('name', e.target.value)} + // error={match(errors.name?.type) + // .with( + // 'matches', + // () => '이름은 1~50자 한/영문에 숫자나 특수문자를 사용할 수 없습니다.' + // ) + // .otherwise(() => undefined)} + /> +
+
+
+ +