Selaa lähdekoodia

+AdminGoodPage

ilya_shyian 2 vuotta sitten
vanhempi
commit
270479a793

+ 165 - 0
package-lock.json

@@ -7,12 +7,14 @@
     "": {
       "version": "0.1.0",
       "dependencies": {
+        "@dnd-kit/core": "^5.0.3",
         "@emotion/react": "^11.9.0",
         "@emotion/styled": "^11.8.1",
         "@mui/material": "^5.6.4",
         "@testing-library/jest-dom": "^5.16.4",
         "@testing-library/react": "^13.2.0",
         "@testing-library/user-event": "^13.5.0",
+        "array-move": "^4.0.0",
         "formik": "^2.2.9",
         "node-sass": "^7.0.1",
         "react": "^18.1.0",
@@ -23,6 +25,8 @@
         "react-responsive-carousel": "^3.2.23",
         "react-router-dom": "^6.3.0",
         "react-scripts": "5.0.1",
+        "react-select": "^5.3.2",
+        "react-sortable-hoc": "^2.0.0",
         "redux": "^4.2.0",
         "redux-devtools-extension": "^2.13.9",
         "redux-thunk": "^2.4.1",
@@ -1874,6 +1878,42 @@
         "postcss": "^8.3"
       }
     },
+    "node_modules/@dnd-kit/accessibility": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.0.tgz",
+      "integrity": "sha512-QwaQ1IJHQHMMuAGOOYHQSx7h7vMZPfO97aDts8t5N/MY7n2QTDSnW+kF7uRQ1tVBkr6vJ+BqHWG5dlgGvwVjow==",
+      "dependencies": {
+        "tslib": "^2.0.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.8.0"
+      }
+    },
+    "node_modules/@dnd-kit/core": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-5.0.3.tgz",
+      "integrity": "sha512-IribcBLsaPqHdYLpc5xG0TqwYIaD+65offdEYxoKh38WDjzRxUjDmrt7hj9oa/ooUKL0epux20u+mBTd92i/zw==",
+      "dependencies": {
+        "@dnd-kit/accessibility": "^3.0.0",
+        "@dnd-kit/utilities": "^3.1.0",
+        "tslib": "^2.0.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.8.0",
+        "react-dom": ">=16.8.0"
+      }
+    },
+    "node_modules/@dnd-kit/utilities": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.1.0.tgz",
+      "integrity": "sha512-2JBdIgjJ7xjMRpKagdMuYKWJdDoVVw9Wc6lfMrLjrq8t4QlMEjtsab5JVUlzWvHgANn7w3Y3VhalFfbp4dQrKg==",
+      "dependencies": {
+        "tslib": "^2.0.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.8.0"
+      }
+    },
     "node_modules/@emotion/babel-plugin": {
       "version": "11.9.2",
       "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz",
@@ -4567,6 +4607,17 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/array-move": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/array-move/-/array-move-4.0.0.tgz",
+      "integrity": "sha512-+RY54S8OuVvg94THpneQvFRmqWdAHeqtMzgMW6JNurHxe8rsS07cHQdfGkXnTUXiBcyZ0j3SiDIxxj0RPiqCkQ==",
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/array-union": {
       "version": "2.1.0",
       "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
@@ -8739,6 +8790,14 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "dependencies": {
+        "loose-envify": "^1.0.0"
+      }
+    },
     "node_modules/ip": {
       "version": "1.1.5",
       "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@@ -11330,6 +11389,11 @@
         "node": ">= 4.0.0"
       }
     },
+    "node_modules/memoize-one": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+      "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
+    },
     "node_modules/meow": {
       "version": "9.0.0",
       "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz",
@@ -14019,6 +14083,39 @@
         }
       }
     },
