From 86477bd4616ac4b7119b0281fe364ebe62093b40 Mon Sep 17 00:00:00 2001 From: Firesieht Date: Sat, 8 Oct 2022 17:32:28 +0300 Subject: [PATCH] first fucking commit --- package-lock.json | 636 ++++++++++++++++++ package.json | 3 + public/cover.png | Bin 0 -> 40631 bytes public/index.html | 3 + public/logo.svg | 22 + public/logout.svg | 4 + public/rub.svg | 10 + src/App.css | 39 -- src/App.test.tsx | 15 - src/App.tsx | 86 +-- .../addAdminMarketCard/addAdminMarket.css | 112 +++ src/admin/addAdminMarketCard/index.tsx | 93 +++ src/admin/adminMarket/adminMarket.css | 34 + src/admin/adminMarket/index.tsx | 56 ++ src/admin/adminMarketCard/adminMarketCard.css | 50 ++ src/admin/adminMarketCard/index.tsx | 28 + .../adminMarketPopUp/adminMarketPopUp.css | 112 +++ src/admin/adminMarketPopUp/index.tsx | 80 +++ src/admin/index.tsx | 75 +++ src/app/admin/adminSlice.ts | 118 ++++ src/app/adminStore.ts | 16 + src/app/consts.ts | 2 + src/app/hooks.ts | 17 +- src/app/interfaces.ts | 57 ++ src/app/store.ts | 17 - src/components/Header/Header.css | 53 ++ src/components/Header/index.tsx | 39 ++ src/components/fileUploader.tsx | 38 ++ src/components/prevMarketCard/index.tsx | 25 + .../prevMarketCard/prevMarketCard.css | 50 ++ src/features/counter/Counter.module.css | 79 --- src/features/counter/Counter.tsx | 68 -- src/features/counter/counterAPI.ts | 6 - src/features/counter/counterSlice.spec.ts | 34 - src/features/counter/counterSlice.ts | 84 --- src/index.css | 8 + src/index.tsx | 41 +- src/logo.svg | 1 - src/react-app-env.d.ts | 1 - src/reportWebVitals.ts | 15 - 40 files changed, 1806 insertions(+), 421 deletions(-) create mode 100644 public/cover.png create mode 100644 public/logo.svg create mode 100644 public/logout.svg create mode 100644 public/rub.svg delete mode 100644 src/App.test.tsx create mode 100644 src/admin/addAdminMarketCard/addAdminMarket.css create mode 100644 src/admin/addAdminMarketCard/index.tsx create mode 100644 src/admin/adminMarket/adminMarket.css create mode 100644 src/admin/adminMarket/index.tsx create mode 100644 src/admin/adminMarketCard/adminMarketCard.css create mode 100644 src/admin/adminMarketCard/index.tsx create mode 100644 src/admin/adminMarketPopUp/adminMarketPopUp.css create mode 100644 src/admin/adminMarketPopUp/index.tsx create mode 100644 src/admin/index.tsx create mode 100644 src/app/admin/adminSlice.ts create mode 100644 src/app/adminStore.ts create mode 100644 src/app/consts.ts create mode 100644 src/app/interfaces.ts delete mode 100644 src/app/store.ts create mode 100644 src/components/Header/Header.css create mode 100644 src/components/Header/index.tsx create mode 100644 src/components/fileUploader.tsx create mode 100644 src/components/prevMarketCard/index.tsx create mode 100644 src/components/prevMarketCard/prevMarketCard.css delete mode 100644 src/features/counter/Counter.module.css delete mode 100644 src/features/counter/Counter.tsx delete mode 100644 src/features/counter/counterAPI.ts delete mode 100644 src/features/counter/counterSlice.spec.ts delete mode 100644 src/features/counter/counterSlice.ts delete mode 100644 src/logo.svg delete mode 100644 src/react-app-env.d.ts delete mode 100644 src/reportWebVitals.ts diff --git a/package-lock.json b/package-lock.json index 659badc..e249977 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,43 @@ "@jridgewell/trace-mapping": "^0.3.9" } }, + "@ant-design/colors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz", + "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==", + "requires": { + "@ctrl/tinycolor": "^3.4.0" + } + }, + "@ant-design/icons": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.7.0.tgz", + "integrity": "sha512-aoB4Z7JA431rt6d4u+8xcNPPCrdufSRMUOpxa1ab6mz1JCQZOEVolj2WVs/tDFmN62zzK30mNelEsprLYsSF3g==", + "requires": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-svg": "^4.2.1", + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "rc-util": "^5.9.4" + } + }, + "@ant-design/icons-svg": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.2.1.tgz", + "integrity": "sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw==" + }, + "@ant-design/react-slick": { + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-0.29.2.tgz", + "integrity": "sha512-kgjtKmkGHa19FW21lHnAfyyH9AAoh35pBdcJ53rHmQ3O+cfFHGHnUbj/HFrRNJ5vIts09FKJVAD8RpaC+RaWfA==", + "requires": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "lodash": "^4.17.21", + "resize-observer-polyfill": "^1.5.1" + } + }, "@apideck/better-ajv-errors": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", @@ -1382,6 +1419,11 @@ "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==" }, + "@ctrl/tinycolor": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz", + "integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==" + }, "@eslint/eslintrc": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", @@ -2071,6 +2113,11 @@ "reselect": "^4.1.5" } }, + "@remix-run/router": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.2.tgz", + "integrity": "sha512-GRSOFhJzjGN+d4sKHTMSvNeUPoZiDHWmRnXfzaxrqe7dE/Nzlc8BiMSJdLDESZlndM7jIUrZ/F4yWqVYlI0rwQ==" + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3172,6 +3219,57 @@ "color-convert": "^1.9.0" } }, + "antd": { + "version": "4.23.4", + "resolved": "https://registry.npmjs.org/antd/-/antd-4.23.4.tgz", + "integrity": "sha512-2VdDSPXEjCc2m2qBgv6DKpKnsKIGyQtJBdcGn223EqHxDWHqCaRxeJIA9bcW50ntHFkwdeBa+IeWLBor377dkA==", + "requires": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons": "^4.7.0", + "@ant-design/react-slick": "~0.29.1", + "@babel/runtime": "^7.18.3", + "@ctrl/tinycolor": "^3.4.0", + "classnames": "^2.2.6", + "copy-to-clipboard": "^3.2.0", + "lodash": "^4.17.21", + "memoize-one": "^6.0.0", + "moment": "^2.29.2", + "rc-cascader": "~3.7.0", + "rc-checkbox": "~2.3.0", + "rc-collapse": "~3.3.0", + "rc-dialog": "~8.9.0", + "rc-drawer": "~5.1.0", + "rc-dropdown": "~4.0.0", + "rc-field-form": "~1.27.0", + "rc-image": "~5.7.0", + "rc-input": "~0.1.2", + "rc-input-number": "~7.3.9", + "rc-mentions": "~1.9.1", + "rc-menu": "~9.6.3", + "rc-motion": "^2.6.1", + "rc-notification": "~4.6.0", + "rc-pagination": "~3.1.17", + "rc-picker": "~2.6.10", + "rc-progress": "~3.3.2", + "rc-rate": "~2.9.0", + "rc-resize-observer": "^1.2.0", + "rc-segmented": "~2.1.0", + "rc-select": "~14.1.13", + "rc-slider": "~10.0.0", + "rc-steps": "~4.1.0", + "rc-switch": "~3.2.0", + "rc-table": "~7.26.0", + "rc-tabs": "~12.1.0-alpha.1", + "rc-textarea": "~0.3.0", + "rc-tooltip": "~5.2.0", + "rc-tree": "~5.7.0", + "rc-tree-select": "~5.5.0", + "rc-trigger": "^5.2.10", + "rc-upload": "~4.3.0", + "rc-util": "^5.22.5", + "scroll-into-view-if-needed": "^2.2.25" + } + }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -3220,6 +3318,11 @@ "is-string": "^1.0.7" } }, + "array-tree-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", + "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" + }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -3274,6 +3377,11 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, + "async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3302,6 +3410,28 @@ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz", "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==" }, + "axios": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.1.2.tgz", + "integrity": "sha512-bznQyETwElsXl2RK7HLLwb5GPpOLlycxHCtrpDR/4RqqBzjARaOTo3jz4IgtntWUYee7Ne4S8UHd92VCuzPaWA==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -3794,6 +3924,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "clean-css": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", @@ -3927,6 +4062,11 @@ } } }, + "compute-scroll-into-view": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz", + "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3980,6 +4120,14 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "copy-to-clipboard": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz", + "integrity": "sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==", + "requires": { + "toggle-selection": "^1.0.6" + } + }, "core-js": { "version": "3.25.5", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.5.tgz", @@ -4298,6 +4446,16 @@ "whatwg-url": "^8.0.0" } }, + "date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" + }, + "dayjs": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz", + "integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -4461,6 +4619,11 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz", "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==" }, + "dom-align": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.3.tgz", + "integrity": "sha512-Gj9hZN3a07cbR6zviMUBOMPdWxYhbMI+x+WS0NAIu2zFZmbK8ys9R79g+iG9qLnlCwpFoaB+fKy8Pdv470GsPA==" + }, "dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -7957,6 +8120,14 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, + "json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "requires": { + "string-convert": "^0.2.0" + } + }, "json5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", @@ -8175,6 +8346,11 @@ "fs-monkey": "^1.0.3" } }, + "memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -8303,6 +8479,11 @@ "minimist": "^1.2.6" } }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -9551,6 +9732,11 @@ } } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -9628,6 +9814,411 @@ } } }, + "rc-align": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.12.tgz", + "integrity": "sha512-3DuwSJp8iC/dgHzwreOQl52soj40LchlfUHtgACOUtwGuoFIOVh6n/sCpfqCU8kO5+iz6qR0YKvjgB8iPdE3aQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "dom-align": "^1.7.0", + "lodash": "^4.17.21", + "rc-util": "^5.3.0", + "resize-observer-polyfill": "^1.5.1" + } + }, + "rc-cascader": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.7.0.tgz", + "integrity": "sha512-SFtGpwmYN7RaWEAGTS4Rkc62ZV/qmQGg/tajr/7mfIkleuu8ro9Hlk6J+aA0x1YS4zlaZBtTcSaXM01QMiEV/A==", + "requires": { + "@babel/runtime": "^7.12.5", + "array-tree-filter": "^2.1.0", + "classnames": "^2.3.1", + "rc-select": "~14.1.0", + "rc-tree": "~5.7.0", + "rc-util": "^5.6.1" + } + }, + "rc-checkbox": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.3.2.tgz", + "integrity": "sha512-afVi1FYiGv1U0JlpNH/UaEXdh6WUJjcWokj/nUN2TgG80bfG+MDdbfHKlLcNNba94mbjy2/SXJ1HDgrOkXGAjg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1" + } + }, + "rc-collapse": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.3.1.tgz", + "integrity": "sha512-cOJfcSe3R8vocrF8T+PgaHDrgeA1tX+lwfhwSj60NX9QVRidsILIbRNDLD6nAzmcvVC5PWiIRiR4S1OobxdhCg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.2.1", + "shallowequal": "^1.1.0" + } + }, + "rc-dialog": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-8.9.0.tgz", + "integrity": "sha512-Cp0tbJnrvPchJfnwIvOMWmJ4yjX3HWFatO6oBFD1jx8QkgsQCR0p8nUWAKdd3seLJhEC39/v56kZaEjwp9muoQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + } + }, + "rc-drawer": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-5.1.0.tgz", + "integrity": "sha512-pU3Tsn99pxGdYowXehzZbdDVE+4lDXSGb7p8vA9mSmr569oc2Izh4Zw5vLKSe/Xxn2p5MSNbLVqD4tz+pK6SOw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.21.2" + } + }, + "rc-dropdown": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.0.1.tgz", + "integrity": "sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g==", + "requires": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.6", + "rc-trigger": "^5.3.1", + "rc-util": "^5.17.0" + } + }, + "rc-field-form": { + "version": "1.27.2", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.27.2.tgz", + "integrity": "sha512-NaTjkSB8JsHRgm52wkDorsDzFf2HH6GmCQ2AqkwO8zo+zIqybw8K1lkzDBMDJI8nw1pFuD46U5QsYZv4blYvdw==", + "requires": { + "@babel/runtime": "^7.18.0", + "async-validator": "^4.1.0", + "rc-util": "^5.8.0" + } + }, + "rc-image": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-5.7.1.tgz", + "integrity": "sha512-QyMfdhoUfb5W14plqXSisaYwpdstcLYnB0MjX5ccIK2rydQM9sDPuekQWu500DDGR2dBaIF5vx9XbWkNFK17Fg==", + "requires": { + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "rc-dialog": "~8.9.0", + "rc-util": "^5.0.6" + } + }, + "rc-input": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-0.1.2.tgz", + "integrity": "sha512-ZPmwcFspgfYpUfbSx3KnLk9gImBcLOrlQCr4oTJ4jBoIXgJLTfm26yelzRgBJewhkvD8uJbgX0sQ/yOzuOHnJg==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + } + }, + "rc-input-number": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-7.3.9.tgz", + "integrity": "sha512-u0+miS+SATdb6DtssYei2JJ1WuZME+nXaG6XGtR8maNyW5uGDytfDu60OTWLQEb0Anv/AcCzehldV8CKmKyQfA==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.23.0" + } + }, + "rc-mentions": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.9.2.tgz", + "integrity": "sha512-uxb/lzNnEGmvraKWNGE6KXMVXvt8RQv9XW8R0Dqi3hYsyPiAZeHRCHQKdLARuk5YBhFhZ6ga55D/8XuY367g3g==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-menu": "~9.6.0", + "rc-textarea": "^0.3.0", + "rc-trigger": "^5.0.4", + "rc-util": "^5.22.5" + } + }, + "rc-menu": { + "version": "9.6.4", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.6.4.tgz", + "integrity": "sha512-6DiNAjxjVIPLZXHffXxxcyE15d4isRL7iQ1ru4MqYDH2Cqc5bW96wZOdMydFtGLyDdnmEQ9jVvdCE9yliGvzkw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.2.0", + "rc-trigger": "^5.1.2", + "rc-util": "^5.12.0", + "shallowequal": "^1.1.0" + } + }, + "rc-motion": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.6.2.tgz", + "integrity": "sha512-4w1FaX3dtV749P8GwfS4fYnFG4Rb9pxvCYPc/b2fw1cmlHJWNNgOFIz7ysiD+eOrzJSvnLJWlNQQncpNMXwwpg==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.21.0" + } + }, + "rc-notification": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-4.6.0.tgz", + "integrity": "sha512-xF3MKgIoynzjQAO4lqsoraiFo3UXNYlBfpHs0VWvwF+4pimen9/H1DYLN2mfRWhHovW6gRpla73m2nmyIqAMZQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.2.0", + "rc-util": "^5.20.1" + } + }, + "rc-overflow": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.2.8.tgz", + "integrity": "sha512-QJ0UItckWPQ37ZL1dMEBAdY1dhfTXFL9k6oTTcyydVwoUNMnMqCGqnRNA98axSr/OeDKqR6DVFyi8eA5RQI/uQ==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.19.2" + } + }, + "rc-pagination": { + "version": "3.1.17", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.1.17.tgz", + "integrity": "sha512-/BQ5UxcBnW28vFAcP2hfh+Xg15W0QZn8TWYwdCApchMH1H0CxiaUUcULP8uXcFM1TygcdKWdt3JqsL9cTAfdkQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1" + } + }, + "rc-picker": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-2.6.10.tgz", + "integrity": "sha512-9wYtw0DFWs9FO92Qh2D76P0iojUr8ZhLOtScUeOit6ks/F+TBLrOC1uze3IOu+u9gbDAjmosNWLKbBzx/Yuv2w==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "date-fns": "2.x", + "dayjs": "1.x", + "moment": "^2.24.0", + "rc-trigger": "^5.0.4", + "rc-util": "^5.4.0", + "shallowequal": "^1.1.0" + } + }, + "rc-progress": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.3.3.tgz", + "integrity": "sha512-MDVNVHzGanYtRy2KKraEaWeZLri2ZHWIRyaE1a9MQ2MuJ09m+Wxj5cfcaoaR6z5iRpHpA59YeUxAlpML8N4PJw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + } + }, + "rc-rate": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.9.2.tgz", + "integrity": "sha512-SaiZFyN8pe0Fgphv8t3+kidlej+cq/EALkAJAc3A0w0XcPaH2L1aggM8bhe1u6GAGuQNAoFvTLjw4qLPGRKV5g==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + } + }, + "rc-resize-observer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.2.0.tgz", + "integrity": "sha512-6W+UzT3PyDM0wVCEHfoW3qTHPTvbdSgiA43buiy8PzmeMnfgnDeb9NjdimMXMl3/TcrvvWl5RRVdp+NqcR47pQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.15.0", + "resize-observer-polyfill": "^1.5.1" + } + }, + "rc-segmented": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.1.0.tgz", + "integrity": "sha512-hUlonro+pYoZcwrH6Vm56B2ftLfQh046hrwif/VwLIw1j3zGt52p5mREBwmeVzXnSwgnagpOpfafspzs1asjGw==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + } + }, + "rc-select": { + "version": "14.1.13", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.1.13.tgz", + "integrity": "sha512-WMEsC3gTwA1dbzWOdVIXDmWyidYNLq68AwvvUlRROw790uGUly0/vmqDozXrIr0QvN/A3CEULx12o+WtLCAefg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.0.0", + "rc-trigger": "^5.0.4", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.2.0" + } + }, + "rc-slider": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.0.1.tgz", + "integrity": "sha512-igTKF3zBet7oS/3yNiIlmU8KnZ45npmrmHlUUio8PNbIhzMcsh+oE/r2UD42Y6YD2D/s+kzCQkzQrPD6RY435Q==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.18.1", + "shallowequal": "^1.1.0" + } + }, + "rc-steps": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-4.1.4.tgz", + "integrity": "sha512-qoCqKZWSpkh/b03ASGx1WhpKnuZcRWmvuW+ZUu4mvMdfvFzVxblTwUM+9aBd0mlEUFmt6GW8FXhMpHkK3Uzp3w==", + "requires": { + "@babel/runtime": "^7.10.2", + "classnames": "^2.2.3", + "rc-util": "^5.0.1" + } + }, + "rc-switch": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-3.2.2.tgz", + "integrity": "sha512-+gUJClsZZzvAHGy1vZfnwySxj+MjLlGRyXKXScrtCTcmiYNPzxDFOxdQ/3pK1Kt/0POvwJ/6ALOR8gwdXGhs+A==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.0.1" + } + }, + "rc-table": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.26.0.tgz", + "integrity": "sha512-0cD8e6S+DTGAt5nBZQIPFYEaIukn17sfa5uFL98faHlH/whZzD8ii3dbFL4wmUDEL4BLybhYop+QUfZJ4CPvNQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.22.5", + "shallowequal": "^1.1.0" + } + }, + "rc-tabs": { + "version": "12.1.0-alpha.1", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-12.1.0-alpha.1.tgz", + "integrity": "sha512-M+B88WEnGSuE+mR54fpgPbZLAakzxa/H6FmEetLBl5WG4I3AcwSk9amuIPC/tu0KXBl+H6Bg5ZwrrEUOBUvgzg==", + "requires": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.0.0", + "rc-menu": "~9.6.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.5.0" + } + }, + "rc-textarea": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-0.3.7.tgz", + "integrity": "sha512-yCdZ6binKmAQB13hc/oehh0E/QRwoPP1pjF21aHBxlgXO3RzPF6dUu4LG2R4FZ1zx/fQd2L1faktulrXOM/2rw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.7.0", + "shallowequal": "^1.1.0" + } + }, + "rc-tooltip": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-5.2.2.tgz", + "integrity": "sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg==", + "requires": { + "@babel/runtime": "^7.11.2", + "classnames": "^2.3.1", + "rc-trigger": "^5.0.0" + } + }, + "rc-tree": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.7.0.tgz", + "integrity": "sha512-F+Ewkv/UcutshnVBMISP+lPdHDlcsL+YH/MQDVWbk+QdkfID7vXiwrHMEZn31+2Rbbm21z/HPceGS8PXGMmnQg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.4.8" + } + }, + "rc-tree-select": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.5.0.tgz", + "integrity": "sha512-XS0Jvw4OjFz/Xvb2byEkBWv55JFKFz0HVvTBa/cPOHJaQh/3EaYwymEMnCCvGEzS1+5CfDVwMtA8j/v4rt1DHw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-select": "~14.1.0", + "rc-tree": "~5.7.0", + "rc-util": "^5.16.1" + } + }, + "rc-trigger": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.3.1.tgz", + "integrity": "sha512-5gaFbDkYSefZ14j2AdzucXzlWgU2ri5uEjkHvsf1ynRhdJbKxNOnw4PBZ9+FVULNGFiDzzlVF8RJnR9P/xrnKQ==", + "requires": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.6", + "rc-align": "^4.0.0", + "rc-motion": "^2.0.0", + "rc-util": "^5.19.2" + } + }, + "rc-upload": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.3.4.tgz", + "integrity": "sha512-uVbtHFGNjHG/RyAfm9fluXB6pvArAGyAx8z7XzXXyorEgVIWj6mOlriuDm0XowDHYz4ycNK0nE0oP3cbFnzxiQ==", + "requires": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + } + }, + "rc-util": { + "version": "5.24.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.24.4.tgz", + "integrity": "sha512-2a4RQnycV9eV7lVZPEJ7QwJRPlZNc06J7CwcwZo4vIHr3PfUqtYgl1EkUV9ETAc6VRRi8XZOMFhYG63whlIC9Q==", + "requires": { + "@babel/runtime": "^7.18.3", + "react-is": "^16.12.0", + "shallowequal": "^1.1.0" + } + }, + "rc-virtual-list": { + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.4.8.tgz", + "integrity": "sha512-qSN+Rv4i/E7RCTvTMr1uZo7f3crJJg/5DekoCagydo9zsXrxj07zsFSxqizqW+ldGA16lwa8So/bIbV9Ofjddg==", + "requires": { + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.15.0" + } + }, "react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -9779,6 +10370,23 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, + "react-router": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.2.tgz", + "integrity": "sha512-Rb0BAX9KHhVzT1OKhMvCDMw776aTYM0DtkxqUBP8dNBom3mPXlfNs76JNGK8wKJ1IZEY1+WGj+cvZxHVk/GiKw==", + "requires": { + "@remix-run/router": "1.0.2" + } + }, + "react-router-dom": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.2.tgz", + "integrity": "sha512-yM1kjoTkpfjgczPrcyWrp+OuQMyB1WleICiiGfstnQYo/S8hPEEnVjr/RdmlH6yKK4Tnj1UGXFSa7uwAtmDoLQ==", + "requires": { + "@remix-run/router": "1.0.2", + "react-router": "6.4.2" + } + }, "react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -10068,6 +10676,11 @@ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.6.tgz", "integrity": "sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ==" }, + "resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -10279,6 +10892,14 @@ "ajv-keywords": "^3.5.2" } }, + "scroll-into-view-if-needed": { + "version": "2.2.29", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz", + "integrity": "sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==", + "requires": { + "compute-scroll-into-view": "^1.0.17" + } + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -10426,6 +11047,11 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -10595,6 +11221,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" + }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -10942,6 +11573,11 @@ "is-number": "^7.0.0" } }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, "toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", diff --git a/package.json b/package.json index 022cd16..4e29e8c 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,12 @@ "@types/node": "^17.0.45", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", + "antd": "^4.23.4", + "axios": "^1.1.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.0.4", + "react-router-dom": "^6.4.2", "react-scripts": "5.0.1", "typescript": "^4.8.4", "web-vitals": "^2.1.4" diff --git a/public/cover.png b/public/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..085102a6336d40ea1dc242ff982c27fb9b1f6e95 GIT binary patch literal 40631 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 literal 0 HcmV?d00001 diff --git a/public/index.html b/public/index.html index 1dbdca6..bc133c4 100644 --- a/public/index.html +++ b/public/index.html @@ -24,6 +24,9 @@ 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`. --> + + + React Redux App diff --git a/public/logo.svg b/public/logo.svg new file mode 100644 index 0000000..8ee6eb7 --- /dev/null +++ b/public/logo.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/logout.svg b/public/logout.svg new file mode 100644 index 0000000..7b14930 --- /dev/null +++ b/public/logout.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/rub.svg b/public/rub.svg new file mode 100644 index 0000000..419af90 --- /dev/null +++ b/public/rub.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/App.css b/src/App.css index 01cc586..e69de29 100644 --- a/src/App.css +++ b/src/App.css @@ -1,39 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-float infinite 3s ease-in-out; - } -} - -.App-header { - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); -} - -.App-link { - color: rgb(112, 76, 182); -} - -@keyframes App-logo-float { - 0% { - transform: translateY(0); - } - 50% { - transform: translateY(10px); - } - 100% { - transform: translateY(0px); - } -} diff --git a/src/App.test.tsx b/src/App.test.tsx deleted file mode 100644 index 659cc13..0000000 --- a/src/App.test.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import { Provider } from 'react-redux'; -import { store } from './app/store'; -import App from './App'; - -test('renders learn react link', () => { - const { getByText } = render( - - - - ); - - expect(getByText(/learn/i)).toBeInTheDocument(); -}); diff --git a/src/App.tsx b/src/App.tsx index e8da502..26364c5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,57 +1,45 @@ import React from 'react'; -import logo from './logo.svg'; -import { Counter } from './features/counter/Counter'; import './App.css'; +import { Provider } from 'react-redux'; +import { adminStore} from './app/adminStore'; +import { + BrowserRouter as Router, + Route, + Routes, + Link, + createBrowserRouter, + createRoutesFromElements +} from "react-router-dom"; +import { AdminPage } from './admin'; +import { AdminMarket } from './admin/adminMarket'; +import { AdminMarketPopUp } from './admin/adminMarketPopUp'; +import { AddAdminMarketProduct } from './admin/addAdminMarketCard'; function App() { + return ( -
-
- logo - -

- Edit src/App.tsx and save to reload. -

- - Learn - - React - - , - - Redux - - , - - Redux Toolkit - - , and - - React Redux - - -
-
+
+ + + {/* A looks through its children s and + renders the first one that matches the current URL. */} + +
); } diff --git a/src/admin/addAdminMarketCard/addAdminMarket.css b/src/admin/addAdminMarketCard/addAdminMarket.css new file mode 100644 index 0000000..8b2c69b --- /dev/null +++ b/src/admin/addAdminMarketCard/addAdminMarket.css @@ -0,0 +1,112 @@ +.addProduct{ + padding-top: 200px; + width: 100%; + height: 100vh; + background: linear-gradient(85.91deg, #096DD9 0%, #40A9FF 100%); + display: flex; + flex-direction: column; + align-items: center; +} + +.addProductCard{ + background: #FAFAFA; + border-radius: 16px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 32px 64px; + gap: 36px; + width: 75%; + font-family: 'Roboto', sans-serif; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 22px; + /* identical to box height, or 157% */ + + text-align: right; + + /* Character/Title .85 */ + + color: rgba(0, 0, 0, 0.85); +} + +.addProductH1{ + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + font-size: 24px; + line-height: 32px; + color: rgba(0, 0, 0, 0.85) +} + +.addBodyWrapper{ + display: flex; + flex-direction: row; + align-items: center; + gap: 50px +} + +.InpWrapper{ + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 25px; + width: 100%; +} +.fieldsWrapper{ + display: flex; + flex-direction: column; + align-items: center; + gap: 20px +} + +.btn1{ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 5px 36px; + filter: drop-shadow(0px 2px 0px rgba(0, 0, 0, 0.016)); + border-radius: 16px; + border: 1px solid #1890FF; + font-style: normal; + font-weight: 700; + font-size: 16px; + line-height: 24px; + /* identical to box height, or 150% */ + + text-align: center; +} + +.btn2{ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 5px 36px; + filter: drop-shadow(0px 2px 0px rgba(0, 0, 0, 0.016)); + border-radius: 16px; + background: #1890FF; + border: 1px solid #1890FF; + font-style: normal; + font-weight: 700; + font-size: 16px; + line-height: 24px; + /* identical to box height, or 150% */ + + text-align: center; + + /* Character / Primary(inverse) */ + + color: #FFFFFF; +} + +.addBtnWrapper{ + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap:25px +} \ No newline at end of file diff --git a/src/admin/addAdminMarketCard/index.tsx b/src/admin/addAdminMarketCard/index.tsx new file mode 100644 index 0000000..7814332 --- /dev/null +++ b/src/admin/addAdminMarketCard/index.tsx @@ -0,0 +1,93 @@ +import "./addAdminMarket.css" +import React, { useState } from "react" +import { useNavigate, useParams } from "react-router-dom" +import { useAppDispatch, useAppSelector } from "../../app/hooks" +import { RootAdminState } from "../../app/adminStore" +import { fetchAddProduct, fetchChangeProduct, getProductByID, getUser } from "../../app/admin/adminSlice" +import { Button, Input } from "antd" +import { ProductIE } from "../../app/interfaces" +import { FileUploader } from "../../components/fileUploader" +import { Header } from "../../components/Header" +import { PrevMarketCard } from "../../components/prevMarketCard" + +export const AddAdminMarketProduct:React.FC = () =>{ + const [name, setName] = useState("") + const [descr, setDescr] = useState("") + const [cost, setCost] = useState(0) + const [file, setFile] = useState() as any + let user = useAppSelector((state:RootAdminState)=>getUser(state)) + + let dispatch = useAppDispatch() + let navigate = useNavigate() + const onDiscard = () =>{ + setName("") + setCost(0) + setDescr("") + } + + const onAcceept = () =>{ + fetchAddProduct(dispatch, {image: file, name:name, cost:cost, descr:descr}) + alert("Успешно создан товар:" + name) + navigate("/admin/market") + } + const { TextArea } = Input; + + return( +
+
+
+
Создать новый продукт (NFT сертификат)
+ +
+
+ +
+
+
+
Название
+ setName(e.target.value)} placeholder="Название товара"> +
+
+
Описание
+ +
+
+
Стоимость
+ setCost(Number(e.target.value))} placeholder="100"> +
+
+
Изображение
+
+ setFile(file)}> +
+
+
+ +
+
+ + +
+
+
+ ); +} \ No newline at end of file diff --git a/src/admin/adminMarket/adminMarket.css b/src/admin/adminMarket/adminMarket.css new file mode 100644 index 0000000..c77cb92 --- /dev/null +++ b/src/admin/adminMarket/adminMarket.css @@ -0,0 +1,34 @@ +.marketCard{ + background: #FAFAFA; + border-radius: 16px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 32px 64px; + gap: 36px; + width: 75%; + font-family: 'Roboto', sans-serif; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 22px; + text-align: right; + color: rgba(0, 0, 0, 0.85); +} +.market{ + padding-top: 200px; + width: 100%; + height: 100vh; + background: linear-gradient(85.91deg, #096DD9 0%, #40A9FF 100%); + display: flex; + flex-direction: column; + align-items: center; +} + +.productWrapper{ + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap:50px +} \ No newline at end of file diff --git a/src/admin/adminMarket/index.tsx b/src/admin/adminMarket/index.tsx new file mode 100644 index 0000000..2ee3138 --- /dev/null +++ b/src/admin/adminMarket/index.tsx @@ -0,0 +1,56 @@ +import React, { useState } from "react" +import { getProducts, getUser } from "../../app/admin/adminSlice"; +import { RootAdminState } from "../../app/adminStore"; +import { useAppSelector } from "../../app/hooks"; +import { Header } from "../../components/Header"; +import { AdminMarketCard } from "../adminMarketCard"; +import "./adminMarket.css" +import { + BrowserRouter as Router, + Route, + Routes, + Link + } from "react-router-dom"; +import { AdminMarketPopUp } from "../adminMarketPopUp"; + +export const AdminMarket:React.FC = () =>{ + const [opened, setOpened] = useState(false); + let user = useAppSelector((state:RootAdminState)=>getUser(state)) + let cards: JSX.Element[] = [] + let products = useAppSelector( + (state: RootAdminState)=>getProducts(state)).forEach( + product=>cards.push()) + + return( +
+
+
+
Market Place товаров и услуг
+
+ {cards} +
+
+
+ + ); +} \ No newline at end of file diff --git a/src/admin/adminMarketCard/adminMarketCard.css b/src/admin/adminMarketCard/adminMarketCard.css new file mode 100644 index 0000000..007207b --- /dev/null +++ b/src/admin/adminMarketCard/adminMarketCard.css @@ -0,0 +1,50 @@ +.adminCard{ + width: 240px; + max-height: 400px; + display: flex; + flex-direction: column; + background: #FFFFFF; + border-radius: 16px; + border: 1px solid #1890FF; + +} + +.adminImg{ + height: 50%; + border-radius: 16px 16px 0px 0px; +} + +.adminCardWrapper{ + padding: 15px; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items:flex-start; + gap: 15px; + text-align: left; +} + +.adminCost{ + border: 1px solid #1890FF; + border-radius: 16px; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 5px 16px; + gap:10px; +} +.adminCardH2{ + font-weight: 400; + font-size: 16px; + line-height: 24px; + color: rgba(0, 0, 0, 0.85) +} + +.adminCardDescr{ + font-size: 14px; + line-height: 22px; + color: rgba(0, 0, 0, 0.45); + max-width: 210px; + overflow-x:hidden +} \ No newline at end of file diff --git a/src/admin/adminMarketCard/index.tsx b/src/admin/adminMarketCard/index.tsx new file mode 100644 index 0000000..8c3fe7b --- /dev/null +++ b/src/admin/adminMarketCard/index.tsx @@ -0,0 +1,28 @@ +import { Button } from "antd"; +import React, { useState } from "react" +import { useNavigate, useParams } from "react-router-dom"; +import { fetchDelProduct, getProductByID } from "../../app/admin/adminSlice"; +import { RootAdminState } from "../../app/adminStore"; +import { useAppDispatch, useAppSelector } from "../../app/hooks"; +import { ProductIE } from "../../app/interfaces"; +import "./adminMarketCard.css" + + +export const AdminMarketCard:React.FC = (props) =>{ + let dispatch = useAppDispatch() + let navigate = useNavigate() + + return( +
+ +
+ +
{props.cost}
+
+
{props.name}
+
{props.description}
+ + +
+ ) +} \ No newline at end of file diff --git a/src/admin/adminMarketPopUp/adminMarketPopUp.css b/src/admin/adminMarketPopUp/adminMarketPopUp.css new file mode 100644 index 0000000..8ab03ed --- /dev/null +++ b/src/admin/adminMarketPopUp/adminMarketPopUp.css @@ -0,0 +1,112 @@ +.changeProduct{ + padding-top: 200px; + width: 100%; + height: 100vh; + background: linear-gradient(85.91deg, #096DD9 0%, #40A9FF 100%); + display: flex; + flex-direction: column; + align-items: center; +} + +.changeProductCard{ + background: #FAFAFA; + border-radius: 16px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 32px 64px; + gap: 36px; + width: 75%; + font-family: 'Roboto', sans-serif; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 22px; + /* identical to box height, or 157% */ + + text-align: right; + + /* Character/Title .85 */ + + color: rgba(0, 0, 0, 0.85); +} + +.addProductH1{ + font-family: 'Roboto'; + font-style: normal; + font-weight: 500; + font-size: 24px; + line-height: 32px; + color: rgba(0, 0, 0, 0.85) +} + +.addBodyWrapper{ + display: flex; + flex-direction: row; + align-items: center; + gap: 50px +} + +.InpWrapper{ + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 25px; + width: 100%; +} +.fieldsWrapper{ + display: flex; + flex-direction: column; + align-items: center; + gap: 20px +} + +.btn1{ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 5px 36px; + filter: drop-shadow(0px 2px 0px rgba(0, 0, 0, 0.016)); + border-radius: 16px; + border: 1px solid #1890FF; + font-style: normal; + font-weight: 700; + font-size: 16px; + line-height: 24px; + /* identical to box height, or 150% */ + + text-align: center; +} + +.btn2{ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 5px 36px; + filter: drop-shadow(0px 2px 0px rgba(0, 0, 0, 0.016)); + border-radius: 16px; + background: #1890FF; + border: 1px solid #1890FF; + font-style: normal; + font-weight: 700; + font-size: 16px; + line-height: 24px; + /* identical to box height, or 150% */ + + text-align: center; + + /* Character / Primary(inverse) */ + + color: #FFFFFF; +} + +.addBtnWrapper{ + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap:25px +} \ No newline at end of file diff --git a/src/admin/adminMarketPopUp/index.tsx b/src/admin/adminMarketPopUp/index.tsx new file mode 100644 index 0000000..4692ba5 --- /dev/null +++ b/src/admin/adminMarketPopUp/index.tsx @@ -0,0 +1,80 @@ +import "./adminMarketPopUp.css" +import React, { useState } from "react" +import { useNavigate, useParams } from "react-router-dom" +import { useAppDispatch, useAppSelector } from "../../app/hooks" +import { RootAdminState } from "../../app/adminStore" +import { fetchChangeProduct, getProductByID, getUser } from "../../app/admin/adminSlice" +import { Button, Input } from "antd" +import { ProductIE } from "../../app/interfaces" +import { PrevMarketCard } from "../../components/prevMarketCard" +import { Header } from "../../components/Header" + +export const AdminMarketPopUp:React.FC = () =>{ + let {id} = useParams() + let product = useAppSelector((state: RootAdminState)=>getProductByID(state, Number(id))) + const [cost, setCost] = useState(product.cost) + const [name, setName] = useState(product.name) + const [descr, setDescr] = useState(product.description) + let user = useAppSelector((state:RootAdminState)=>getUser(state)) + + let dispatch = useAppDispatch() + let navigate = useNavigate() + const onSave = () =>{ + console.log("cocb") + fetchChangeProduct(dispatch, { + cost: cost, + name: name, + description: descr, + id:product.id, + image: product.image + } as ProductIE) + navigate("/admin/market") + } + + return( +
+
+
+
Изменение товара
+
+ +
+
+
Цена
+ setCost(Number(e.target.value))} placeholder="Цена"> +
+
+
Название
+ setName(e.target.value)} placeholder="Название"> +
+
+
Описание
+ setDescr(e.target.value)} placeholder="Описание"> +
+
+
+ + +
+
+ ) +} \ No newline at end of file diff --git a/src/admin/index.tsx b/src/admin/index.tsx new file mode 100644 index 0000000..624a983 --- /dev/null +++ b/src/admin/index.tsx @@ -0,0 +1,75 @@ +import React, { useState } from "react"; +import 'antd/dist/antd.css'; +import { Button, Input } from 'antd'; +import { fetchAddProduct, fetchDelProduct, fetchSendCoins, getProducts, getUser } from "../app/admin/adminSlice"; +import { adminFetcher, useAppDispatch, useAppSelector } from "../app/hooks"; +import { useSelector } from "react-redux"; +import { RootAdminState } from "../app/adminStore"; +import { Header } from "../components/Header"; + +export const AdminPage:React.FC = () => { + const [respProducts, setRespProducts] = useState([-1 as any]) + let products = useAppSelector((state:RootAdminState)=>getProducts(state)) + let user = useAppSelector((state:RootAdminState)=>getUser(state)) + let dispatch = useAppDispatch() + if (products.length == 0){ + adminFetcher.get("marketplace/product/").then( + (response)=> setRespProducts(response.data as any) + ) + } + + if (respProducts[0] != -1){ + respProducts.forEach((product)=>{ + fetchAddProduct(dispatch, product) + }) + } + + + return( +
+
+ ghbdtn + {/*
+ setUsername(e.target.value)} placeholder="userID"> + setAmount(e.target.value)} placeholder="amount"> + +
+ {"Баланс:" + useSelector((state: RootAdminState)=>getUser(state)).balance} +
+
+
+ Продукты: +
+ {products.map(el=>JSON.stringify(el))} +
+
+
+ Добавить продукт: + setName(e.target.value)} placeholder="productName"> + setDescr(e.target.value)} placeholder="description"> + setImage(e.target.value)} placeholder="imageURL"> + setCost(e.target.value)} placeholder="cost"> + +
+
+ Удалить проодукт: + setDelID(e.target.value)} placeholder="ID to delete"> + +
*/} +
+ ); +} diff --git a/src/app/admin/adminSlice.ts b/src/app/admin/adminSlice.ts new file mode 100644 index 0000000..88c0780 --- /dev/null +++ b/src/app/admin/adminSlice.ts @@ -0,0 +1,118 @@ +import { createAsyncThunk, createSlice, createSelector, PayloadAction } from '@reduxjs/toolkit' +import { stat } from 'fs' +import { Market, Roles, SortTypes, UserIE, ProductIE} from '../interfaces' +import { AppAdminDispatch, RootAdminState } from '../adminStore' +import { adminFetcher, useAppDispatch } from '../hooks' +import { host, token } from '../consts' + + + + + +const initState = { + user: { + wallet:"123214", + balance: 100, + id:1, + role:Roles.admin, + name:"Firesieht" + } as UserIE, //потом достается запросом + market: { + sortType: SortTypes.sortByPriceSmaller, + products: [] + } as Market // потом достается запросом +} + +const adminSlice = createSlice( + { + name: "adminSlice", + initialState: initState, + reducers:{ + sendCoins(state, action: PayloadAction){ + state.user.balance = state.user.balance - action.payload + }, + addProduct(state, action: PayloadAction){ + state.market.products = state.market.products.concat([action.payload]) + }, + delProduct(state, action:PayloadAction){ + let products = state.market.products + let ind = 0 + products.forEach((product, index)=>{ + if (product.id == action.payload){ + ind = index + } + }) + products.splice(ind, 1) + state.market.products = products + }, + changeProduct(state, action:PayloadAction){ + let products = state.market.products + products.forEach((product,index)=>{ + if (product.id == action.payload.id){ + products[index] = action.payload + } + }) + state.market.products = products + } + } + } +) + + +export async function fetchSendCoins(dispatch:AppAdminDispatch, params:{userID:number, amount:number}) { + //тут идет фетч + dispatch(sendCoins(params.amount)) +} + +export async function fetchAddProduct(dispatch:AppAdminDispatch, params:{image: FormData, descr: string, name:string, cost:number}) { + //тут идет фетч + let data = { + image: "", + description: params.descr, + name: params.name, + cost: params.cost, + id: params.cost + } as ProductIE //vмоковая даата + adminFetcher.post("marketplace/product/", { + + }) + + dispatch(addProduct(data)) +} + +export async function fetchDelProduct(dispatch:AppAdminDispatch, id:number) { + //тут идет фетч + dispatch(delProduct(id)) +} + +export async function fetchChangeProduct(dispatch:AppAdminDispatch, params:ProductIE) { + dispatch(changeProduct(params)) +} + +export const getProducts = createSelector( + (state:RootAdminState) => state.adminSlice.market.products, + (field)=>field +) + +export const getProductByID = createSelector( + (state:RootAdminState, id:number) => state.adminSlice.market.products.filter((product)=>product.id == id)[0], + (field)=>field +) + +export const getSortType = createSelector( + (state:RootAdminState) => state.adminSlice.market.sortType, + (field)=>field +) +export const getUser = createSelector( + (state:RootAdminState) => state.adminSlice.user, + (field)=>field +) + +export const { + sendCoins, + addProduct, + delProduct, + changeProduct, +} = adminSlice.actions + +export default adminSlice.reducer \ No newline at end of file diff --git a/src/app/adminStore.ts b/src/app/adminStore.ts new file mode 100644 index 0000000..1902f0d --- /dev/null +++ b/src/app/adminStore.ts @@ -0,0 +1,16 @@ +import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit'; +import adminSlice from './admin/adminSlice'; +export const adminStore = configureStore({ + reducer: { + adminSlice: adminSlice, + }, +}); + +export type AppAdminDispatch = typeof adminStore.dispatch; +export type RootAdminState = ReturnType; +export type AppAdminThunk = ThunkAction< + ReturnType, + RootAdminState, + unknown, + Action +>; diff --git a/src/app/consts.ts b/src/app/consts.ts new file mode 100644 index 0000000..2538250 --- /dev/null +++ b/src/app/consts.ts @@ -0,0 +1,2 @@ +export const host = "https://dev.akarpov.ru/api/" +export const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjY1ODI0ODQxLCJpYXQiOjE2NjUyMjQ4NDEsImp0aSI6ImIyMjgzZjg0MmQ0NjQ4ZDU5MGY3N2Y1NzU2NDU3YjUyIiwidXNlcl9pZCI6NH0.-jAQjFLV9WCZEbthdpO-JDbRaL3N3eTCNr9Vo-PAUEk" \ No newline at end of file diff --git a/src/app/hooks.ts b/src/app/hooks.ts index 520e84e..350cd1c 100644 --- a/src/app/hooks.ts +++ b/src/app/hooks.ts @@ -1,6 +1,17 @@ +import axios from 'axios'; import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; -import type { RootState, AppDispatch } from './store'; +import type { RootAdminState, AppAdminDispatch } from './adminStore'; +import { host, token } from './consts'; // Use throughout your app instead of plain `useDispatch` and `useSelector` -export const useAppDispatch = () => useDispatch(); -export const useAppSelector: TypedUseSelectorHook = useSelector; +export const useAppDispatch = () => useDispatch(); +export const useAppSelector: TypedUseSelectorHook = useSelector; +export const adminFetcher = axios.create( + { + baseURL: host, + timeout: 1000, + headers: { + Authorization: 'Bearer ' + token + } + } +) \ No newline at end of file diff --git a/src/app/interfaces.ts b/src/app/interfaces.ts new file mode 100644 index 0000000..e65eb84 --- /dev/null +++ b/src/app/interfaces.ts @@ -0,0 +1,57 @@ +export enum Roles{ + user, + admin, + hr +} +export enum Specialities{ + designer, + frontend, + backend, + DevOps, + smm, +} + + +export interface UserIE{ + wallet:string, + id:number + role:Roles + balance: number, + name:string, +} + + + +export interface EmployerIE extends UserIE{ + jobTittle:Specialities, + respect: number, +} + + +export interface EventIE{ + name:string, + description: string, + date: Date, + time:Date, + org: number; + visitors: number[] +} + +export interface ProductIE{ + name:string, + description:string, + image: string, + cost: number, + id: number, +} + +export enum SortTypes{ + sortByPriceSmaller, + sortByPriceBigger, + sortByLetter +} + +export interface Market{ + sortType: SortTypes, + products: ProductIE[], +} diff --git a/src/app/store.ts b/src/app/store.ts deleted file mode 100644 index 133ff34..0000000 --- a/src/app/store.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit'; -import counterReducer from '../features/counter/counterSlice'; - -export const store = configureStore({ - reducer: { - counter: counterReducer, - }, -}); - -export type AppDispatch = typeof store.dispatch; -export type RootState = ReturnType; -export type AppThunk = ThunkAction< - ReturnType, - RootState, - unknown, - Action ->; diff --git a/src/components/Header/Header.css b/src/components/Header/Header.css new file mode 100644 index 0000000..10c8220 --- /dev/null +++ b/src/components/Header/Header.css @@ -0,0 +1,53 @@ +.header{ + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + background: #262626; + position: fixed; + top:0px; + width: 100%; + padding:10px 20px; + font-family: 'Roboto', sans-serif; + font-style: normal; + font-weight: 700; + font-size: 16px; + line-height: 24px; + + color: #FFFFFF; +} +.links{ + display: flex; + flex-direction: row; + gap:16px; + font-style: normal; + font-weight: 700; + font-size: 14px; + line-height: 22px; + +} +.link{ + filter: drop-shadow(0px 2px 0px rgba(0, 0, 0, 0.043)); + border-radius: 101px; + padding: 8px 16px; + border: 1px solid #1890FF; + + +} + +.activeLink{ + background: #1890FF; + /* drop-shadow / button-primary */ + + box-shadow: 0px 2px 0px rgba(0, 0, 0, 0.043); + border-radius: 101px; + padding: 8px 16px; + +} + +.userInfo{ + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; +} \ No newline at end of file diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx new file mode 100644 index 0000000..601deb5 --- /dev/null +++ b/src/components/Header/index.tsx @@ -0,0 +1,39 @@ +import "./Header.css" +import React from "react" +import { Link, useLocation, useParams } from "react-router-dom" +import axios, { AxiosHeaders } from 'axios'; +import { host, token } from "../../app/consts"; + +interface HeaderIE{ + links: { + link:string, + name:string + }[], + name:string +} + +export const Header:React.FC = (props) =>{ + let location = useLocation() + const onClick = () =>{ + + } + + + return( +
+ +
+ { + props.links.map(link=>
+ {link.name} +
) + } +
+
+
{props.name}
+ onClick()} src="/logout.svg"> +
+
+ ); +} diff --git a/src/components/fileUploader.tsx b/src/components/fileUploader.tsx new file mode 100644 index 0000000..e65bf8e --- /dev/null +++ b/src/components/fileUploader.tsx @@ -0,0 +1,38 @@ +import React, { useState } from "react"; +import { Button, message, Upload } from "antd" +import Icon, { UploadOutlined } from '@ant-design/icons'; +import 'antd/dist/antd.css'; +import { host } from "../app/consts"; + + +interface FileUploaderIE{ + onResponse: (response:any)=>void +} +export const FileUploader:React.FC = (data) =>{ + + const props = { + name: 'file', + action: host + '/api/', + headers: { + authorization: 'authorization-text', + }, + + onChange(info:any) { + if (info.file.status !== 'uploading') { + } + + if (info.file.status === 'done') { + data.onResponse(info.file.response) + message.success(`${info.file.name} file uploaded successfully`); + } else if (info.file.status === 'error') { + message.error(`${info.file.name} file upload failed.`); + } + }, + }; + + return ( + + + + ); +} \ No newline at end of file diff --git a/src/components/prevMarketCard/index.tsx b/src/components/prevMarketCard/index.tsx new file mode 100644 index 0000000..773fb5f --- /dev/null +++ b/src/components/prevMarketCard/index.tsx @@ -0,0 +1,25 @@ +import React from "react" +import "./prevMarketCard.css" +interface PrevMarketCardIE{ + image:string, + cost: number, + descr: string, + name:string +} + +export const PrevMarketCard:React.FC = (props) =>{ + + return( +
+ +
+
+ +
{props.cost}
+
+
{props.name}
+
{props.descr.split(" ").slice(0,6).join(" ")}
+
+
+ ) +} \ No newline at end of file diff --git a/src/components/prevMarketCard/prevMarketCard.css b/src/components/prevMarketCard/prevMarketCard.css new file mode 100644 index 0000000..4b3c2e3 --- /dev/null +++ b/src/components/prevMarketCard/prevMarketCard.css @@ -0,0 +1,50 @@ +.prevCard{ + width: 240px; + max-height: 400px; + display: flex; + flex-direction: column; + background: #FFFFFF; + border-radius: 16px; + border: 1px solid #1890FF; + +} + +.prevImg{ + height: 50%; + border-radius: 16px 16px 0px 0px; +} + +.prevCardWrapper{ + padding: 15px; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items:flex-start; + gap: 15px; + text-align: left; +} + +.prevCost{ + border: 1px solid #1890FF; + border-radius: 16px; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 5px 16px; + gap:10px; +} +.prevCardH2{ + font-weight: 400; + font-size: 16px; + line-height: 24px; + color: rgba(0, 0, 0, 0.85) +} + +.prevCardDescr{ + font-size: 14px; + line-height: 22px; + color: rgba(0, 0, 0, 0.45); + max-width: 210px; + overflow-x:hidden +} \ No newline at end of file diff --git a/src/features/counter/Counter.module.css b/src/features/counter/Counter.module.css deleted file mode 100644 index 025bb72..0000000 --- a/src/features/counter/Counter.module.css +++ /dev/null @@ -1,79 +0,0 @@ -.row { - display: flex; - align-items: center; - justify-content: center; -} - -.row > button { - margin-left: 4px; - margin-right: 8px; -} - -.row:not(:last-child) { - margin-bottom: 16px; -} - -.value { - font-size: 78px; - padding-left: 16px; - padding-right: 16px; - margin-top: 2px; - font-family: 'Courier New', Courier, monospace; -} - -.button { - appearance: none; - background: none; - font-size: 32px; - padding-left: 12px; - padding-right: 12px; - outline: none; - border: 2px solid transparent; - color: rgb(112, 76, 182); - padding-bottom: 4px; - cursor: pointer; - background-color: rgba(112, 76, 182, 0.1); - border-radius: 2px; - transition: all 0.15s; -} - -.textbox { - font-size: 32px; - padding: 2px; - width: 64px; - text-align: center; - margin-right: 4px; -} - -.button:hover, -.button:focus { - border: 2px solid rgba(112, 76, 182, 0.4); -} - -.button:active { - background-color: rgba(112, 76, 182, 0.2); -} - -.asyncButton { - composes: button; - position: relative; -} - -.asyncButton:after { - content: ''; - background-color: rgba(112, 76, 182, 0.15); - display: block; - position: absolute; - width: 100%; - height: 100%; - left: 0; - top: 0; - opacity: 0; - transition: width 1s linear, opacity 0.5s ease 1s; -} - -.asyncButton:active:after { - width: 0%; - opacity: 1; - transition: 0s; -} diff --git a/src/features/counter/Counter.tsx b/src/features/counter/Counter.tsx deleted file mode 100644 index ece5191..0000000 --- a/src/features/counter/Counter.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React, { useState } from 'react'; - -import { useAppSelector, useAppDispatch } from '../../app/hooks'; -import { - decrement, - increment, - incrementByAmount, - incrementAsync, - incrementIfOdd, - selectCount, -} from './counterSlice'; -import styles from './Counter.module.css'; - -export function Counter() { - const count = useAppSelector(selectCount); - const dispatch = useAppDispatch(); - const [incrementAmount, setIncrementAmount] = useState('2'); - - const incrementValue = Number(incrementAmount) || 0; - - return ( -
-
- - {count} - -
-
- setIncrementAmount(e.target.value)} - /> - - - -
-
- ); -} diff --git a/src/features/counter/counterAPI.ts b/src/features/counter/counterAPI.ts deleted file mode 100644 index 0a9cdd3..0000000 --- a/src/features/counter/counterAPI.ts +++ /dev/null @@ -1,6 +0,0 @@ -// A mock function to mimic making an async request for data -export function fetchCount(amount = 1) { - return new Promise<{ data: number }>((resolve) => - setTimeout(() => resolve({ data: amount }), 500) - ); -} diff --git a/src/features/counter/counterSlice.spec.ts b/src/features/counter/counterSlice.spec.ts deleted file mode 100644 index 098163b..0000000 --- a/src/features/counter/counterSlice.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import counterReducer, { - CounterState, - increment, - decrement, - incrementByAmount, -} from './counterSlice'; - -describe('counter reducer', () => { - const initialState: CounterState = { - value: 3, - status: 'idle', - }; - it('should handle initial state', () => { - expect(counterReducer(undefined, { type: 'unknown' })).toEqual({ - value: 0, - status: 'idle', - }); - }); - - it('should handle increment', () => { - const actual = counterReducer(initialState, increment()); - expect(actual.value).toEqual(4); - }); - - it('should handle decrement', () => { - const actual = counterReducer(initialState, decrement()); - expect(actual.value).toEqual(2); - }); - - it('should handle incrementByAmount', () => { - const actual = counterReducer(initialState, incrementByAmount(2)); - expect(actual.value).toEqual(5); - }); -}); diff --git a/src/features/counter/counterSlice.ts b/src/features/counter/counterSlice.ts deleted file mode 100644 index 015dca0..0000000 --- a/src/features/counter/counterSlice.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { RootState, AppThunk } from '../../app/store'; -import { fetchCount } from './counterAPI'; - -export interface CounterState { - value: number; - status: 'idle' | 'loading' | 'failed'; -} - -const initialState: CounterState = { - value: 0, - status: 'idle', -}; - -// The function below is called a thunk and allows us to perform async logic. It -// can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This -// will call the thunk with the `dispatch` function as the first argument. Async -// code can then be executed and other actions can be dispatched. Thunks are -// typically used to make async requests. -export const incrementAsync = createAsyncThunk( - 'counter/fetchCount', - async (amount: number) => { - const response = await fetchCount(amount); - // The value we return becomes the `fulfilled` action payload - return response.data; - } -); - -export const counterSlice = createSlice({ - name: 'counter', - initialState, - // The `reducers` field lets us define reducers and generate associated actions - reducers: { - increment: (state) => { - // Redux Toolkit allows us to write "mutating" logic in reducers. It - // doesn't actually mutate the state because it uses the Immer library, - // which detects changes to a "draft state" and produces a brand new - // immutable state based off those changes - state.value += 1; - }, - decrement: (state) => { - state.value -= 1; - }, - // Use the PayloadAction type to declare the contents of `action.payload` - incrementByAmount: (state, action: PayloadAction) => { - state.value += action.payload; - }, - }, - // The `extraReducers` field lets the slice handle actions defined elsewhere, - // including actions generated by createAsyncThunk or in other slices. - extraReducers: (builder) => { - builder - .addCase(incrementAsync.pending, (state) => { - state.status = 'loading'; - }) - .addCase(incrementAsync.fulfilled, (state, action) => { - state.status = 'idle'; - state.value += action.payload; - }) - .addCase(incrementAsync.rejected, (state) => { - state.status = 'failed'; - }); - }, -}); - -export const { increment, decrement, incrementByAmount } = counterSlice.actions; - -// The function below is called a selector and allows us to select a value from -// the state. Selectors can also be defined inline where they're used instead of -// in the slice file. For example: `useSelector((state: RootState) => state.counter.value)` -export const selectCount = (state: RootState) => state.counter.value; - -// We can also write thunks by hand, which may contain both sync and async logic. -// Here's an example of conditionally dispatching actions based on current state. -export const incrementIfOdd = - (amount: number): AppThunk => - (dispatch, getState) => { - const currentValue = selectCount(getState()); - if (currentValue % 2 === 1) { - dispatch(incrementByAmount(amount)); - } - }; - -export default counterSlice.reducer; diff --git a/src/index.css b/src/index.css index ec2585e..ebbd87e 100644 --- a/src/index.css +++ b/src/index.css @@ -11,3 +11,11 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } +a{ + text-decoration: none !important; + color: #FFFFFF !important; +} +a:active{ + text-decoration: none !important; + color: #FFFFFF; +} diff --git a/src/index.tsx b/src/index.tsx index 0e6466f..392ee03 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,23 +1,44 @@ import React from 'react'; import { createRoot } from 'react-dom/client'; -import { Provider } from 'react-redux'; -import { store } from './app/store'; + import App from './App'; -import reportWebVitals from './reportWebVitals'; import './index.css'; +import { Provider } from 'react-redux'; +import { adminStore} from './app/adminStore'; +import { AdminPage } from './admin'; +import { AdminMarket } from './admin/adminMarket'; +import { AdminMarketPopUp } from './admin/adminMarketPopUp'; +import { AddAdminMarketProduct } from './admin/addAdminMarketCard'; +import { + Route, + createBrowserRouter, + createRoutesFromElements, + RouterProvider, + Link, + Routes +} from "react-router-dom"; const container = document.getElementById('root')!; const root = createRoot(container); +const router = createBrowserRouter( + createRoutesFromElements( + + }> + }> + }> + }> + + + + + ) +); + root.render( - - - + + ); -// 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(); diff --git a/src/logo.svg b/src/logo.svg deleted file mode 100644 index 8466738..0000000 --- a/src/logo.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts deleted file mode 100644 index 6431bc5..0000000 --- a/src/react-app-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts deleted file mode 100644 index 49a2a16..0000000 --- a/src/reportWebVitals.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ReportHandler } from 'web-vitals'; - -const reportWebVitals = (onPerfEntry?: ReportHandler) => { - if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); - } -}; - -export default reportWebVitals;