porting to typescript
This commit is contained in:
parent
c29c20c15b
commit
853af548d3
411
package-lock.json
generated
411
package-lock.json
generated
@ -1,30 +1,36 @@
|
|||||||
{
|
{
|
||||||
"name": "react-crypto",
|
"name": "react-crypto-ts",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "react-crypto",
|
"name": "react-crypto-ts",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/resolve-uri": "^3.1.0",
|
"@jridgewell/resolve-uri": "^3.1.0",
|
||||||
"@testing-library/dom": "^10.4.1",
|
"@testing-library/dom": "^10.4.1",
|
||||||
"@testing-library/jest-dom": "^6.9.1",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
"@testing-library/react": "^16.3.1",
|
"@testing-library/react": "^16.3.2",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
"@types/jest": "^27.5.2",
|
||||||
|
"@types/node": "^16.18.126",
|
||||||
|
"@types/react": "^19.2.9",
|
||||||
|
"@types/react-dom": "^19.2.3",
|
||||||
"axios": "^1.13.0",
|
"axios": "^1.13.0",
|
||||||
"chart.js": "^4.5.0",
|
"chart.js": "^4.5.0",
|
||||||
"chartjs-adapter-date-fns": "^3.0.0",
|
"chartjs-adapter-date-fns": "^3.0.0",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.4",
|
||||||
"react-chartjs-2": "^5.3.0",
|
"react-chartjs-2": "^5.3.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.4",
|
||||||
"react-hot-toast": "^2.6.0",
|
"react-hot-toast": "^2.6.0",
|
||||||
|
"react-icons": "^5.5.0",
|
||||||
"react-router": "^7.7.0",
|
"react-router": "^7.7.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-spinners": "^0.17.0",
|
"react-spinners": "^0.17.0",
|
||||||
"sass": "^1.97.0",
|
"sass": "^1.97.0",
|
||||||
|
"typescript": "^4.9.5",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
"zustand": "^5.0.0"
|
"zustand": "^5.0.0"
|
||||||
}
|
}
|
||||||
@ -255,16 +261,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-define-polyfill-provider": {
|
"node_modules/@babel/helper-define-polyfill-provider": {
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz",
|
||||||
"integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==",
|
"integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-compilation-targets": "^7.27.2",
|
"@babel/helper-compilation-targets": "^7.28.6",
|
||||||
"@babel/helper-plugin-utils": "^7.27.1",
|
"@babel/helper-plugin-utils": "^7.28.6",
|
||||||
"debug": "^4.4.1",
|
"debug": "^4.4.3",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
"resolve": "^1.22.10"
|
"resolve": "^1.22.11"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||||
@ -2942,9 +2948,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher": {
|
"node_modules/@parcel/watcher": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
|
||||||
"integrity": "sha512-WYa2tUVV5HiArWPB3ydlOc4R2ivq0IDrlqhMi3l7mVsFEXNcTfxYFPIHXHXIh/ca/y/V5N4E1zecyxdIBjYnkQ==",
|
"integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
@ -2962,25 +2968,25 @@
|
|||||||
"url": "https://opencollective.com/parcel"
|
"url": "https://opencollective.com/parcel"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@parcel/watcher-android-arm64": "2.5.4",
|
"@parcel/watcher-android-arm64": "2.5.6",
|
||||||
"@parcel/watcher-darwin-arm64": "2.5.4",
|
"@parcel/watcher-darwin-arm64": "2.5.6",
|
||||||
"@parcel/watcher-darwin-x64": "2.5.4",
|
"@parcel/watcher-darwin-x64": "2.5.6",
|
||||||
"@parcel/watcher-freebsd-x64": "2.5.4",
|
"@parcel/watcher-freebsd-x64": "2.5.6",
|
||||||
"@parcel/watcher-linux-arm-glibc": "2.5.4",
|
"@parcel/watcher-linux-arm-glibc": "2.5.6",
|
||||||
"@parcel/watcher-linux-arm-musl": "2.5.4",
|
"@parcel/watcher-linux-arm-musl": "2.5.6",
|
||||||
"@parcel/watcher-linux-arm64-glibc": "2.5.4",
|
"@parcel/watcher-linux-arm64-glibc": "2.5.6",
|
||||||
"@parcel/watcher-linux-arm64-musl": "2.5.4",
|
"@parcel/watcher-linux-arm64-musl": "2.5.6",
|
||||||
"@parcel/watcher-linux-x64-glibc": "2.5.4",
|
"@parcel/watcher-linux-x64-glibc": "2.5.6",
|
||||||
"@parcel/watcher-linux-x64-musl": "2.5.4",
|
"@parcel/watcher-linux-x64-musl": "2.5.6",
|
||||||
"@parcel/watcher-win32-arm64": "2.5.4",
|
"@parcel/watcher-win32-arm64": "2.5.6",
|
||||||
"@parcel/watcher-win32-ia32": "2.5.4",
|
"@parcel/watcher-win32-ia32": "2.5.6",
|
||||||
"@parcel/watcher-win32-x64": "2.5.4"
|
"@parcel/watcher-win32-x64": "2.5.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-android-arm64": {
|
"node_modules/@parcel/watcher-android-arm64": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz",
|
||||||
"integrity": "sha512-hoh0vx4v+b3BNI7Cjoy2/B0ARqcwVNrzN/n7DLq9ZB4I3lrsvhrkCViJyfTj/Qi5xM9YFiH4AmHGK6pgH1ss7g==",
|
"integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -2998,9 +3004,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-darwin-arm64": {
|
"node_modules/@parcel/watcher-darwin-arm64": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz",
|
||||||
"integrity": "sha512-kphKy377pZiWpAOyTgQYPE5/XEKVMaj6VUjKT5VkNyUJlr2qZAn8gIc7CPzx+kbhvqHDT9d7EqdOqRXT6vk0zw==",
|
"integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -3018,9 +3024,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-darwin-x64": {
|
"node_modules/@parcel/watcher-darwin-x64": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz",
|
||||||
"integrity": "sha512-UKaQFhCtNJW1A9YyVz3Ju7ydf6QgrpNQfRZ35wNKUhTQ3dxJ/3MULXN5JN/0Z80V/KUBDGa3RZaKq1EQT2a2gg==",
|
"integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -3038,9 +3044,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-freebsd-x64": {
|
"node_modules/@parcel/watcher-freebsd-x64": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz",
|
||||||
"integrity": "sha512-Dib0Wv3Ow/m2/ttvLdeI2DBXloO7t3Z0oCp4bAb2aqyqOjKPPGrg10pMJJAQ7tt8P4V2rwYwywkDhUia/FgS+Q==",
|
"integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -3058,9 +3064,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz",
|
||||||
"integrity": "sha512-I5Vb769pdf7Q7Sf4KNy8Pogl/URRCKu9ImMmnVKYayhynuyGYMzuI4UOWnegQNa2sGpsPSbzDsqbHNMyeyPCgw==",
|
"integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -3078,9 +3084,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm-musl": {
|
"node_modules/@parcel/watcher-linux-arm-musl": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz",
|
||||||
"integrity": "sha512-kGO8RPvVrcAotV4QcWh8kZuHr9bXi9a3bSZw7kFarYR0+fGliU7hd/zevhjw8fnvIKG3J9EO5G6sXNGCSNMYPQ==",
|
"integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -3098,9 +3104,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz",
|
||||||
"integrity": "sha512-KU75aooXhqGFY2W5/p8DYYHt4hrjHZod8AhcGAmhzPn/etTa+lYCDB2b1sJy3sWJ8ahFVTdy+EbqSBvMx3iFlw==",
|
"integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -3118,9 +3124,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz",
|
||||||
"integrity": "sha512-Qx8uNiIekVutnzbVdrgSanM+cbpDD3boB1f8vMtnuG5Zau4/bdDbXyKwIn0ToqFhIuob73bcxV9NwRm04/hzHQ==",
|
"integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -3138,9 +3144,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz",
|
||||||
"integrity": "sha512-UYBQvhYmgAv61LNUn24qGQdjtycFBKSK3EXr72DbJqX9aaLbtCOO8+1SkKhD/GNiJ97ExgcHBrukcYhVjrnogA==",
|
"integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -3158,9 +3164,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-linux-x64-musl": {
|
"node_modules/@parcel/watcher-linux-x64-musl": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz",
|
||||||
"integrity": "sha512-YoRWCVgxv8akZrMhdyVi6/TyoeeMkQ0PGGOf2E4omODrvd1wxniXP+DBynKoHryStks7l+fDAMUBRzqNHrVOpg==",
|
"integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -3178,9 +3184,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-win32-arm64": {
|
"node_modules/@parcel/watcher-win32-arm64": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz",
|
||||||
"integrity": "sha512-iby+D/YNXWkiQNYcIhg8P5hSjzXEHaQrk2SLrWOUD7VeC4Ohu0WQvmV+HDJokZVJ2UjJ4AGXW3bx7Lls9Ln4TQ==",
|
"integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -3198,9 +3204,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-win32-ia32": {
|
"node_modules/@parcel/watcher-win32-ia32": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz",
|
||||||
"integrity": "sha512-vQN+KIReG0a2ZDpVv8cgddlf67J8hk1WfZMMP7sMeZmJRSmEax5xNDNWKdgqSe2brOKTQQAs3aCCUal2qBHAyg==",
|
"integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@ -3218,9 +3224,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-win32-x64": {
|
"node_modules/@parcel/watcher-win32-x64": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz",
|
||||||
"integrity": "sha512-3A6efb6BOKwyw7yk9ro2vus2YTt2nvcd56AuzxdMiVOxL9umDyN5PKkKfZ/gZ9row41SjVmTVQNWQhaRRGpOKw==",
|
"integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -3691,9 +3697,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@testing-library/react": {
|
"node_modules/@testing-library/react": {
|
||||||
"version": "16.3.1",
|
"version": "16.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz",
|
||||||
"integrity": "sha512-gr4KtAWqIOQoucWYD/f6ki+j5chXfcPc74Col/6poTyqTmn7zRmodWahWRCp8tYd+GMqBonw6hstNzqjbs6gjw==",
|
"integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5"
|
"@babel/runtime": "^7.12.5"
|
||||||
@ -3952,6 +3958,16 @@
|
|||||||
"@types/istanbul-lib-report": "*"
|
"@types/istanbul-lib-report": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/jest": {
|
||||||
|
"version": "27.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz",
|
||||||
|
"integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jest-matcher-utils": "^27.0.0",
|
||||||
|
"pretty-format": "^27.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
@ -3971,13 +3987,10 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "25.0.9",
|
"version": "16.18.126",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz",
|
||||||
"integrity": "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==",
|
"integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"dependencies": {
|
|
||||||
"undici-types": "~7.16.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"node_modules/@types/node-forge": {
|
"node_modules/@types/node-forge": {
|
||||||
"version": "1.3.14",
|
"version": "1.3.14",
|
||||||
@ -4018,6 +4031,24 @@
|
|||||||
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
|
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react": {
|
||||||
|
"version": "19.2.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.10.tgz",
|
||||||
|
"integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"csstype": "^3.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/react-dom": {
|
||||||
|
"version": "19.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
|
||||||
|
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/react": "^19.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/resolve": {
|
"node_modules/@types/resolve": {
|
||||||
"version": "1.17.1",
|
"version": "1.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
|
||||||
@ -4768,12 +4799,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ansi-styles": {
|
"node_modules/ansi-styles": {
|
||||||
"version": "5.2.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||||
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^2.0.1"
|
||||||
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=8"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
@ -5114,9 +5148,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.13.2",
|
"version": "1.13.4",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.4.tgz",
|
||||||
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
|
"integrity": "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
@ -5248,13 +5282,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-plugin-polyfill-corejs2": {
|
"node_modules/babel-plugin-polyfill-corejs2": {
|
||||||
"version": "0.4.14",
|
"version": "0.4.15",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz",
|
||||||
"integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==",
|
"integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/compat-data": "^7.27.7",
|
"@babel/compat-data": "^7.28.6",
|
||||||
"@babel/helper-define-polyfill-provider": "^0.6.5",
|
"@babel/helper-define-polyfill-provider": "^0.6.6",
|
||||||
"semver": "^6.3.1"
|
"semver": "^6.3.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@ -5284,12 +5318,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-plugin-polyfill-regenerator": {
|
"node_modules/babel-plugin-polyfill-regenerator": {
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz",
|
||||||
"integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==",
|
"integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-define-polyfill-provider": "^0.6.5"
|
"@babel/helper-define-polyfill-provider": "^0.6.6"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||||
@ -5394,9 +5428,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/baseline-browser-mapping": {
|
"node_modules/baseline-browser-mapping": {
|
||||||
"version": "2.9.15",
|
"version": "2.9.18",
|
||||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.15.tgz",
|
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.18.tgz",
|
||||||
"integrity": "sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==",
|
"integrity": "sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"baseline-browser-mapping": "dist/cli.js"
|
"baseline-browser-mapping": "dist/cli.js"
|
||||||
@ -5715,9 +5749,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001764",
|
"version": "1.0.30001766",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz",
|
||||||
"integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==",
|
"integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@ -5759,21 +5793,6 @@
|
|||||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/chalk/node_modules/ansi-styles": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"color-convert": "^2.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/char-regex": {
|
"node_modules/char-regex": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
|
||||||
@ -6189,9 +6208,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/core-js": {
|
"node_modules/core-js": {
|
||||||
"version": "3.47.0",
|
"version": "3.48.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.48.0.tgz",
|
||||||
"integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==",
|
"integrity": "sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
@ -6200,12 +6219,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/core-js-compat": {
|
"node_modules/core-js-compat": {
|
||||||
"version": "3.47.0",
|
"version": "3.48.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz",
|
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz",
|
||||||
"integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==",
|
"integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"browserslist": "^4.28.0"
|
"browserslist": "^4.28.1"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@ -6213,9 +6232,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/core-js-pure": {
|
"node_modules/core-js-pure": {
|
||||||
"version": "3.47.0",
|
"version": "3.48.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.47.0.tgz",
|
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.48.0.tgz",
|
||||||
"integrity": "sha512-BcxeDbzUrRnXGYIVAGFtcGQVNpFcUhVjr6W7F8XktvQW2iJP9e66GP6xdKotCRFlrxBvNIBrhwKteRXqMV86Nw==",
|
"integrity": "sha512-1slJgk89tWC51HQ1AEqG+s2VuwpTRr8ocu4n20QUcH1v9lAN0RXen0Q0AABa/DK1I7RrNWLucplOHMx8hfTGTw==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
@ -7139,9 +7158,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.267",
|
"version": "1.5.279",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.279.tgz",
|
||||||
"integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
|
"integrity": "sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/emittery": {
|
"node_modules/emittery": {
|
||||||
@ -10872,6 +10891,18 @@
|
|||||||
"@types/yargs-parser": "*"
|
"@types/yargs-parser": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jest-watch-typeahead/node_modules/ansi-styles": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jest-watch-typeahead/node_modules/emittery": {
|
"node_modules/jest-watch-typeahead/node_modules/emittery": {
|
||||||
"version": "0.10.2",
|
"version": "0.10.2",
|
||||||
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz",
|
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz",
|
||||||
@ -11459,9 +11490,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.23",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lodash.debounce": {
|
"node_modules/lodash.debounce": {
|
||||||
@ -13762,6 +13793,18 @@
|
|||||||
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
|
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pretty-format/node_modules/ansi-styles": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/process-nextick-args": {
|
"node_modules/process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
@ -13963,9 +14006,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "19.2.3",
|
"version": "19.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
|
||||||
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
|
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
@ -14104,15 +14147,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "19.2.3",
|
"version": "19.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
|
||||||
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
|
"integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.27.0"
|
"scheduler": "^0.27.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^19.2.3"
|
"react": "^19.2.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-error-overlay": {
|
"node_modules/react-error-overlay": {
|
||||||
@ -14138,6 +14181,15 @@
|
|||||||
"react-dom": ">=16"
|
"react-dom": ">=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-icons": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
@ -14154,9 +14206,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
"version": "7.12.0",
|
"version": "7.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.0.tgz",
|
||||||
"integrity": "sha512-kTPDYPFzDVGIIGNLS5VJykK0HfHLY5MF3b+xj0/tTyNYL1gF1qs7u67Z9jEhQk2sQ98SUaHxlG31g1JtF7IfVw==",
|
"integrity": "sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cookie": "^1.0.1",
|
"cookie": "^1.0.1",
|
||||||
@ -14784,9 +14836,9 @@
|
|||||||
"license": "CC0-1.0"
|
"license": "CC0-1.0"
|
||||||
},
|
},
|
||||||
"node_modules/sass": {
|
"node_modules/sass": {
|
||||||
"version": "1.97.2",
|
"version": "1.97.3",
|
||||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.97.2.tgz",
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.97.3.tgz",
|
||||||
"integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==",
|
"integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^4.0.0",
|
"chokidar": "^4.0.0",
|
||||||
@ -15026,21 +15078,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/serve-index": {
|
"node_modules/serve-index": {
|
||||||
"version": "1.9.1",
|
"version": "1.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz",
|
||||||
"integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
|
"integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": "~1.3.4",
|
"accepts": "~1.3.8",
|
||||||
"batch": "0.6.1",
|
"batch": "0.6.1",
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"escape-html": "~1.0.3",
|
"escape-html": "~1.0.3",
|
||||||
"http-errors": "~1.6.2",
|
"http-errors": "~1.8.0",
|
||||||
"mime-types": "~2.1.17",
|
"mime-types": "~2.1.35",
|
||||||
"parseurl": "~1.3.2"
|
"parseurl": "~1.3.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/serve-index/node_modules/debug": {
|
"node_modules/serve-index/node_modules/debug": {
|
||||||
@ -15062,38 +15118,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/serve-index/node_modules/http-errors": {
|
"node_modules/serve-index/node_modules/http-errors": {
|
||||||
"version": "1.6.3",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
|
||||||
"integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
|
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"depd": "~1.1.2",
|
"depd": "~1.1.2",
|
||||||
"inherits": "2.0.3",
|
"inherits": "2.0.4",
|
||||||
"setprototypeof": "1.1.0",
|
"setprototypeof": "1.2.0",
|
||||||
"statuses": ">= 1.4.0 < 2"
|
"statuses": ">= 1.5.0 < 2",
|
||||||
|
"toidentifier": "1.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/serve-index/node_modules/inherits": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
|
|
||||||
"license": "ISC"
|
|
||||||
},
|
|
||||||
"node_modules/serve-index/node_modules/ms": {
|
"node_modules/serve-index/node_modules/ms": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/serve-index/node_modules/setprototypeof": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
|
|
||||||
"license": "ISC"
|
|
||||||
},
|
|
||||||
"node_modules/serve-index/node_modules/statuses": {
|
"node_modules/serve-index/node_modules/statuses": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||||
@ -16675,17 +16720,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "5.9.3",
|
"version": "4.9.5",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.17"
|
"node": ">=4.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/unbox-primitive": {
|
"node_modules/unbox-primitive": {
|
||||||
@ -16712,12 +16756,6 @@
|
|||||||
"integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==",
|
"integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/undici-types": {
|
|
||||||
"version": "7.16.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
|
||||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/unicode-canonical-property-names-ecmascript": {
|
"node_modules/unicode-canonical-property-names-ecmascript": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
|
||||||
@ -17736,21 +17774,6 @@
|
|||||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/wrap-ansi/node_modules/ansi-styles": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"color-convert": "^2.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/wrappy": {
|
"node_modules/wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-crypto",
|
"name": "react-crypto",
|
||||||
"version": "0.1.0",
|
"version": "0.2.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
@ -32,6 +32,10 @@
|
|||||||
"@testing-library/jest-dom": "^6.9.1",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
"@testing-library/react": "^16.3.1",
|
"@testing-library/react": "^16.3.1",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
"@types/jest": "^27.5.2",
|
||||||
|
"@types/node": "^16.18.126",
|
||||||
|
"@types/react": "^19.2.9",
|
||||||
|
"@types/react-dom": "^19.2.3",
|
||||||
"axios": "^1.13.0",
|
"axios": "^1.13.0",
|
||||||
"chart.js": "^4.5.0",
|
"chart.js": "^4.5.0",
|
||||||
"chartjs-adapter-date-fns": "^3.0.0",
|
"chartjs-adapter-date-fns": "^3.0.0",
|
||||||
@ -40,10 +44,12 @@
|
|||||||
"react-chartjs-2": "^5.3.0",
|
"react-chartjs-2": "^5.3.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
"react-hot-toast": "^2.6.0",
|
"react-hot-toast": "^2.6.0",
|
||||||
|
"react-icons": "^5.5.0",
|
||||||
"react-router": "^7.7.0",
|
"react-router": "^7.7.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-spinners": "^0.17.0",
|
"react-spinners": "^0.17.0",
|
||||||
"sass": "^1.97.0",
|
"sass": "^1.97.0",
|
||||||
|
"typescript": "^4.9.5",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
"zustand": "^5.0.0"
|
"zustand": "^5.0.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
work correctly both with client-side routing and a non-root public URL.
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>React App</title>
|
<title>Crypto-Viewer</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|||||||
38
src/App.css
Normal file
38
src/App.css
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
.App {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-logo {
|
||||||
|
height: 40vmin;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.App-logo {
|
||||||
|
animation: App-logo-spin infinite 20s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-header {
|
||||||
|
background-color: #282c34;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: calc(10px + 2vmin);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-link {
|
||||||
|
color: #61dafb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes App-logo-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
import React from 'react';
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
|
||||||
@ -8,6 +8,7 @@ import Footer from "./components/footer";
|
|||||||
import "./styles/main.scss";
|
import "./styles/main.scss";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header />
|
<Header />
|
||||||
@ -18,9 +19,9 @@ const App = () => {
|
|||||||
<Route path="*" element={<NotFound />} />
|
<Route path="*" element={<NotFound />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
26
src/_App.tsx
Normal file
26
src/_App.tsx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import logo from './logo.svg';
|
||||||
|
import './App.css';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div className="App">
|
||||||
|
<header className="App-header">
|
||||||
|
<img src={logo} className="App-logo" alt="logo" />
|
||||||
|
<p>
|
||||||
|
Edit <code>src/App.tsx</code> and save to reload.
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
className="App-link"
|
||||||
|
href="https://reactjs.org"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Learn React
|
||||||
|
</a>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
@ -1,7 +1,12 @@
|
|||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import { nameShorten } from "../utils/string-helper";
|
import { nameShorten } from "../utils/string-helper";
|
||||||
|
import { ICoinMarketData } from "../utils/interfaces";
|
||||||
|
|
||||||
const CoinCard = ({ coin }) => {
|
interface ICoin {
|
||||||
|
coin: ICoinMarketData;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CoinCard = ({ coin }: ICoin) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link to={`/coin/${coin.id}`} >
|
<Link to={`/coin/${coin.id}`} >
|
||||||
@ -14,16 +19,13 @@ const CoinCard = ({ coin }) => {
|
|||||||
<p>
|
<p>
|
||||||
Price: <span>$ {coin.current_price.toLocaleString()}</span>
|
Price: <span>$ {coin.current_price.toLocaleString()}</span>
|
||||||
</p>
|
</p>
|
||||||
<p className={
|
<p className={coin.price_change_percentage_24h >= 0 ? 'positive' : 'negative'}>
|
||||||
coin?.price_change_percentage_24h
|
|
||||||
? coin.price_change_percentage_24h >= 0 ? 'positive' : 'negative'
|
|
||||||
: ''
|
|
||||||
}>
|
|
||||||
{/* coin.price_change_percentage_24h.toFixed(2) */}
|
{/* coin.price_change_percentage_24h.toFixed(2) */}
|
||||||
{parseFloat(coin?.price_change_percentage_24h || 0).toFixed(2)}
|
{/* {parseFloat(coin?.price_change_percentage_24h || 0).toFixed(2)} */}
|
||||||
|
{coin.price_change_percentage_24h.toFixed(2)} %
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Market Cap: <span>{parseInt(coin?.market_cap || 0).toLocaleString()}</span>
|
Market Cap: <span>{coin?.market_cap.toLocaleString()}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
@ -24,9 +24,33 @@ ChartJS.register(
|
|||||||
TimeScale
|
TimeScale
|
||||||
);
|
);
|
||||||
|
|
||||||
const CoinChart = ({ coinId }) => {
|
interface IProp {
|
||||||
|
coinId: string;
|
||||||
|
}
|
||||||
|
|
||||||
const [chartData, setChartData] = useState(null);
|
interface IQuote {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IDataSet {
|
||||||
|
label: string;
|
||||||
|
data: IQuote[];
|
||||||
|
fill: boolean;
|
||||||
|
borderColor: string;
|
||||||
|
backgroundColor: string;
|
||||||
|
pointRadius: number;
|
||||||
|
tension: number;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IChartData {
|
||||||
|
datasets: IDataSet[],
|
||||||
|
}
|
||||||
|
|
||||||
|
const CoinChart = ({ coinId }: IProp) => {
|
||||||
|
|
||||||
|
const [chartData, setChartData] = useState<IChartData | null>(null);
|
||||||
|
|
||||||
const error = useCoinPricesStore(state => state.error);
|
const error = useCoinPricesStore(state => state.error);
|
||||||
const coinPrices = useCoinPricesStore(state => state.coinPrices);
|
const coinPrices = useCoinPricesStore(state => state.coinPrices);
|
||||||
@ -38,11 +62,11 @@ const CoinChart = ({ coinId }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (coinPrices) {
|
if (coinPrices) {
|
||||||
const quotes = coinPrices.prices.map(price => {
|
const quotes: IQuote[] = coinPrices.map(price => {
|
||||||
return {
|
return {
|
||||||
x: price[0],
|
x: price.timestamp,
|
||||||
y: price[1],
|
y: price.price,
|
||||||
}
|
} as IQuote;
|
||||||
});
|
});
|
||||||
setChartData({
|
setChartData({
|
||||||
datasets: [
|
datasets: [
|
||||||
@ -1,5 +1,10 @@
|
|||||||
|
import { ICoinInfo } from "../utils/interfaces";
|
||||||
|
|
||||||
const CoinInfo = ({ coin }) => {
|
interface ICoinInfoProps {
|
||||||
|
coin: ICoinInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CoinInfo = ({ coin }: ICoinInfoProps) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -9,9 +14,9 @@ const CoinInfo = ({ coin }) => {
|
|||||||
|
|
||||||
{coin && (
|
{coin && (
|
||||||
<>
|
<>
|
||||||
<img src={coin?.image?.large} alt={coin?.name} className="coin-details-image" />
|
<img src={coin?.image_large} alt={coin?.name} className="coin-details-image" />
|
||||||
<p className="coin-details-description">
|
<p className="coin-details-description">
|
||||||
{coin?.description?.en.split(". ")[0] + "."}
|
{coin?.description?.split(". ")[0] + "."}
|
||||||
</p>
|
</p>
|
||||||
<div className="coin-details-info">
|
<div className="coin-details-info">
|
||||||
<h3>
|
<h3>
|
||||||
@ -20,20 +25,20 @@ const CoinInfo = ({ coin }) => {
|
|||||||
<h3>
|
<h3>
|
||||||
Current Price: {" "}
|
Current Price: {" "}
|
||||||
<span>
|
<span>
|
||||||
${coin.market_data.current_price.usd.toLocaleString()}
|
${coin.market_data.current_price.toLocaleString()}
|
||||||
</span>
|
</span>
|
||||||
</h3>
|
</h3>
|
||||||
<h4>
|
<h4>
|
||||||
Market Cap:{" "}
|
Market Cap:{" "}
|
||||||
<span>${coin.market_data.market_cap.usd.toLocaleString()}</span>
|
<span>${coin.market_data.market_cap.toLocaleString()}</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h4>
|
<h4>
|
||||||
24h High:{" "}
|
24h High:{" "}
|
||||||
<span>${coin.market_data.high_24h.usd.toLocaleString()}</span>
|
<span>${coin.market_data.high_24h.toLocaleString()}</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h4>
|
<h4>
|
||||||
24h Low:{" "}
|
24h Low:{" "}
|
||||||
<span>${coin.market_data.low_24h.usd.toLocaleString()}</span>
|
<span>${coin.market_data.low_24h.toLocaleString()}</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h4>
|
<h4>
|
||||||
24h Price Change:{" "}
|
24h Price Change:{" "}
|
||||||
@ -42,6 +47,7 @@ const CoinInfo = ({ coin }) => {
|
|||||||
{coin.market_data.price_change_percentage_24h.toFixed(2)}%)
|
{coin.market_data.price_change_percentage_24h.toFixed(2)}%)
|
||||||
</span>
|
</span>
|
||||||
</h4>
|
</h4>
|
||||||
|
{/*
|
||||||
<h4>
|
<h4>
|
||||||
Circulating Supply:{" "}
|
Circulating Supply:{" "}
|
||||||
<span>
|
<span>
|
||||||
@ -54,18 +60,19 @@ const CoinInfo = ({ coin }) => {
|
|||||||
{coin.market_data.total_supply?.toLocaleString() || "N/A"}
|
{coin.market_data.total_supply?.toLocaleString() || "N/A"}
|
||||||
</span>
|
</span>
|
||||||
</h4>
|
</h4>
|
||||||
|
*/}
|
||||||
<h4>
|
<h4>
|
||||||
All-Time High:{" "}
|
All-Time High:{" "}
|
||||||
<span>
|
<span>
|
||||||
${coin.market_data.ath.usd.toLocaleString()} on{" "}
|
${coin.market_data.ath.toLocaleString()} on{" "}
|
||||||
{new Date(coin.market_data.ath_date.usd).toLocaleDateString()}
|
{new Date(coin.market_data.ath_date).toLocaleDateString()}
|
||||||
</span>
|
</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h4>
|
<h4>
|
||||||
All-Time Low:{" "}
|
All-Time Low:{" "}
|
||||||
<span>
|
<span>
|
||||||
${coin.market_data.atl.usd.toLocaleString()} on{" "}
|
${coin.market_data.atl.toLocaleString()} on{" "}
|
||||||
{new Date(coin.market_data.atl_date.usd).toLocaleDateString()}
|
{new Date(coin.market_data.atl_date).toLocaleDateString()}
|
||||||
</span>
|
</span>
|
||||||
</h4>
|
</h4>
|
||||||
<h4>
|
<h4>
|
||||||
@ -1,7 +1,12 @@
|
|||||||
import { messages } from "../utils/constants";
|
import { messages } from "../utils/constants";
|
||||||
import RefreshButton from "./refresh-button";
|
import RefreshButton from "./refresh-button";
|
||||||
|
|
||||||
const ErrorCard = ({ message }) => {
|
|
||||||
|
export interface IErrorCardProp {
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ErrorCard = ({ message }: IErrorCardProp) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -4,13 +4,13 @@ import { messages } from "../utils/constants";
|
|||||||
const FilterInput = () => {
|
const FilterInput = () => {
|
||||||
const toggleFilter = useFilterStore(state => state.toggleFilter);
|
const toggleFilter = useFilterStore(state => state.toggleFilter);
|
||||||
|
|
||||||
const onFilterChange = (e) => {
|
const onFilterChange = (e:React.ChangeEvent<HTMLInputElement>) => {
|
||||||
toggleFilter(e.target.value);
|
toggleFilter(e.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="filter">
|
<div className="filter">
|
||||||
<input type="text" placeholder={messages.filterPlaceholder} onChange={(e) => onFilterChange(e)} />
|
<input type="text" placeholder={messages.filterPlaceholder} onChange={(e) => onFilterChange(e)}></input>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -5,10 +5,10 @@ const LimitSelector = () => {
|
|||||||
|
|
||||||
const limit = useLimitStore(state => state.limit);
|
const limit = useLimitStore(state => state.limit);
|
||||||
const toggleLimit = useLimitStore(state => state.toggleLimit);
|
const toggleLimit = useLimitStore(state => state.toggleLimit);
|
||||||
|
|
||||||
const onSelectChange = (e) => {
|
const onSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
toggleLimit(parseInt(e.target.value));
|
toggleLimit(parseInt(e.target.value));
|
||||||
fetchCoins( parseInt( e.target.value ) );
|
fetchCoins(parseInt(e.target.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -2,8 +2,9 @@ import { fetchCoins, getCoinsLength } from "../store/coins-market";
|
|||||||
import { getTimestampOfLastPersist } from "../store/coins-market";
|
import { getTimestampOfLastPersist } from "../store/coins-market";
|
||||||
import toast, { Toaster } from "react-hot-toast";
|
import toast, { Toaster } from "react-hot-toast";
|
||||||
import { messages } from "../utils/constants";
|
import { messages } from "../utils/constants";
|
||||||
|
import { MdRefresh } from "react-icons/md";
|
||||||
|
|
||||||
const notify = (text) => toast.error(text, { duration: 3000, id: "reloadRapidDisallowed", style: { textAlign: 'center' } });
|
const notify = (text:string) => toast.error(text, { duration: 3000, id: "reloadRapidDisallowed", style: { textAlign: 'center' } });
|
||||||
|
|
||||||
const RefreshButton = () => {
|
const RefreshButton = () => {
|
||||||
|
|
||||||
@ -14,7 +15,12 @@ const RefreshButton = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button className="refresh-btn" onClick={(e) => onButonClick()} >⟳ Reload</button>
|
<button className="refresh-btn" onClick={(e) => onButonClick()} >
|
||||||
|
<span className="icon">
|
||||||
|
<MdRefresh />
|
||||||
|
</span>
|
||||||
|
Reload
|
||||||
|
</button>
|
||||||
<Toaster />
|
<Toaster />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -5,7 +5,7 @@ const SortSelector = () => {
|
|||||||
const sortBy = useSortByStore(state => state.sortBy);
|
const sortBy = useSortByStore(state => state.sortBy);
|
||||||
const toggleSortBy = useSortByStore(state => state.toggleSortBy);
|
const toggleSortBy = useSortByStore(state => state.toggleSortBy);
|
||||||
|
|
||||||
const onSelectChange = (e) => {
|
const onSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
toggleSortBy(e.target.value);
|
toggleSortBy(e.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
14
src/index.js
14
src/index.js
@ -1,14 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom/client';
|
|
||||||
import { BrowserRouter } from "react-router";
|
|
||||||
import './index.css';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
||||||
root.render(
|
|
||||||
//<React.StrictMode>
|
|
||||||
<BrowserRouter>
|
|
||||||
<App />
|
|
||||||
</BrowserRouter>
|
|
||||||
//</React.StrictMode>
|
|
||||||
);
|
|
||||||
22
src/index.tsx
Normal file
22
src/index.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import { BrowserRouter } from "react-router";
|
||||||
|
import './index.css';
|
||||||
|
import App from './App';
|
||||||
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(
|
||||||
|
document.getElementById('root') as HTMLElement
|
||||||
|
);
|
||||||
|
root.render(
|
||||||
|
//<React.StrictMode>
|
||||||
|
<BrowserRouter>
|
||||||
|
<App />
|
||||||
|
</BrowserRouter>
|
||||||
|
//</React.StrictMode>
|
||||||
|
);
|
||||||
|
|
||||||
|
// If you want to start measuring performance in your app, pass a function
|
||||||
|
// to log results (for example: reportWebVitals(console.log))
|
||||||
|
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||||
|
//reportWebVitals();
|
||||||
@ -7,7 +7,7 @@ import Spinner from "../components/spinner";
|
|||||||
|
|
||||||
const CoinDetail = () => {
|
const CoinDetail = () => {
|
||||||
|
|
||||||
const { id } = useParams();
|
const { id } = useParams<string>();
|
||||||
|
|
||||||
const coin = useCoinInfoStore(state => state.coinInfo);
|
const coin = useCoinInfoStore(state => state.coinInfo);
|
||||||
const loading = useCoinInfoStore(state => state.loading);
|
const loading = useCoinInfoStore(state => state.loading);
|
||||||
@ -19,7 +19,7 @@ const CoinDetail = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetch = async () => {
|
const fetch = async () => {
|
||||||
fetchCoinInfos(id);
|
fetchCoinInfos( String(id));
|
||||||
}
|
}
|
||||||
fetch();
|
fetch();
|
||||||
}, [id]);
|
}, [id]);
|
||||||
@ -10,6 +10,7 @@ import Spinner from "../components/spinner";
|
|||||||
import RefreshButton from "../components/refresh-button";
|
import RefreshButton from "../components/refresh-button";
|
||||||
import ErrorCard from "../components/error-card";
|
import ErrorCard from "../components/error-card";
|
||||||
import { initialCoinsCoint } from "../utils/conf";
|
import { initialCoinsCoint } from "../utils/conf";
|
||||||
|
import { ICoinMarketData } from "../utils/interfaces";
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ const Home = () => {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
let filteredCoins = [];
|
let filteredCoins:ICoinMarketData[] = [];
|
||||||
|
|
||||||
if (coins) {
|
if (coins) {
|
||||||
filteredCoins = coinsFilter(coins, filter, sortBy);
|
filteredCoins = coinsFilter(coins, filter, sortBy);
|
||||||
1
src/react-app-env.d.ts
vendored
Normal file
1
src/react-app-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/// <reference types="react-scripts" />
|
||||||
@ -1,4 +1,6 @@
|
|||||||
const reportWebVitals = onPerfEntry => {
|
import { ReportHandler } from 'web-vitals';
|
||||||
|
|
||||||
|
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
|
||||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||||
getCLS(onPerfEntry);
|
getCLS(onPerfEntry);
|
||||||
@ -1,86 +0,0 @@
|
|||||||
import { create } from "zustand";
|
|
||||||
import axios from "axios";
|
|
||||||
import { join } from "../utils/path";
|
|
||||||
import { messages } from "../utils/constants";
|
|
||||||
import { apiBaseUrl, apiKey } from "../utils/conf";
|
|
||||||
import sleep from "../utils/sleep";
|
|
||||||
|
|
||||||
const init = {
|
|
||||||
coinId: null,
|
|
||||||
coinInfo: null,
|
|
||||||
loading: false,
|
|
||||||
error: null,
|
|
||||||
ts: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useCoinInfoStore = create((set, get) => ({
|
|
||||||
|
|
||||||
...init,
|
|
||||||
clear: () => {
|
|
||||||
set(state => ({
|
|
||||||
coinId: null,
|
|
||||||
coinInfo: null,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
persistCoinInfo: (coinId, coinInfo) => {
|
|
||||||
set(state => ({
|
|
||||||
coinId: coinId,
|
|
||||||
coinInfo: coinInfo,
|
|
||||||
ts: Date.now(),
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
setError: (message) => {
|
|
||||||
set(state => ({
|
|
||||||
error: message,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
fetch: async (id) => {
|
|
||||||
try {
|
|
||||||
set({ loading: true });
|
|
||||||
if (get().ts) await sleep(get().ts);
|
|
||||||
const keyParam = (apiKey()) ? `?x_cg_demo_api_key=${apiKey()}` : "";
|
|
||||||
const url = join(
|
|
||||||
apiBaseUrl(),
|
|
||||||
`coins/${id}${keyParam}`
|
|
||||||
);
|
|
||||||
const res = await axios.get(url);
|
|
||||||
get().persistCoinInfo(id, res.data);
|
|
||||||
} catch (err) {
|
|
||||||
switch (err.code) {
|
|
||||||
case 'ERR_NETWORK':
|
|
||||||
get().setError(messages.serverOverload);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
get().setError(err.message);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
set({ loading: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const reset = () => {
|
|
||||||
useCoinInfoStore.getState().clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
export const persist = (coinId, coinInfo) => {
|
|
||||||
useCoinInfoStore.getState().persistCoinPrices(coinId, coinInfo);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toggleLoading = (isLoading) => {
|
|
||||||
useCoinInfoStore.setState({ loading: isLoading })
|
|
||||||
};
|
|
||||||
|
|
||||||
export const errorLoading = (message) => {
|
|
||||||
useCoinInfoStore.setState()({ error: message });
|
|
||||||
};
|
|
||||||
|
|
||||||
export const fetchCoinInfos = (coinId) => {
|
|
||||||
useCoinInfoStore.getState().fetch(coinId);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getTimestampOfLastPersist = () => {
|
|
||||||
return useCoinInfoStore.getState().ts;
|
|
||||||
}
|
|
||||||
146
src/store/coin-info.ts
Normal file
146
src/store/coin-info.ts
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import { create } from "zustand";
|
||||||
|
import axios from "axios";
|
||||||
|
import { join } from "../utils/path";
|
||||||
|
import { messages } from "../utils/constants";
|
||||||
|
import { apiBaseUrl, apiKey } from "../utils/conf";
|
||||||
|
import sleep from "../utils/sleep";
|
||||||
|
import { ICoinInfo, ICoinInfoMarketData } from "../utils/interfaces";
|
||||||
|
|
||||||
|
const init = {
|
||||||
|
coinId: null,
|
||||||
|
coinInfo: null,
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
ts: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ICoinsInfoState {
|
||||||
|
coinId: string | null;
|
||||||
|
coinInfo: ICoinInfo | null;
|
||||||
|
loading: boolean;
|
||||||
|
error: string | null;
|
||||||
|
ts: number;
|
||||||
|
|
||||||
|
clear: () => void;
|
||||||
|
persistCoinInfo: (coinId: string, coinInfo: ICoinInfo) => void;
|
||||||
|
setError: (message: string) => void;
|
||||||
|
fetch: (id: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const useCoinInfoStore = create<ICoinsInfoState>((set, get) => ({
|
||||||
|
...init,
|
||||||
|
clear: () => {
|
||||||
|
set(state => ({
|
||||||
|
coinId: null,
|
||||||
|
coinInfo: null,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
persistCoinInfo: (coinId, coinInfo) => {
|
||||||
|
set(state => ({
|
||||||
|
coinId: coinId,
|
||||||
|
coinInfo: coinInfo,
|
||||||
|
ts: Date.now(),
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
setError: (message) => {
|
||||||
|
set(state => ({
|
||||||
|
error: message,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
fetch: async (id) => {
|
||||||
|
try {
|
||||||
|
set({ loading: true });
|
||||||
|
if (get().ts) await sleep(get().ts);
|
||||||
|
const keyParam = (apiKey()) ? `?x_cg_demo_api_key=${apiKey()}` : "";
|
||||||
|
const url = join(
|
||||||
|
apiBaseUrl(),
|
||||||
|
`coins/${id}${keyParam}`
|
||||||
|
);
|
||||||
|
const res = await axios.get(url);
|
||||||
|
const { symbol, name, image, description, market_cap_rank, last_updated } = res.data;
|
||||||
|
const {
|
||||||
|
current_price,
|
||||||
|
market_cap,
|
||||||
|
high_24h,
|
||||||
|
low_24h,
|
||||||
|
price_change_24h,
|
||||||
|
price_change_percentage_24h,
|
||||||
|
circulating_supply,
|
||||||
|
total_supply,
|
||||||
|
ath_date,
|
||||||
|
atl_date,
|
||||||
|
ath,
|
||||||
|
atl
|
||||||
|
} = res.data?.market_data;
|
||||||
|
|
||||||
|
const coinInfo: ICoinInfo = {
|
||||||
|
id: res.data?.id ?? "",
|
||||||
|
symbol: symbol ?? "",
|
||||||
|
name: name ?? "",
|
||||||
|
image_thumb: image?.thumb ?? "",
|
||||||
|
image_small: image?.small ?? "",
|
||||||
|
image_large: image?.large ?? "",
|
||||||
|
description: description?.en ?? "",
|
||||||
|
market_cap_rank: market_cap_rank ?? 0,
|
||||||
|
last_updated: last_updated ?? 0,
|
||||||
|
market_data: {
|
||||||
|
current_price: current_price?.usd ?? 0,
|
||||||
|
market_cap: market_cap?.usd ?? 0,
|
||||||
|
high_24h: high_24h?.usd ?? 0,
|
||||||
|
low_24h: low_24h?.usd ?? 0,
|
||||||
|
price_change_24h: price_change_24h ?? 0,
|
||||||
|
price_change_percentage_24h: price_change_percentage_24h ?? 0,
|
||||||
|
circulating_supply: circulating_supply ?? 0,
|
||||||
|
total_supply: total_supply ?? 0,
|
||||||
|
ath_date: ath_date?.usd ?? "",
|
||||||
|
atl_date: atl_date?.usd ?? "",
|
||||||
|
ath: ath?.usd ?? 0,
|
||||||
|
atl: atl?.usd ?? 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get().persistCoinInfo(id, coinInfo);
|
||||||
|
} catch (err) {
|
||||||
|
if (axios.isAxiosError(err)) {
|
||||||
|
switch (err.code) {
|
||||||
|
case 'ERR_NETWORK':
|
||||||
|
get().setError(messages.serverOverload);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
get().setError(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
get().setError((err as Error).message);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
set({ loading: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const reset = () => {
|
||||||
|
useCoinInfoStore.getState().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
export const persist = (coinId: string, coinInfo: ICoinInfo) => {
|
||||||
|
useCoinInfoStore.getState().persistCoinInfo(coinId, coinInfo);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const toggleLoading = (isLoading: boolean) => {
|
||||||
|
useCoinInfoStore.setState({ loading: isLoading })
|
||||||
|
};
|
||||||
|
|
||||||
|
export const errorLoading = (message: string) => {
|
||||||
|
useCoinInfoStore.getState().setError(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchCoinInfos = (coinId: string) => {
|
||||||
|
useCoinInfoStore.getState().fetch(coinId);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTimestampOfLastPersist = () => {
|
||||||
|
return useCoinInfoStore.getState().ts;
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ import { join } from "../utils/path";
|
|||||||
import { messages } from "../utils/constants";
|
import { messages } from "../utils/constants";
|
||||||
import { apiBaseUrl, apiKey } from "../utils/conf";
|
import { apiBaseUrl, apiKey } from "../utils/conf";
|
||||||
import sleep from "../utils/sleep";
|
import sleep from "../utils/sleep";
|
||||||
|
import { ICoinMarketData } from "../utils/interfaces";
|
||||||
|
|
||||||
const init = {
|
const init = {
|
||||||
coins: null,
|
coins: null,
|
||||||
@ -13,7 +14,20 @@ const init = {
|
|||||||
ts: 0,
|
ts: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCoinsMarketStore = create((set, get) => {
|
interface ICoinsMarketState {
|
||||||
|
coins: ICoinMarketData[] | null;
|
||||||
|
size: number;
|
||||||
|
loading: boolean;
|
||||||
|
error: string | null;
|
||||||
|
ts: number;
|
||||||
|
reset: () => void;
|
||||||
|
persistCoins: (coins: ICoinMarketData[]) => void;
|
||||||
|
setError: (message: string) => void;
|
||||||
|
fetch: (limit: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const useCoinsMarketStore = create<ICoinsMarketState>((set, get) => {
|
||||||
return {
|
return {
|
||||||
...init,
|
...init,
|
||||||
reset: () => {
|
reset: () => {
|
||||||
@ -21,18 +35,6 @@ export const useCoinsMarketStore = create((set, get) => {
|
|||||||
...init,
|
...init,
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
addCoins: (coins) => {
|
|
||||||
set(state => ({
|
|
||||||
coins: [...state.coins, ...coins]
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
|
|
||||||
removeCoin: (coinId) => {
|
|
||||||
set(state => ({
|
|
||||||
coins: state.coins.filter(coin => coin.id !== coinId)
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
|
|
||||||
persistCoins: (coins) => {
|
persistCoins: (coins) => {
|
||||||
set(state => ({
|
set(state => ({
|
||||||
size: coins.length,
|
size: coins.length,
|
||||||
@ -56,14 +58,32 @@ export const useCoinsMarketStore = create((set, get) => {
|
|||||||
`coins/markets?vs_currency=usd&order=market_cap_desc&per_page=${limit}&page=1&sparkline=false${keyParam}`,
|
`coins/markets?vs_currency=usd&order=market_cap_desc&per_page=${limit}&page=1&sparkline=false${keyParam}`,
|
||||||
);
|
);
|
||||||
const res = await axios.get(url);
|
const res = await axios.get(url);
|
||||||
get().persistCoins(res.data);
|
|
||||||
|
const coins: ICoinMarketData[] = res.data.map((item: any) => {
|
||||||
|
const obj: ICoinMarketData = {
|
||||||
|
id: item["id"],
|
||||||
|
symbol: item["symbol"],
|
||||||
|
name: item["name"],
|
||||||
|
image: item["image"],
|
||||||
|
current_price: parseFloat(item["current_price"]),
|
||||||
|
market_cap: parseInt(item["market_cap"]),
|
||||||
|
market_cap_rank: parseInt(item["market_cap_rank"]),
|
||||||
|
price_change_percentage_24h: parseFloat(item["price_change_percentage_24h"]),
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
});
|
||||||
|
get().persistCoins(coins);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
switch (err.code) {
|
if (axios.isAxiosError(err)) {
|
||||||
case 'ERR_NETWORK':
|
switch (err.code) {
|
||||||
get().setError(messages.serverOverload);
|
case 'ERR_NETWORK':
|
||||||
break;
|
get().setError(messages.serverOverload);
|
||||||
default:
|
break;
|
||||||
get().setError(err.message);
|
default:
|
||||||
|
get().setError(err.message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
get().setError((err as Error).message);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
set({ loading: false });
|
set({ loading: false });
|
||||||
@ -77,23 +97,19 @@ export const reset = () => {
|
|||||||
useCoinsMarketStore.getState().reset();
|
useCoinsMarketStore.getState().reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tsLastFetch = () => {
|
|
||||||
return useCoinsMarketStore.getState().ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getTimestampOfLastPersist = () => {
|
export const getTimestampOfLastPersist = () => {
|
||||||
return useCoinsMarketStore.getState().ts;
|
return useCoinsMarketStore.getState().ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const persist = (coins) => {
|
export const persist = (coins: any[]) => {
|
||||||
useCoinsMarketStore.getState().persistCoins(coins);
|
useCoinsMarketStore.getState().persistCoins(coins);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const toggleLoading = (isLoading) => {
|
export const toggleLoading = (isLoading: boolean) => {
|
||||||
useCoinsMarketStore.setState({ loading: isLoading })
|
useCoinsMarketStore.setState({ loading: isLoading })
|
||||||
};
|
};
|
||||||
|
|
||||||
export const errorLoading = (message) => {
|
export const errorLoading = (message: string) => {
|
||||||
useCoinsMarketStore.getState().setError(message);
|
useCoinsMarketStore.getState().setError(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1,9 +1,9 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import axios from "axios";
|
import axios, { AxiosError } from "axios";
|
||||||
import { join } from "../utils/path";
|
import { join } from "../utils/path";
|
||||||
import { messages } from "../utils/constants";
|
import { messages } from "../utils/constants";
|
||||||
import { apiBaseUrl, apiKey } from "../utils/conf";
|
import { apiBaseUrl, apiKey } from "../utils/conf";
|
||||||
import sleep from "../utils/sleep";
|
import { ICoinPrice } from "../utils/interfaces"
|
||||||
|
|
||||||
const init = {
|
const init = {
|
||||||
coinId: null,
|
coinId: null,
|
||||||
@ -12,7 +12,18 @@ const init = {
|
|||||||
error: null,
|
error: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCoinPricesStore = create((set, get) => {
|
interface ICoinPricesState {
|
||||||
|
coinId: string | null;
|
||||||
|
coinPrices: ICoinPrice[] | null;
|
||||||
|
loading: boolean;
|
||||||
|
error: string | null;
|
||||||
|
reset: () => void;
|
||||||
|
persistCoinPrices: (coinId: string, coinPrices: ICoinPrice[]) => void;
|
||||||
|
setError: (message: string) => void;
|
||||||
|
fetch: (coinId: string, limit: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useCoinPricesStore = create<ICoinPricesState>((set, get) => {
|
||||||
return {
|
return {
|
||||||
...init,
|
...init,
|
||||||
reset: () => {
|
reset: () => {
|
||||||
@ -34,18 +45,30 @@ export const useCoinPricesStore = create((set, get) => {
|
|||||||
fetch: async (coinId, limit) => {
|
fetch: async (coinId, limit) => {
|
||||||
try {
|
try {
|
||||||
set({ loading: true });
|
set({ loading: true });
|
||||||
if (get().ts) await sleep(get().ts);
|
|
||||||
const keyParam = (apiKey()) ? `&x_cg_demo_api_key=${apiKey()}` : "";
|
const keyParam = (apiKey()) ? `&x_cg_demo_api_key=${apiKey()}` : "";
|
||||||
const url = join(apiBaseUrl(), `coins/${coinId}/market_chart?vs_currency=usd&days=${limit}${keyParam}`);
|
const url = join(apiBaseUrl(), `coins/${coinId}/market_chart?vs_currency=usd&days=${limit}${keyParam}`);
|
||||||
const res = await axios.get(url);
|
const res = await axios.get(url);
|
||||||
get().persistCoinPrices(coinId, res.data);
|
|
||||||
|
let prices: ICoinPrice[] = res.data?.["prices"].map((item: any) => {
|
||||||
|
let price: ICoinPrice = {
|
||||||
|
price: item[1],
|
||||||
|
timestamp: item[0],
|
||||||
|
}
|
||||||
|
return price;
|
||||||
|
});
|
||||||
|
get().persistCoinPrices(coinId, prices);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
switch (err.code) {
|
if (axios.isAxiosError(err)) {
|
||||||
case 'ERR_NETWORK':
|
switch (err.code) {
|
||||||
get().setError(messages.serverOverload);
|
case 'ERR_NETWORK':
|
||||||
break;
|
get().setError(messages.serverOverload);
|
||||||
default:
|
break;
|
||||||
get().setError(err.message);
|
default:
|
||||||
|
get().setError(err.message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
get().setError((err as Error).message);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
set({ loading: false });
|
set({ loading: false });
|
||||||
@ -58,18 +81,18 @@ export const reset = () => {
|
|||||||
useCoinPricesStore.getState().reset();
|
useCoinPricesStore.getState().reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
export const persist = (coinId, prices) => {
|
export const persist = (coinId: string, prices: ICoinPrice[]) => {
|
||||||
useCoinPricesStore.getState().persistCoinPrices(coinId, prices);
|
useCoinPricesStore.getState().persistCoinPrices(coinId, prices);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const toggleLoading = (isLoading) => {
|
export const toggleLoading = (isLoading: boolean) => {
|
||||||
useCoinPricesStore.setState({ loading: isLoading })
|
useCoinPricesStore.setState({ loading: isLoading })
|
||||||
};
|
};
|
||||||
|
|
||||||
export const errorLoading = (message) => {
|
export const errorLoading = (message: string) => {
|
||||||
useCoinPricesStore.setState({ error: message });
|
useCoinPricesStore.setState({ error: message });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchCoinPrices = (coinId, limit = 10) => {
|
export const fetchCoinPrices = (coinId: string, limit = 10) => {
|
||||||
useCoinPricesStore.getState().fetch(coinId, limit);
|
useCoinPricesStore.getState().fetch(coinId, limit);
|
||||||
};
|
};
|
||||||
@ -1,7 +1,13 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { SortBy } from "../utils/enum";
|
import { SortBy } from "../utils/enum";
|
||||||
|
|
||||||
export const useRefreshStore = create((set, get) => {
|
interface IRefreshControlStore {
|
||||||
|
previousRefreshDatetime: number | null;
|
||||||
|
refreshDatetime: number | null;
|
||||||
|
refresh: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useRefreshStore = create<IRefreshControlStore>((set, get) => {
|
||||||
return {
|
return {
|
||||||
previousRefreshDatetime: null,
|
previousRefreshDatetime: null,
|
||||||
refreshDatetime: null,
|
refreshDatetime: null,
|
||||||
@ -14,7 +20,13 @@ export const useRefreshStore = create((set, get) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useFilterStore = create((set, get) => {
|
|
||||||
|
interface IFilterControlStore {
|
||||||
|
filter: string;
|
||||||
|
toggleFilter: (filter: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useFilterStore = create<IFilterControlStore>((set, get) => {
|
||||||
return {
|
return {
|
||||||
filter: "",
|
filter: "",
|
||||||
toggleFilter: (filter) => {
|
toggleFilter: (filter) => {
|
||||||
@ -26,10 +38,16 @@ export const useFilterStore = create((set, get) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const clearFilter = () => {
|
export const clearFilter = () => {
|
||||||
useFilterStore.setState({filter: ""});
|
useFilterStore.setState({ filter: "" });
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useSortByStore = create((set, get) => {
|
|
||||||
|
interface ISortByControlStore {
|
||||||
|
sortBy: string;
|
||||||
|
toggleSortBy: (sortBy: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSortByStore = create<ISortByControlStore>((set, get) => {
|
||||||
return {
|
return {
|
||||||
sortBy: SortBy.MARKET_CAP_DESC,
|
sortBy: SortBy.MARKET_CAP_DESC,
|
||||||
toggleSortBy: (sortBy) => {
|
toggleSortBy: (sortBy) => {
|
||||||
@ -40,7 +58,12 @@ export const useSortByStore = create((set, get) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useLimitStore = create((set, get) => {
|
interface ILimitControlStore {
|
||||||
|
limit: number;
|
||||||
|
toggleLimit: (limit: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useLimitStore = create<ILimitControlStore>((set, get) => {
|
||||||
return {
|
return {
|
||||||
limit: 10,
|
limit: 10,
|
||||||
toggleLimit: (limit) => {
|
toggleLimit: (limit) => {
|
||||||
@ -1,7 +1,7 @@
|
|||||||
/* About Page */
|
/* About Page */
|
||||||
.about {
|
.about {
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
margin: 2rem auto;
|
margin: 0rem auto;
|
||||||
background-color: #161b22;
|
background-color: #161b22;
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
.coin-details-container {
|
.coin-details-container {
|
||||||
max-width: 700px;
|
max-width: 700px;
|
||||||
margin: 40px auto;
|
margin: 0px auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
h3,
|
h3,
|
||||||
h4 {
|
h4 {
|
||||||
margin: 5px 0;
|
margin: 4px 0;
|
||||||
color: #222;
|
color: #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,7 +53,8 @@
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
&.refresh-btn {
|
&.refresh-btn {
|
||||||
padding: 0.75rem 1rem;
|
position: relative;
|
||||||
|
padding: 0.75rem 0.5rem 0.75rem 2rem;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: none;
|
border: none;
|
||||||
background: $controls-bg-color;
|
background: $controls-bg-color;
|
||||||
@ -64,5 +65,12 @@ button {
|
|||||||
&:hover {
|
&:hover {
|
||||||
background: #2b303a;
|
background: #2b303a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
top: 8px;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,3 @@
|
|||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
background-color: $background-color;
|
background-color: $background-color;
|
||||||
@ -15,10 +9,12 @@ body {
|
|||||||
h1 {
|
h1 {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
30
src/styles/_reset.css
Normal file
30
src/styles/_reset.css
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
*, *:before, *:after {
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body, h1, h2, h3, h4, h5, h6, p, ol, ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol, ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
@import 'variables';
|
@import 'variables';
|
||||||
@import 'common';
|
@import 'reset';
|
||||||
|
@import 'global';
|
||||||
@import 'controls';
|
@import 'controls';
|
||||||
@import 'nav';
|
@import 'nav';
|
||||||
@import 'about';
|
@import 'about';
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { SortBy } from "./enum";
|
import { SortBy } from "./enum";
|
||||||
|
import { ICoinMarketData } from "../utils/interfaces";
|
||||||
|
|
||||||
export const coinsFilter = (coins, filter, sortBy) => {
|
export const coinsFilter = (coins: ICoinMarketData[], filter: string, sortBy: string) => {
|
||||||
let filteredCoins = coins
|
let filteredCoins = coins
|
||||||
.filter(coin => {
|
.filter(coin => {
|
||||||
return (
|
return (
|
||||||
@ -1,10 +1,10 @@
|
|||||||
const env = process.env;
|
const env = process.env;
|
||||||
|
|
||||||
export const apiBaseUrl = () => env?.REACT_APP_CRYPTO_API || "";
|
export const apiBaseUrl = () => env?.REACT_APP_CRYPTO_API || "";
|
||||||
export const apiReloadWaitTime = () => env?.REACT_APP_API_RELOAD_WAIT_TIME || 3000;
|
export const apiReloadWaitTime = () => env?.REACT_APP_API_RELOAD_WAIT_TIME ? parseInt(env.REACT_APP_API_RELOAD_WAIT_TIME) : 3000;
|
||||||
export const isNetworkOnline = () => env?.REACT_APP_NETWORK_ONLINE || true;
|
export const isNetworkOnline = () => env?.REACT_APP_NETWORK_ONLINE ? Boolean(env.REACT_APP_NETWORK_ONLINE) : true;
|
||||||
export const rateLimitInterval = () => env?.REACT_APP_NETWORK_RATE_LIMIT_INTERVAL || 5000;
|
export const rateLimitInterval = () => env?.REACT_APP_NETWORK_RATE_LIMIT_INTERVAL ? parseInt(env.REACT_APP_NETWORK_RATE_LIMIT_INTERVAL) : 5000;
|
||||||
export const apiKey = () => env?.REACT_APP_CRYPTO_API_KEY || "";
|
export const apiKey = () => env?.REACT_APP_CRYPTO_API_KEY || "";
|
||||||
export const footerLinkUrl = () => env?.REACT_APP_FOOTER_LINK_URL || "";
|
export const footerLinkUrl = () => env?.REACT_APP_FOOTER_LINK_URL || "";
|
||||||
export const footerLinkText = () => env?.REACT_APP_FOOTER_LINK_TEXT || "";
|
export const footerLinkText = () => env?.REACT_APP_FOOTER_LINK_TEXT || "";
|
||||||
export const initialCoinsCoint = () => env?.REACT_APP_INITIAL_COINS_COUNT || 10;
|
export const initialCoinsCoint = () => env?.REACT_APP_INITIAL_COINS_COUNT ? parseInt(env.REACT_APP_INITIAL_COINS_COUNT) : 10;
|
||||||
47
src/utils/interfaces.ts
Normal file
47
src/utils/interfaces.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
export interface ICoinPrice {
|
||||||
|
timestamp: number;
|
||||||
|
price: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface ICoinMarketData {
|
||||||
|
id: string;
|
||||||
|
symbol: string;
|
||||||
|
name: string;
|
||||||
|
image: string;
|
||||||
|
current_price: number;
|
||||||
|
market_cap: number;
|
||||||
|
market_cap_rank: number;
|
||||||
|
price_change_percentage_24h: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface ICoinInfoMarketData {
|
||||||
|
//currency: string;
|
||||||
|
current_price:number;
|
||||||
|
market_cap:number;
|
||||||
|
high_24h:number;
|
||||||
|
low_24h:number;
|
||||||
|
price_change_24h:number;
|
||||||
|
price_change_percentage_24h:number;
|
||||||
|
circulating_supply:number;
|
||||||
|
total_supply:number;
|
||||||
|
ath_date:string;
|
||||||
|
ath:number;
|
||||||
|
atl_date:string;
|
||||||
|
atl:number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICoinInfo {
|
||||||
|
id: string;
|
||||||
|
symbol: string;
|
||||||
|
name: string;
|
||||||
|
image_thumb:string;
|
||||||
|
image_small:string;
|
||||||
|
image_large:string;
|
||||||
|
description:string;
|
||||||
|
market_cap_rank:number;
|
||||||
|
last_updated:number;
|
||||||
|
market_data: ICoinInfoMarketData;
|
||||||
|
}
|
||||||
|
|
||||||
@ -3,21 +3,17 @@
|
|||||||
* @param {...string} segments
|
* @param {...string} segments
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
export const join = (...segments) => {
|
export const join = (...segments: string[]) => {
|
||||||
const parts = segments.reduce((parts, segment) => {
|
const partss = segments.reduce((parts: any, segment: string) => {
|
||||||
// Remove leading slashes from non-first part
|
// Remove leading slashes from non-first part
|
||||||
if (parts.length > 0) {
|
if (parts.length > 0) segment = segment.replace(/^\//, '')
|
||||||
segment = segment.replace(/^\//, '')
|
|
||||||
}
|
|
||||||
// Remove trailing slashes
|
// Remove trailing slashes
|
||||||
segment = segment.replace(/\/$/, '')
|
segment = segment.replace(/\/$/, '')
|
||||||
return parts.concat(segment.split('/'))
|
return parts.concat(segment.split('/'));
|
||||||
}, [])
|
}, [])
|
||||||
const resultParts = []
|
const resultParts: string[] = []
|
||||||
for (const part of parts) {
|
for (const part of partss) {
|
||||||
if (part === '.') {
|
if (part === '.') continue;
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (part === '..') {
|
if (part === '..') {
|
||||||
resultParts.pop()
|
resultParts.pop()
|
||||||
continue
|
continue
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { rateLimitInterval } from "./conf";
|
import { rateLimitInterval } from "./conf";
|
||||||
|
|
||||||
const sleep = (lastTimestamp) => {
|
const sleep = (lastTimestamp: number): Promise<undefined | any> => {
|
||||||
let p = new Promise(resolve => resolve());
|
let p = new Promise(resolve => resolve(undefined));
|
||||||
const currentTimestamp = Date.now();
|
const currentTimestamp = Date.now();
|
||||||
if (currentTimestamp < lastTimestamp + rateLimitInterval()) {
|
if (currentTimestamp < lastTimestamp + rateLimitInterval()) {
|
||||||
const iv = currentTimestamp - lastTimestamp;
|
const iv = currentTimestamp - lastTimestamp;
|
||||||
@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
const shorten = (text, maxLength) => {
|
const shorten = (text:string, maxLength:number):string => {
|
||||||
return text.slice(0, maxLength - 1);
|
return text.slice(0, maxLength - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nameShorten = (text) => {
|
const nameShorten = (text:string) => {
|
||||||
let parts = text.split(" ");
|
let parts = text.split(" ");
|
||||||
return (parts.length >= 2) ? `${parts[0]} ${parts[1]}` : parts[0];
|
return (parts.length >= 2) ? `${parts[0]} ${parts[1]}` : parts[0];
|
||||||
}
|
}
|
||||||
29
tsconfig.json
Normal file
29
tsconfig.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2020",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"es2020"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
//"noUnusedLocals": true,
|
||||||
|
//"noUnusedParameters": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx"
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src"
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user