diff --git a/package-lock.json b/package-lock.json
index 5114fa3..d0507ec 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -27,6 +27,7 @@
"react-dom": "^18.2.0",
"react-error-boundary": "^6.0.0",
"react-icons": "^5.4.0",
+ "recharts": "^3.1.2",
"type-hangul": "^0.2.4"
},
"devDependencies": {
@@ -6306,6 +6307,32 @@
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
}
},
+ "node_modules/@reduxjs/toolkit": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.9.0.tgz",
+ "integrity": "sha512-fSfQlSRu9Z5yBkvsNhYF2rPS8cGXn/TZVrlwN1948QyZ8xMZ0JvP50S2acZNaf+o63u6aEeMjipFyksjIcWrog==",
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.0.0",
+ "@standard-schema/utils": "^0.3.0",
+ "immer": "^10.0.3",
+ "redux": "^5.0.1",
+ "redux-thunk": "^3.1.0",
+ "reselect": "^5.1.0"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0 || ^18 || ^19",
+ "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@rtsao/scc": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
@@ -6341,6 +6368,18 @@
"integrity": "sha512-vPJ8Tn4uebnHa6scBcIypW154HTDenkazX9Nw8T1na44n7OtLoz40R4RoirteV7taPWW7w7ZZPCiEpi2ReYFAQ==",
"license": "MIT"
},
+ "node_modules/@standard-schema/spec": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz",
+ "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==",
+ "license": "MIT"
+ },
+ "node_modules/@standard-schema/utils": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz",
+ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==",
+ "license": "MIT"
+ },
"node_modules/@studio-freight/lenis": {
"version": "1.0.42",
"resolved": "https://registry.npmjs.org/@studio-freight/lenis/-/lenis-1.0.42.tgz",
@@ -6401,6 +6440,69 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@types/d3-array": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
+ "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-ease": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-interpolate": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
+ "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
+ "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz",
+ "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
+ "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==",
+ "license": "MIT"
+ },
+ "node_modules/@types/d3-timer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
+ "license": "MIT"
+ },
"node_modules/@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -6437,12 +6539,18 @@
"version": "19.1.5",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.5.tgz",
"integrity": "sha512-piErsCVVbpMMT2r7wbawdZsq4xMvIAhQuac2gedQHysu1TZYEigE6pnFfgZT+/jQnrRuF5r+SHzuehFjfRjr4g==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"csstype": "^3.0.2"
}
},
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
+ "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
+ "license": "MIT"
+ },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.32.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz",
@@ -7603,9 +7711,130 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
+ "node_modules/d3-array": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+ "license": "ISC",
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-path": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+ "license": "ISC",
+ "dependencies": {
+ "d3-time": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -7691,6 +7920,12 @@
"integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==",
"license": "MIT"
},
+ "node_modules/decimal.js-light": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
+ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
+ "license": "MIT"
+ },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -7983,6 +8218,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/es-toolkit": {
+ "version": "1.39.10",
+ "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.10.tgz",
+ "integrity": "sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w==",
+ "license": "MIT",
+ "workspaces": [
+ "docs",
+ "benchmarks"
+ ]
+ },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -8444,6 +8689,12 @@
"node": ">=0.10.0"
}
},
+ "node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "license": "MIT"
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -8999,6 +9250,16 @@
"node": ">= 4"
}
},
+ "node_modules/immer": {
+ "version": "10.1.3",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.3.tgz",
+ "integrity": "sha512-tmjF/k8QDKydUlm3mZU+tjM6zeq9/fFpPqH9SzWmBnVVKsPBg/V66qsMwb3/Bo90cgUN+ghdVBess+hPsxUyRw==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -9070,6 +9331,15 @@
"node": ">= 0.4"
}
},
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/intl-messageformat": {
"version": "10.7.16",
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.16.tgz",
@@ -10573,9 +10843,31 @@
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true,
"license": "MIT"
},
+ "node_modules/react-redux": {
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
+ "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/use-sync-external-store": "^0.0.6",
+ "use-sync-external-store": "^1.4.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^18.2.25 || ^19",
+ "react": "^18.0 || ^19",
+ "redux": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-textarea-autosize": {
"version": "8.5.9",
"resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz",
@@ -10614,6 +10906,57 @@
"node": ">=8.10.0"
}
},
+ "node_modules/recharts": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.1.2.tgz",
+ "integrity": "sha512-vhNbYwaxNbk/IATK0Ki29k3qvTkGqwvCgyQAQ9MavvvBwjvKnMTswdbklJpcOAoMPN/qxF3Lyqob0zO+ZXkZ4g==",
+ "license": "MIT",
+ "dependencies": {
+ "@reduxjs/toolkit": "1.x.x || 2.x.x",
+ "clsx": "^2.1.1",
+ "decimal.js-light": "^2.5.1",
+ "es-toolkit": "^1.39.3",
+ "eventemitter3": "^5.0.1",
+ "immer": "^10.1.1",
+ "react-redux": "8.x.x || 9.x.x",
+ "reselect": "5.1.1",
+ "tiny-invariant": "^1.3.3",
+ "use-sync-external-store": "^1.2.2",
+ "victory-vendor": "^37.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/recharts/node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/redux": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
+ "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
+ "license": "MIT"
+ },
+ "node_modules/redux-thunk": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz",
+ "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "redux": "^5.0.0"
+ }
+ },
"node_modules/reflect.getprototypeof": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -10658,6 +11001,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/reselect": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz",
+ "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==",
+ "license": "MIT"
+ },
"node_modules/resolve": {
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
@@ -11525,6 +11874,12 @@
"node": ">=0.8"
}
},
+ "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==",
+ "license": "MIT"
+ },
"node_modules/tinyglobby": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
@@ -11861,12 +12216,43 @@
}
}
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
+ "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"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==",
"license": "MIT"
},
+ "node_modules/victory-vendor": {
+ "version": "37.3.6",
+ "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz",
+ "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==",
+ "license": "MIT AND ISC",
+ "dependencies": {
+ "@types/d3-array": "^3.0.3",
+ "@types/d3-ease": "^3.0.0",
+ "@types/d3-interpolate": "^3.0.1",
+ "@types/d3-scale": "^4.0.2",
+ "@types/d3-shape": "^3.1.0",
+ "@types/d3-time": "^3.0.0",
+ "@types/d3-timer": "^3.0.0",
+ "d3-array": "^3.1.6",
+ "d3-ease": "^3.0.1",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "d3-shape": "^3.1.0",
+ "d3-time": "^3.0.0",
+ "d3-timer": "^3.0.1"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index 9ac79aa..dd6956f 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"react-dom": "^18.2.0",
"react-error-boundary": "^6.0.0",
"react-icons": "^5.4.0",
+ "recharts": "^3.1.2",
"type-hangul": "^0.2.4"
},
"devDependencies": {
diff --git a/src/app/admin/page.jsx b/src/app/admin/page.jsx
index 59c75dc..d9b708a 100644
--- a/src/app/admin/page.jsx
+++ b/src/app/admin/page.jsx
@@ -8,6 +8,7 @@ import UserDetailsModal from '@/components/admin/UserDetailsModal';
import AdminTableCell from '@/components/admin/AdminTableCell';
import AdminTableTopContent from '@/components/admin/AdminTableTopContent';
import AdminTableBottomContent from '@/components/admin/AdminTableBottomContent';
+import AdminDashboard from '@/components/admin/AdminDashboard';
import { useAuthenticatedApi } from '@/hooks/useAuthenticatedApi';
@@ -36,6 +37,12 @@ export default function Page() {
const [totalUsers, setTotalUsers] = React.useState(0);
const [totalPages, setTotalPages] = React.useState(0);
+ // 대시보드 통계용 전체 멤버 데이터
+ const [statsUsers, setStatsUsers] = React.useState([]);
+ const [statsTotal, setStatsTotal] = React.useState(0);
+ const [statsLoading, setStatsLoading] = React.useState(false);
+ const [statsError, setStatsError] = React.useState('');
+
const rowsPerPage = 10; //한 페이지당 표시될 유저 수
//유저 데이터 조회
@@ -67,6 +74,45 @@ export default function Page() {
}
}, [apiClient, page, rowsPerPage, query]);
+ // 통계용 전체 멤버 데이터 조회 (페이지네이션 병렬 수집)
+ const fetchAllUsersForStats = useCallback(async () => {
+ setStatsLoading(true);
+ setStatsError('');
+ try {
+ const pageSize = 200;
+ const baseParams = { size: pageSize, sort: 'createdAt', dir: 'DESC' };
+
+ const firstRes = await apiClient.get('/recruit/members', { params: { ...baseParams, page: 0 } });
+ const firstList = Array.isArray(firstRes?.data?.data) ? firstRes.data.data : [];
+ const total = firstRes?.data?.meta?.totalElements ?? firstList.length;
+ const totalPagesForStats = Math.max(1, Math.ceil(total / pageSize));
+
+ let all = firstList;
+ if (totalPagesForStats > 1) {
+ const promises = [];
+ for (let p = 1; p < totalPagesForStats; p++) {
+ promises.push(apiClient.get('/recruit/members', { params: { ...baseParams, page: p } }));
+ }
+ const results = await Promise.allSettled(promises);
+ results.forEach((res) => {
+ if (res.status === 'fulfilled') {
+ const list = Array.isArray(res.value?.data?.data) ? res.value.data.data : [];
+ all = all.concat(list);
+ }
+ });
+ }
+
+ setStatsUsers(all);
+ setStatsTotal(total);
+ } catch (e) {
+ setStatsUsers([]);
+ setStatsTotal(0);
+ setStatsError(String(e?.message || 'failed to load stats'));
+ } finally {
+ setStatsLoading(false);
+ }
+ }, [apiClient]);
+
//회비 지불여부 체크박스
const handleTogglePay = useCallback(
async (userId, nextValue) => {
@@ -159,11 +205,15 @@ export default function Page() {
fetchUsers();
}, [fetchUsers]);
+ useEffect(() => {
+ fetchAllUsersForStats();
+ }, [fetchAllUsersForStats]);
+
return (
<>
@@ -197,7 +247,7 @@ export default function Page() {
>
{(item) => (
handleRowClick(item)}
>
@@ -212,6 +262,15 @@ export default function Page() {
+
+ {/* 대시보드 */}
+ {/* {statsError ? (
+
대시보드 로드 실패: {statsError}
+ ) : statsLoading ? (
+
대시보드 불러오는 중...
+ ) : (
+
+ )} */}
>
);
diff --git a/src/app/core-recruit/layout.js b/src/app/core-recruit/layout.js
new file mode 100644
index 0000000..10272c4
--- /dev/null
+++ b/src/app/core-recruit/layout.js
@@ -0,0 +1,17 @@
+import { Suspense } from "react";
+import Loader from '@/components/ui/common/Loader.jsx';
+
+export const metadata = {
+ title: "Core Recruit",
+ description: "GDGoC INHA Core Member Recruitment Form",
+};
+
+export default function CoreRecruitLayout({ children }) {
+ return (
+ }>
+ {children}
+
+ );
+}
+
+
diff --git a/src/app/core-recruit/page.jsx b/src/app/core-recruit/page.jsx
new file mode 100644
index 0000000..e791ee5
--- /dev/null
+++ b/src/app/core-recruit/page.jsx
@@ -0,0 +1,497 @@
+"use client";
+
+import { useState, useMemo } from "react";
+import { useRouter } from 'next/navigation';
+import { Button, Textarea, Input, Checkbox, Autocomplete, AutocompleteItem, AutocompleteSection } from '@nextui-org/react';
+import axios from 'axios';
+import { majorOptions } from '@/constant/majorOptions';
+
+const TEAM_OPTIONS = ["HR", "BD", "TECH", "PR/DESIGN"];
+
+export default function CoreRecruit() {
+ const router = useRouter();
+ const [form, setForm] = useState({
+ name: "",
+ studentId: "",
+ phone: "",
+ major: "",
+ email: "",
+ team: "",
+ motivation: "",
+ wish: "",
+ strengths: "",
+ pledge: "",
+ });
+
+ const [files, setFiles] = useState([]);
+ const [uploadedFileUrls, setUploadedFileUrls] = useState([]);
+ const [uploading, setUploading] = useState(false);
+ const [submitting, setSubmitting] = useState(false);
+ const [touched, setTouched] = useState(false);
+
+ const handleValueChange = (key) => (value) => {
+ setForm((prev) => ({ ...prev, [key]: value }));
+ };
+
+ const handlePreventEnter = (event) => {
+ if (event.key === 'Enter') {
+ event.preventDefault();
+ }
+ };
+
+ const handleFiles = async (e) => {
+ const selected = Array.from(e.target.files || []);
+ const limited = selected.slice(0, 10);
+ const filtered = limited.filter((f) => f.size <= 10 * 1024 * 1024);
+ setFiles(filtered);
+ setUploadedFileUrls([]);
+ if (filtered.length === 0) return;
+ try {
+ setUploading(true);
+ const urls = await Promise.all(
+ filtered.map(async (file) => {
+ try {
+ const formData = new FormData();
+ formData.append('file', file);
+ const res = await axios.post(`${process.env.NEXT_PUBLIC_BASE_API_URL}/fileupload`, formData, {
+ headers: { 'Content-Type': 'multipart/form-data' },
+ });
+ const data = res?.data;
+ const url = data?.url || data?.data?.url || data?.data?.[0]?.url || null;
+ return url;
+ } catch (err) {
+ console.error('파일 업로드 실패:', file?.name, err);
+ return null;
+ }
+ })
+ );
+ const successUrls = urls.filter((u) => !!u);
+ setUploadedFileUrls(successUrls);
+ if (successUrls.length !== filtered.length) {
+ alert('일부 파일 업로드에 실패했습니다. 다시 시도해주세요.');
+ }
+ } catch (err) {
+ console.error('파일 업로드 중 오류', err);
+ alert('파일 업로드 중 오류가 발생했습니다.');
+ } finally {
+ setUploading(false);
+ }
+ };
+
+ const isValid = useMemo(() => {
+ if (!form.name || !form.studentId || !form.phone || !form.major || !form.email) return false;
+ if (!form.team) return false;
+ if (!form.motivation || form.motivation.length > 500) return false;
+ if (!form.wish || form.wish.length > 500) return false;
+ if (!form.pledge || form.pledge.length > 100) return false;
+ if (files.some((f) => f.size > 10 * 1024 * 1024) || files.length > 10) return false;
+ if (files.length > 0 && uploadedFileUrls.length !== files.length) return false;
+ return true;
+ }, [form, files, uploadedFileUrls]);
+
+ const handleSubmit = async () => {
+ setTouched(true);
+ if (!isValid) {
+ alert("필수 항목을 확인해주세요.");
+ return;
+ }
+ try {
+ setSubmitting(true);
+ const payload = {
+ ...form,
+ files: (files || []).map((f) => ({ name: f.name, size: f.size, type: f.type })),
+ fileUrls: uploadedFileUrls,
+ };
+ console.log('[CoreRecruit Submit]', payload);
+ await axios.post(`${process.env.NEXT_PUBLIC_BASE_API_URL}/core-recruit`, payload, {
+ headers: { 'Content-Type': 'application/json' },
+ });
+ router.push('/core-recruit/submit');
+ } catch (e) {
+ alert("제출 중 오류가 발생했습니다. 다시 시도해주세요.");
+ } finally {
+ setSubmitting(false);
+ }
+ };
+
+ return (
+
+
+ {/* 구글 로고 - 커스텀 그라데이션 적용 */}
+
+ GDGoC INHA Core Member 지원
+
+
+
+
+
{
+ const num = (value || '').replace(/\D/g, '').slice(0, 8);
+ setForm((prev) => ({ ...prev, studentId: num }));
+ }}
+ variant='bordered'
+ autoComplete='off'
+ labelPlacement='outside'
+ placeholder='8자리 학번을 입력해주세요'
+ inputMode='numeric'
+ disableAutoFocus
+ className='!mt-[10px]'
+ classNames={{
+ mainWrapper: 'h-[57px] w-full',
+ label: '!text-white text-xl pb-[18px] mobile:text-lg',
+ inputWrapper: `h-[57px] border-[1.5px] rounded-md text-white text-xl mobile:text-lg !border-[#bbbbbb30] group-data-[focus=true]:!border-[#bbbbbb30] group-data-[hover=true]:!border-[#bbbbbb30]`,
+ input: 'text-lg mobile:text-base',
+ errorMessage: 'hidden',
+ }}
+ />
+
+
+
setForm((prev) => ({ ...prev, major: value }))}
+ >
+ {majorOptions.map((major) => (
+
+ {major.items.map((item) => (
+
+ {item.value}
+
+ ))}
+
+ ))}
+
+
+
+
+
+
팀
+
+ {TEAM_OPTIONS.map((label) => (
+ setForm((prev) => ({ ...prev, team: label }))}
+ radius='none'
+ classNames={{
+ wrapper: 'hidden',
+ label: `text-white text-xl w-[150px] h-[57px] flex justify-center items-center rounded-md mobile:text-base mobile:w-[27vw] mobile:h-[49px] ${form.team === label ? 'bg-[#471915] border-[1.5px] border-[#ea4335]' : 'bg-[#181818]'}`,
+ }}
+ >
+ {label}
+
+ ))}
+
+
+
+
+
+
+ {touched && (!form.motivation || form.motivation.length > 500) && (
+ 필수 입력이며 500자 이내로 작성해주세요.
+ )}
+
+
+
+
+
+ {touched && (!form.wish || form.wish.length > 500) && (
+ 필수 입력이며 500자 이내로 작성해주세요.
+ )}
+
+
+
+
+
+
+ 예시: 리더십/꼼꼼함/성실함, 자격증, 스킬, 툴(피그마/노션), 수상/대외활동/인턴 등
+
+
+
+
+
+
+ {files.length > 0 && (
+
선택된 파일: {files.length}개
+ )}
+ {touched && (files.length > 10 || files.some((f)=> f.size > 10 * 1024 * 1024)) && (
+
파일 개수/크기 제한을 확인해주세요.
+ )}
+
+
+
+
+
+ {touched && (!form.pledge || form.pledge.length > 100) && (
+ 필수 입력이며 100자 이내로 작성해주세요.
+ )}
+
+
+
+
마지막으로 일정을 확인해주시기 바랍니다!
+
+
코어멤버 모집 안내
+
✅ 서류 지원 기간 : 2025년 09월 8일 (월) - 2025년 09월 12일 (금) 23:59:59
+
✅ 서류 결과 발표 : ~ 2025년 09월 14일 (일)
+
✅ 면접 진행 기간 : 2025년 09월 15일 (월) - 2025년 09월 19일 (금)
+
✅ 최종 결과 발표 : ~ 2025년 09월 21일 (일)
+
※ 면접은 지원자와 면접관의 일정에 따라 조정되며, 인하대학교 내부 장소에서 진행됩니다.
+
※ 면접은 대면을 원칙으로 하며, 부득이한 경우에만 비대면으로 진행됩니다.
+
❗️운영진으로 활동 시, 매주 화요일 19:00~21:00 정기 운영진 회의에 반드시 참석해야 합니다.
+
+
+
+
+
+
+
+
+
+ );
+}
+
+
diff --git a/src/app/core-recruit/submit/page.jsx b/src/app/core-recruit/submit/page.jsx
new file mode 100644
index 0000000..d0f2a1f
--- /dev/null
+++ b/src/app/core-recruit/submit/page.jsx
@@ -0,0 +1,48 @@
+"use client";
+
+import { useState, useEffect } from 'react';
+import { useRouter } from 'next/navigation';
+import { Button } from "@nextui-org/react";
+
+export default function CoreRecruitSubmit() {
+ const router = useRouter();
+ const [checkMotion, setCheckMotion] = useState(false);
+
+ useEffect(() => {
+ const timer = setTimeout(() => setCheckMotion(true), 50);
+ return () => clearTimeout(timer);
+ }, []);
+
+ return (
+
+
+
+ ✓
+
+
+
코어 멤버 지원서 제출이 완료되었습니다.
+
+
+
아래 일정과 안내를 한번더 확인해주세요!
+
✅ 서류 지원 기간 : 2025년 09월 8일 (월) - 2025년 09월 12일 (금) 23:59:59
+
✅ 서류 결과 발표 : ~ 2025년 09월 14일 (일)
+
✅ 면접 진행 기간 : 2025년 09월 15일 (월) - 2025년 09월 19일 (금)
+
✅ 최종 결과 발표 : ~ 2025년 09월 21일 (일)
+
※ 면접은 지원자와 면접관의 일정에 따라 조정되며, 인하대학교 내부 장소에서 진행됩니다.
+
※ 면접은 대면을 원칙으로 하며, 부득이한 경우에만 비대면으로 진행됩니다.
+
❗️운영진으로 활동 시, 매주 화요일 19:00~21:00 정기 운영진 회의에 반드시 참석해야 합니다.
+
+
+
+
+
+
+
+ );
+}
+
+
diff --git a/src/components/admin/AdminDashboard.jsx b/src/components/admin/AdminDashboard.jsx
new file mode 100644
index 0000000..6ee70e5
--- /dev/null
+++ b/src/components/admin/AdminDashboard.jsx
@@ -0,0 +1,210 @@
+'use client';
+
+import React, { useMemo } from 'react';
+import {
+ ResponsiveContainer,
+ PieChart,
+ Pie,
+ Cell,
+ BarChart,
+ Bar,
+ XAxis,
+ YAxis,
+ Tooltip,
+ Legend,
+ CartesianGrid,
+} from 'recharts';
+
+const COLORS = ['#8884d8', '#82ca9d', '#FF8042', '#FFBB28', '#00C49F', '#0088FE'];
+
+function normalizeMembers(rawMembers = []) {
+ return rawMembers.map((u) => ({
+ id: u?.id ?? u?.member?.id,
+ name: u?.name ?? u?.member?.name ?? '',
+ major: u?.major ?? u?.member?.major ?? u?.member?.majors?.main ?? '기타',
+ admissionSemester: u?.admissionSemester ?? u?.member?.admissionSemester ?? '미상',
+ studentId: String(u?.studentId ?? u?.member?.studentId ?? ''),
+ isPayed: typeof (u?.isPayed ?? u?.member?.isPayed) === 'boolean' ? (u?.isPayed ?? u?.member?.isPayed) : false,
+ createdAt: u?.createdAt ?? u?.member?.createdAt ?? null,
+ }));
+}
+
+function buildSemesterData(members) {
+ const map = new Map();
+ members.forEach((m) => {
+ const key = m.admissionSemester || '미상';
+ map.set(key, (map.get(key) || 0) + 1);
+ });
+ const arr = Array.from(map.entries())
+ .map(([name, value]) => ({ name, value }))
+ .sort((a, b) => b.value - a.value);
+ return arr;
+}
+
+function buildMajorTopData(members, topN = 5) {
+ const map = new Map();
+ members.forEach((m) => {
+ const key = m.major || '기타';
+ map.set(key, (map.get(key) || 0) + 1);
+ });
+ const arr = Array.from(map.entries())
+ .map(([name, value]) => ({ name, value }))
+ .sort((a, b) => b.value - a.value)
+ .slice(0, topN);
+ return arr;
+}
+
+function buildPaymentData(members) {
+ let paid = 0;
+ let unpaid = 0;
+ members.forEach((m) => (m.isPayed ? (paid += 1) : (unpaid += 1)));
+ return [
+ { name: '입금', value: paid },
+ { name: '미입금', value: unpaid },
+ ];
+}
+
+function buildSemesterPaymentStackData(members) {
+ const map = new Map();
+ members.forEach((m) => {
+ const key = m.admissionSemester || '미상';
+ const item = map.get(key) || { name: key, 입금: 0, 미입금: 0 };
+ if (m.isPayed) item['입금'] += 1;
+ else item['미입금'] += 1;
+ map.set(key, item);
+ });
+ return Array.from(map.values()).sort((a, b) => (b['입금'] + b['미입금']) - (a['입금'] + a['미입금']));
+}
+
+function buildStudentIdYearData(members) {
+ const map = new Map();
+ members.forEach((m) => {
+ const raw = m.studentId || '';
+ if (raw.length >= 4) {
+ const yy = raw.substring(2, 4);
+ if (/^\d{2}$/.test(yy)) {
+ const label = `${yy}학번`;
+ map.set(label, (map.get(label) || 0) + 1);
+ }
+ }
+ });
+ const arr = Array.from(map.entries()).map(([name, value]) => ({ name, value }));
+ arr.sort((a, b) => parseInt(b.name, 10) - parseInt(a.name, 10));
+ return arr;
+}
+
+export default function AdminDashboard({ members = [], totalCount }) {
+ const normalized = useMemo(() => normalizeMembers(members), [members]);
+
+ const semesterData = useMemo(() => buildSemesterData(normalized), [normalized]);
+ const majorTopData = useMemo(() => buildMajorTopData(normalized), [normalized]);
+ const paymentData = useMemo(() => buildPaymentData(normalized), [normalized]);
+ const semesterPaymentStack = useMemo(() => buildSemesterPaymentStackData(normalized), [normalized]);
+ const studentIdYearData = useMemo(() => buildStudentIdYearData(normalized), [normalized]);
+
+ const totalMembers = totalCount ?? normalized.length;
+ const paidCount = paymentData.find((d) => d.name === '입금')?.value ?? 0;
+ const paidRate = totalMembers ? Math.round((paidCount / totalMembers) * 100) : 0;
+ const topSemester = semesterData[0]?.name ?? '미상';
+ const topSemesterCount = semesterData[0]?.value ?? 0;
+
+ return (
+
+
+
+
총 멤버 수
+
{totalMembers}
+
+
+
+
최다 입학학기
+
{topSemester} ({topSemesterCount})
+
+
+
+
입학학기 분포
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
납부 현황
+
+
+
+
+ {paymentData.map((entry, index) => (
+ |
+ ))}
+
+
+
+
+
+
+
+
+
+
학번(입학년도) 분포
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
입학학기별 납부 상태 (Stacked)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
학과 Top 5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+
diff --git a/yarn.lock b/yarn.lock
index eeb5cf9..84a9e9d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2541,6 +2541,18 @@
"@react-types/overlays" "^3.8.11"
"@react-types/shared" "^3.26.0"
+"@reduxjs/toolkit@1.x.x || 2.x.x":
+ version "2.9.0"
+ resolved "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.9.0.tgz"
+ integrity sha512-fSfQlSRu9Z5yBkvsNhYF2rPS8cGXn/TZVrlwN1948QyZ8xMZ0JvP50S2acZNaf+o63u6aEeMjipFyksjIcWrog==
+ dependencies:
+ "@standard-schema/spec" "^1.0.0"
+ "@standard-schema/utils" "^0.3.0"
+ immer "^10.0.3"
+ redux "^5.0.1"
+ redux-thunk "^3.1.0"
+ reselect "^5.1.0"
+
"@rtsao/scc@^1.1.0":
version "1.1.0"
resolved "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz"
@@ -2568,6 +2580,16 @@
resolved "https://registry.npmjs.org/@splidejs/splide/-/splide-4.1.4.tgz"
integrity sha512-5I30evTJcAJQXt6vJ26g2xEkG+l1nXcpEw4xpKh0/FWQ8ozmAeTbtniVtVmz2sH1Es3vgfC4SS8B2X4o5JMptA==
+"@standard-schema/spec@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz"
+ integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==
+
+"@standard-schema/utils@^0.3.0":
+ version "0.3.0"
+ resolved "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz"
+ integrity sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==
+
"@studio-freight/lenis@^1.0.42":
version "1.0.42"
resolved "https://registry.npmjs.org/@studio-freight/lenis/-/lenis-1.0.42.tgz"
@@ -2611,6 +2633,57 @@
dependencies:
tslib "^2.4.0"
+"@types/d3-array@^3.0.3":
+ version "3.2.1"
+ resolved "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz"
+ integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==
+
+"@types/d3-color@*":
+ version "3.1.3"
+ resolved "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz"
+ integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==
+
+"@types/d3-ease@^3.0.0":
+ version "3.0.2"
+ resolved "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz"
+ integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==
+
+"@types/d3-interpolate@^3.0.1":
+ version "3.0.4"
+ resolved "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz"
+ integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==
+ dependencies:
+ "@types/d3-color" "*"
+
+"@types/d3-path@*":
+ version "3.1.1"
+ resolved "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz"
+ integrity sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==
+
+"@types/d3-scale@^4.0.2":
+ version "4.0.9"
+ resolved "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz"
+ integrity sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==
+ dependencies:
+ "@types/d3-time" "*"
+
+"@types/d3-shape@^3.1.0":
+ version "3.1.7"
+ resolved "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz"
+ integrity sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==
+ dependencies:
+ "@types/d3-path" "*"
+
+"@types/d3-time@*", "@types/d3-time@^3.0.0":
+ version "3.0.4"
+ resolved "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz"
+ integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==
+
+"@types/d3-timer@^3.0.0":
+ version "3.0.2"
+ resolved "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz"
+ integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==
+
"@types/json5@^0.0.29":
version "0.0.29"
resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
@@ -2635,13 +2708,18 @@
dependencies:
undici-types "~6.21.0"
-"@types/react@19.1.5":
+"@types/react@^18.2.25 || ^19", "@types/react@19.1.5":
version "19.1.5"
resolved "https://registry.npmjs.org/@types/react/-/react-19.1.5.tgz"
integrity sha512-piErsCVVbpMMT2r7wbawdZsq4xMvIAhQuac2gedQHysu1TZYEigE6pnFfgZT+/jQnrRuF5r+SHzuehFjfRjr4g==
dependencies:
csstype "^3.0.2"
+"@types/use-sync-external-store@^0.0.6":
+ version "0.0.6"
+ resolved "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz"
+ integrity sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==
+
"@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0":
version "8.32.1"
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz"
@@ -3133,6 +3211,11 @@ clsx@^2.0.0:
resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
+clsx@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
+ integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
+
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
@@ -3207,6 +3290,77 @@ csstype@^3.0.2:
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
+d3-array@^3.1.6, "d3-array@2 - 3", "d3-array@2.10.0 - 3":
+ version "3.2.4"
+ resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz"
+ integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==
+ dependencies:
+ internmap "1 - 2"
+
+"d3-color@1 - 3":
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz"
+ integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==
+
+d3-ease@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz"
+ integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
+
+"d3-format@1 - 3":
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz"
+ integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==
+
+d3-interpolate@^3.0.1, "d3-interpolate@1.2.0 - 3":
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz"
+ integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
+ dependencies:
+ d3-color "1 - 3"
+
+d3-path@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz"
+ integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==
+
+d3-scale@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz"
+ integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==
+ dependencies:
+ d3-array "2.10.0 - 3"
+ d3-format "1 - 3"
+ d3-interpolate "1.2.0 - 3"
+ d3-time "2.1.1 - 3"
+ d3-time-format "2 - 4"
+
+d3-shape@^3.1.0:
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz"
+ integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==
+ dependencies:
+ d3-path "^3.1.0"
+
+"d3-time-format@2 - 4":
+ version "4.1.0"
+ resolved "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz"
+ integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==
+ dependencies:
+ d3-time "1 - 3"
+
+d3-time@^3.0.0, "d3-time@1 - 3", "d3-time@2.1.1 - 3":
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz"
+ integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==
+ dependencies:
+ d3-array "2 - 3"
+
+d3-timer@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz"
+ integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==
+
damerau-levenshtein@^1.0.8:
version "1.0.8"
resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz"
@@ -3253,6 +3407,11 @@ debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.0:
dependencies:
ms "^2.1.3"
+decimal.js-light@^2.5.1:
+ version "2.5.1"
+ resolved "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz"
+ integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==
+
decimal.js@^10.4.3:
version "10.5.0"
resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz"
@@ -3466,6 +3625,11 @@ es-to-primitive@^1.3.0:
is-date-object "^1.0.5"
is-symbol "^1.0.4"
+es-toolkit@^1.39.3:
+ version "1.39.10"
+ resolved "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.10.tgz"
+ integrity sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w==
+
escape-string-regexp@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
@@ -3686,6 +3850,11 @@ esutils@^2.0.2:
resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+eventemitter3@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz"
+ integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
+
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
@@ -4020,6 +4189,11 @@ ignore@^7.0.0:
resolved "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz"
integrity sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==
+immer@^10.0.3, immer@^10.1.1:
+ version "10.1.3"
+ resolved "https://registry.npmjs.org/immer/-/immer-10.1.3.tgz"
+ integrity sha512-tmjF/k8QDKydUlm3mZU+tjM6zeq9/fFpPqH9SzWmBnVVKsPBg/V66qsMwb3/Bo90cgUN+ghdVBess+hPsxUyRw==
+
import-fresh@^3.2.1:
version "3.3.1"
resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz"
@@ -4060,6 +4234,11 @@ internal-slot@^1.1.0:
hasown "^2.0.2"
side-channel "^1.1.0"
+"internmap@1 - 2":
+ version "2.0.3"
+ resolved "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz"
+ integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==
+
intl-messageformat@^10.1.0:
version "10.7.16"
resolved "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.16.tgz"
@@ -4819,7 +4998,7 @@ queue-microtask@^1.2.2:
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
-"react-dom@^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom@^18.0.0 || ^19.0.0", react-dom@^18.2.0, "react-dom@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react-dom@>=18, "react-dom@>=18 || >=19.0.0-rc.0":
+"react-dom@^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom@^18.0.0 || ^19.0.0", react-dom@^18.2.0, "react-dom@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react-dom@>=18, "react-dom@>=18 || >=19.0.0-rc.0":
version "18.3.1"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz"
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
@@ -4839,11 +5018,19 @@ react-icons@^5.4.0:
resolved "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz"
integrity sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==
-react-is@^16.13.1:
+react-is@^16.13.1, "react-is@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0":
version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+"react-redux@^7.2.1 || ^8.1.3 || ^9.0.0", "react-redux@8.x.x || 9.x.x":
+ version "9.2.0"
+ resolved "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz"
+ integrity sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==
+ dependencies:
+ "@types/use-sync-external-store" "^0.0.6"
+ use-sync-external-store "^1.4.0"
+
react-textarea-autosize@^8.5.3:
version "8.5.9"
resolved "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz"
@@ -4853,7 +5040,7 @@ react-textarea-autosize@^8.5.3:
use-composed-ref "^1.3.0"
use-latest "^1.2.1"
-react@*, "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react@^18.0.0 || ^19.0.0", react@^18.2.0, "react@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react@^18.3.1, "react@>= 16 || ^19.0.0-rc", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0", react@>=16.13.1, react@>=18, "react@>=18 || >=19.0.0-rc.0":
+react@*, "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react@^16.9.0 || ^17.0.0 || ^18 || ^19", "react@^18.0 || ^19", "react@^18.0.0 || ^19.0.0", react@^18.2.0, "react@^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", react@^18.3.1, "react@>= 16 || ^19.0.0-rc", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0", react@>=16.13.1, react@>=18, "react@>=18 || >=19.0.0-rc.0":
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==
@@ -4874,6 +5061,33 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"
+recharts@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.npmjs.org/recharts/-/recharts-3.1.2.tgz"
+ integrity sha512-vhNbYwaxNbk/IATK0Ki29k3qvTkGqwvCgyQAQ9MavvvBwjvKnMTswdbklJpcOAoMPN/qxF3Lyqob0zO+ZXkZ4g==
+ dependencies:
+ "@reduxjs/toolkit" "1.x.x || 2.x.x"
+ clsx "^2.1.1"
+ decimal.js-light "^2.5.1"
+ es-toolkit "^1.39.3"
+ eventemitter3 "^5.0.1"
+ immer "^10.1.1"
+ react-redux "8.x.x || 9.x.x"
+ reselect "5.1.1"
+ tiny-invariant "^1.3.3"
+ use-sync-external-store "^1.2.2"
+ victory-vendor "^37.0.2"
+
+redux-thunk@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz"
+ integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==
+
+redux@^5.0.0, redux@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz"
+ integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
+
reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9:
version "1.0.10"
resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz"
@@ -4900,6 +5114,11 @@ regexp.prototype.flags@^1.5.3:
gopd "^1.2.0"
set-function-name "^2.0.2"
+reselect@^5.1.0, reselect@5.1.1:
+ version "5.1.1"
+ resolved "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz"
+ integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==
+
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"
@@ -5368,6 +5587,11 @@ thenify-all@^1.0.0:
dependencies:
any-promise "^1.0.0"
+tiny-invariant@^1.3.3:
+ 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==
+
tinyglobby@^0.2.13:
version "0.2.13"
resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz"
@@ -5541,11 +5765,36 @@ use-latest@^1.2.1:
dependencies:
use-isomorphic-layout-effect "^1.1.1"
+use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0:
+ version "1.5.0"
+ resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz"
+ integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==
+
util-deprecate@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
+victory-vendor@^37.0.2:
+ version "37.3.6"
+ resolved "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz"
+ integrity sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==
+ dependencies:
+ "@types/d3-array" "^3.0.3"
+ "@types/d3-ease" "^3.0.0"
+ "@types/d3-interpolate" "^3.0.1"
+ "@types/d3-scale" "^4.0.2"
+ "@types/d3-shape" "^3.1.0"
+ "@types/d3-time" "^3.0.0"
+ "@types/d3-timer" "^3.0.0"
+ d3-array "^3.1.6"
+ d3-ease "^3.0.1"
+ d3-interpolate "^3.0.1"
+ d3-scale "^4.0.2"
+ d3-shape "^3.1.0"
+ d3-time "^3.0.0"
+ d3-timer "^3.0.1"
+
which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1:
version "1.1.1"
resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz"