first fucking commit

This commit is contained in:
Firesieht 2022-10-08 17:32:28 +03:00
parent 858011bd2f
commit 86477bd461
40 changed files with 1806 additions and 421 deletions

636
package-lock.json generated
View File

@ -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",

View File

@ -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"

BIN
public/cover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -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`.
-->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
<title>React Redux App</title>
</head>
<body>

22
public/logo.svg Normal file
View File

@ -0,0 +1,22 @@
<svg width="92" height="54" viewBox="0 0 92 54" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_31_1632)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.25065 0.5L4.68701 4.78311H26.3556L27.9192 0.5H6.25065ZM3.90471 6.92369L2.34107 11.2058H24.0096L25.5732 6.92369H3.90471ZM1.56364 13.3474L0 17.6295H21.6685L23.2312 13.3474H1.56364Z" fill="white"/>
<mask id="mask0_31_1632" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="32" y="7" width="60" height="27">
<path d="M32.5097 33.2428H91.8248V7.0061H32.5097V33.2428Z" fill="white"/>
</mask>
<g mask="url(#mask0_31_1632)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M46.0659 19.2618V19.3521C47.0562 19.7156 48.0021 20.3512 48.4977 20.7594C50.0289 22.0305 50.7049 23.7098 50.7049 25.8886C50.7049 29.4757 48.813 32.0627 45.7053 32.88C44.7594 33.1521 43.7691 33.2434 41.9216 33.2434H32.5097V7.0061H40.8417C42.5532 7.0061 43.7238 7.09647 44.7594 7.36858C47.7775 8.18589 49.759 10.2743 49.759 13.5873C49.759 15.358 49.1283 16.8565 48.0928 17.8546C47.6425 18.3084 47.0119 18.8536 46.0659 19.2618ZM37.7339 22.0305V28.9305H41.3373C42.4172 28.9305 43.4085 28.8401 44.1297 28.1588C44.85 27.4776 45.1653 26.6156 45.1653 25.4805C45.1653 24.6185 44.9397 23.8012 44.4894 23.2113C43.7238 22.2579 42.7779 22.0305 41.157 22.0305H37.7339ZM37.6886 17.4911H40.616C41.5166 17.4911 41.9669 17.4911 42.4172 17.3551C43.6341 16.9916 44.3997 15.9032 44.3997 14.4046C44.3997 12.6349 43.5888 11.8623 42.4172 11.4998C41.9216 11.3638 41.427 11.3181 40.4357 11.3181H37.6886V17.4911ZM58.5412 33.2434V11.4085H51.0202V7.0061H71.9181L70.4323 11.4085H63.7655V33.2434H58.5412ZM73.539 33.2434V7.0061H90.474L88.9881 11.4085H78.7189V17.219H82.9076C86.2853 17.219 88.0421 18.0363 89.258 19.08C90.204 19.8974 91.8248 21.7127 91.8248 25.2997C91.8248 28.8401 90.1586 30.7915 88.7624 31.7906C87.1416 32.9247 85.43 33.2434 81.9617 33.2434H73.539ZM78.7189 28.8401H82.6376C84.1235 28.8401 85.0241 28.4766 85.6547 27.6593C85.97 27.2512 86.4203 26.5242 86.4203 25.1627C86.4203 23.8012 85.97 22.8478 85.0694 22.1666C84.5294 21.7584 83.8082 21.532 82.5923 21.532H78.7189V28.8401Z" fill="white"/>
</g>
<path d="M32 37.5C32 36.3954 32.8954 35.5 34 35.5H76.1097C77.5073 35.5 78.4739 36.8969 77.9813 38.2049L74.9685 46.2049C74.6751 46.9841 73.9295 47.5 73.0968 47.5H34C32.8954 47.5 32 46.6046 32 45.5V37.5Z" fill="#1890FF"/>
<path d="M37.6592 45.235L37.4715 45.1687L37.3001 45.0942L37.1696 45.0279L36.9247 44.8955L36.7942 44.8209L36.5738 44.6636C36.4188 44.5394 36.28 44.4151 36.1413 44.2826C35.4102 43.5349 35 42.5243 35 41.4711C35 40.4178 35.4102 39.4072 36.1413 38.6595C36.2779 38.5265 36.4223 38.402 36.5738 38.2868C36.6439 38.2297 36.7175 38.1772 36.7942 38.1295C36.9557 38.023 37.1248 37.9289 37.3001 37.8479L37.4715 37.7651L37.6592 37.7071C38.4722 37.4312 39.3515 37.4312 40.1645 37.7071L40.3522 37.7651L40.5236 37.8479C40.7006 37.9253 40.87 38.0196 41.0296 38.1295L41.2581 38.2868C41.4069 38.4021 41.5486 38.5266 41.6824 38.6595L40.3685 39.9928C40.2757 39.9007 40.1746 39.8175 40.0666 39.7444L39.985 39.6864H39.9279L39.8463 39.6367L39.683 39.5705H39.4382C39.2698 39.5303 39.0971 39.5109 38.9241 39.5125C38.751 39.5099 38.5783 39.5293 38.41 39.5705H38.1896L38.0346 39.6367H37.904L37.8306 39.6864L37.7408 39.7444C37.7069 39.7645 37.6742 39.7866 37.6429 39.8106C37.4227 40.0065 37.2463 40.2478 37.1254 40.5185C37.0045 40.7891 36.942 41.0828 36.942 41.38C36.942 41.6771 37.0045 41.9708 37.1254 42.2415C37.2463 42.5121 37.4227 42.7534 37.6429 42.9493L37.7408 43.0321L37.8306 43.0901L38.0591 43.2226L38.2141 43.3054C38.297 43.3352 38.3814 43.3601 38.4671 43.3799C38.6347 43.4267 38.8074 43.4518 38.9812 43.4545C39.1549 43.4506 39.3275 43.4256 39.4953 43.3799L39.7402 43.3054L39.9034 43.2226L40.1237 43.0901L40.2788 42.9741L40.4257 42.8334V41.4752H41.6008C41.6904 41.4741 41.7794 41.4911 41.8625 41.5251C41.9456 41.5592 42.0213 41.6096 42.085 41.6736C42.1488 41.7375 42.1994 41.8136 42.234 41.8976C42.2685 41.9815 42.2863 42.0716 42.2863 42.1626V42.9162C42.2901 43.4208 42.0963 43.9063 41.7477 44.2661C41.6171 44.3986 41.4702 44.5228 41.3233 44.647L41.0948 44.8044L40.9724 44.8706C40.8918 44.9241 40.8073 44.9712 40.7194 45.0114C40.6794 45.04 40.6354 45.0623 40.5889 45.0776L40.4338 45.1439L40.2461 45.2101C39.4332 45.486 38.5538 45.486 37.7408 45.2101L37.6592 45.235Z" fill="white"/>
<path d="M46.1708 37.9473C46.2213 37.8201 46.3081 37.7111 46.42 37.6344C46.532 37.5576 46.6641 37.5166 46.7992 37.5167C46.9309 37.5176 47.0596 37.5562 47.1708 37.628C47.2819 37.6997 47.3709 37.8018 47.4275 37.9225L50.8877 45.442H48.9536L48.1946 43.7857H45.4037L44.6529 45.442H42.727L46.1708 37.9473ZM47.3867 42.0301L46.8155 40.7713L46.2361 42.0301H47.3867Z" fill="white"/>
<path d="M51.8833 37.5001H53.5562C53.5909 37.501 53.625 37.5096 53.656 37.5254C53.687 37.5411 53.7142 37.5636 53.7358 37.5912L55.8494 40.0756L57.9711 37.5912C57.9948 37.5618 58.0247 37.5384 58.0587 37.5226C58.0926 37.5068 58.1297 37.4991 58.167 37.5001H59.7991V45.442H57.9467V40.4731L57.0653 41.5249L56.3472 42.353C56.2821 42.4272 56.2023 42.4866 56.113 42.5273C56.0236 42.568 55.9269 42.589 55.829 42.589C55.7311 42.589 55.6343 42.568 55.545 42.5273C55.4557 42.4866 55.3758 42.4272 55.3108 42.353L53.6786 40.4649V45.4337H51.8261L51.8833 37.5001Z" fill="white"/>
<path d="M61.3007 37.5001H65.2831C65.4649 37.5001 65.6393 37.5734 65.7678 37.7038C65.8964 37.8343 65.9686 38.0112 65.9686 38.1957V39.3883H63.1287V40.5311H65.936V42.4193H63.1287V43.5621H65.936V45.442H61.2681L61.3007 37.5001Z" fill="white"/>
<path d="M67.2091 43.5953H69.6083C69.7082 43.608 69.8097 43.5994 69.9062 43.5702C70.0027 43.541 70.0922 43.4917 70.169 43.4255C70.2457 43.3593 70.308 43.2776 70.352 43.1857C70.396 43.0937 70.4206 42.9935 70.4244 42.8913V42.8168C70.4241 42.719 70.4032 42.6225 70.3632 42.5335C70.3232 42.4446 70.2649 42.3653 70.1923 42.301C70.1197 42.2368 70.0344 42.189 69.9421 42.1608C69.8499 42.1326 69.7528 42.1248 69.6573 42.1377H69.5838C69.1193 42.1629 68.6584 42.042 68.2641 41.7915C67.8697 41.541 67.5612 41.1732 67.3804 40.7381C67.2797 40.4742 67.2298 40.193 67.2335 39.91C67.2357 39.2833 67.4825 38.683 67.92 38.2406C68.3575 37.7982 68.9499 37.5498 69.5675 37.5498H71.2894C71.4706 37.5519 71.6437 37.6259 71.7718 37.7559C71.8999 37.8859 71.9728 38.0616 71.9749 38.2454V39.3469H69.5838C69.1431 39.3469 68.7677 39.4628 68.7677 39.91V39.9928C68.7677 40.4235 69.135 40.6139 69.5838 40.6139H69.6573C70.1302 40.5714 70.6035 40.6911 71.0015 40.9539C71.3995 41.2166 71.6991 41.6072 71.8525 42.0632C71.9475 42.3288 71.9972 42.6088 71.9994 42.8913C72.0137 43.5468 71.7796 44.1828 71.3453 44.6682C70.911 45.1536 70.3097 45.4514 69.6654 45.5H67.2172L67.2091 43.5953Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_31_1632">
<rect width="92" height="53" fill="white" transform="translate(0 0.5)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

4
public/logout.svg Normal file
View File

@ -0,0 +1,4 @@
<svg width="48" height="36" viewBox="0 0 48 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.138 7.81498C22.5859 7.68062 23.059 7.65282 23.5196 7.73382C23.9802 7.81481 24.4154 8.00235 24.7906 8.28146C25.1658 8.56058 25.4706 8.92354 25.6805 9.34138C25.8905 9.75921 25.9999 10.2204 26 10.688V25.312C25.9999 25.7796 25.8905 26.2408 25.6805 26.6586C25.4706 27.0764 25.1658 27.4394 24.7906 27.7185C24.4154 27.9976 23.9802 28.1852 23.5196 28.2662C23.059 28.3471 22.5859 28.3194 22.138 28.185L16.138 26.385C15.5201 26.1996 14.9784 25.82 14.5933 25.3025C14.2082 24.785 14.0001 24.1571 14 23.512V12.488C14.0001 11.8429 14.2082 11.215 14.5933 10.6975C14.9784 10.1799 15.5201 9.80034 16.138 9.61498L22.138 7.81498ZM27 9.99998C27 9.73477 27.1054 9.48041 27.2929 9.29288C27.4804 9.10534 27.7348 8.99998 28 8.99998H31C31.7956 8.99998 32.5587 9.31606 33.1213 9.87866C33.6839 10.4413 34 11.2043 34 12V13C34 13.2652 33.8946 13.5196 33.7071 13.7071C33.5196 13.8946 33.2652 14 33 14C32.7348 14 32.4804 13.8946 32.2929 13.7071C32.1054 13.5196 32 13.2652 32 13V12C32 11.7348 31.8946 11.4804 31.7071 11.2929C31.5196 11.1053 31.2652 11 31 11H28C27.7348 11 27.4804 10.8946 27.2929 10.7071C27.1054 10.5196 27 10.2652 27 9.99998ZM33 22C33.2652 22 33.5196 22.1053 33.7071 22.2929C33.8946 22.4804 34 22.7348 34 23V24C34 24.7956 33.6839 25.5587 33.1213 26.1213C32.5587 26.6839 31.7956 27 31 27H28C27.7348 27 27.4804 26.8946 27.2929 26.7071C27.1054 26.5196 27 26.2652 27 26C27 25.7348 27.1054 25.4804 27.2929 25.2929C27.4804 25.1053 27.7348 25 28 25H31C31.2652 25 31.5196 24.8946 31.7071 24.7071C31.8946 24.5196 32 24.2652 32 24V23C32 22.7348 32.1054 22.4804 32.2929 22.2929C32.4804 22.1053 32.7348 22 33 22ZM21 17C20.7348 17 20.4804 17.1053 20.2929 17.2929C20.1054 17.4804 20 17.7348 20 18C20 18.2652 20.1054 18.5196 20.2929 18.7071C20.4804 18.8946 20.7348 19 21 19H21.001C21.2662 19 21.5206 18.8946 21.7081 18.7071C21.8956 18.5196 22.001 18.2652 22.001 18C22.001 17.7348 21.8956 17.4804 21.7081 17.2929C21.5206 17.1053 21.2662 17 21.001 17H21Z" fill="white"/>
<path d="M28 18H33M33 18L31 16M33 18L31 20" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

10
public/rub.svg Normal file
View File

@ -0,0 +1,10 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="14" height="14" rx="7" fill="url(#paint0_linear_31_7396)"/>
<path d="M4 7.61187C4.00216 7.42709 4.07653 7.25048 4.2072 7.11981C4.33787 6.98914 4.51448 6.91477 4.69927 6.91261H6.97189C7.10843 6.91514 7.24403 6.88941 7.37015 6.83704C7.49627 6.78467 7.61019 6.70679 7.70478 6.6083C7.79937 6.5098 7.87258 6.39281 7.9198 6.26467C7.96702 6.13653 7.98724 6.00002 7.97918 5.86369C7.96629 5.60164 7.85248 5.35475 7.66161 5.17474C7.47073 4.99473 7.21761 4.89556 6.95525 4.89803H4V3.00001H6.94692C7.71978 2.99777 8.46224 3.30095 9.01262 3.84354C9.56301 4.38613 9.87674 5.12418 9.88552 5.897C9.88646 6.4451 9.73009 6.98197 9.43497 7.44383C9.13984 7.9057 8.71836 8.27317 8.22059 8.50261L10.718 11H8.07907L5.91467 8.8356V11H4.01665L4 7.61187Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_31_7396" x1="-1.04308e-07" y1="14" x2="14.9243" y2="12.9335" gradientUnits="userSpaceOnUse">
<stop stop-color="#096DD9"/>
<stop offset="1" stop-color="#40A9FF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -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);
}
}

View File

@ -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(
<Provider store={store}>
<App />
</Provider>
);
expect(getByText(/learn/i)).toBeInTheDocument();
});

View File

@ -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 (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<Counter />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<span>
<span>Learn </span>
<a
className="App-link"
href="https://reactjs.org/"
target="_blank"
rel="noopener noreferrer"
>
React
</a>
<span>, </span>
<a
className="App-link"
href="https://redux.js.org/"
target="_blank"
rel="noopener noreferrer"
>
Redux
</a>
<span>, </span>
<a
className="App-link"
href="https://redux-toolkit.js.org/"
target="_blank"
rel="noopener noreferrer"
>
Redux Toolkit
</a>
,<span> and </span>
<a
className="App-link"
href="https://react-redux.js.org/"
target="_blank"
rel="noopener noreferrer"
>
React Redux
</a>
</span>
</header>
</div>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/admin">Admin</Link>
</li>
<li>
<Link to="/user">User</Link>
</li>
<li>
<Link to="/hr">HR</Link>
</li>
</ul>
</nav>
{/* A <Switch> looks through its children <Route>s and
renders the first one that matches the current URL. */}
</div>
);
}

View File

@ -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
}

View File

@ -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(
<div className="addProduct">
<Header links={[
{
link:"/admin/market",
name:"Market place"
},
{
link:"/admin/market/add",
name:"Cоздать товар (NFT)"
},
{
link:"/admin/users",
name:"Участники"
}
]}
name={user.name}></Header>
<div className="addProductCard">
<div className="addProductH1">Создать новый продукт (NFT сертификат)</div>
<div className="addBodyWrapper">
<div>
<PrevMarketCard
image={"/cover.png"}
name={name}
descr={descr}
cost={cost}
></PrevMarketCard>
</div>
<div className="fieldsWrapper">
<div className="InpWrapper" >
<div>Название</div>
<Input value={name} onChange={(e)=>setName(e.target.value)} placeholder="Название товара"></Input>
</div>
<div className="InpWrapper">
<div>Описание</div>
<TextArea rows={4} value={descr} onChange={(e)=>setDescr(e.target.value)} placeholder="Описание товара"></TextArea>
</div>
<div className="InpWrapper">
<div>Стоимость</div>
<Input value={cost} onChange={(e)=>setCost(Number(e.target.value))} placeholder="100"></Input>
</div>
<div className="InpWrapper">
<div>Изображение</div>
<div>
<FileUploader onResponse={(file)=>setFile(file)}></FileUploader>
</div>
</div>
</div>
</div>
<div className="addBtnWrapper">
<Button className="btn1" onClick={()=>onDiscard()}>Отмена</Button>
<Button className="btn2" onClick={()=>onAcceept()}>Опубликовать</Button>
</div>
</div>
</div>
);
}

View File

@ -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
}

View File

@ -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(<AdminMarketCard
name={product.name}
description={product.description}
image={product.image}
cost={product.cost}
id={product.id}
></AdminMarketCard>))
return(
<div className="market">
<Header links={[
{
link:"/admin/market",
name:"Market place"
},
{
link:"/admin/market/add",
name:"Cоздать товар (NFT)"
},
{
link:"/admin/users",
name:"Участники"
}
]}
name={user.name}></Header>
<div className="marketCard">
<div className="addProductH1">Market Place товаров и услуг</div>
<div className="productWrapper">
{cards}
</div>
</div>
</div>
);
}

View File

@ -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
}

View File

@ -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<ProductIE> = (props) =>{
let dispatch = useAppDispatch()
let navigate = useNavigate()
return(
<div className="adminCard">
<img src={props.image}></img>
<div className="adminCost">
<img src="/rub.svg"></img>
<div>{props.cost}</div>
</div>
<div>{props.name}</div>
<div>{props.description}</div>
<Button className="btn1" onClick={()=>navigate("/admin/market/" + props.id) }>Редактировать</Button>
<Button className="btn2" onClick={()=>fetchDelProduct(dispatch, props.id)}>Удалить</Button>
</div>
)
}

View File

@ -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
}

View File

@ -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(
<div className="changeProduct">
<Header links={[
{
link:"/admin/market",
name:"Market place"
},
{
link:"/admin/market/add",
name:"Cоздать товар (NFT)"
},
{
link:"/admin/users",
name:"Участники"
}
]}
name={user.name}></Header>
<div className="changeProductCard">
<div className="addProductH1">Изменение товара</div>
<div className="addBodyWrapper">
<PrevMarketCard
image={"/cover.png"}
name={name}
descr={descr}
cost={cost}
></PrevMarketCard>
<div className="fieldsWrapper">
<div className="InpWrapper">
<div>Цена</div>
<Input value={cost} onChange={(e)=>setCost(Number(e.target.value))} placeholder="Цена"></Input>
</div>
<div className="InpWrapper">
<div>Название</div>
<Input value={name} onChange={(e)=>setName(e.target.value)} placeholder="Название"></Input>
</div>
<div className="InpWrapper">
<div>Описание</div>
<Input value={descr} onChange={(e)=>setDescr(e.target.value)} placeholder="Описание"></Input>
</div>
</div>
</div>
<Button className="btn1" onClick={()=>onSave()}>Cохранить</Button>
</div>
</div>
)
}

75
src/admin/index.tsx Normal file
View File

@ -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(
<div>
<Header links={[
{
link:"/admin/market",
name:"Market place"
},
{
link:"/admin/market/add",
name:"Cоздать товар (NFT)"
},
{
link:"/admin/users",
name:"Участники"
}
]}
name={user.name}></Header>
ghbdtn
{/* <div>
<Input type="number" onChange={(e)=>setUsername(e.target.value)} placeholder="userID"></Input>
<Input type="number" onChange={(e)=>setAmount(e.target.value)} placeholder="amount"></Input>
<Button onClick={()=> fetchSendCoins(dispatch, {userID:Number(username), amount:Number(amount)})}>Отправить деньги</Button>
<div>
{"Баланс:" + useSelector((state: RootAdminState)=>getUser(state)).balance}
</div>
</div>
<div>
Продукты:
<div>
{products.map(el=>JSON.stringify(el))}
</div>
</div>
<div>
Добавить продукт:
<Input onChange={(e)=>setName(e.target.value)} placeholder="productName"></Input>
<Input onChange={(e)=>setDescr(e.target.value)} placeholder="description"></Input>
<Input onChange={(e)=>setImage(e.target.value)} placeholder="imageURL"></Input>
<Input type="number" onChange={(e)=>setCost(e.target.value)} placeholder="cost"></Input>
<Button onClick={()=> fetchAddProduct(dispatch, {name:name, descr:descr, image:image as any,cost:Number(cost)})}>Cоздать продукт</Button>
</div>
<div>
Удалить проодукт:
<Input type="number" onChange={(e)=>setDelID(e.target.value)} placeholder="ID to delete"></Input>
<Button onClick={()=> fetchDelProduct(dispatch, Number(delID))}>Удалить продукт</Button>
</div> */}
</div>
);
}

118
src/app/admin/adminSlice.ts Normal file
View File

@ -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<number>){
state.user.balance = state.user.balance - action.payload
},
addProduct(state, action: PayloadAction<ProductIE>){
state.market.products = state.market.products.concat([action.payload])
},
delProduct(state, action:PayloadAction<number>){
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<ProductIE>){
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

16
src/app/adminStore.ts Normal file
View File

@ -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<typeof adminStore.getState>;
export type AppAdminThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootAdminState,
unknown,
Action<string>
>;

2
src/app/consts.ts Normal file
View File

@ -0,0 +1,2 @@
export const host = "https://dev.akarpov.ru/api/"
export const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjY1ODI0ODQxLCJpYXQiOjE2NjUyMjQ4NDEsImp0aSI6ImIyMjgzZjg0MmQ0NjQ4ZDU5MGY3N2Y1NzU2NDU3YjUyIiwidXNlcl9pZCI6NH0.-jAQjFLV9WCZEbthdpO-JDbRaL3N3eTCNr9Vo-PAUEk"

View File

@ -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<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
export const useAppDispatch = () => useDispatch<AppAdminDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootAdminState> = useSelector;
export const adminFetcher = axios.create(
{
baseURL: host,
timeout: 1000,
headers: {
Authorization: 'Bearer ' + token
}
}
)

57
src/app/interfaces.ts Normal file
View File

@ -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[],
}

View File

@ -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<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string>
>;

View File

@ -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;
}

View File

@ -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<HeaderIE> = (props) =>{
let location = useLocation()
const onClick = () =>{
}
return(
<header className="header">
<img src="/logo.svg" className="logo"></img>
<div className="links">
{
props.links.map(link=><div
className={location.pathname.split("/").pop() == link.link.split('/').pop()? "activeLink":"link"}>
<Link to={link.link}>{link.name}</Link>
</div>)
}
</div>
<div className="userInfo">
<div>{props.name}</div>
<img onClick={()=>onClick()} src="/logout.svg"></img>
</div>
</header>
);
}

View File

@ -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<FileUploaderIE> = (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 (
<Upload {...props} multiple>
<Button icon={<UploadOutlined></UploadOutlined>}>Загрузите файлы для проверки</Button>
</Upload>
);
}

View File

@ -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<PrevMarketCardIE> = (props) =>{
return(
<div className="prevCard">
<img className="prevImg" src={props.image}></img>
<div className="prevCardWrapper">
<div className="prevCost">
<img src="/rub.svg"></img>
<div>{props.cost}</div>
</div>
<div className="prevCardH2">{props.name}</div>
<div className="prevCardDescr">{props.descr.split(" ").slice(0,6).join(" ")}</div>
</div>
</div>
)
}

View File

@ -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
}

View File

@ -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;
}

View File

@ -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 (
<div>
<div className={styles.row}>
<button
className={styles.button}
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
-
</button>
<span className={styles.value}>{count}</span>
<button
className={styles.button}
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
+
</button>
</div>
<div className={styles.row}>
<input
className={styles.textbox}
aria-label="Set increment amount"
value={incrementAmount}
onChange={(e) => setIncrementAmount(e.target.value)}
/>
<button
className={styles.button}
onClick={() => dispatch(incrementByAmount(incrementValue))}
>
Add Amount
</button>
<button
className={styles.asyncButton}
onClick={() => dispatch(incrementAsync(incrementValue))}
>
Add Async
</button>
<button
className={styles.button}
onClick={() => dispatch(incrementIfOdd(incrementValue))}
>
Add If Odd
</button>
</div>
</div>
);
}

View File

@ -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)
);
}

View File

@ -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);
});
});

View File

@ -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<number>) => {
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;

View File

@ -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;
}

View File

@ -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(
<Route>
<Route path="admin"element={<Provider store={adminStore}><AdminPage></AdminPage></Provider>}></Route>
<Route path='admin/market' element={<Provider store={adminStore}><AdminMarket></AdminMarket></Provider>}></Route>
<Route path='admin/market/:id' element={<Provider store={adminStore}><AdminMarketPopUp></AdminMarketPopUp></Provider>}></Route>
<Route path='admin/market/add' element={<Provider store={adminStore}><AddAdminMarketProduct></AddAdminMarketProduct></Provider>}></Route>
<Route path="hr"></Route>
<Route path="user"></Route>
</Route>
)
);
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
<RouterProvider router={router} />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><g fill="#764ABC"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1 +0,0 @@
/// <reference types="react-scripts" />

View File

@ -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;