+    "node_modules/react-select": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.3.2.tgz",
+      "integrity": "sha512-W6Irh7U6Ha7p5uQQ2ZnemoCQ8mcfgOtHfw3wuMzG6FAu0P+CYicgofSLOq97BhjMx8jS+h+wwWdCBeVVZ9VqlQ==",
+      "dependencies": {
+        "@babel/runtime": "^7.12.0",
+        "@emotion/cache": "^11.4.0",
+        "@emotion/react": "^11.8.1",
+        "@types/react-transition-group": "^4.4.0",
+        "memoize-one": "^5.0.0",
+        "prop-types": "^15.6.0",
+        "react-transition-group": "^4.3.0"
+      },
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+        "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+      }
+    },
+    "node_modules/react-sortable-hoc": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-2.0.0.tgz",
+      "integrity": "sha512-JZUw7hBsAHXK7PTyErJyI7SopSBFRcFHDjWW5SWjcugY0i6iH7f+eJkY8cJmGMlZ1C9xz1J3Vjz0plFpavVeRg==",
+      "dependencies": {
+        "@babel/runtime": "^7.2.0",
+        "invariant": "^2.2.4",
+        "prop-types": "^15.5.7"
+      },
+      "peerDependencies": {
+        "prop-types": "^15.5.7",
+        "react": "^16.3.0 || ^17.0.0",
+        "react-dom": "^16.3.0 || ^17.0.0"
+      }
+    },
     "node_modules/react-transition-group": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
@@ -18224,6 +18321,32 @@
       "integrity": "sha512-T5ZyNSw9G0x0UDFiXV40a7VjKw2b+l4G+S0sctKqxhx8cg9QtMUAGwJBVU9mHPDPoZEmwm0tEoukjl4zb9MU7Q==",
       "requires": {}
     },
+    "@dnd-kit/accessibility": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.0.tgz",
+      "integrity": "sha512-QwaQ1IJHQHMMuAGOOYHQSx7h7vMZPfO97aDts8t5N/MY7n2QTDSnW+kF7uRQ1tVBkr6vJ+BqHWG5dlgGvwVjow==",
+      "requires": {
+        "tslib": "^2.0.0"
+      }
+    },
+    "@dnd-kit/core": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-5.0.3.tgz",
+      "integrity": "sha512-IribcBLsaPqHdYLpc5xG0TqwYIaD+65offdEYxoKh38WDjzRxUjDmrt7hj9oa/ooUKL0epux20u+mBTd92i/zw==",
+      "requires": {
+        "@dnd-kit/accessibility": "^3.0.0",
+        "@dnd-kit/utilities": "^3.1.0",
+        "tslib": "^2.0.0"
+      }
+    },
+    "@dnd-kit/utilities": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.1.0.tgz",
+      "integrity": "sha512-2JBdIgjJ7xjMRpKagdMuYKWJdDoVVw9Wc6lfMrLjrq8t4QlMEjtsab5JVUlzWvHgANn7w3Y3VhalFfbp4dQrKg==",
+      "requires": {
+        "tslib": "^2.0.0"
+      }
+    },
     "@emotion/babel-plugin": {
       "version": "11.9.2",
       "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz",
@@ -20118,6 +20241,11 @@
         "is-string": "^1.0.7"
       }
     },
+    "array-move": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/array-move/-/array-move-4.0.0.tgz",
+      "integrity": "sha512-+RY54S8OuVvg94THpneQvFRmqWdAHeqtMzgMW6JNurHxe8rsS07cHQdfGkXnTUXiBcyZ0j3SiDIxxj0RPiqCkQ=="
+    },
     "array-union": {
       "version": "2.1.0",
       "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="
@@ -23076,6 +23204,14 @@
         "side-channel": "^1.0.4"
       }
     },
+    "invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "requires": {
+        "loose-envify": "^1.0.0"
+      }
+    },
     "ip": {
       "version": "1.1.5",
       "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@@ -24903,6 +25039,11 @@
         "fs-monkey": "1.0.3"
       }
     },
+    "memoize-one": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+      "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
+    },
     "meow": {
       "version": "9.0.0",
       "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz",
@@ -26647,6 +26788,30 @@
         "workbox-webpack-plugin": "^6.4.1"
       }
     },
