diff --git a/package-lock.json b/package-lock.json
index 4db0f49..dbe7a4d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,26 +13,26 @@
"@mantine/form": "^8.1.1",
"@mantine/hooks": "^8.1.1",
"@mantine/notifications": "^8.1.1",
- "@tanstack/react-query": "^5.80.10",
- "@tanstack/react-query-devtools": "^5.80.10",
- "@tanstack/react-query-persist-client": "^5.80.10",
+ "@tanstack/react-query": "^5.81.2",
+ "@tanstack/react-query-devtools": "^5.81.2",
+ "@tanstack/react-query-persist-client": "^5.81.2",
"idb-keyval": "^6.2.2",
"jotai": "^2.12.5",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-icons": "^5.5.0",
"react-router-dom": "^7.6.2",
- "recharts": "^2.15.3"
+ "recharts": "^3.0.0"
},
"devDependencies": {
- "@types/node": "^24.0.3",
+ "@types/node": "^24.0.4",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
- "@vitejs/plugin-react": "^4.5.2",
+ "@vitejs/plugin-react": "^4.6.0",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/ui": "^3.2.4",
"typescript": "^5.8.3",
- "vite": "^6.3.5",
+ "vite": "^7.0.0",
"vite-plugin-dts": "~4.5.4",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.2.4"
@@ -1160,10 +1160,36 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@reduxjs/toolkit": {
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.8.2.tgz",
+ "integrity": "sha512-MYlOhQ0sLdw4ud48FoC5w0dH9VfWQjtCjreKwYTT3l+r427qYC5Y8PihNutepr8XrNaBUDQo9khWUwQxZaqt5A==",
+ "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/@rolldown/pluginutils": {
- "version": "1.0.0-beta.11",
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.11.tgz",
- "integrity": "sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==",
+ "version": "1.0.0-beta.19",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.19.tgz",
+ "integrity": "sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==",
"dev": true,
"license": "MIT"
},
@@ -1591,10 +1617,22 @@
"sprintf-js": "~1.0.2"
}
},
+ "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/@tanstack/query-core": {
- "version": "5.80.10",
- "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.80.10.tgz",
- "integrity": "sha512-mUNQOtzxkjL6jLbyChZoSBP6A5gQDVRUiPvW+/zw/9ftOAz+H754zCj3D8PwnzPKyHzGkQ9JbH48ukhym9LK1Q==",
+ "version": "5.81.2",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.81.2.tgz",
+ "integrity": "sha512-QLYkPdrudoMATDFa3MiLEwRhNnAlzHWDf0LKaXUqJd0/+QxN8uTPi7bahRlxoAyH0UbLMBdeDbYzWALj7THOtw==",
"license": "MIT",
"funding": {
"type": "github",
@@ -1602,9 +1640,9 @@
}
},
"node_modules/@tanstack/query-devtools": {
- "version": "5.80.0",
- "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.80.0.tgz",
- "integrity": "sha512-D6gH4asyjaoXrCOt5vG5Og/YSj0D/TxwNQgtLJIgWbhbWCC/emu2E92EFoVHh4ppVWg1qT2gKHvKyQBEFZhCuA==",
+ "version": "5.81.2",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.81.2.tgz",
+ "integrity": "sha512-jCeJcDCwKfoyyBXjXe9+Lo8aTkavygHHsUHAlxQKKaDeyT0qyQNLKl7+UyqYH2dDF6UN/14873IPBHchcsU+Zg==",
"license": "MIT",
"funding": {
"type": "github",
@@ -1612,12 +1650,12 @@
}
},
"node_modules/@tanstack/query-persist-client-core": {
- "version": "5.80.10",
- "resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-5.80.10.tgz",
- "integrity": "sha512-3fcLDW4hDkiGfG/NRj6hgl/+G94lsgtx/Wj9jxuUN0LiawKpIMfGrSNCERFPYpJMuTtCyX9A2mqHE++sV13lsA==",
+ "version": "5.81.2",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-persist-client-core/-/query-persist-client-core-5.81.2.tgz",
+ "integrity": "sha512-FSLHr3DL+eezaKNiAexM7+KdgpXvLmUuMQhtORPIC7QuhemM6kfzcrQC5AN34zhvVh2PZXRcib2JnHKeTMjyyg==",
"license": "MIT",
"dependencies": {
- "@tanstack/query-core": "5.80.10"
+ "@tanstack/query-core": "5.81.2"
},
"funding": {
"type": "github",
@@ -1625,12 +1663,12 @@
}
},
"node_modules/@tanstack/react-query": {
- "version": "5.80.10",
- "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.80.10.tgz",
- "integrity": "sha512-6zM098J8sLy9oU60XAdzUlAH4wVzoMVsWUWiiE/Iz4fd67PplxeyL4sw/MPcVJJVhbwGGXCsHn9GrQt2mlAzig==",
+ "version": "5.81.2",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.81.2.tgz",
+ "integrity": "sha512-pe8kFlTrL2zFLlcAj2kZk9UaYYHDk9/1hg9EBaoO3cxDhOZf1FRGJeziSXKrVZyxIfs7b3aoOj/bw7Lie0mDUg==",
"license": "MIT",
"dependencies": {
- "@tanstack/query-core": "5.80.10"
+ "@tanstack/query-core": "5.81.2"
},
"funding": {
"type": "github",
@@ -1641,36 +1679,36 @@
}
},
"node_modules/@tanstack/react-query-devtools": {
- "version": "5.80.10",
- "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.80.10.tgz",
- "integrity": "sha512-6JL63fSc7kxyGOLV2w466SxhMn/m7LZk/ximQciy6OpVt+n2A8Mq3S0QwhIzfm4WEwLK/F3OELfzRToQburnYA==",
+ "version": "5.81.2",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.81.2.tgz",
+ "integrity": "sha512-TX0OQ4cbgX6z2uN8c9x0QUNbyePGyUGdcgrGnV6TYEJc7KPT8PqeASuzoA5NGw1CiMGvyFAkIGA2KipvhM9d1g==",
"license": "MIT",
"dependencies": {
- "@tanstack/query-devtools": "5.80.0"
+ "@tanstack/query-devtools": "5.81.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
- "@tanstack/react-query": "^5.80.10",
+ "@tanstack/react-query": "^5.81.2",
"react": "^18 || ^19"
}
},
"node_modules/@tanstack/react-query-persist-client": {
- "version": "5.80.10",
- "resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-5.80.10.tgz",
- "integrity": "sha512-0LcPhQElmffSNXh+omPOOZJnutk7Z7NMTrWl9WP3aH7Xn4OaFXImkyey1ajez5o23D8TFwj3kHmi/85J+E6sgQ==",
+ "version": "5.81.2",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-query-persist-client/-/react-query-persist-client-5.81.2.tgz",
+ "integrity": "sha512-HUlnB7FGqN/he4AOvR0vNA06Wn4dg3rEK7EgzenWfc0gQ9Aa6thqTWgT3Q27CnKiTkzhRn2uZJKRseTP4g54LQ==",
"license": "MIT",
"dependencies": {
- "@tanstack/query-persist-client-core": "5.80.10"
+ "@tanstack/query-persist-client-core": "5.81.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
- "@tanstack/react-query": "^5.80.10",
+ "@tanstack/react-query": "^5.81.2",
"react": "^18 || ^19"
}
},
@@ -1734,22 +1772,26 @@
"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=="
+ "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=="
+ "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=="
+ "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": "*"
}
@@ -1757,12 +1799,14 @@
"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=="
+ "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": "*"
}
@@ -1771,6 +1815,7 @@
"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": "*"
}
@@ -1778,12 +1823,14 @@
"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=="
+ "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=="
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
+ "license": "MIT"
},
"node_modules/@types/deep-eql": {
"version": "4.0.2",
@@ -1800,9 +1847,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "24.0.3",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.3.tgz",
- "integrity": "sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg==",
+ "version": "24.0.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.4.tgz",
+ "integrity": "sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1836,16 +1883,16 @@
"license": "MIT"
},
"node_modules/@vitejs/plugin-react": {
- "version": "4.5.2",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.5.2.tgz",
- "integrity": "sha512-QNVT3/Lxx99nMQWJWF7K4N6apUEuT0KlZA3mx/mVaoGj3smm/8rc8ezz15J1pcbcjDK0V15rpHetVfya08r76Q==",
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.6.0.tgz",
+ "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.27.4",
"@babel/plugin-transform-react-jsx-self": "^7.27.1",
"@babel/plugin-transform-react-jsx-source": "^7.27.1",
- "@rolldown/pluginutils": "1.0.0-beta.11",
+ "@rolldown/pluginutils": "1.0.0-beta.19",
"@types/babel__core": "^7.20.5",
"react-refresh": "^0.17.0"
},
@@ -2456,6 +2503,7 @@
"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"
},
@@ -2467,6 +2515,7 @@
"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"
}
@@ -2475,6 +2524,7 @@
"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"
}
@@ -2483,6 +2533,7 @@
"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"
}
@@ -2491,6 +2542,7 @@
"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"
},
@@ -2502,6 +2554,7 @@
"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"
}
@@ -2510,6 +2563,7 @@
"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",
@@ -2525,6 +2579,7 @@
"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"
},
@@ -2536,6 +2591,7 @@
"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"
},
@@ -2547,6 +2603,7 @@
"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"
},
@@ -2558,6 +2615,7 @@
"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"
}
@@ -2589,7 +2647,8 @@
"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=="
+ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
+ "license": "MIT"
},
"node_modules/deep-eql": {
"version": "5.0.2",
@@ -2653,6 +2712,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/es-toolkit": {
+ "version": "1.39.5",
+ "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.5.tgz",
+ "integrity": "sha512-z9V0qU4lx1TBXDNFWfAASWk6RNU6c6+TJBKE+FLIg8u0XJ6Yw58Hi0yX8ftEouj6p1QARRlXLFfHbIli93BdQQ==",
+ "license": "MIT",
+ "workspaces": [
+ "docs",
+ "benchmarks"
+ ]
+ },
"node_modules/esbuild": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz",
@@ -2710,9 +2779,10 @@
"dev": true
},
"node_modules/eventemitter3": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
- "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "license": "MIT"
},
"node_modules/expect-type": {
"version": "1.2.1",
@@ -2735,14 +2805,6 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
- "node_modules/fast-equals": {
- "version": "5.2.2",
- "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz",
- "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==",
- "engines": {
- "node": ">=6.0.0"
- }
- },
"node_modules/fast-uri": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
@@ -2760,9 +2822,9 @@
]
},
"node_modules/fdir": {
- "version": "6.4.4",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
- "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
+ "version": "6.4.6",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz",
+ "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
"dev": true,
"license": "MIT",
"peerDependencies": {
@@ -2923,6 +2985,16 @@
"integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==",
"license": "Apache-2.0"
},
+ "node_modules/immer": {
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
+ "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
"node_modules/import-lazy": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz",
@@ -2936,6 +3008,7 @@
"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"
}
@@ -3159,7 +3232,8 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
},
"node_modules/loose-envify": {
"version": "1.4.0",
@@ -3310,6 +3384,7 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -3428,9 +3503,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.3",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
- "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"dev": true,
"funding": [
{
@@ -3446,8 +3521,9 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
- "nanoid": "^3.3.8",
+ "nanoid": "^3.3.11",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -3655,20 +3731,6 @@
"react-dom": ">=18"
}
},
- "node_modules/react-smooth": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz",
- "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==",
- "dependencies": {
- "fast-equals": "^5.0.1",
- "prop-types": "^15.8.1",
- "react-transition-group": "^4.4.5"
- },
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
- "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
"node_modules/react-style-singleton": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
@@ -3723,47 +3785,47 @@
}
},
"node_modules/recharts": {
- "version": "2.15.3",
- "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.3.tgz",
- "integrity": "sha512-EdOPzTwcFSuqtvkDoaM5ws/Km1+WTAO2eizL7rqiG0V2UVhTnz0m7J2i0CjVPUCdEkZImaWvXLbZDS2H5t6GFQ==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.0.0.tgz",
+ "integrity": "sha512-GODedlXZEOQ/KN15puHqaEk9JaiUvFr+Wef/nSagi7g9wHPFLB7prH1/J8vyEBtA2Es6r8qGY1t2OqkuAIpgBg==",
"license": "MIT",
"dependencies": {
- "clsx": "^2.0.0",
- "eventemitter3": "^4.0.1",
- "lodash": "^4.17.21",
- "react-is": "^18.3.1",
- "react-smooth": "^4.0.4",
- "recharts-scale": "^0.4.4",
- "tiny-invariant": "^1.3.1",
- "victory-vendor": "^36.6.8"
+ "@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": ">=14"
+ "node": ">=18"
},
"peerDependencies": {
- "react": "^16.0.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": "^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-scale": {
- "version": "0.4.5",
- "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
- "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
- "dependencies": {
- "decimal.js-light": "^2.4.1"
- }
- },
- "node_modules/recharts/node_modules/react-is": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
- },
"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/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
@@ -3778,6 +3840,12 @@
"node": ">=0.10.0"
}
},
+ "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",
@@ -4427,9 +4495,10 @@
}
},
"node_modules/victory-vendor": {
- "version": "36.9.2",
- "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
- "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
+ "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",
@@ -4448,24 +4517,24 @@
}
},
"node_modules/vite": {
- "version": "6.3.5",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
- "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.0.tgz",
+ "integrity": "sha512-ixXJB1YRgDIw2OszKQS9WxGHKwLdCsbQNkpJN171udl6szi/rIySHL6/Os3s2+oE4P/FLD4dxg4mD7Wust+u5g==",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "^0.25.0",
- "fdir": "^6.4.4",
+ "fdir": "^6.4.6",
"picomatch": "^4.0.2",
- "postcss": "^8.5.3",
- "rollup": "^4.34.9",
- "tinyglobby": "^0.2.13"
+ "postcss": "^8.5.6",
+ "rollup": "^4.40.0",
+ "tinyglobby": "^0.2.14"
},
"bin": {
"vite": "bin/vite.js"
},
"engines": {
- "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ "node": "^20.19.0 || >=22.12.0"
},
"funding": {
"url": "https://github.com/vitejs/vite?sponsor=1"
@@ -4474,14 +4543,14 @@
"fsevents": "~2.3.3"
},
"peerDependencies": {
- "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "@types/node": "^20.19.0 || >=22.12.0",
"jiti": ">=1.21.0",
- "less": "*",
+ "less": "^4.0.0",
"lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
"terser": "^5.16.0",
"tsx": "^4.8.1",
"yaml": "^2.4.2"
diff --git a/package.json b/package.json
index 58681d4..1b2e313 100644
--- a/package.json
+++ b/package.json
@@ -15,26 +15,26 @@
"@mantine/form": "^8.1.1",
"@mantine/hooks": "^8.1.1",
"@mantine/notifications": "^8.1.1",
- "@tanstack/react-query": "^5.80.10",
- "@tanstack/react-query-devtools": "^5.80.10",
- "@tanstack/react-query-persist-client": "^5.80.10",
+ "@tanstack/react-query": "^5.81.2",
+ "@tanstack/react-query-devtools": "^5.81.2",
+ "@tanstack/react-query-persist-client": "^5.81.2",
"idb-keyval": "^6.2.2",
"jotai": "^2.12.5",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-icons": "^5.5.0",
"react-router-dom": "^7.6.2",
- "recharts": "^2.15.3"
+ "recharts": "^3.0.0"
},
"devDependencies": {
- "@types/node": "^24.0.3",
+ "@types/node": "^24.0.4",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
- "@vitejs/plugin-react": "^4.5.2",
+ "@vitejs/plugin-react": "^4.6.0",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/ui": "^3.2.4",
"typescript": "^5.8.3",
- "vite": "^6.3.5",
+ "vite": "^7.0.0",
"vite-plugin-dts": "~4.5.4",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.2.4"
diff --git a/src/components/HelpModal/HelpModal.tsx b/src/components/HelpModal/HelpModal.tsx
index c8c3925..267862b 100644
--- a/src/components/HelpModal/HelpModal.tsx
+++ b/src/components/HelpModal/HelpModal.tsx
@@ -1,4 +1,4 @@
-import { Divider, Modal, Stack } from '@mantine/core';
+import { Modal, Stack } from '@mantine/core';
import { useCommonHooks } from 'hooks';
import { modalClasses } from 'styles';
import type { Application, Provider } from 'types';
@@ -56,7 +56,7 @@ export function HelpModal({
};
})}
/>
-
+
{
diff --git a/src/components/HelpModal/HelpSection.tsx b/src/components/HelpModal/HelpSection.tsx
index db23f3a..4d43130 100644
--- a/src/components/HelpModal/HelpSection.tsx
+++ b/src/components/HelpModal/HelpSection.tsx
@@ -1,4 +1,4 @@
-import { Divider, Group } from '@mantine/core';
+import { Group } from '@mantine/core';
import type { SearchShortcut } from 'types';
import HintItem from './HintItem';
@@ -10,7 +10,7 @@ function HelpSection({ name, items }: { name: string; items: SearchShortcut[] })
zIndex: 0,
padding: '.5rem',
marginTop: 0,
- marginBottom: '-2rem',
+ marginBottom: '-1.25rem',
borderRadius: '8px',
color: 'var(--mantine-color-background-0)',
backgroundColor: 'var(--mantine-color-border-0)',
@@ -18,7 +18,6 @@ function HelpSection({ name, items }: { name: string; items: SearchShortcut[] })
>
{name}
-
diff --git a/src/pages/homepage/components/Search/Search.tsx b/src/pages/homepage/components/Search/Search.tsx
index eed9711..fc9cfef 100644
--- a/src/pages/homepage/components/Search/Search.tsx
+++ b/src/pages/homepage/components/Search/Search.tsx
@@ -1,4 +1,4 @@
-import { Group, type OptionsFilter, Select, Stack, Text } from '@mantine/core';
+import { Group, type OptionsFilter, Overlay, Select, Stack, Text } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { HelpModal, WeatherModal } from 'components';
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
@@ -61,7 +61,7 @@ export default function Search({
searchValue,
setSearchValue,
} = useCommonHooks();
- const [placeholderValue, setPlaceholderValue] = useState('');
+ const [placeholderValue, setPlaceholderValue] = useState('');
const [value, setValue] = useState(0);
const handleSearchHistoryItem = ({ option }: { option: SearchHistoryItem }) => {
@@ -322,118 +322,125 @@ export default function Search({
}, [searchValue]);
return (
-
-
+ data-active={searchValue !== ''}
+ dropdownOpened={dropdownOpened}
+ comboboxProps={{
+ transitionProps: { transition: 'fade', duration: 200 },
+ }}
+ styles={{
+ input: {
+ zIndex: 1000,
+ },
+ }}
+ spellCheck={true}
+ searchable
+ autoFocus={!isMobile}
+ leftSection={providerLabel}
+ rightSection={}
+ renderOption={(item: any) => {
+ const Icon = allIcons[item.option.icon];
+ return !searchValue.startsWith('!') ? (
+
+ ) : (
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ handleAppLaunchItem(item);
+ }}
+ >
+
+ Launch
+
+ {Icon && (
+
+ )}
+
+ {item.option.name}
+
+
+ );
+ }}
+ onBlur={() => {
+ setPlaceholderValue('');
+ setListIndex(0);
+ closeDropdown();
+ }}
+ onFocus={() => {
+ if (searchValue !== '') {
+ openDropdown();
+ }
+ }}
+ onKeyDown={(e) => {
+ if (e.key === 'Tab') {
+ e.preventDefault();
+ }
+ }}
+ onInput={onInput}
+ onKeyUp={handleKeyUp}
+ />
+
+
+
+ >
);
}
diff --git a/src/pages/homepage/components/SettingsButton/SettingsButton.tsx b/src/pages/homepage/components/SettingsButton/SettingsButton.tsx
index 6475927..6f93144 100644
--- a/src/pages/homepage/components/SettingsButton/SettingsButton.tsx
+++ b/src/pages/homepage/components/SettingsButton/SettingsButton.tsx
@@ -1,32 +1,13 @@
-import {
- ActionIcon,
- Button,
- type ComboboxItem,
- Group,
- Menu,
- MultiSelect,
- Overlay,
- Select,
- Slider,
- Stack,
- Text,
- Tooltip,
-} from '@mantine/core';
+import { Button, Group, Menu, Stack } from '@mantine/core';
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
import { useEffect, useState } from 'react';
-import { FaDice } from 'react-icons/fa';
-import { FiMenu, FiPower, FiSettings, FiShuffle } from 'react-icons/fi';
+import { FiMenu, FiSettings } from 'react-icons/fi';
import { useNavigate } from 'react-router-dom';
-import {
- actionIconClasses,
- buttonClasses,
- menuClasses,
- multiSelectClasses,
- selectClasses,
- sliderClasses,
- stackClasses,
-} from 'styles';
-import type { AppCategory, Theme, ThemePlaylist, WolClient } from 'types';
+import { buttonClasses, menuClasses } from 'styles';
+import type { AppCategory, WolClient } from 'types';
+import SettingsCard from './SettingsCard';
+import ThemingCard from './ThemingCard';
+import WakeOnLan from './WakeOnLanCard';
function SettingsButton() {
const { data: appCategoryData, isFetched: appCategoryDataIsFetched } = useQueryAPI({
@@ -36,24 +17,14 @@ function SettingsButton() {
endpoint: 'api/wolClients',
});
const [wolClients, setWolClients] = useState([]);
- const { data: allThemeData, isFetched: allThemeDataIsFetched } = useQueryAPI({
- endpoint: 'api/themes',
- });
- const { data: themePlaylistData } = useQueryAPI({
- endpoint: 'api/themePlaylists',
- });
+
const { mutateAsync } = useMutationAPI();
- const [allThemes, setAllThemes] = useState([]);
const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]);
const [selectedClient] = useState(wolClientData?.[0]);
- const [overlayOpened, setOverlayOpened] = useState(false);
const navigate = useNavigate();
const {
- currentTheme,
- setCurrentTheme,
- setThemeName,
- handleThemeChange,
theme,
+ isMobile,
appFilter,
setAppFilter,
appSort,
@@ -66,10 +37,8 @@ function SettingsButton() {
setBookmarkFilter,
bookmarkDensity,
setBookmarkDensity,
- isMobile,
- currentThemePlaylist,
- setCurrentThemePlaylist,
} = useCommonHooks();
+
const handleWakeRequest = () => {
mutateAsync({
method: 'POST',
@@ -94,459 +63,84 @@ function SettingsButton() {
}
}, [wolClientData, wolClientDataIsFetched]);
- useEffect(() => {
- if (allThemeData && allThemeDataIsFetched) {
- setAllThemes(allThemeData);
- }
- }, [allThemeData, allThemeDataIsFetched]);
return (
- <>
- {overlayOpened && (
- {
- e.stopPropagation();
- }}
- />
- )}
-
+
+
);
}
diff --git a/src/pages/homepage/components/SettingsButton/SettingsCard.tsx b/src/pages/homepage/components/SettingsButton/SettingsCard.tsx
new file mode 100644
index 0000000..e42c78a
--- /dev/null
+++ b/src/pages/homepage/components/SettingsButton/SettingsCard.tsx
@@ -0,0 +1,121 @@
+import {
+ type ComboboxItem,
+ Group,
+ MultiSelect,
+ Select,
+ Slider,
+ Stack,
+ Text,
+} from '@mantine/core';
+import { multiSelectClasses, selectClasses, sliderClasses, stackClasses } from 'styles';
+
+function SettingsCard({
+ categories,
+ sectionTitle,
+ filter,
+ setFilter,
+ sort,
+ setSort,
+ density,
+ setDensity,
+}: {
+ categories: ComboboxItem[];
+ sectionTitle: string;
+ filter: any;
+ setFilter: any;
+ sort: any;
+ setSort: any;
+ density: any;
+ setDensity: any;
+}) {
+ return (
+
+
+ {sectionTitle}
+
+
+ Density
+
+
+ setDensity(value)}
+ min={1}
+ max={8}
+ />
+
+
+
+ a.label.localeCompare(b.label),
+ ) ?? []
+ }
+ placeholder={
+ filter.length > 0
+ ? filter.length === 1
+ ? filter[0]
+ : `${filter.length} ${sectionTitle.toLocaleLowerCase()}s selected`
+ : `No ${sectionTitle.toLocaleLowerCase()}s selected`
+ }
+ defaultValue={filter}
+ onChange={(data: string[]) => {
+ setFilter(data);
+ }}
+ classNames={multiSelectClasses}
+ comboboxProps={{
+ withinPortal: false,
+ position: 'top',
+ }}
+ />
+ Z', 'Z>A', 'Newest', 'Oldest']}
+ classNames={{
+ root: selectClasses.menuSelectRoot,
+ input: selectClasses.menuSelectInput,
+ label: selectClasses.menuSelectLabel,
+ options: selectClasses.menuSelectOptions,
+ option: selectClasses.menuSelectOption,
+ }}
+ comboboxProps={{
+ withinPortal: false,
+ position: 'top',
+ }}
+ onChange={(_value, option: ComboboxItem) => {
+ setSort(option.value);
+ }}
+ />
+
+
+ );
+}
+
+export default SettingsCard;
diff --git a/src/pages/homepage/components/SettingsButton/ThemingCard.tsx b/src/pages/homepage/components/SettingsButton/ThemingCard.tsx
new file mode 100644
index 0000000..7c2883d
--- /dev/null
+++ b/src/pages/homepage/components/SettingsButton/ThemingCard.tsx
@@ -0,0 +1,201 @@
+import {
+ ActionIcon,
+ type ComboboxItem,
+ Group,
+ Menu,
+ Select,
+ Stack,
+ Text,
+ Tooltip,
+} from '@mantine/core';
+import { useCommonHooks, useQueryAPI } from 'hooks';
+import { useEffect, useState } from 'react';
+import { FaDice } from 'react-icons/fa';
+import { FiShuffle } from 'react-icons/fi';
+import { actionIconClasses, selectClasses, stackClasses } from 'styles';
+import type { Theme, ThemePlaylist } from 'types';
+
+function ThemingCard() {
+ const { data: themePlaylistData } = useQueryAPI({
+ endpoint: 'api/themePlaylists',
+ });
+ const { data: allThemeData, isFetched: allThemeDataIsFetched } = useQueryAPI({
+ endpoint: 'api/themes',
+ });
+ const [allThemes, setAllThemes] = useState([]);
+ useEffect(() => {
+ if (allThemeData && allThemeDataIsFetched) {
+ setAllThemes(allThemeData);
+ }
+ }, [allThemeData, allThemeDataIsFetched]);
+ const {
+ currentTheme,
+ setCurrentTheme,
+ setThemeName,
+ handleThemeChange,
+ theme,
+ currentThemePlaylist,
+ setCurrentThemePlaylist,
+ } = useCommonHooks();
+ return (
+
+ Themes
+
+
+ {
+ setCurrentTheme(currentTheme === 'random' ? theme.name : 'random');
+ setCurrentThemePlaylist('All');
+ }}
+ >
+
+
+
+
+ {
+ const themeList = JSON.parse(
+ themePlaylistData?.find(
+ (t: ThemePlaylist) => t?.name === currentThemePlaylist,
+ )?.themeList ?? '[]',
+ );
+ if (themeList.length > 0) {
+ const filteredThemes = allThemes.filter((t: Theme) =>
+ themeList.includes(t.id),
+ );
+ handleThemeChange(filteredThemes, false);
+ } else if (currentThemePlaylist === 'All') {
+ handleThemeChange(allThemes, false);
+ } else if (currentThemePlaylist === 'Backgrounds') {
+ handleThemeChange(
+ allThemes.filter(
+ (a: any) => !a.backgroundImage.toLowerCase().includes('none'),
+ ),
+ false,
+ );
+ } else if (currentThemePlaylist === 'No Backgrounds') {
+ handleThemeChange(
+ allThemes.filter((a: any) =>
+ a.backgroundImage.toLowerCase().includes('none'),
+ ),
+ false,
+ );
+ }
+ }}
+ >
+
+
+
+
+
+ Currently:{' '}
+
+ {theme.name}
+
+ Playlist:{' '}
+
+ !a.backgroundImage.toLowerCase().includes('none'),
+ ).length === 0,
+ },
+ {
+ value: 'No Backgrounds',
+ label: 'No Backgrounds',
+ disabled:
+ allThemes.filter((a: any) =>
+ a.backgroundImage.toLowerCase().includes('none'),
+ ).length === 0,
+ },
+ ...(themePlaylistData
+ ?.map((playlist: ThemePlaylist) => {
+ return {
+ value: playlist.name,
+ label: playlist.name,
+ disabled: JSON.parse(playlist.themeList).length === 0,
+ };
+ })
+ .toSorted((a: ComboboxItem, b: ComboboxItem) =>
+ a.label.localeCompare(b.label),
+ ) ?? []),
+ ]}
+ w='92%'
+ classNames={{
+ root: selectClasses.menuSelectRoot,
+ input: selectClasses.menuSelectInput,
+ label: selectClasses.menuSelectLabel,
+ options: selectClasses.menuSelectOptions,
+ option: selectClasses.menuSelectOption,
+ }}
+ comboboxProps={{
+ withinPortal: false,
+ position: 'top',
+ }}
+ onChange={(_value, option: ComboboxItem) => {
+ setCurrentThemePlaylist(option.value);
+ if (option.value !== 'Time of Day') {
+ setThemeName('random');
+ } else {
+ const themeList = JSON.parse(
+ themePlaylistData.find((t: ThemePlaylist) => t.name === 'Time of Day')
+ .themeList,
+ );
+ setThemeName(
+ allThemeData.find(
+ (t: Theme) =>
+ t.id === Number(themeList[Math.floor(new Date().getHours() / 6)]),
+ ).name,
+ );
+ }
+ }}
+ />
+
+ );
+}
+
+export default ThemingCard;
diff --git a/src/pages/homepage/components/SettingsButton/WakeOnLanCard.tsx b/src/pages/homepage/components/SettingsButton/WakeOnLanCard.tsx
new file mode 100644
index 0000000..440e19d
--- /dev/null
+++ b/src/pages/homepage/components/SettingsButton/WakeOnLanCard.tsx
@@ -0,0 +1,72 @@
+import { Button, type ComboboxItem, Menu, Select, Stack } from '@mantine/core';
+import { FiPower } from 'react-icons/fi';
+import { buttonClasses, selectClasses, stackClasses } from 'styles';
+import type { WolClient } from 'types';
+
+function WakeOnLan({
+ wolClients,
+ selectedClient,
+ handleWakeRequest,
+}: {
+ wolClients: WolClient[];
+ selectedClient: WolClient | null;
+ handleWakeRequest: () => void;
+}) {
+ return (
+
+ Wake on LAN
+
+ {
+ return {
+ value: wolClient.hostname,
+ label: `${wolClient.hostname} (${wolClient.macAddress})`,
+ hostname: wolClient.hostname,
+ macAddress: wolClient.macAddress,
+ };
+ })
+ .toSorted((a: ComboboxItem, b: ComboboxItem) =>
+ a.label.localeCompare(b.label),
+ ) ?? []
+ }
+ w='92%'
+ classNames={{
+ root: selectClasses.menuSelectRoot,
+ input: selectClasses.menuSelectInput,
+ label: selectClasses.menuSelectLabel,
+ options: selectClasses.menuSelectOptions,
+ option: selectClasses.menuSelectOption,
+ }}
+ comboboxProps={{
+ withinPortal: false,
+ position: 'top',
+ width: 'fit-content',
+ }}
+ />
+
+ );
+}
+
+export default WakeOnLan;
diff --git a/src/pages/settings/components/Applications/Applications.tsx b/src/pages/settings/components/Applications/Applications.tsx
index 92f7262..834cedb 100644
--- a/src/pages/settings/components/Applications/Applications.tsx
+++ b/src/pages/settings/components/Applications/Applications.tsx
@@ -4,7 +4,6 @@ import {
Button,
type ComboboxItem,
type ComboboxLikeRenderOptionInput,
- Divider,
Grid,
GridCol,
Group,
@@ -223,14 +222,8 @@ const ApplicationSettings = () => {
withAsterisk
/>
-
-
-
-