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 0000000..085102a Binary files /dev/null and b/public/cover.png differ 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;