+    "react-select": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.3.2.tgz",
+      "integrity": "sha512-W6Irh7U6Ha7p5uQQ2ZnemoCQ8mcfgOtHfw3wuMzG6FAu0P+CYicgofSLOq97BhjMx8jS+h+wwWdCBeVVZ9VqlQ==",
+      "requires": {
+        "@babel/runtime": "^7.12.0",
+        "@emotion/cache": "^11.4.0",
+        "@emotion/react": "^11.8.1",
+        "@types/react-transition-group": "^4.4.0",
+        "memoize-one": "^5.0.0",
+        "prop-types": "^15.6.0",
+        "react-transition-group": "^4.3.0"
+      }
+    },
+    "react-sortable-hoc": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-2.0.0.tgz",
+      "integrity": "sha512-JZUw7hBsAHXK7PTyErJyI7SopSBFRcFHDjWW5SWjcugY0i6iH7f+eJkY8cJmGMlZ1C9xz1J3Vjz0plFpavVeRg==",
+      "requires": {
+        "@babel/runtime": "^7.2.0",
+        "invariant": "^2.2.4",
+        "prop-types": "^15.5.7"
+      }
+    },
     "react-transition-group": {
       "version": "4.4.2",
       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",

+ 4 - 0
package.json

@@ -3,12 +3,14 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "@dnd-kit/core": "^5.0.3",
     "@emotion/react": "^11.9.0",
     "@emotion/styled": "^11.8.1",
     "@mui/material": "^5.6.4",
     "@testing-library/jest-dom": "^5.16.4",
     "@testing-library/react": "^13.2.0",
     "@testing-library/user-event": "^13.5.0",
+    "array-move": "^4.0.0",
     "formik": "^2.2.9",
     "node-sass": "^7.0.1",
     "react": "^18.1.0",
@@ -19,6 +21,8 @@
     "react-responsive-carousel": "^3.2.23",
     "react-router-dom": "^6.3.0",
     "react-scripts": "5.0.1",
+    "react-select": "^5.3.2",
+    "react-sortable-hoc": "^2.0.0",
     "redux": "^4.2.0",
     "redux-devtools-extension": "^2.13.9",
     "redux-thunk": "^2.4.1",

+ 10 - 0
src/actions/actionCatById.js

@@ -26,9 +26,11 @@ export const actionCatById = (_id) => async (dispatch, getState) => {
                                           amount: 9999,
                                           images: [
                                               {
+                                                  _id: 1,
                                                   url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                               },
                                               {
+                                                  _id: 2,
                                                   url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                               },
                                           ],
@@ -41,9 +43,11 @@ export const actionCatById = (_id) => async (dispatch, getState) => {
                                           amount: 9999,
                                           images: [
                                               {
+                                                  _id: 1,
                                                   url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                               },
                                               {
+                                                  _id: 2,
                                                   url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                               },
                                           ],
@@ -64,9 +68,11 @@ export const actionCatById = (_id) => async (dispatch, getState) => {
                                           amount: 9999,
                                           images: [
                                               {
+                                                  _id: 1,
                                                   url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                               },
                                               {
+                                                  _id: 2,
                                                   url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                               },
                                           ],
@@ -79,9 +85,11 @@ export const actionCatById = (_id) => async (dispatch, getState) => {
                                           amount: 9999,
                                           images: [
                                               {
+                                                  _id: 1,
                                                   url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                               },
                                               {
+                                                  _id: 2,
                                                   url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                               },
                                           ],
@@ -94,9 +102,11 @@ export const actionCatById = (_id) => async (dispatch, getState) => {
                                           amount: 9999,
                                           images: [
                                               {
+                                                  _id: 1,
                                                   url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                               },
                                               {
+                                                  _id: 2,
                                                   url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                               },
                                           ],

+ 10 - 0
src/actions/actionGoodById.js

@@ -19,9 +19,19 @@ export const actionGoodById =
                                       price: '999',
                                       images: [
                                           {
+                                              _id: 1,
                                               url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                           },
                                           {
+                                              _id: 2,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
+                                          {
+                                              _id: 3,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
+                                          {
+                                              _id: 4,
                                               url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
                                           },
                                       ],

+ 8 - 2
src/actions/actionGoodUpsert.js

@@ -15,8 +15,14 @@ export const actionGoodUpsert = (good) => async (dispatch) => {
                                   price: '999',
                                   amount: 9999,
                                   images: [
-                                      { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                      { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                      {
+                                          _id: 1,
+                                          url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                      },
+                                      {
+                                          _id: 2,
+                                          url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                      },
                                   ],
                               },
                           })

+ 40 - 10
src/actions/actionGoodsAll.js

@@ -18,8 +18,14 @@ export const actionGoodsAll =
                                           price: '999',
                                           amount: 9999,
                                           images: [
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                              {
+                                                  _id: 1,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
+                                              {
+                                                  _id: 2,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
                                           ],
                                           categories: [{ _id: 1, name: 'Category 1' }],
                                       },
@@ -30,8 +36,14 @@ export const actionGoodsAll =
                                           price: '999',
                                           amount: 9999,
                                           images: [
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                              {
+                                                  _id: 1,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
+                                              {
+                                                  _id: 2,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
                                           ],
                                           categories: [{ _id: 1, name: 'Category 1' }],
                                       },
@@ -51,8 +63,14 @@ export const actionGoodsAll =
                                           price: '999',
                                           amount: 9999,
                                           images: [
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                              {
+                                                  _id: 1,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
+                                              {
+                                                  _id: 2,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
                                           ],
                                           categories: [
                                               { _id: 1, name: 'Category 1' },
@@ -66,8 +84,14 @@ export const actionGoodsAll =
                                           price: '999',
                                           amount: 9999,
                                           images: [
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                              {
+                                                  _id: 1,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
+                                              {
+                                                  _id: 2,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
                                           ],
                                           categories: [{ _id: 1, name: 'Category 1' }],
                                       },
@@ -78,8 +102,14 @@ export const actionGoodsAll =
                                           price: '999',
                                           amount: 9999,
                                           images: [
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                              {
+                                                  _id: 1,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
+                                              {
+                                                  _id: 2,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
                                           ],
                                           categories: [{ _id: 1, name: 'Category 1' }],
                                       },

+ 40 - 10
src/actions/actionGoodsFind.js

@@ -18,8 +18,14 @@ export const actionGoodsFind =
                                           price: '999',
                                           amount: 9999,
                                           images: [
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                              {
+                                                  _id: 1,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
+                                              {
+                                                  _id: 2,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
                                           ],
                                       },
                                       {
@@ -29,8 +35,14 @@ export const actionGoodsFind =
                                           price: '999',
                                           amount: 9999,
                                           images: [
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                              {
+                                                  _id: 1,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
+                                              {
+                                                  _id: 2,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
                                           ],
                                       },
                                       {
@@ -48,8 +60,14 @@ export const actionGoodsFind =
                                           price: '999',
                                           amount: 9999,
                                           images: [
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                              {
+                                                  _id: 1,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
+                                              {
+                                                  _id: 2,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
                                           ],
                                       },
                                       {
@@ -59,8 +77,14 @@ export const actionGoodsFind =
                                           price: '999',
                                           amount: 9999,
                                           images: [
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                              {
+                                                  _id: 1,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
+                                              {
+                                                  _id: 2,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
                                           ],
                                       },
                                       {
@@ -70,8 +94,14 @@ export const actionGoodsFind =
                                           price: '999',
                                           amount: 9999,
                                           images: [
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                              { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                              {
+                                                  _id: 1,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
+                                              {
+                                                  _id: 2,
+                                                  url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                              },
                                           ],
                                       },
                                   ],

+ 40 - 10
src/actions/actionGoodsPopular.js

@@ -18,8 +18,14 @@ export const actionGoodsPopular = () => async (dispatch, getState) => {
                                       price: '999',
                                       amount: 9999,
                                       images: [
-                                          { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                          { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                          {
+                                              _id: 1,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
+                                          {
+                                              _id: 2,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
                                       ],
                                   },
                                   {
@@ -29,8 +35,14 @@ export const actionGoodsPopular = () => async (dispatch, getState) => {
                                       price: '999',
                                       amount: 9999,
                                       images: [
-                                          { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                          { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                          {
+                                              _id: 1,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
+                                          {
+                                              _id: 2,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
                                       ],
                                   },
                                   {
@@ -48,8 +60,14 @@ export const actionGoodsPopular = () => async (dispatch, getState) => {
                                       price: '999',
                                       amount: 9999,
                                       images: [
-                                          { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                          { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                          {
+                                              _id: 1,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
+                                          {
+                                              _id: 2,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
                                       ],
                                   },
                                   {
@@ -59,8 +77,14 @@ export const actionGoodsPopular = () => async (dispatch, getState) => {
                                       price: '999',
                                       amount: 9999,
                                       images: [
-                                          { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                          { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                          {
+                                              _id: 1,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
+                                          {
+                                              _id: 2,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
                                       ],
                                   },
                                   {
@@ -70,8 +94,14 @@ export const actionGoodsPopular = () => async (dispatch, getState) => {
                                       price: '999',
                                       amount: 9999,
                                       images: [
-                                          { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
-                                          { url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg' },
+                                          {
+                                              _id: 1,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
+                                          {
+                                              _id: 2,
+                                              url: 'https://content2.rozetka.com.ua/goods/images/big/183546719.jpg',
+                                          },
                                       ],
                                   },
                               ],

+ 2 - 0
src/actions/actionPageStart.js

@@ -1,8 +1,10 @@
+import { actionCatAll } from './actionCatAll';
 import { actionGoodsPopular } from './actionGoodsPopular';
 import { actionRootCats } from './actionRootCats';
 
 export const actionPageStart = () => async (dispatch, getState) => {
     dispatch(actionRootCats());
+    dispatch(actionCatAll());
     dispatch(actionGoodsPopular());
 
     // const {

+ 49 - 18
src/components/admin/AdminGoodPage/GoodForm.js

@@ -1,19 +1,32 @@
 import { connect } from 'react-redux';
 import React, { useState, useEffect } from 'react';
 import { actionPromise, actionPromiseClear } from '../../../reducers';
-
+import Select from 'react-select';
 import { actionGoodUpdate } from '../../../actions/actionGoodUpdate';
 import { EntityEditor } from '../../common/EntityEditor';
 import { actionUploadFiles } from '../../../actions/actionUploadFiles';
-import { Box, Button, InputLabel, Stack, TextareaAutosize, TextField, Typography } from '@mui/material';
+import {
+    Box,
+    Button,
+    Chip,
+    FormControl,
+    InputLabel,
+    MenuItem,
+    OutlinedInput,
+    Stack,
+    TextareaAutosize,
+    TextField,
+    Typography,
+} from '@mui/material';
 import { useFormik } from 'formik';
 import * as Yup from 'yup';
 import { Error } from '../../common/Error';
 
 const goodSchema = Yup.object().shape({
-    name: Yup.string().min(3, 'Too Short!').max(15, 'Too Long!').required('Required'),
-    description: Yup.string().min(3, 'Too Short!').max(15, 'Too Long!').required('Required'),
-    price: Yup.number().min(0, 'Должно быть больше нуля'),
+    name: Yup.string().required("Обов'язкове"),
+    description: Yup.string().required("Обов'язкове"),
+    price: Yup.number().min(0, 'більше або равно 0'),
+    amount: Yup.number().min(0, 'більше або равно 0'),
 });
 
 const CGoodEditor = connect(
@@ -43,6 +56,7 @@ export const GoodForm = ({
             name: '',
             description: '',
             price: 0,
+            amount: 0,
         },
         validationSchema: goodSchema,
         validateOnChange: true,
@@ -52,6 +66,7 @@ export const GoodForm = ({
             goodToSave.name = formik.values.name;
             goodToSave.description = formik.values.description;
             goodToSave.price = +formik.values.price;
+            goodToSave.amount = +formik.values.amount;
             goodToSave.categories = inputCategories;
             goodToSave.images = inputImages?.map(({ _id }) => ({ _id })) || [];
 
@@ -65,6 +80,7 @@ export const GoodForm = ({
         setInputImages(good?.images || []);
         formik.setFieldValue('name', good.name || '');
         formik.setFieldValue('description', good.description || '');
+        formik.setFieldValue('amount', good.amount || 0);
         formik.setFieldValue('price', good.price || 0);
     }, [good]);
 
@@ -82,8 +98,8 @@ export const GoodForm = ({
             <TextField
                 id="name"
                 name="name"
-                variant="standard"
-                label="Название"
+                variant="outlined"
+                label="Назва"
                 error={formik.touched.name && Boolean(formik.errors.name)}
                 value={formik.values.name}
                 onBlur={formik.handleBlur}
@@ -95,15 +111,15 @@ export const GoodForm = ({
             />
 
             <Box sx={{ mt: 3 }}>
-                <InputLabel>Картинки</InputLabel>
+                <InputLabel>Зображення</InputLabel>
                 <CGoodEditor onImagesSave={(images) => setInputImages(images)} />
             </Box>
 
             <TextField
-                variant="standard"
+                variant="outlined"
                 id="description"
                 name="description"
-                label="Описание"
+                label="Опис"
                 error={formik.touched.description && Boolean(formik.errors.description)}
                 value={formik.values.description}
                 onBlur={formik.handleBlur}
@@ -115,12 +131,11 @@ export const GoodForm = ({
             />
 
             <Box sx={{ mt: 3 }}>
-                <InputLabel>Цена</InputLabel>
                 <TextField
-                    variant="standard"
+                    variant="outlined"
                     id="price"
                     name="price"
-                    label="Цена"
+                    label="Ціна"
                     error={formik.touched.price && Boolean(formik.errors.price)}
                     value={formik.values.price}
                     onBlur={formik.handleBlur}
@@ -133,19 +148,35 @@ export const GoodForm = ({
             </Box>
 
             <Box sx={{ mt: 3 }}>
-                <InputLabel>Категории</InputLabel>
-                {/* <Select
+                <InputLabel>Категорії</InputLabel>
+                <Select
+                    placeholder="Обрати категорії"
                     value={inputCategories.map(({ _id, name }) => ({ value: _id, label: name }))}
                     closeMenuOnSelect={false}
                     onChange={(e) => setInputCategories(e.map(({ label, value }) => ({ _id: value, name: label })))}
                     options={catList?.map(({ _id, name }) => ({ value: _id, label: name }))}
                     isMulti={true}
-                /> */}
+                />
+                {/* <TextField
+                        classes={{ root: classes.root }}
+                        select
+                        name="userRoles"
+                        id="userRoles"
+                        variant="outlined"
+                        label="userRoles"
+                        SelectProps={{
+                            multiple: true,
+                            value: formState.userRoles,
+                            onChange: catList?.map(({ _id, name }) => ({ value: _id, label: name })),
+                        }}
+                    >
+                        {catList?.map(({ _id, name }) => ({ value: _id, label: name }))}
+                    </TextField> */}
             </Box>
 
             <Box direction="row" sx={{ mt: 3 }} justifyContent="flex-end">
-                <Button disabled={!formik.isValid} type="submit">
-                    Сохранить
+                <Button variant="contained" disabled={!formik.isValid || formik.isSubmitting} type="submit" fullWidth>
+                    Зберегти
                 </Button>
             </Box>
         </Box>

+ 0 - 20
src/components/common/DropZone.js

@@ -1,20 +0,0 @@
-import { useDropzone } from "react-dropzone";
-import { useEffect } from "react";
-import { connect } from "react-redux";
-import { Box } from "@mui/material";
-export const DropZone = ({ onFileDrop, children }) => {
-    const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
-
-    useEffect(() => {
-        if (acceptedFiles.length) {
-            onFileDrop(acceptedFiles);
-        }
-    }, [acceptedFiles]);
-
-    return (
-        <Box {...getRootProps({ className: "Dropzone" })}>
-            {/* <input {...getInputProps()} /> */}
-            {children}
-        </Box>
-    );
-};

+ 20 - 0
src/components/common/DropZone/index.js

@@ -0,0 +1,20 @@
+import { useDropzone } from 'react-dropzone';
+import { useEffect } from 'react';
+import { connect } from 'react-redux';
+import { Box } from '@mui/material';
+export const DropZone = ({ onFileDrop, children }) => {
+    const { acceptedFiles, getRootProps, getInputProps } = useDropzone();
+
+    useEffect(() => {
+        if (acceptedFiles.length) {
+            onFileDrop(acceptedFiles);
+        }
+    }, [acceptedFiles]);
+
+    return (
+        <Box {...getRootProps({ className: 'Dropzone' })}>
+            {/* <input {...getInputProps()} /> */}
+            {children}
+        </Box>
+    );
+};

+ 0 - 77
src/components/common/EntityEditor.js

@@ -1,77 +0,0 @@
-import { useEffect, useState } from 'react';
-import { arrayMoveImmutable } from 'array-move';
-import { DropZone } from './DropZone';
-import { SortableList } from './SortableList';
-import { SortableItem } from './SortableItem';
-import { backendURL } from '../helpers';
-import { Box, Button, IconButton, ImageList, ImageListItem, ImageListItemBar, Typography } from '@mui/material';
-import { MdClose } from 'react-icons/md';
-
-export const EntityEditor = ({ entity = { images: [] }, onSave, onFileDrop, uploadFiles, onImagesSave }) => {
-    const [state, setState] = useState(entity);
-
-    useEffect(() => {
-        if (uploadFiles?.status === 'FULFILLED') {
-            setState({ ...state, images: [...(state.images || []), ...uploadFiles?.payload] });
-        }
-    }, [uploadFiles]);
-
-    useEffect(() => {
-        onImagesSave && onImagesSave(state.images?.filter((img) => img?._id && img?.url));
-    }, [state.images]);
-
-    const onSortEnd = ({ oldIndex, newIndex }) => {
-        setState({ ...state, images: arrayMoveImmutable(state.images, oldIndex, newIndex) });
-    };
-    const onItemRemove = (toRemoveId) => {
-        setState({ ...state, images: [...state.images.filter((el) => el?._id !== toRemoveId)] });
-    };
-
-    return (
-        <Box className="EntityEditor">
-            <DropZone onFileDrop={(files) => onFileDrop(files)}>
-                <Typography>Drop images here!</Typography>
-            </DropZone>
-            <SortableList pressDelay={200} onSortEnd={onSortEnd} axis="xy" className="SortableContainer">
-                <ImageList sx={{ maxHeight: 800 }} cols={3} rowHeight={164} fullwidth>
-                    {state.images?.map(
-                        (image, index) =>
-                            !!image?._id &&
-                            !!image?.url && (
-                                <SortableItem key={`item-${image._id}`} index={index}>
-                                    <ImageListItem key={image._id}>
-                                        <ImageListItemBar
-                                            sx={{
-                                                background: 'rgba(0,0,0,0.1)',
-                                            }}
-                                            actionIcon={
-                                                <IconButton onClick={() => onItemRemove(image._id)}>
-                                                    <MdClose />
-                                                </IconButton>
-                                            }
-                                        />
-                                        <Box
-                                            component="img"
-                                            className="DropZoneImage"
-                                            src={`/${image.url}`}
-                                            loading="lazy"
-                                            sx={{ width: 165, height: 165 }}
-                                        />
-                                    </ImageListItem>
-                                </SortableItem>
-                            )
-                    )}
-                </ImageList>
-            </SortableList>
-            {!!onSave && (
-                <Button
-                    onClick={() => {
-                        onSave(entity._id, state.images);
-                    }}
-                >
-                    Save
-                </Button>
-            )}
-        </Box>
-    );
-};

+ 1 - 1
src/components/common/EntityEditor/SortableItem.js

@@ -1,2 +1,2 @@
-import { SortableElement } from "react-sortable-hoc";
+import { SortableElement } from 'react-sortable-hoc';
 export const SortableItem = SortableElement(({ children }) => <div className="SortableItem">{children}</div>);

+ 9 - 4
src/components/common/EntityEditor/index.js

@@ -1,6 +1,6 @@
 import { useEffect, useState } from 'react';
 import { arrayMoveImmutable } from 'array-move';
-import { DropZone } from './DropZone';
+import { DropZone } from '../DropZone';
 import { SortableList } from './SortableList';
 import { SortableItem } from './SortableItem';
 import { Box, Button, IconButton, ImageList, ImageListItem, ImageListItemBar, Typography } from '@mui/material';
@@ -9,6 +9,11 @@ import { MdClose } from 'react-icons/md';
 export const EntityEditor = ({ entity = { images: [] }, onSave, onFileDrop, uploadFiles, onImagesSave }) => {
     const [state, setState] = useState(entity);
 
+    useEffect(() => {
+        setState(entity);
+        console.log(entity.images);
+    }, [entity]);
+
     useEffect(() => {
         if (uploadFiles?.status === 'FULFILLED') {
             setState({ ...state, images: [...(state.images || []), ...uploadFiles?.payload] });
@@ -16,6 +21,7 @@ export const EntityEditor = ({ entity = { images: [] }, onSave, onFileDrop, uplo
     }, [uploadFiles]);
 
     useEffect(() => {
+        console.log(entity.images);
         onImagesSave && onImagesSave(state.images?.filter((img) => img?._id && img?.url));
     }, [state.images]);
 
@@ -32,7 +38,7 @@ export const EntityEditor = ({ entity = { images: [] }, onSave, onFileDrop, uplo
                 <Typography>Drop images here!</Typography>
             </DropZone>
             <SortableList pressDelay={200} onSortEnd={onSortEnd} axis="xy" className="SortableContainer">
-                <ImageList sx={{ maxHeight: 800 }} cols={3} rowHeight={164} fullwidth>
+                <ImageList sx={{ maxHeight: 800 }} cols={3} fullwidth>
                     {state.images?.map(
                         (image, index) =>
                             !!image?._id &&
@@ -52,9 +58,8 @@ export const EntityEditor = ({ entity = { images: [] }, onSave, onFileDrop, uplo
                                         <Box
                                             component="img"
                                             className="DropZoneImage"
-                                            src={`/${image.url}`}
+                                            src={`${image.url}`}
                                             loading="lazy"
-                                            sx={{ width: 165, height: 165 }}
                                         />
                                     </ImageListItem>
                                 </SortableItem>

src/components/common/Error.js → src/components/common/Error/index.js


+ 9 - 1
src/index.scss

@@ -169,14 +169,22 @@
       padding-bottom: 400px;
 
       & .AdminGoodPage{
+        & .GoodForm{
+          width:40%;
+          text-align: left;
+        }
         & .EntityEditor{
+          & .DropZoneImage{
+            width: 100%;
+          }
           & .Dropzone{
             background: #F1F2F4;
-            width: 400px;
+            width: 100%;
             padding: 70px 0;
             border: 1px dashed #E9EAEC;
             border-radius: 5px;
             text-align: center;
+
           }
         }
       }