Compare commits
	
		
			104 Commits
		
	
	
		
			30c316a335
			...
			current-de
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					16a5a1f548 | ||
| 
						 | 
					a763c5a69a | ||
| 
						 | 
					a7c58b2609 | ||
| 
						 | 
					3b8ec8e100 | ||
| 94136c97e6 | |||
| 4810412bd7 | |||
| 
						 | 
					3f46d60720 | ||
| d49a2eb0c8 | |||
| 
						 | 
					8de343016f | ||
| 
						 | 
					470bf6ec67 | ||
| 
						 | 
					dea1eb6104 | ||
| 
						 | 
					ee20b49993 | ||
| 
						 | 
					0e04e19c1b | ||
| bd4bfacd66 | |||
| 1bdabd32bf | |||
| 2d861de330 | |||
| 
						 | 
					60aa8c7301 | ||
| 
						 | 
					13df697614 | ||
| 
						 | 
					79299d1177 | ||
| 68a2df23c4 | |||
| 
						 | 
					291e6a4a5d | ||
| 
						 | 
					0d436e71e4 | ||
| 
						 | 
					7a55188904 | ||
| 
						 | 
					3e80159c44 | ||
| 363d43e04c | |||
| 
						 | 
					a1da184bb0 | ||
| 
						 | 
					066cd569d3 | ||
| 
						 | 
					86a784bee2 | ||
| 
						 | 
					adf6ff4a1d | ||
| 9ffb981b67 | |||
| 
						 | 
					0860591d28 | ||
| 4a20d5e4fa | |||
| 
						 | 
					1434792d42 | ||
| 
						 | 
					ade31b767a | ||
| fafab29d25 | |||
| 
						 | 
					10ffb1f7f1 | ||
| 
						 | 
					75cf13d945 | ||
| 
						 | 
					a3e39b75d8 | ||
| 271374b6c6 | |||
| 811ef4f69d | |||
| 
						 | 
					c532302f73 | ||
| 
						 | 
					36bdaf15e5 | ||
| 7400319650 | |||
| 
						 | 
					7580006e05 | ||
| 93d5ab015a | |||
| 90274e8b17 | |||
| 
						 | 
					9f98a0fea2 | ||
| 
						 | 
					1e950e9de0 | ||
| 
						 | 
					a3bcfc7cf7 | ||
| 
						 | 
					140d4689fe | ||
| 
						 | 
					b19e00d98f | ||
| 
						 | 
					3580e25457 | ||
| 
						 | 
					9a0364e686 | ||
| 3e54f947b4 | |||
| 
						 | 
					35f76abe60 | ||
| 
						 | 
					caaee74810 | ||
| c9dafd95a9 | |||
| c14590a0cb | |||
| 
						 | 
					5ad50a8ed0 | ||
| 
						 | 
					56344fa26e | ||
| 
						 | 
					f76e448951 | ||
| 42b597d585 | |||
| 
						 | 
					77628b0de4 | ||
| 6e6d3d1823 | |||
| 
						 | 
					2a5991da1f | ||
| 
						 | 
					6afccb19d8 | ||
| 
						 | 
					43ca1b54f1 | ||
| 
						 | 
					923a84e488 | ||
| 
						 | 
					3013dd1bd2 | ||
| 
						 | 
					882bdfcc24 | ||
| f180586eb3 | |||
| 
						 | 
					78f2b34810 | ||
| 
						 | 
					f2ad6b43bd | ||
| 727d55798a | |||
| 8797ba0778 | |||
| 
						 | 
					176dd29625 | ||
| 
						 | 
					2ed0be6664 | ||
| 012ef7d4b6 | |||
| 
						 | 
					e251711b4a | ||
| 
						 | 
					a43db43f42 | ||
| 
						 | 
					72c48e98c3 | ||
| 14d3b6fa45 | |||
| 
						 | 
					05ce4da8c5 | ||
| 
						 | 
					ea3c0ae576 | ||
| 
						 | 
					95363f82ea | ||
| 
						 | 
					4603e2dc8b | ||
| 
						 | 
					23e8c5c683 | ||
| 
						 | 
					46c91cfbff | ||
| 
						 | 
					4d148cc57d | ||
| f1a692f6c5 | |||
| 
						 | 
					2889569238 | ||
| 
						 | 
					0b02a71a1a | ||
| d9781b6396 | |||
| 0df30c74c9 | |||
| 
						 | 
					59d0f5eae6 | ||
| 
						 | 
					57cc2bc1fa | ||
| 
						 | 
					ce775e03ab | ||
| 3a0426ae6d | |||
| 
						 | 
					c972df0656 | ||
| 
						 | 
					5dbf1421f0 | ||
| 9b01381af1 | |||
| 
						 | 
					deac5ec94d | ||
| 
						 | 
					07574e98a6 | ||
| 
						 | 
					23b8c3ad8a | 
							
								
								
									
										182
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						@@ -1,5 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
<<<<<<< HEAD
 | 
			
		||||
  "name": "itguild.info",
 | 
			
		||||
=======
 | 
			
		||||
  "name": "outstaffing-react",
 | 
			
		||||
>>>>>>> 42b597d58589cfa47890a35c06fd651fc654742a
 | 
			
		||||
  "version": "0.1.0",
 | 
			
		||||
  "lockfileVersion": 3,
 | 
			
		||||
  "requires": true,
 | 
			
		||||
@@ -9,7 +13,9 @@
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@ckeditor/ckeditor5-build-classic": "^38.0.1",
 | 
			
		||||
        "@ckeditor/ckeditor5-react": "^6.0.0",
 | 
			
		||||
        "@emotion/react": "^11.11.4",
 | 
			
		||||
        "@reduxjs/toolkit": "^1.6.0",
 | 
			
		||||
        "@table-library/react-table-library": "^4.1.7",
 | 
			
		||||
        "@testing-library/jest-dom": "^5.12.0",
 | 
			
		||||
        "@testing-library/react": "^11.2.7",
 | 
			
		||||
        "@testing-library/user-event": "^12.8.3",
 | 
			
		||||
@@ -2830,21 +2836,21 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/babel-plugin": {
 | 
			
		||||
      "version": "11.10.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz",
 | 
			
		||||
      "integrity": "sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==",
 | 
			
		||||
      "version": "11.11.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
 | 
			
		||||
      "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@babel/helper-module-imports": "^7.16.7",
 | 
			
		||||
        "@babel/runtime": "^7.18.3",
 | 
			
		||||
        "@emotion/hash": "^0.9.0",
 | 
			
		||||
        "@emotion/memoize": "^0.8.0",
 | 
			
		||||
        "@emotion/serialize": "^1.1.1",
 | 
			
		||||
        "@emotion/hash": "^0.9.1",
 | 
			
		||||
        "@emotion/memoize": "^0.8.1",
 | 
			
		||||
        "@emotion/serialize": "^1.1.2",
 | 
			
		||||
        "babel-plugin-macros": "^3.1.0",
 | 
			
		||||
        "convert-source-map": "^1.5.0",
 | 
			
		||||
        "escape-string-regexp": "^4.0.0",
 | 
			
		||||
        "find-root": "^1.1.0",
 | 
			
		||||
        "source-map": "^0.5.7",
 | 
			
		||||
        "stylis": "4.1.3"
 | 
			
		||||
        "stylis": "4.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
 | 
			
		||||
@@ -2867,39 +2873,39 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/cache": {
 | 
			
		||||
      "version": "11.10.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.5.tgz",
 | 
			
		||||
      "integrity": "sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==",
 | 
			
		||||
      "version": "11.11.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
 | 
			
		||||
      "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@emotion/memoize": "^0.8.0",
 | 
			
		||||
        "@emotion/sheet": "^1.2.1",
 | 
			
		||||
        "@emotion/utils": "^1.2.0",
 | 
			
		||||
        "@emotion/weak-memoize": "^0.3.0",
 | 
			
		||||
        "stylis": "4.1.3"
 | 
			
		||||
        "@emotion/memoize": "^0.8.1",
 | 
			
		||||
        "@emotion/sheet": "^1.2.2",
 | 
			
		||||
        "@emotion/utils": "^1.2.1",
 | 
			
		||||
        "@emotion/weak-memoize": "^0.3.1",
 | 
			
		||||
        "stylis": "4.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/hash": {
 | 
			
		||||
      "version": "0.9.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz",
 | 
			
		||||
      "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ=="
 | 
			
		||||
      "version": "0.9.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
 | 
			
		||||
      "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/memoize": {
 | 
			
		||||
      "version": "0.8.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
 | 
			
		||||
      "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
 | 
			
		||||
      "version": "0.8.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
 | 
			
		||||
      "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/react": {
 | 
			
		||||
      "version": "11.10.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.6.tgz",
 | 
			
		||||
      "integrity": "sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==",
 | 
			
		||||
      "version": "11.11.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz",
 | 
			
		||||
      "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@babel/runtime": "^7.18.3",
 | 
			
		||||
        "@emotion/babel-plugin": "^11.10.6",
 | 
			
		||||
        "@emotion/cache": "^11.10.5",
 | 
			
		||||
        "@emotion/serialize": "^1.1.1",
 | 
			
		||||
        "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0",
 | 
			
		||||
        "@emotion/utils": "^1.2.0",
 | 
			
		||||
        "@emotion/weak-memoize": "^0.3.0",
 | 
			
		||||
        "@emotion/babel-plugin": "^11.11.0",
 | 
			
		||||
        "@emotion/cache": "^11.11.0",
 | 
			
		||||
        "@emotion/serialize": "^1.1.3",
 | 
			
		||||
        "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
 | 
			
		||||
        "@emotion/utils": "^1.2.1",
 | 
			
		||||
        "@emotion/weak-memoize": "^0.3.1",
 | 
			
		||||
        "hoist-non-react-statics": "^3.3.1"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
@@ -2912,44 +2918,44 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/serialize": {
 | 
			
		||||
      "version": "1.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz",
 | 
			
		||||
      "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==",
 | 
			
		||||
      "version": "1.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz",
 | 
			
		||||
      "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@emotion/hash": "^0.9.0",
 | 
			
		||||
        "@emotion/memoize": "^0.8.0",
 | 
			
		||||
        "@emotion/unitless": "^0.8.0",
 | 
			
		||||
        "@emotion/utils": "^1.2.0",
 | 
			
		||||
        "@emotion/hash": "^0.9.1",
 | 
			
		||||
        "@emotion/memoize": "^0.8.1",
 | 
			
		||||
        "@emotion/unitless": "^0.8.1",
 | 
			
		||||
        "@emotion/utils": "^1.2.1",
 | 
			
		||||
        "csstype": "^3.0.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/sheet": {
 | 
			
		||||
      "version": "1.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz",
 | 
			
		||||
      "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA=="
 | 
			
		||||
      "version": "1.2.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz",
 | 
			
		||||
      "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/unitless": {
 | 
			
		||||
      "version": "0.8.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz",
 | 
			
		||||
      "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw=="
 | 
			
		||||
      "version": "0.8.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
 | 
			
		||||
      "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==",
 | 
			
		||||
      "version": "1.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
 | 
			
		||||
      "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "react": ">=16.8.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/utils": {
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw=="
 | 
			
		||||
      "version": "1.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz",
 | 
			
		||||
      "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@emotion/weak-memoize": {
 | 
			
		||||
      "version": "0.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg=="
 | 
			
		||||
      "version": "0.3.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz",
 | 
			
		||||
      "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@eslint-community/eslint-utils": {
 | 
			
		||||
      "version": "4.4.0",
 | 
			
		||||
@@ -5203,6 +5209,21 @@
 | 
			
		||||
        "url": "https://github.com/sponsors/gregberge"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@table-library/react-table-library": {
 | 
			
		||||
      "version": "4.1.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@table-library/react-table-library/-/react-table-library-4.1.7.tgz",
 | 
			
		||||
      "integrity": "sha512-KKFjdACvEUeD9yhgXBjZUJSdE9pxUbJdou4Pp71FW8dxQWc7LcMcSxpveSfGXw8KlcWY0hThJOwyjQb+UKOmnw==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "clsx": "1.1.1",
 | 
			
		||||
        "react-virtualized-auto-sizer": "1.0.7",
 | 
			
		||||
        "react-window": "1.8.7"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "@emotion/react": ">= 11",
 | 
			
		||||
        "react": ">=16.8.0",
 | 
			
		||||
        "react-dom": ">=16.8.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@testing-library/jest-dom": {
 | 
			
		||||
      "version": "5.16.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz",
 | 
			
		||||
@@ -8011,9 +8032,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/caniuse-lite": {
 | 
			
		||||
      "version": "1.0.30001458",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz",
 | 
			
		||||
      "integrity": "sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==",
 | 
			
		||||
      "version": "1.0.30001597",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001597.tgz",
 | 
			
		||||
      "integrity": "sha512-7LjJvmQU6Sj7bL0j5b5WY/3n7utXUJvAe1lxhsHDbLmwX9mdL86Yjtr+5SRCyf8qME4M7pU2hswj0FpyBVCv9w==",
 | 
			
		||||
      "funding": [
 | 
			
		||||
        {
 | 
			
		||||
          "type": "opencollective",
 | 
			
		||||
@@ -8022,6 +8043,10 @@
 | 
			
		||||
        {
 | 
			
		||||
          "type": "tidelift",
 | 
			
		||||
          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "type": "github",
 | 
			
		||||
          "url": "https://github.com/sponsors/ai"
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
@@ -8247,6 +8272,14 @@
 | 
			
		||||
        "node": ">=6"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/clsx": {
 | 
			
		||||
      "version": "1.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
 | 
			
		||||
      "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==",
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">=6"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/co": {
 | 
			
		||||
      "version": "4.6.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
 | 
			
		||||
@@ -21332,6 +21365,39 @@
 | 
			
		||||
        "react-dom": ">=16.6.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-virtualized-auto-sizer": {
 | 
			
		||||
      "version": "1.0.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.7.tgz",
 | 
			
		||||
      "integrity": "sha512-Mxi6lwOmjwIjC1X4gABXMJcKHsOo0xWl3E3ugOgufB8GJU+MqrtY35aBuvCYv/razQ1Vbp7h1gWJjGjoNN5pmA==",
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">8.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc",
 | 
			
		||||
        "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-window": {
 | 
			
		||||
      "version": "1.8.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.7.tgz",
 | 
			
		||||
      "integrity": "sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@babel/runtime": "^7.0.0",
 | 
			
		||||
        "memoize-one": ">=3.1.1 <6"
 | 
			
		||||
      },
 | 
			
		||||
      "engines": {
 | 
			
		||||
        "node": ">8.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
 | 
			
		||||
        "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/react-window/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/react-yandex-metrika": {
 | 
			
		||||
      "version": "2.6.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/react-yandex-metrika/-/react-yandex-metrika-2.6.0.tgz",
 | 
			
		||||
@@ -23086,9 +23152,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/stylis": {
 | 
			
		||||
      "version": "4.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz",
 | 
			
		||||
      "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA=="
 | 
			
		||||
      "version": "4.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/supports-color": {
 | 
			
		||||
      "version": "5.5.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,9 @@
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@ckeditor/ckeditor5-build-classic": "^38.0.1",
 | 
			
		||||
    "@ckeditor/ckeditor5-react": "^6.0.0",
 | 
			
		||||
    "@emotion/react": "^11.11.4",
 | 
			
		||||
    "@reduxjs/toolkit": "^1.6.0",
 | 
			
		||||
    "@table-library/react-table-library": "^4.1.7",
 | 
			
		||||
    "@testing-library/jest-dom": "^5.12.0",
 | 
			
		||||
    "@testing-library/react": "^11.2.7",
 | 
			
		||||
    "@testing-library/user-event": "^12.8.3",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										151
									
								
								src/App.jsx
									
									
									
									
									
								
							
							
						
						@@ -10,52 +10,12 @@ import {
 | 
			
		||||
 | 
			
		||||
import { getNotification } from "@redux/outstaffingSlice";
 | 
			
		||||
 | 
			
		||||
import { AuthForCandidate } from "@pages/AuthForCandidate/AuthForCandidate";
 | 
			
		||||
import CatalogSpecialists from "@pages/CatalogSpecialists/CatalogSpecialists";
 | 
			
		||||
import { CompanyInfo } from "@pages/CompanyInfo/CompanyInfo";
 | 
			
		||||
import { FrequentlyAskedQuestion } from "@pages/FrequentlyAskedQuestion/FrequentlyAskedQuestion";
 | 
			
		||||
import { FrequentlyAskedQuestions } from "@pages/FrequentlyAskedQuestions/FrequentlyAskedQuestions";
 | 
			
		||||
import { PartnerAddRequest } from "@pages/PartnerAddRequest/PartnerAddRequest";
 | 
			
		||||
import { PartnerBid } from "@pages/PartnerBid/PartnerBid";
 | 
			
		||||
import { PartnerEmployeeReport } from "@pages/PartnerEmployeeReport/PartnerEmployeeReport";
 | 
			
		||||
import { PartnerEmployees } from "@pages/PartnerEmployees/PartnerEmployees";
 | 
			
		||||
import { PartnerRequests } from "@pages/PartnerRequests/PartnerRequests";
 | 
			
		||||
import { PartnerSettings } from "@pages/PartnerSettings/PartnerSettings";
 | 
			
		||||
import { PartnerTreaties } from "@pages/PartnerTreaties/PartnerTreaties";
 | 
			
		||||
import { PartnerCategories } from "@pages/PartnerСategories/PartnerСategories";
 | 
			
		||||
import { Payouts } from "@pages/Payouts/Payouts";
 | 
			
		||||
import { Profile } from "@pages/Profile/Profile";
 | 
			
		||||
import { ProfileCandidate } from "@pages/ProfileCandidate/ProfileCandidate";
 | 
			
		||||
import { ProjectTracker } from "@pages/ProjectTracker/ProjectTracker";
 | 
			
		||||
import { PassingTests } from "@pages/Quiz/PassingTests";
 | 
			
		||||
import { QuizPage } from "@pages/Quiz/QuizPage";
 | 
			
		||||
import { QuizReportPage } from "@pages/Quiz/QuizReportPage";
 | 
			
		||||
import { RegistrationForCandidate } from "@pages/RegistrationForCandidate/RegistrationForCandidate";
 | 
			
		||||
import { RegistrationSetting } from "@pages/RegistrationSetting/RegistrationSetting";
 | 
			
		||||
import Statistics from "@pages/Statistics/Statistics";
 | 
			
		||||
import { Summary } from "@pages/Summary/Summary";
 | 
			
		||||
import { Tracker } from "@pages/Tracker/Tracker";
 | 
			
		||||
import { TrackerAuth } from "@pages/TrackerAuth/TrackerAuth";
 | 
			
		||||
import { TrackerIntro } from "@pages/TrackerIntro/TrackerIntro";
 | 
			
		||||
import { TrackerRegistration } from "@pages/TrackerRegistration/TrackerRegistration";
 | 
			
		||||
import { ViewReport } from "@pages/ViewReport/ViewReport";
 | 
			
		||||
import { MainPage } from "@pages/MainPage/MainPage";
 | 
			
		||||
 | 
			
		||||
import { TicketFullScreen } from "@components/Modal/Tracker/TicketFullScreen/TicketFullScreen";
 | 
			
		||||
import Notification from "@components/Notification/Notification";
 | 
			
		||||
import { ProfileCalendar } from "@components/ProfileCalendar/ProfileCalendar";
 | 
			
		||||
import { Notification } from "@components/Notification/Notification";
 | 
			
		||||
 | 
			
		||||
import "./assets/fonts/stylesheet.css";
 | 
			
		||||
import "./assets/global.scss";
 | 
			
		||||
import Calendar from "./components/Calendar/Calendar";
 | 
			
		||||
import Candidate from "./components/Candidate/Candidate";
 | 
			
		||||
import FreeDevelopers from "./components/FreeDevelopers/FreeDevelopers";
 | 
			
		||||
import ReportForm from "./components/ReportForm/ReportForm";
 | 
			
		||||
import Article from "./pages/Article/Article";
 | 
			
		||||
import Auth from "./pages/Auth/Auth";
 | 
			
		||||
import Blog from "./pages/Blog/Blog";
 | 
			
		||||
import FormPage from "./pages/FormPage/FormPage";
 | 
			
		||||
import Home from "./pages/Home/Home";
 | 
			
		||||
import SingleReportPage from "./pages/SingleReportPage/SingleReportPage";
 | 
			
		||||
import "assets/fonts/stylesheet.css";
 | 
			
		||||
import "assets/global.scss";
 | 
			
		||||
 | 
			
		||||
const App = () => {
 | 
			
		||||
  const notification = useSelector(getNotification);
 | 
			
		||||
@@ -63,108 +23,7 @@ const App = () => {
 | 
			
		||||
    <>
 | 
			
		||||
      <Router>
 | 
			
		||||
        <Routes>
 | 
			
		||||
          <Route exact path="/auth" element={<Auth />} />
 | 
			
		||||
          <Route exact path="/tracker-intro" element={<TrackerIntro />} />
 | 
			
		||||
          <Route exact path="/tracker-auth" element={<TrackerAuth />} />
 | 
			
		||||
          <Route
 | 
			
		||||
            exact
 | 
			
		||||
            path="/tracker-registration"
 | 
			
		||||
            element={<TrackerRegistration />}
 | 
			
		||||
          />
 | 
			
		||||
          <Route exact path="/company" element={<CompanyInfo />} />
 | 
			
		||||
          <Route
 | 
			
		||||
            exact
 | 
			
		||||
            path="/registration-setting"
 | 
			
		||||
            element={<RegistrationSetting />}
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            exact
 | 
			
		||||
            path="/catalog-specialists"
 | 
			
		||||
            element={<CatalogSpecialists />}
 | 
			
		||||
          />
 | 
			
		||||
 | 
			
		||||
          <Route exact path="/worker/:id" element={<FreeDevelopers />} />
 | 
			
		||||
          <Route
 | 
			
		||||
            exact
 | 
			
		||||
            path="/tracker/task/:id"
 | 
			
		||||
            element={<TicketFullScreen />}
 | 
			
		||||
          ></Route>
 | 
			
		||||
          <Route
 | 
			
		||||
            exact
 | 
			
		||||
            path="/tracker/project/:id"
 | 
			
		||||
            element={<ProjectTracker />}
 | 
			
		||||
          />
 | 
			
		||||
 | 
			
		||||
          <Route exact path="/auth-candidate" element={<AuthForCandidate />} />
 | 
			
		||||
          <Route
 | 
			
		||||
            exact
 | 
			
		||||
            path="/registration-candidate"
 | 
			
		||||
            element={<RegistrationForCandidate />}
 | 
			
		||||
          />
 | 
			
		||||
 | 
			
		||||
          <Route exact path="/blog" element={<Blog />}></Route>
 | 
			
		||||
          <Route exact path="/blog/article/:id" element={<Article />}></Route>
 | 
			
		||||
          <Route
 | 
			
		||||
            exact
 | 
			
		||||
            path="/frequently-asked-questions"
 | 
			
		||||
            element={<FrequentlyAskedQuestions />}
 | 
			
		||||
          />
 | 
			
		||||
          <Route
 | 
			
		||||
            exact
 | 
			
		||||
            path="/frequently-asked-question/:id"
 | 
			
		||||
            element={<FrequentlyAskedQuestion />}
 | 
			
		||||
          />
 | 
			
		||||
 | 
			
		||||
          <Route exact path="/candidate/:id" element={<Candidate />} />
 | 
			
		||||
          <Route exact path="/candidate/:id/form" element={<FormPage />} />
 | 
			
		||||
          <Route path="/:userId/calendar" element={<Calendar />} />
 | 
			
		||||
 | 
			
		||||
          <Route path="/report/:id" element={<SingleReportPage />} />
 | 
			
		||||
 | 
			
		||||
          <Route exact path="profile">
 | 
			
		||||
            <Route index element={<Profile />} />
 | 
			
		||||
            <Route exact path="catalog" element={<Home />} />
 | 
			
		||||
            <Route exact path="calendar" element={<ProfileCalendar />} />
 | 
			
		||||
            <Route exact path="calendar/report" element={<ReportForm />} />
 | 
			
		||||
            <Route
 | 
			
		||||
              exact
 | 
			
		||||
              path="calendar/view/:date/:id"
 | 
			
		||||
              element={<ViewReport />}
 | 
			
		||||
            />
 | 
			
		||||
            <Route exact path="summary" element={<Summary />} />
 | 
			
		||||
            <Route exact path="tracker" element={<Tracker />} />
 | 
			
		||||
            <Route exact path="statistics/:id" element={<Statistics />} />
 | 
			
		||||
            <Route exact path="payouts" element={<Payouts />} />
 | 
			
		||||
            <Route exact path="settings" element={<PartnerSettings />} />
 | 
			
		||||
            <Route exact path="requests" element={<PartnerRequests />} />
 | 
			
		||||
            <Route exact path="requests-add" element={<PartnerAddRequest />} />
 | 
			
		||||
            <Route exact path="requests-edit" element={<PartnerAddRequest />} />
 | 
			
		||||
            <Route exact path="requests-bid" element={<PartnerBid />} />
 | 
			
		||||
            <Route exact path="employees" element={<PartnerCategories />} />
 | 
			
		||||
            <Route
 | 
			
		||||
              exact
 | 
			
		||||
              path="employees/report/:uuid"
 | 
			
		||||
              element={<PartnerEmployeeReport />}
 | 
			
		||||
            />
 | 
			
		||||
            <Route exact path="treaties" element={<PartnerTreaties />} />
 | 
			
		||||
            <Route exact path="quiz">
 | 
			
		||||
              <Route index element={<QuizPage />} />
 | 
			
		||||
              <Route exact path="test/:uuid" element={<PassingTests />} />
 | 
			
		||||
              <Route exact path="report/:uuid" element={<QuizReportPage />} />
 | 
			
		||||
            </Route>
 | 
			
		||||
 | 
			
		||||
            <Route
 | 
			
		||||
              exact
 | 
			
		||||
              path="categories/employees"
 | 
			
		||||
              element={<PartnerEmployees />}
 | 
			
		||||
            />
 | 
			
		||||
          </Route>
 | 
			
		||||
 | 
			
		||||
          <Route exact path="profile-candidate/:id">
 | 
			
		||||
            <Route index element={<ProfileCandidate />} />
 | 
			
		||||
          </Route>
 | 
			
		||||
 | 
			
		||||
          <Route path="*" element={<Navigate to="/auth" replace />} />
 | 
			
		||||
          <Route path="*" element={<MainPage />} />
 | 
			
		||||
        </Routes>
 | 
			
		||||
      </Router>
 | 
			
		||||
      {notification.show && <Notification />}
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ export const apiRequest = (
 | 
			
		||||
          if (response.data?.redirect || response.status === 401) {
 | 
			
		||||
            window.location.replace("/auth");
 | 
			
		||||
            localStorage.clear();
 | 
			
		||||
            // dispatch(auth(false));
 | 
			
		||||
            store.dispatch(auth(false));
 | 
			
		||||
            store.dispatch(setProfileInfo({}));
 | 
			
		||||
          }
 | 
			
		||||
          return resolve(response);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/assets/fonts/GeraspohekoRegular.eot
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								src/assets/fonts/GeraspohekoRegular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								src/assets/fonts/GeraspohekoRegular.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								src/assets/fonts/GeraspohekoRegular.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -394,3 +394,16 @@
 | 
			
		||||
  url('LabGrotesque-Light.ttf') format('truetype');
 | 
			
		||||
  font-weight: 300;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@font-face {
 | 
			
		||||
  font-family: 'Geraspoheko';
 | 
			
		||||
  src: url('GeraspohekoRegular.eot');
 | 
			
		||||
  src: local('Geraspoheko'), local('GeraspohekoRegular'),
 | 
			
		||||
  url('GeraspohekoRegular.eot?#iefix') format('embedded-opentype'),
 | 
			
		||||
  url('GeraspohekoRegular.woff2') format('woff2'),
 | 
			
		||||
  url('GeraspohekoRegular.woff') format('woff'),
 | 
			
		||||
  url('GeraspohekoRegular.ttf') format('truetype');
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
  font-display: swap;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								src/assets/icons/arrows/arrowCalendar_left.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 229 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/icons/arrows/arrowCalendar_right.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 238 B  | 
							
								
								
									
										10
									
								
								src/assets/icons/arrows/arrowLanding.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,10 @@
 | 
			
		||||
<svg width="27" height="15" viewBox="0 0 27 15" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
<g clip-path="url(#clip0_76_12)">
 | 
			
		||||
<path d="M22.7685 8.75957H22.345C15.3781 8.75957 8.41109 8.75957 1.44414 8.75957C1.22469 8.76628 1.00541 8.7416 0.792717 8.68623C0.259454 8.5302 -0.0459255 8.00204 0.00624986 7.38338C0.0222895 7.10907 0.131776 6.84899 0.315899 6.64783C0.500021 6.44667 0.747298 6.31697 1.01524 6.28102C1.18606 6.26022 1.35806 6.2511 1.53009 6.25372C8.46839 6.25372 15.407 6.25372 22.3458 6.25372H22.7931C22.6734 6.12655 22.6066 6.05322 22.5376 5.98222C21.3043 4.73398 20.0705 3.48392 18.8362 2.23203C18.4764 1.86848 18.2991 1.45188 18.438 0.941657C18.4905 0.730456 18.5968 0.537048 18.7462 0.38089C18.8956 0.224732 19.0828 0.111333 19.289 0.052101C19.4952 -0.00713091 19.7131 -0.0101062 19.9208 0.043474C20.1284 0.0970542 20.3186 0.205301 20.472 0.357322C20.9393 0.80435 21.3828 1.27556 21.8355 1.73663C23.3982 3.32762 24.9604 4.9181 26.5221 6.50805C27.1582 7.15557 27.1597 7.85069 26.5275 8.4951C24.5402 10.5235 22.5445 12.5363 20.568 14.5725C19.717 15.4494 18.6574 14.8432 18.4418 14.0724C18.377 13.8673 18.3702 13.6478 18.4221 13.439C18.4741 13.2301 18.5827 13.0403 18.7357 12.8913C19.0672 12.541 19.4086 12.2 19.747 11.856L22.5092 9.04745C22.5798 8.96787 22.6465 8.88985 22.7685 8.75957Z" fill="#A7CA60"/>
 | 
			
		||||
</g>
 | 
			
		||||
<defs>
 | 
			
		||||
<clipPath id="clip0_76_12">
 | 
			
		||||
<rect width="27" height="15" fill="white"/>
 | 
			
		||||
</clipPath>
 | 
			
		||||
</defs>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/icons/arrows/arrowReviewsLeft.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 298 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/icons/arrows/arrowReviewsRight.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 296 B  | 
| 
		 Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB  | 
							
								
								
									
										3
									
								
								src/assets/icons/arrows/tableArrow.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,3 @@
 | 
			
		||||
<svg width="9" height="6" viewBox="0 0 9 6" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
<path d="M4.11629 5.8584L8.07227 0.858398H0.160323L4.11629 5.8584Z" fill="#2E3A59"/>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 184 B  | 
							
								
								
									
										11
									
								
								src/assets/icons/authIcon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,11 @@
 | 
			
		||||
<svg width="15" height="18" viewBox="0 0 15 18" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
<g clip-path="url(#clip0_68_166)">
 | 
			
		||||
<path d="M7.83533 -0.000427246C8.01139 0.0347969 8.19098 0.0603351 8.36352 0.106127C10.1325 0.574608 11.2721 1.69782 11.6378 3.48501C12.1598 6.0326 10.4182 8.17423 8.22135 8.59868C7.24129 8.79102 6.22489 8.63913 5.34382 8.16864C4.46275 7.69816 3.771 6.93791 3.38538 6.0163C2.7159 4.41052 3.02929 2.48332 4.40345 1.19367C5.09537 0.544667 5.89733 0.14003 6.8441 0.0330362C6.87122 0.0255363 6.89714 0.014272 6.92113 -0.000427246H7.83533Z" fill="#838383"/>
 | 
			
		||||
<path d="M7.5037 17.9969C5.99838 17.9969 4.49305 18.0057 2.98817 17.993C2.33244 17.997 1.69302 17.7886 1.16549 17.399C0.50526 16.9094 0.11176 16.2485 0.0408957 15.4344C-0.0880693 13.9523 0.0822738 12.4997 0.633346 11.1106C0.967863 10.2674 1.46655 9.54135 2.29624 9.0962C2.79777 8.82462 3.36124 8.68806 3.93142 8.69993C4.11276 8.70345 4.30467 8.79195 4.47016 8.88178C4.7369 9.0262 4.98559 9.20408 5.24263 9.36611C6.01995 9.85749 6.86152 10.1243 7.78716 10.0547C8.46852 10.0037 9.09838 9.77647 9.67982 9.42071C9.87921 9.29874 10.0861 9.18338 10.2674 9.03764C10.7428 8.65414 11.2683 8.64798 11.8295 8.77346C12.8648 9.00374 13.5937 9.61928 14.0981 10.5311C14.6025 11.443 14.8301 12.4244 14.9273 13.4442C14.9789 13.9979 15.0026 14.5538 14.9982 15.1099C14.989 16.6108 13.8608 17.8252 12.3652 17.9648C12.1328 17.9863 11.8982 17.9987 11.6649 17.9991C10.2767 18.0026 8.88887 17.9991 7.50063 17.9991L7.5037 17.9969Z" fill="#838383"/>
 | 
			
		||||
</g>
 | 
			
		||||
<defs>
 | 
			
		||||
<clipPath id="clip0_68_166">
 | 
			
		||||
<rect width="15" height="18" fill="white"/>
 | 
			
		||||
</clipPath>
 | 
			
		||||
</defs>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.6 KiB  | 
@@ -1,4 +1,3 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
 | 
			
		||||
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
    <path d="M1411.824 0c31.17 0 56.47 25.3 56.47 56.471v56.47h169.412c93.403 0 169.412 76.01 169.412 169.412V1920H113V282.353c0-93.402 76.009-169.412 169.412-169.412h169.41v-56.47c0-31.172 25.3-56.47 56.472-56.47s56.47 25.298 56.47 56.47v56.47h790.589v-56.47c0-31.172 25.299-56.47 56.47-56.47Zm282.352 564.705H225.942v1242.353h1468.234V564.705Zm-1016.47 677.648v338.824H338.882v-338.824h338.824Zm451.765 0v338.824H790.647v-338.824h338.824Zm451.764 0v338.824h-338.823v-338.824h338.823Zm-1016.47 112.941H451.824v112.941h112.941v-112.941Zm451.764 0H903.588v112.941h112.941v-112.941Zm451.765 0h-112.941v112.941h112.941v-112.941ZM677.706 790.588v338.824H338.882V790.588h338.824Zm451.765 0v338.824H790.647V790.588h338.824Zm451.764 0v338.824h-338.823V790.588h338.823ZM564.765 903.53H451.824v112.941h112.941V903.53Zm451.764 0H903.588v112.941h112.941V903.53Zm451.765 0h-112.941v112.941h112.941V903.53ZM451.823 225.882H282.412c-31.06 0-56.47 25.3-56.47 56.471v169.412h1468.234V282.353c0-31.172-25.411-56.47-56.47-56.47h-169.412v56.47c0 31.172-25.3 56.471-56.47 56.471-31.172 0-56.471-25.299-56.471-56.47v-56.472H564.765v56.471c0 31.172-25.3 56.471-56.471 56.471-31.171 0-56.471-25.299-56.471-56.47v-56.472Z" fill-rule="evenodd"/>
 | 
			
		||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
<path d="M14.569 2.26115H12.9023V1.42782C12.9023 1.2068 12.8145 0.99484 12.6583 0.83856C12.502 0.68228 12.29 0.594482 12.069 0.594482C11.848 0.594482 11.636 0.68228 11.4798 0.83856C11.3235 0.99484 11.2357 1.2068 11.2357 1.42782V2.26115H6.23568V1.42782C6.23568 1.2068 6.14788 0.99484 5.9916 0.83856C5.83532 0.68228 5.62336 0.594482 5.40234 0.594482C5.18133 0.594482 4.96937 0.68228 4.81309 0.83856C4.65681 0.99484 4.56901 1.2068 4.56901 1.42782V2.26115H2.90234C2.2393 2.26115 1.60342 2.52454 1.13458 2.99338C0.665736 3.46222 0.402344 4.09811 0.402344 4.76115V14.7611C0.402344 15.4242 0.665736 16.0601 1.13458 16.5289C1.60342 16.9978 2.2393 17.2612 2.90234 17.2612H14.569C15.2321 17.2612 15.8679 16.9978 16.3368 16.5289C16.8056 16.0601 17.069 15.4242 17.069 14.7611V4.76115C17.069 4.09811 16.8056 3.46222 16.3368 2.99338C15.8679 2.52454 15.2321 2.26115 14.569 2.26115ZM15.4023 14.7611C15.4023 14.9822 15.3145 15.1941 15.1583 15.3504C15.002 15.5067 14.79 15.5945 14.569 15.5945H2.90234C2.68133 15.5945 2.46937 15.5067 2.31309 15.3504C2.15681 15.1941 2.06901 14.9822 2.06901 14.7611V8.92782H15.4023V14.7611ZM15.4023 7.26115H2.06901V4.76115C2.06901 4.54014 2.15681 4.32817 2.31309 4.17189C2.46937 4.01561 2.68133 3.92782 2.90234 3.92782H4.56901V4.76115C4.56901 4.98216 4.65681 5.19412 4.81309 5.3504C4.96937 5.50669 5.18133 5.59448 5.40234 5.59448C5.62336 5.59448 5.83532 5.50669 5.9916 5.3504C6.14788 5.19412 6.23568 4.98216 6.23568 4.76115V3.92782H11.2357V4.76115C11.2357 4.98216 11.3235 5.19412 11.4798 5.3504C11.636 5.50669 11.848 5.59448 12.069 5.59448C12.29 5.59448 12.502 5.50669 12.6583 5.3504C12.8145 5.19412 12.9023 4.98216 12.9023 4.76115V3.92782H14.569C14.79 3.92782 15.002 4.01561 15.1583 4.17189C15.3145 4.32817 15.4023 4.54014 15.4023 4.76115V7.26115Z" fill="#406128"/>
 | 
			
		||||
</svg>
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/icons/financeIcon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 726 B  | 
							
								
								
									
										9
									
								
								src/assets/icons/landingClue.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.1 MiB  | 
							
								
								
									
										15
									
								
								src/assets/icons/telegramIcon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,15 @@
 | 
			
		||||
<svg width="23" height="22" viewBox="0 0 23 22" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
<g clip-path="url(#clip0_64_66)">
 | 
			
		||||
<mask id="mask0_64_66" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="23" height="22">
 | 
			
		||||
<path d="M22.0015 0H0V22H22.0015V0Z" fill="white"/>
 | 
			
		||||
</mask>
 | 
			
		||||
<g mask="url(#mask0_64_66)">
 | 
			
		||||
<path d="M10.9461 22.0001C4.87347 21.9702 -0.0423218 16.9977 0.000274756 10.9273C0.0436186 4.86661 4.99678 -0.0297562 11.0545 0.000136144C17.1159 0.0307758 22.0317 4.98468 22.0018 11.0349C21.9719 17.1247 17.0255 22.0293 10.9461 22.0001ZM16.0487 7.6025C16.0711 6.87985 15.8103 6.63324 15.2715 6.68256C14.9591 6.71096 14.664 6.8126 14.3777 6.93217C12.3622 7.77513 10.3475 8.61809 8.335 9.46778C7.12361 9.97969 5.91447 10.4968 4.71056 11.0259C4.48935 11.1231 4.25096 11.2531 4.27338 11.567C4.2958 11.8749 4.56782 11.9234 4.77557 11.9937C5.37491 12.1962 5.97874 12.392 6.59303 12.5415C7.0997 12.6655 7.61161 12.6199 8.06298 12.3173C9.56955 11.3069 11.0709 10.2898 12.5782 9.28021C12.7307 9.17857 12.9108 8.94392 13.0901 9.15316C13.2747 9.36764 13.0087 9.5029 12.8801 9.62995C11.8354 10.6612 10.7809 11.6828 9.7362 12.7133C9.26839 13.1752 9.31397 13.6011 9.85727 13.9718C10.1547 14.1743 10.4603 14.3656 10.76 14.5667C11.5544 15.0995 12.3361 15.6525 13.1447 16.1629C14.0243 16.7182 14.4457 16.5523 14.7476 15.5852C14.7768 15.4911 14.8029 15.3947 14.8239 15.2983C15.1318 13.9016 15.3246 12.4847 15.5465 11.073C15.7378 9.85713 15.8993 8.63678 16.0472 7.6025H16.0487Z" fill="#9F9F9F"/>
 | 
			
		||||
</g>
 | 
			
		||||
</g>
 | 
			
		||||
<defs>
 | 
			
		||||
<clipPath id="clip0_64_66">
 | 
			
		||||
<rect width="23" height="22" fill="white"/>
 | 
			
		||||
</clipPath>
 | 
			
		||||
</defs>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.6 KiB  | 
							
								
								
									
										16
									
								
								src/assets/icons/vkIcon.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,16 @@
 | 
			
		||||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
<g clip-path="url(#clip0_64_59)">
 | 
			
		||||
<mask id="mask0_64_59" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="22" height="22">
 | 
			
		||||
<path d="M21.9955 0H0V22H21.9955V0Z" fill="white"/>
 | 
			
		||||
</mask>
 | 
			
		||||
<g mask="url(#mask0_64_59)">
 | 
			
		||||
<path d="M10.9755 22C4.9123 21.9881 -0.0230861 17.0228 8.12304e-05 10.9589C0.0232485 4.91 4.97209 -0.0119356 11.0195 2.17408e-05C17.07 0.0119791 21.9994 4.95335 21.9956 11.003C21.9919 17.0743 17.0438 22.012 10.9755 22ZM11.4724 9.84166C11.4724 9.53076 11.4807 9.21913 11.4702 8.90824C11.4545 8.42621 11.3454 8.29393 10.8716 8.20798C10.2289 8.09215 9.58239 8.10336 8.93968 8.20873C8.77303 8.23638 8.60861 8.31336 8.4569 8.39332C8.28875 8.48151 8.26708 8.58987 8.47858 8.66012C8.78797 8.76325 8.99424 8.96653 9.04132 9.29162C9.12203 9.84689 9.16313 10.4044 9.05552 10.9634C8.95164 11.503 8.5974 11.6315 8.1774 11.2691C8.07502 11.1801 7.98758 11.0718 7.90014 10.9671C7.31797 10.2669 6.96373 9.44856 6.68348 8.59436C6.58409 8.29019 6.37633 8.13923 6.07739 8.134C5.45561 8.12279 4.83308 8.12129 4.2113 8.13998C3.84959 8.15119 3.76739 8.28645 3.91685 8.62126C4.63728 10.2355 5.43095 11.8101 6.52953 13.2084C7.66324 14.6515 9.10634 15.4354 10.9874 15.2972C11.314 15.2733 11.515 15.2045 11.4702 14.8226C11.4538 14.6784 11.4821 14.5237 11.5158 14.3795C11.6234 13.9139 11.9208 13.7756 12.3491 13.9841C12.6428 14.1276 12.8931 14.3376 13.127 14.5581C13.6898 15.0909 14.3302 15.3689 15.1202 15.2987C15.5155 15.2636 15.9161 15.2927 16.3144 15.292C16.6387 15.292 17.0117 15.3241 17.1589 14.9684C17.3001 14.6261 17.0109 14.3854 16.7957 14.1702C16.3024 13.6792 15.7838 13.2136 15.2868 12.7256C14.9468 12.3916 14.9274 12.1935 15.2046 11.8116C15.4819 11.4297 15.789 11.0688 16.0768 10.6944C16.5401 10.0913 16.9661 9.465 17.1634 8.71617C17.2785 8.27898 17.2037 8.15567 16.7576 8.14521C15.999 8.12802 15.2397 8.14297 14.4812 8.15119C14.2189 8.15418 14.0874 8.32307 14.0066 8.554C13.8788 8.91646 13.757 9.28265 13.6038 9.63464C13.334 10.2557 12.9701 10.8192 12.4634 11.2758C12.2885 11.4335 12.0793 11.5874 11.8252 11.4963C11.5509 11.3984 11.4919 11.1368 11.4784 10.8849C11.4597 10.5374 11.4739 10.1884 11.4724 9.84016V9.84166Z" fill="#9F9F9F"/>
 | 
			
		||||
<path d="M11.4733 9.84153C11.4733 10.1898 11.4598 10.5388 11.4785 10.8863C11.492 11.1381 11.5518 11.3997 11.8253 11.4976C12.0794 11.588 12.2894 11.4341 12.4635 11.2772C12.9702 10.8205 13.3334 10.257 13.6039 9.63601C13.7571 9.28402 13.879 8.91782 14.0067 8.55537C14.0882 8.32369 14.219 8.15479 14.4813 8.15255C15.2398 8.14433 15.9991 8.13013 16.7577 8.14657C17.2038 8.15629 17.2793 8.2796 17.1635 8.71754C16.9662 9.46636 16.5402 10.0926 16.0769 10.6957C15.7891 11.0701 15.482 11.4311 15.2047 11.813C14.9275 12.1956 14.9461 12.3929 15.2869 12.727C15.7839 13.215 16.3026 13.6806 16.7958 14.1716C17.011 14.3861 17.3002 14.6267 17.159 14.9697C17.0125 15.3255 16.6396 15.2933 16.3145 15.2933C15.9162 15.2933 15.5156 15.2649 15.1203 15.3C14.3303 15.3703 13.6906 15.0923 13.1271 14.5594C12.894 14.3382 12.6436 14.129 12.3492 13.9855C11.9209 13.7762 11.6235 13.9152 11.5159 14.3808C11.4823 14.5251 11.4539 14.6798 11.4703 14.824C11.5144 15.2059 11.3141 15.2746 10.9875 15.2986C9.10646 15.4368 7.66337 14.6529 6.52967 13.2098C5.43109 11.8115 4.63817 10.2369 3.91699 8.62262C3.76752 8.28782 3.84973 8.15255 4.21144 8.14134C4.83321 8.12266 5.45575 8.12415 6.07753 8.13536C6.37721 8.1406 6.58422 8.29156 6.68362 8.59572C6.96312 9.44992 7.3181 10.2683 7.90028 10.9685C7.98772 11.0739 8.07441 11.1822 8.17754 11.2704C8.59679 11.6329 8.95178 11.5051 9.05566 10.9648C9.16327 10.4058 9.12217 9.84825 9.04146 9.29298C8.99437 8.96715 8.78811 8.76387 8.47871 8.66149C8.26647 8.59124 8.28889 8.48287 8.45704 8.39469C8.60875 8.31472 8.77315 8.237 8.93981 8.2101C9.58177 8.10472 10.229 8.09351 10.8717 8.20935C11.3455 8.29455 11.4546 8.42682 11.4703 8.9096C11.48 9.22049 11.4725 9.53213 11.4725 9.84302L11.4733 9.84153Z" fill="#FBFBFB"/>
 | 
			
		||||
</g>
 | 
			
		||||
</g>
 | 
			
		||||
<defs>
 | 
			
		||||
<clipPath id="clip0_64_59">
 | 
			
		||||
<rect width="22" height="22" fill="white"/>
 | 
			
		||||
</clipPath>
 | 
			
		||||
</defs>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 4.0 KiB  | 
							
								
								
									
										12
									
								
								src/assets/images/EllipseIntro.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,12 @@
 | 
			
		||||
<svg width="1005" height="969" viewBox="0 0 1005 969" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
<g filter="url(#filter0_f_53_13)">
 | 
			
		||||
<circle cx="502.5" cy="466.5" r="281.5" fill="white"/>
 | 
			
		||||
</g>
 | 
			
		||||
<defs>
 | 
			
		||||
<filter id="filter0_f_53_13" x="0.300003" y="-35.7" width="1004.4" height="1004.4" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
 | 
			
		||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
 | 
			
		||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
 | 
			
		||||
<feGaussianBlur stdDeviation="110.35" result="effect1_foregroundBlur_53_13"/>
 | 
			
		||||
</filter>
 | 
			
		||||
</defs>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 596 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/backgroundLandingIntro.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 40 KiB  | 
							
								
								
									
										11
									
								
								src/assets/images/backgroundLandingIntro.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 21 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/backgroundOpportunity.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 33 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/cat.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 163 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/clue.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.6 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/landingBackgroundCode.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 6.6 KiB  | 
							
								
								
									
										11
									
								
								src/assets/images/landingBackgroundCode.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 26 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/landingBackgroundCode1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 6.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/landingCat.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 28 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/reviewsImgMok.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 15 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/stackProjectsFlag.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 14 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/stackProjectsFly.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 23 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/stackProjectsHand.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 17 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/stackProjectsRabota.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 15 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								src/assets/images/stackSteptsPortfolio.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 24 KiB  | 
@@ -108,7 +108,7 @@ export const AuthBlock = ({ title, description, img, resetModal }) => {
 | 
			
		||||
          >
 | 
			
		||||
            {isLoading ? <Loader /> : "Войти"}
 | 
			
		||||
          </button>
 | 
			
		||||
          <NavLink to="/tracker-registration" className="auth__registration">
 | 
			
		||||
          <NavLink to="/auth" className="auth__registration">
 | 
			
		||||
            Регистрация
 | 
			
		||||
          </NavLink>
 | 
			
		||||
        </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -70,6 +70,7 @@ export const AuthBox = ({ title }) => {
 | 
			
		||||
          dispatch(setUserInfo(res));
 | 
			
		||||
          dispatch(loading(false));
 | 
			
		||||
          dispatch(setRole("ROLE_PARTNER"));
 | 
			
		||||
          navigate("/profile");
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ import { currentMonth } from "../../utils/calendarHelper";
 | 
			
		||||
import CalendarComponent from "./CalendarComponent";
 | 
			
		||||
import "./calendar.scss";
 | 
			
		||||
 | 
			
		||||
const Calendar = () => {
 | 
			
		||||
export const Calendar = () => {
 | 
			
		||||
  if (localStorage.getItem("role_status") !== "18") {
 | 
			
		||||
    return <Navigate to="/profile" replace />;
 | 
			
		||||
  }
 | 
			
		||||
@@ -84,5 +84,3 @@ const Calendar = () => {
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default Calendar;
 | 
			
		||||
 
 | 
			
		||||
@@ -23,10 +23,14 @@
 | 
			
		||||
 | 
			
		||||
      .calendar__hours {
 | 
			
		||||
        margin: 0 5px;
 | 
			
		||||
        line-height: 0;
 | 
			
		||||
        font-size: 22px;
 | 
			
		||||
        font-weight: 500;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        span {
 | 
			
		||||
          font-size: 22px;
 | 
			
		||||
          font-weight: 500;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -54,21 +58,33 @@
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &-box {
 | 
			
		||||
      background-color: #e5f1fb;
 | 
			
		||||
      height: 47px;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      margin-left: 20px;
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
      margin: 0 15px;
 | 
			
		||||
      padding: 0 20px;
 | 
			
		||||
      border-radius: 5px;
 | 
			
		||||
 | 
			
		||||
      font-weight: 400;
 | 
			
		||||
      font-size: 16px;
 | 
			
		||||
      color: #406128;
 | 
			
		||||
 | 
			
		||||
      img {
 | 
			
		||||
        margin: 0px 10px;
 | 
			
		||||
        width: 12px;
 | 
			
		||||
        height: 12px;
 | 
			
		||||
 | 
			
		||||
        &:first-child {
 | 
			
		||||
          transform: rotate(180deg);
 | 
			
		||||
          margin: 0;
 | 
			
		||||
        }
 | 
			
		||||
        width: 17px;
 | 
			
		||||
        height: 17px;
 | 
			
		||||
        margin: 0 10px 0 0;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &-arrow {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
      height: 47px;
 | 
			
		||||
      padding: 0 8px;
 | 
			
		||||
      background-color: #e5f1fb;
 | 
			
		||||
      border-radius: 5px;
 | 
			
		||||
 | 
			
		||||
      span {
 | 
			
		||||
        color: #18586e;
 | 
			
		||||
@@ -107,12 +123,9 @@
 | 
			
		||||
      grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
 | 
			
		||||
 | 
			
		||||
      p {
 | 
			
		||||
        color: #398208;
 | 
			
		||||
        font-size: 25px;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        font-style: normal;
 | 
			
		||||
        letter-spacing: normal;
 | 
			
		||||
        line-height: 30px;
 | 
			
		||||
        color: #9babc5;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        font-weight: 500;
 | 
			
		||||
        text-align: center;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -127,24 +140,48 @@
 | 
			
		||||
 | 
			
		||||
    button {
 | 
			
		||||
      margin: 0 auto;
 | 
			
		||||
      width: 125px;
 | 
			
		||||
      height: 42px;
 | 
			
		||||
      width: 135px;
 | 
			
		||||
      height: 82px;
 | 
			
		||||
      padding: 0px;
 | 
			
		||||
      box-shadow: 0 0 59px rgba(44, 44, 44, 0.05);
 | 
			
		||||
      border-radius: 5px;
 | 
			
		||||
      border-radius: 10px;
 | 
			
		||||
      border: 1px solid #c4c4c4;
 | 
			
		||||
      background-color: #ffffff;
 | 
			
		||||
      margin-top: 20px;
 | 
			
		||||
      font-size: 1.2em;
 | 
			
		||||
      text-align: center;
 | 
			
		||||
 | 
			
		||||
      .form-date {
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        padding: 5px 0 0 15px;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .form-box {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        border-bottom-left-radius: 10px;
 | 
			
		||||
        border-bottom-right-radius: 10px;
 | 
			
		||||
        border-top: #eff5fa 2px solid;
 | 
			
		||||
 | 
			
		||||
        .form-hours {
 | 
			
		||||
          display: none;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      a {
 | 
			
		||||
        color: black;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
        font-weight: 500;
 | 
			
		||||
        font-size: 12px;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        font-size: 16px;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
 | 
			
		||||
        @media (max-width: 500px) {
 | 
			
		||||
          font-size: 10px;
 | 
			
		||||
@@ -152,20 +189,6 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      img {
 | 
			
		||||
        width: 16px;
 | 
			
		||||
        height: 16px;
 | 
			
		||||
        margin: 0 5px 0 0;
 | 
			
		||||
 | 
			
		||||
        @media (max-width: 968px) {
 | 
			
		||||
          margin-right: 2px;
 | 
			
		||||
 | 
			
		||||
          @media (max-width: 610px) {
 | 
			
		||||
            display: none;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @media (max-width: 1200px) {
 | 
			
		||||
        width: 110px;
 | 
			
		||||
      }
 | 
			
		||||
@@ -214,17 +237,6 @@
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar__icon {
 | 
			
		||||
  margin-right: 10px;
 | 
			
		||||
  margin-top: -4px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (max-width: 575.98px) {
 | 
			
		||||
  .calendar__icon {
 | 
			
		||||
    display: none;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.select-days {
 | 
			
		||||
  border-style: dashed !important;
 | 
			
		||||
 | 
			
		||||
@@ -246,11 +258,48 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.before {
 | 
			
		||||
  background-color: #e5f9b6 !important;
 | 
			
		||||
  background-color: #ffffff !important;
 | 
			
		||||
 | 
			
		||||
  .form-date {
 | 
			
		||||
    height: 35% !important;
 | 
			
		||||
  }
 | 
			
		||||
  .form-box {
 | 
			
		||||
    background-color: #fafbfe;
 | 
			
		||||
 | 
			
		||||
    .form-hours {
 | 
			
		||||
      color: #6dd077;
 | 
			
		||||
      background-color: #6dd0772f;
 | 
			
		||||
      border-spacing: 10px;
 | 
			
		||||
      border-radius: 5px;
 | 
			
		||||
      display: flex !important;
 | 
			
		||||
      flex-direction: row;
 | 
			
		||||
      width: 95%;
 | 
			
		||||
      font-weight: 400;
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
      padding: 0 7px;
 | 
			
		||||
      position: relative;
 | 
			
		||||
 | 
			
		||||
      span {
 | 
			
		||||
        color: #1458dd;
 | 
			
		||||
        font-weight: 700;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        margin: auto;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    .form-hours::before {
 | 
			
		||||
      content: "";
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      top: 10%;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      height: 75%;
 | 
			
		||||
      border-left: 2px solid #6dd077;
 | 
			
		||||
      border-radius: 5px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pass {
 | 
			
		||||
  background-color: #f7d7c9 !important;
 | 
			
		||||
  background-color: #ba5c33 !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.today {
 | 
			
		||||
@@ -259,7 +308,7 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.selected {
 | 
			
		||||
  background-color: #f9f9c3 !important;
 | 
			
		||||
  background-color: #cbcbb4 !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.block {
 | 
			
		||||
@@ -271,18 +320,25 @@
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  column-gap: 16px;
 | 
			
		||||
  font-size: 16px;
 | 
			
		||||
  font-weight: 500;
 | 
			
		||||
  font-weight: 400;
 | 
			
		||||
  position: relative;
 | 
			
		||||
 | 
			
		||||
  .select {
 | 
			
		||||
    background-color: #e5f1fb;
 | 
			
		||||
    color: #406128;
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
    border: 2px solid #c4c4c4;
 | 
			
		||||
    box-shadow: 0 0 59px rgba(44, 44, 44, 0.05);
 | 
			
		||||
    padding: 5px 8px;
 | 
			
		||||
    padding: 15px;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .hint {
 | 
			
		||||
    color: #6f6f6f;
 | 
			
		||||
    font-size: 14px;
 | 
			
		||||
    font-weight: 300;
 | 
			
		||||
    margin: 0 0 0 20px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .close {
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    margin-left: 8px;
 | 
			
		||||
 
 | 
			
		||||
@@ -28,11 +28,11 @@ import rectangle from "assets/images/rectangle_secondPage.png";
 | 
			
		||||
 | 
			
		||||
import "./candidate.scss";
 | 
			
		||||
 | 
			
		||||
const Candidate = () => {
 | 
			
		||||
export const Candidate = () => {
 | 
			
		||||
  if (localStorage.getItem("role_status") !== "18") {
 | 
			
		||||
    return <Navigate to="/profile" replace />;
 | 
			
		||||
  }
 | 
			
		||||
  // const { id: candidateId } = useParams();
 | 
			
		||||
  const { id: candidateId } = useParams();
 | 
			
		||||
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
@@ -47,7 +47,7 @@ const Candidate = () => {
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    apiRequest(`/user/me`, {}).then((el) =>
 | 
			
		||||
    apiRequest(`/resume?userId=${candidateId}`).then((el) =>
 | 
			
		||||
      dispatch(currentCandidate(el.userCard))
 | 
			
		||||
    );
 | 
			
		||||
  }, [dispatch]);
 | 
			
		||||
@@ -91,10 +91,10 @@ const Candidate = () => {
 | 
			
		||||
  const { header, img, classes } = setStyles();
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="candidate__wrapper">
 | 
			
		||||
    <div className="candidate">
 | 
			
		||||
      <ProfileHeader />
 | 
			
		||||
      <Navigation />
 | 
			
		||||
      <div className="container candidate">
 | 
			
		||||
      <div className="container">
 | 
			
		||||
        <ProfileBreadcrumbs
 | 
			
		||||
          links={[
 | 
			
		||||
            { name: "Главная", link: "/profile" },
 | 
			
		||||
@@ -103,9 +103,7 @@ const Candidate = () => {
 | 
			
		||||
              link: "/profile/catalog"
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              name: `${currentCandidateObj.specification} ${
 | 
			
		||||
                SKILLS[currentCandidateObj.position_id]
 | 
			
		||||
              }, ${LEVELS[currentCandidateObj.level]}`,
 | 
			
		||||
              name: `${currentCandidateObj.fio}`,
 | 
			
		||||
              link: `/candidate/${currentCandidateObj.id}`
 | 
			
		||||
            }
 | 
			
		||||
          ]}
 | 
			
		||||
@@ -115,6 +113,7 @@ const Candidate = () => {
 | 
			
		||||
          <div className="col-12 candidate__header">
 | 
			
		||||
            <div className="candidate__header__left">
 | 
			
		||||
              <h3>
 | 
			
		||||
                {currentCandidateObj.fio}  {" "}
 | 
			
		||||
                {currentCandidateObj.specification}  {" "}
 | 
			
		||||
                {SKILLS[currentCandidateObj.position_id]}  {" "}
 | 
			
		||||
                {LEVELS[currentCandidateObj.level]}
 | 
			
		||||
@@ -238,5 +237,3 @@ const Candidate = () => {
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default Candidate;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,22 +1,23 @@
 | 
			
		||||
@use "sass:math";
 | 
			
		||||
 | 
			
		||||
.candidate {
 | 
			
		||||
  padding-top: 23px;
 | 
			
		||||
  z-index: 0;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  background: #f1f1f1;
 | 
			
		||||
 | 
			
		||||
  &__wrapper {
 | 
			
		||||
    background: #f1f1f1;
 | 
			
		||||
    min-height: 100vh;
 | 
			
		||||
  .container {
 | 
			
		||||
    margin-top: 23px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    flex: 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .profile-breadcrumbs {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    z-index: -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .row {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    z-index: -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__header {
 | 
			
		||||
@@ -32,13 +33,11 @@
 | 
			
		||||
 | 
			
		||||
  .col-xl-8 {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    z-index: -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__main {
 | 
			
		||||
    margin-top: 60px;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    z-index: -1;
 | 
			
		||||
 | 
			
		||||
    &-description {
 | 
			
		||||
      padding-left: 16px;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ export const CardControl = ({ title, path, description, img }) => {
 | 
			
		||||
    <Link to={`/${path}`} className="control-card">
 | 
			
		||||
      <div className="control-card__about">
 | 
			
		||||
        <img src={img} alt="itemImg" />
 | 
			
		||||
        <h3>{title}</h3>
 | 
			
		||||
        <h3 dangerouslySetInnerHTML={{ __html: title }}></h3>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div className="control-card__info">
 | 
			
		||||
        <p dangerouslySetInnerHTML={{ __html: description }}></p>
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@
 | 
			
		||||
      font-weight: 500;
 | 
			
		||||
      font-size: 18px;
 | 
			
		||||
      line-height: 22px;
 | 
			
		||||
      max-width: 125px;
 | 
			
		||||
      max-width: 165px;
 | 
			
		||||
      margin-bottom: 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -24,9 +24,9 @@ export const AuthHeader = () => {
 | 
			
		||||
                  <span>Главная</span>
 | 
			
		||||
                </NavLink>
 | 
			
		||||
              </li>
 | 
			
		||||
              <li>
 | 
			
		||||
                <NavLink to={"/auth"}>Кабинет разработчика</NavLink>
 | 
			
		||||
              </li>
 | 
			
		||||
              {/*<li>*/}
 | 
			
		||||
              {/*  <NavLink to={"/profile"}>Кабинет разработчика</NavLink>*/}
 | 
			
		||||
              {/*</li>*/}
 | 
			
		||||
              <li>
 | 
			
		||||
                <NavLink to={"/tracker-intro"}>Трекер</NavLink>
 | 
			
		||||
              </li>
 | 
			
		||||
@@ -51,5 +51,3 @@ export const AuthHeader = () => {
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default AuthHeader;
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,7 @@
 | 
			
		||||
    background: #ffffff;
 | 
			
		||||
 | 
			
		||||
    .auth-nav {
 | 
			
		||||
      height: 35px;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: row;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
@@ -48,11 +49,13 @@
 | 
			
		||||
            text-decoration: none;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          a:focus, a.active {
 | 
			
		||||
          a:focus,
 | 
			
		||||
          a.active {
 | 
			
		||||
            color: #000000;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .candidate {
 | 
			
		||||
            background: transparent;
 | 
			
		||||
            color: #1458dd;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,19 +5,25 @@ import "./modalLayout.scss";
 | 
			
		||||
export const ModalLayout = ({
 | 
			
		||||
  active,
 | 
			
		||||
  setActive,
 | 
			
		||||
  onClose,
 | 
			
		||||
  children,
 | 
			
		||||
  styles,
 | 
			
		||||
  type,
 | 
			
		||||
  ...props
 | 
			
		||||
}) => {
 | 
			
		||||
  const handleClose = (event) => {
 | 
			
		||||
    if (event.target.className === "modal-layout active") {
 | 
			
		||||
      setActive(false);
 | 
			
		||||
      if (onClose) {
 | 
			
		||||
        onClose(); // Вызов колбэк-функции при закрытии модального окна
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      className={active ? `modal-layout active` : "modal-layout"}
 | 
			
		||||
      onClick={(event) => {
 | 
			
		||||
        if (event.target.className === "modal-layout active") {
 | 
			
		||||
          setActive(false);
 | 
			
		||||
        }
 | 
			
		||||
      }}
 | 
			
		||||
      onClick={handleClose}
 | 
			
		||||
      {...props}
 | 
			
		||||
    >
 | 
			
		||||
      <div
 | 
			
		||||
 
 | 
			
		||||
@@ -61,7 +61,7 @@
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        row-gap: 5px;
 | 
			
		||||
        &__input {
 | 
			
		||||
          margin: 0;
 | 
			
		||||
          margin: 10px 0 10px 0;
 | 
			
		||||
          min-width: 240px;
 | 
			
		||||
          height: 42px;
 | 
			
		||||
 | 
			
		||||
@@ -79,6 +79,9 @@
 | 
			
		||||
          max-width: 190px;
 | 
			
		||||
          width: 100%;
 | 
			
		||||
        }
 | 
			
		||||
        .email-error-message {
 | 
			
		||||
          color: red;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @media (max-width: 805px) {
 | 
			
		||||
 
 | 
			
		||||
@@ -4,10 +4,15 @@ import { backendImg } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import { useNotification } from "@hooks/useNotification";
 | 
			
		||||
 | 
			
		||||
import close from "assets/icons/closeProjectPersons.svg";
 | 
			
		||||
 | 
			
		||||
const FileTracker = ({ file, setDeletedTask, taskId }) => {
 | 
			
		||||
  const [openImg, setOpenImg] = useState(false);
 | 
			
		||||
 | 
			
		||||
  const { showNotification } = useNotification();
 | 
			
		||||
 | 
			
		||||
  function deleteFile(file) {
 | 
			
		||||
    apiRequest("/file/detach", {
 | 
			
		||||
      method: "DELETE",
 | 
			
		||||
@@ -17,9 +22,22 @@ const FileTracker = ({ file, setDeletedTask, taskId }) => {
 | 
			
		||||
        entity_id: taskId,
 | 
			
		||||
        status: 0
 | 
			
		||||
      }
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      setDeletedTask(file);
 | 
			
		||||
    });
 | 
			
		||||
    })
 | 
			
		||||
      .then(() => {
 | 
			
		||||
        setDeletedTask(file);
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Файл успешно удален",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
      })
 | 
			
		||||
      .catch(() => {
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Ошибка при удалении файла",
 | 
			
		||||
          type: "error"
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,8 @@ import withReactContent from "sweetalert2-react-content";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import { useNotification } from "@hooks/useNotification";
 | 
			
		||||
 | 
			
		||||
import { Loader } from "@components/Common/Loader/Loader";
 | 
			
		||||
 | 
			
		||||
import "./form.scss";
 | 
			
		||||
@@ -18,6 +20,8 @@ const Form = () => {
 | 
			
		||||
 | 
			
		||||
  const urlParams = useParams();
 | 
			
		||||
 | 
			
		||||
  const { showNotification } = useNotification();
 | 
			
		||||
 | 
			
		||||
  const [status, setStatus] = useState(null);
 | 
			
		||||
  const [data, setData] = useState({
 | 
			
		||||
    email: "",
 | 
			
		||||
@@ -75,10 +79,23 @@ const Form = () => {
 | 
			
		||||
        profile_id: urlParams.id,
 | 
			
		||||
        ...data
 | 
			
		||||
      }
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      setStatus(res);
 | 
			
		||||
      setIsFetching(false);
 | 
			
		||||
    });
 | 
			
		||||
    })
 | 
			
		||||
      .then((res) => {
 | 
			
		||||
        setStatus(res);
 | 
			
		||||
        setIsFetching(false);
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Отправка успешно завершена",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
      })
 | 
			
		||||
      .catch(() => {
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Ошибка отправки",
 | 
			
		||||
          type: "error"
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ import { Link } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
import { scrollToForm } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import AuthHeader from "@components/Common/AuthHeader/AuthHeader";
 | 
			
		||||
import { AuthHeader } from "@components/Common/AuthHeader/AuthHeader";
 | 
			
		||||
import BaseButton from "@components/Common/BaseButton/BaseButton";
 | 
			
		||||
import { Footer } from "@components/Common/Footer/Footer";
 | 
			
		||||
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
import React, { useState } from "react";
 | 
			
		||||
import { Link, useNavigate } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
import { useFormValidation } from "@hooks/useFormValidation";
 | 
			
		||||
import { useNotification } from "@hooks/useNotification";
 | 
			
		||||
@@ -17,6 +18,7 @@ import "./modalRegistration.scss";
 | 
			
		||||
export const ModalRegistration = ({ active, setActive }) => {
 | 
			
		||||
  const [loader, setLoader] = useState(false);
 | 
			
		||||
  const [isPartner, setIsPartner] = useState(false);
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  const fields = {
 | 
			
		||||
    username: "",
 | 
			
		||||
@@ -32,10 +34,10 @@ export const ModalRegistration = ({ active, setActive }) => {
 | 
			
		||||
  const apiEndpoint = "/register/sign-up";
 | 
			
		||||
 | 
			
		||||
  const { showNotification } = useNotification();
 | 
			
		||||
  const showNotificationError = () => {
 | 
			
		||||
  const showNotificationError = (error) => {
 | 
			
		||||
    showNotification({
 | 
			
		||||
      show: true,
 | 
			
		||||
      text: "Аккаунт с таким логином или email уже существует",
 | 
			
		||||
      text: error,
 | 
			
		||||
      type: "error"
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
@@ -58,7 +60,9 @@ export const ModalRegistration = ({ active, setActive }) => {
 | 
			
		||||
    fields,
 | 
			
		||||
    showNotificationError,
 | 
			
		||||
    showNotificationTrue,
 | 
			
		||||
    isPartner
 | 
			
		||||
    isPartner,
 | 
			
		||||
    setLoader,
 | 
			
		||||
    closeModal
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
@@ -137,17 +141,13 @@ export const ModalRegistration = ({ active, setActive }) => {
 | 
			
		||||
 | 
			
		||||
        <div className="button-box">
 | 
			
		||||
          {loader ? (
 | 
			
		||||
            <Loader style={"green"} />
 | 
			
		||||
            <Loader />
 | 
			
		||||
          ) : (
 | 
			
		||||
            <BaseButton
 | 
			
		||||
              onClick={async (e) => {
 | 
			
		||||
                e.preventDefault();
 | 
			
		||||
                setLoader(true);
 | 
			
		||||
                const result = await handleSubmit(e);
 | 
			
		||||
                if (result === true) {
 | 
			
		||||
                  closeModal();
 | 
			
		||||
                }
 | 
			
		||||
                setLoader(false);
 | 
			
		||||
                await handleSubmit(e);
 | 
			
		||||
                navigate("/welcome-page");
 | 
			
		||||
              }}
 | 
			
		||||
              styles="button-box__submit"
 | 
			
		||||
            >
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      width: 65%;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
 | 
			
		||||
      @media (max-width: 1106px) {
 | 
			
		||||
        width: 100%;
 | 
			
		||||
@@ -115,6 +116,8 @@
 | 
			
		||||
          .input-container {
 | 
			
		||||
            margin: 0 0 20px 0;
 | 
			
		||||
            width: 100%;
 | 
			
		||||
            display: flex;
 | 
			
		||||
            flex-direction: column;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          span {
 | 
			
		||||
@@ -246,6 +249,5 @@
 | 
			
		||||
 | 
			
		||||
  .loader {
 | 
			
		||||
    justify-content: start;
 | 
			
		||||
    left: 80px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ import { useNotification } from "@hooks/useNotification";
 | 
			
		||||
import { Loader } from "@components/Common/Loader/Loader";
 | 
			
		||||
import ModalLayout from "@components/Common/ModalLayout/ModalLayout";
 | 
			
		||||
 | 
			
		||||
import arrow from "assets/icons/arrows/arrowCalendar.png";
 | 
			
		||||
import arrow from "assets/icons/arrows/arrowRight.png";
 | 
			
		||||
import close from "assets/icons/close.png";
 | 
			
		||||
 | 
			
		||||
import "./modalResetPassword.scss";
 | 
			
		||||
 
 | 
			
		||||
@@ -6,10 +6,12 @@ import {
 | 
			
		||||
  modalToggle
 | 
			
		||||
} from "@redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import { caseOfNum, urlForLocal } from "@utils/helper";
 | 
			
		||||
import { caseOfNum, removeLast, urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import { useNotification } from "@hooks/useNotification";
 | 
			
		||||
 | 
			
		||||
import ModalLayout from "@components/Common/ModalLayout/ModalLayout";
 | 
			
		||||
 | 
			
		||||
import close from "assets/icons/close.png";
 | 
			
		||||
@@ -24,6 +26,7 @@ const ListEmployees = ({
 | 
			
		||||
  setModalAdd
 | 
			
		||||
}) => {
 | 
			
		||||
  const dispatch = useDispatch();
 | 
			
		||||
  const { showNotification } = useNotification();
 | 
			
		||||
 | 
			
		||||
  function deletePerson(userId) {
 | 
			
		||||
    apiRequest("/project/del-user", {
 | 
			
		||||
@@ -32,9 +35,22 @@ const ListEmployees = ({
 | 
			
		||||
        project_id: projectBoard.id,
 | 
			
		||||
        user_id: userId
 | 
			
		||||
      }
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      dispatch(deletePersonOnProject(userId));
 | 
			
		||||
    });
 | 
			
		||||
    })
 | 
			
		||||
      .then(() => {
 | 
			
		||||
        dispatch(deletePersonOnProject(userId));
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Участник успешно удален",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
      })
 | 
			
		||||
      .catch(() => {
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Ошибка удаления участника",
 | 
			
		||||
          type: "error"
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
@@ -67,7 +83,7 @@ const ListEmployees = ({
 | 
			
		||||
                  }
 | 
			
		||||
                  alt="avatar"
 | 
			
		||||
                />
 | 
			
		||||
                <span>{person.user.fio}</span>
 | 
			
		||||
                <span>{removeLast(person.user.fio)}</span>
 | 
			
		||||
                <img
 | 
			
		||||
                  className="delete"
 | 
			
		||||
                  src={close}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,10 +11,10 @@ import { getProfileInfo } from "@redux/outstaffingSlice";
 | 
			
		||||
import { setProjectBoardFetch } from "@redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  backendImg,
 | 
			
		||||
  caseOfNum,
 | 
			
		||||
  getCorrectRequestDate,
 | 
			
		||||
  getToken,
 | 
			
		||||
  removeLast,
 | 
			
		||||
  urlForLocal
 | 
			
		||||
} from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
@@ -99,6 +99,18 @@ export const ModalTiсket = ({
 | 
			
		||||
  const { showNotification } = useNotification();
 | 
			
		||||
  const [commentSendDisable, setCommentSendDisable] = useState(false);
 | 
			
		||||
 | 
			
		||||
  const closeModal = () => {
 | 
			
		||||
    setActive(false);
 | 
			
		||||
    // Восстанавливаем скролл при закрытии модального окна
 | 
			
		||||
    document.body.style.overflow = "auto";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const [isExpanded, setIsExpanded] = useState(false);
 | 
			
		||||
 | 
			
		||||
  const toggleModalSize = () => {
 | 
			
		||||
    setIsExpanded((prevState) => !prevState);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  function deleteTask() {
 | 
			
		||||
    apiRequest("/task/update-task", {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
@@ -106,15 +118,23 @@ export const ModalTiсket = ({
 | 
			
		||||
        task_id: task.id,
 | 
			
		||||
        status: 0
 | 
			
		||||
      }
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      setActive(false);
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId));
 | 
			
		||||
      showNotification({
 | 
			
		||||
        show: true,
 | 
			
		||||
        text: "Задача успешно была перемещена в архив",
 | 
			
		||||
        type: "archive"
 | 
			
		||||
    })
 | 
			
		||||
      .then(() => {
 | 
			
		||||
        closeModal();
 | 
			
		||||
        dispatch(setProjectBoardFetch(projectId));
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Задача успешно удалена",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
      })
 | 
			
		||||
      .catch(() => {
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Ошибка удаления",
 | 
			
		||||
          type: "error"
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const priority = {
 | 
			
		||||
@@ -157,15 +177,23 @@ export const ModalTiсket = ({
 | 
			
		||||
        title: inputsValue.title,
 | 
			
		||||
        description: inputsValue.description
 | 
			
		||||
      }
 | 
			
		||||
    }).then((res) => {
 | 
			
		||||
      setEditOpen(!editOpen);
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId));
 | 
			
		||||
      showNotification({
 | 
			
		||||
        show: true,
 | 
			
		||||
        text: "Изменения сохранены",
 | 
			
		||||
        type: "success"
 | 
			
		||||
    })
 | 
			
		||||
      .then((res) => {
 | 
			
		||||
        setEditOpen(!editOpen);
 | 
			
		||||
        dispatch(setProjectBoardFetch(projectId));
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Изменения сохранены",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
      })
 | 
			
		||||
      .catch(() => {
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Ошибка при сохранении изменений",
 | 
			
		||||
          type: "error"
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function createComment() {
 | 
			
		||||
@@ -594,20 +622,20 @@ export const ModalTiсket = ({
 | 
			
		||||
    <div
 | 
			
		||||
      className={active ? "modal-ticket active" : "modal-ticket"}
 | 
			
		||||
      onClick={(e) => {
 | 
			
		||||
        if (e.target.className.includes("modal-ticket")) setActive(false);
 | 
			
		||||
        if (e.target.className.includes("modal-ticket")) closeModal();
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      <div className="modal-ticket__content">
 | 
			
		||||
      <div className={`modal-ticket__content ${isExpanded ? "expanded" : ""}`}>
 | 
			
		||||
        <div className="content">
 | 
			
		||||
          <h3 className="title-project">
 | 
			
		||||
            <img src={category} className="title-project__category"></img>
 | 
			
		||||
            {projectName}
 | 
			
		||||
            <Link
 | 
			
		||||
              to={`/tracker/task/${task.id}`}
 | 
			
		||||
            <img
 | 
			
		||||
              src={fullScreen}
 | 
			
		||||
              alt="Full screen"
 | 
			
		||||
              onClick={toggleModalSize}
 | 
			
		||||
              className="title-project__full"
 | 
			
		||||
            >
 | 
			
		||||
              <img src={fullScreen}></img>
 | 
			
		||||
            </Link>
 | 
			
		||||
            />
 | 
			
		||||
          </h3>
 | 
			
		||||
          <div className="content__task">
 | 
			
		||||
            {editOpen ? (
 | 
			
		||||
@@ -636,11 +664,8 @@ export const ModalTiсket = ({
 | 
			
		||||
                      "EasyImage",
 | 
			
		||||
                      "Image",
 | 
			
		||||
                      "ImageCaption",
 | 
			
		||||
                      "ImageStyle",
 | 
			
		||||
                      "ImageToolbar",
 | 
			
		||||
                      "ImageUpload",
 | 
			
		||||
                      "MediaEmbed",
 | 
			
		||||
                      "BlockQuote"
 | 
			
		||||
                      "MediaEmbed"
 | 
			
		||||
                    ]
 | 
			
		||||
                  }}
 | 
			
		||||
                  onChange={(event, editor) => {
 | 
			
		||||
@@ -757,14 +782,14 @@ export const ModalTiсket = ({
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="workers">
 | 
			
		||||
          <div className="workers_box task__info">
 | 
			
		||||
            <span className="exit" onClick={() => setActive(false)}></span>
 | 
			
		||||
            <span className="exit" onClick={() => closeModal()}></span>
 | 
			
		||||
            <h5>Создатель: </h5>
 | 
			
		||||
            <p className="workers__creator">{task.user?.fio}</p>
 | 
			
		||||
            <p className="workers__creator">{removeLast(task.user?.fio)}</p>
 | 
			
		||||
            {executor ? (
 | 
			
		||||
              <>
 | 
			
		||||
                <h5>Исполнитель: </h5>
 | 
			
		||||
                <div className="executor">
 | 
			
		||||
                  <p>{executor.fio}</p>
 | 
			
		||||
                  <p>{removeLast(executor.fio)}</p>
 | 
			
		||||
                  <img
 | 
			
		||||
                    src={
 | 
			
		||||
                      executor?.avatar
 | 
			
		||||
@@ -803,7 +828,7 @@ export const ModalTiсket = ({
 | 
			
		||||
                          key={person.user_id}
 | 
			
		||||
                          onClick={() => taskExecutor(person)}
 | 
			
		||||
                        >
 | 
			
		||||
                          <span>{person.user.fio}</span>
 | 
			
		||||
                          <span>{removeLast(person.user.fio)}</span>
 | 
			
		||||
                          <img
 | 
			
		||||
                            src={
 | 
			
		||||
                              person.user?.avatar
 | 
			
		||||
@@ -826,7 +851,7 @@ export const ModalTiсket = ({
 | 
			
		||||
                  {members.map((member) => {
 | 
			
		||||
                    return (
 | 
			
		||||
                      <div className="worker" key={member.user_id}>
 | 
			
		||||
                        <p>{member.fio}</p>
 | 
			
		||||
                        <p>{removeLast(member.fio)}</p>
 | 
			
		||||
                        <img
 | 
			
		||||
                          src={
 | 
			
		||||
                            member?.avatar
 | 
			
		||||
@@ -869,7 +894,7 @@ export const ModalTiсket = ({
 | 
			
		||||
                          key={person.user_id}
 | 
			
		||||
                          onClick={() => addMember(person)}
 | 
			
		||||
                        >
 | 
			
		||||
                          <span>{person.user.fio}</span>
 | 
			
		||||
                          <span>{removeLast(person.user.fio)}</span>
 | 
			
		||||
                          <img
 | 
			
		||||
                            src={
 | 
			
		||||
                              person.user?.avatar
 | 
			
		||||
@@ -895,7 +920,7 @@ export const ModalTiсket = ({
 | 
			
		||||
                className="dead-line__container"
 | 
			
		||||
                onClick={() => setDatePickerOpen(!datePickerOpen)}
 | 
			
		||||
              >
 | 
			
		||||
                <img src={calendarIcon} alt="calendar" />
 | 
			
		||||
                <p>⌛</p>
 | 
			
		||||
                <span>
 | 
			
		||||
                  {deadLine ? getCorrectDate(deadLine) : "Срок исполнения"}
 | 
			
		||||
                </span>
 | 
			
		||||
 
 | 
			
		||||
@@ -15,13 +15,20 @@
 | 
			
		||||
  display: flex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.modal-ticket__content.expanded {
 | 
			
		||||
  width: 100vw;
 | 
			
		||||
  height: 100vh;
 | 
			
		||||
  max-height: none;
 | 
			
		||||
  max-width: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.modal-ticket__content {
 | 
			
		||||
  background: #ffffff;
 | 
			
		||||
  border-radius: 8px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row;
 | 
			
		||||
  max-height: 700px;
 | 
			
		||||
  // overflow-y: auto;
 | 
			
		||||
  max-width: 915px;
 | 
			
		||||
 | 
			
		||||
  @media (max-width: 990px) {
 | 
			
		||||
    width: 96%;
 | 
			
		||||
@@ -52,7 +59,7 @@
 | 
			
		||||
    position: relative;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    width: 630px;
 | 
			
		||||
    width: 68%;
 | 
			
		||||
    margin: 26px 0 0 21px;
 | 
			
		||||
 | 
			
		||||
    .title-project {
 | 
			
		||||
@@ -160,7 +167,6 @@
 | 
			
		||||
 | 
			
		||||
      .comments__list {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        overflow-y: auto;
 | 
			
		||||
        height: 190px;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
 | 
			
		||||
@@ -364,7 +370,6 @@
 | 
			
		||||
      column-gap: 25px;
 | 
			
		||||
      row-gap: 20px;
 | 
			
		||||
      margin-top: 33px;
 | 
			
		||||
      overflow-y: auto;
 | 
			
		||||
 | 
			
		||||
      .task-file {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
@@ -607,6 +612,7 @@
 | 
			
		||||
  .workers {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    border-left: 1px solid #f1f1f1;
 | 
			
		||||
    width: 32%;
 | 
			
		||||
 | 
			
		||||
    .exit {
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
@@ -976,7 +982,7 @@
 | 
			
		||||
          position: relative;
 | 
			
		||||
 | 
			
		||||
          row-gap: 10px;
 | 
			
		||||
          padding: 10px 40px 0px 20px;
 | 
			
		||||
          padding: 10px 20px 0px 20px;
 | 
			
		||||
          border-radius: 10px;
 | 
			
		||||
          margin-bottom: 10px;
 | 
			
		||||
 | 
			
		||||
@@ -1107,7 +1113,7 @@
 | 
			
		||||
 | 
			
		||||
      &-priority {
 | 
			
		||||
        position: relative;
 | 
			
		||||
        padding: 10px 40px 0 20px;
 | 
			
		||||
        padding: 10px 20px 0 20px;
 | 
			
		||||
        border-radius: 10px;
 | 
			
		||||
        margin-bottom: 10px;
 | 
			
		||||
        .priority {
 | 
			
		||||
@@ -1167,7 +1173,7 @@
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &-bottom {
 | 
			
		||||
        padding: 0px 90px 10px 35px;
 | 
			
		||||
        padding: 0px 30px 10px 20px;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        line-height: 32px;
 | 
			
		||||
@@ -1190,9 +1196,10 @@
 | 
			
		||||
        .edit {
 | 
			
		||||
          background: #52b709;
 | 
			
		||||
          border-radius: 50px;
 | 
			
		||||
 | 
			
		||||
          width: fit-content;
 | 
			
		||||
          p {
 | 
			
		||||
            font-weight: 700;
 | 
			
		||||
            padding-right: 10px;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ import {
 | 
			
		||||
  caseOfNum,
 | 
			
		||||
  getCorrectRequestDate,
 | 
			
		||||
  getToken,
 | 
			
		||||
  removeLast,
 | 
			
		||||
  urlForLocal
 | 
			
		||||
} from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
@@ -31,12 +32,12 @@ import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadc
 | 
			
		||||
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
 | 
			
		||||
import TrackerTaskComment from "@components/TrackerTaskComment/TrackerTaskComment";
 | 
			
		||||
 | 
			
		||||
import arrow from "assets/icons/arrows/arrowCalendar.png";
 | 
			
		||||
import arrow from "assets/icons/arrows/arrowRight.png";
 | 
			
		||||
import arrowStart from "assets/icons/arrows/arrowStart.png";
 | 
			
		||||
import arrowDown from "assets/icons/arrows/selectArrow.png";
 | 
			
		||||
import calendarIcon from "assets/icons/calendar.svg";
 | 
			
		||||
import close from "assets/icons/crossWhite.svg";
 | 
			
		||||
import fileDelete from "assets/icons/closeProjectPersons.svg";
 | 
			
		||||
import close from "assets/icons/crossWhite.svg";
 | 
			
		||||
import del from "assets/icons/delete.svg";
 | 
			
		||||
import edit from "assets/icons/edit.svg";
 | 
			
		||||
import file from "assets/icons/fileModal.svg";
 | 
			
		||||
@@ -630,14 +631,6 @@ export const TicketFullScreen = () => {
 | 
			
		||||
            <img src={tasks} alt="img" />
 | 
			
		||||
            <p>Все мои задачи</p>
 | 
			
		||||
          </Link>
 | 
			
		||||
          <Link
 | 
			
		||||
            to="/profile/tracker"
 | 
			
		||||
            className="tab"
 | 
			
		||||
            onClick={() => toggleTabs(3)}
 | 
			
		||||
          >
 | 
			
		||||
            <img src={archive} alt="img" />
 | 
			
		||||
            <p>Архив</p>
 | 
			
		||||
          </Link>
 | 
			
		||||
        </div>
 | 
			
		||||
        {loader ? (
 | 
			
		||||
          <Loader />
 | 
			
		||||
@@ -690,11 +683,8 @@ export const TicketFullScreen = () => {
 | 
			
		||||
                            "EasyImage",
 | 
			
		||||
                            "Image",
 | 
			
		||||
                            "ImageCaption",
 | 
			
		||||
                            "ImageStyle",
 | 
			
		||||
                            "ImageToolbar",
 | 
			
		||||
                            "ImageUpload",
 | 
			
		||||
                            "MediaEmbed",
 | 
			
		||||
                            "BlockQuote"
 | 
			
		||||
                            "MediaEmbed"
 | 
			
		||||
                          ]
 | 
			
		||||
                        }}
 | 
			
		||||
                        onChange={(event, editor) => {
 | 
			
		||||
@@ -812,14 +802,14 @@ export const TicketFullScreen = () => {
 | 
			
		||||
              <div className="workers fullscreen-workers">
 | 
			
		||||
                <div className="workers_box task__info">
 | 
			
		||||
                  <div className="workers__creator">
 | 
			
		||||
                    Создатель: <p>{taskInfo.user?.fio}</p>
 | 
			
		||||
                    Создатель: <p>{removeLast(taskInfo.user?.fio)}</p>
 | 
			
		||||
                  </div>
 | 
			
		||||
 | 
			
		||||
                  {taskInfo.executor ? (
 | 
			
		||||
                    <>
 | 
			
		||||
                      <h5>Исполнитель: </h5>
 | 
			
		||||
                      <div className="executor">
 | 
			
		||||
                        <p>{taskInfo.executor.fio}</p>
 | 
			
		||||
                        <p>{removeLast(taskInfo.executor.fio)}</p>
 | 
			
		||||
                        <img
 | 
			
		||||
                          src={
 | 
			
		||||
                            taskInfo.executor?.avatar
 | 
			
		||||
@@ -858,7 +848,7 @@ export const TicketFullScreen = () => {
 | 
			
		||||
                                key={person.user_id}
 | 
			
		||||
                                onClick={() => taskExecutor(person)}
 | 
			
		||||
                              >
 | 
			
		||||
                                <span>{person.user.fio}</span>
 | 
			
		||||
                                <span>{removeLast(person.user.fio)}</span>
 | 
			
		||||
                                <img
 | 
			
		||||
                                  src={
 | 
			
		||||
                                    person.user?.avatar
 | 
			
		||||
@@ -881,7 +871,7 @@ export const TicketFullScreen = () => {
 | 
			
		||||
                        {taskInfo.taskUsers.map((member) => {
 | 
			
		||||
                          return (
 | 
			
		||||
                            <div className="worker" key={member.user_id}>
 | 
			
		||||
                              <p>{member.fio}</p>
 | 
			
		||||
                              <p>{removeLast(member.fio)}</p>
 | 
			
		||||
                              <img
 | 
			
		||||
                                src={
 | 
			
		||||
                                  member?.avatar
 | 
			
		||||
@@ -924,7 +914,7 @@ export const TicketFullScreen = () => {
 | 
			
		||||
                                key={person.user_id}
 | 
			
		||||
                                onClick={() => addMember(person)}
 | 
			
		||||
                              >
 | 
			
		||||
                                <span>{person.user.fio}</span>
 | 
			
		||||
                                <span>{removeLast(person.user.fio)}</span>
 | 
			
		||||
                                <img
 | 
			
		||||
                                  src={
 | 
			
		||||
                                    person.user?.avatar
 | 
			
		||||
@@ -950,7 +940,7 @@ export const TicketFullScreen = () => {
 | 
			
		||||
                      className="dead-line__container"
 | 
			
		||||
                      onClick={() => setDatePickerOpen(!datePickerOpen)}
 | 
			
		||||
                    >
 | 
			
		||||
                      <img src={calendarIcon} alt="calendar" />
 | 
			
		||||
                      <p>⌛</p>
 | 
			
		||||
                      <span>
 | 
			
		||||
                        {deadLine
 | 
			
		||||
                          ? getCorrectDate(deadLine)
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ import {
 | 
			
		||||
} from "@redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import { getCorrectDate } from "@utils/calendarHelper";
 | 
			
		||||
import { getCorrectRequestDate, urlForLocal } from "@utils/helper";
 | 
			
		||||
import { getCorrectRequestDate, removeLast, urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
@@ -72,6 +72,7 @@ export const TrackerModal = ({
 | 
			
		||||
  const [selectWorkersOpen, setSelectWorkersOpen] = useState(false);
 | 
			
		||||
  const [selectedWorker, setSelectedWorker] = useState(null);
 | 
			
		||||
  const [emailWorker, setEmailWorker] = useState("");
 | 
			
		||||
  const [emailError, setEmailError] = useState("");
 | 
			
		||||
  const [selectColumnPriority, setSelectColumnPriority] = useState(
 | 
			
		||||
    "Выберите приоритет колонки"
 | 
			
		||||
  );
 | 
			
		||||
@@ -114,6 +115,19 @@ export const TrackerModal = ({
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const existingColumn = projectBoard.columns.find(
 | 
			
		||||
      (column) => column.title === valueColumn
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (existingColumn) {
 | 
			
		||||
      showNotification({
 | 
			
		||||
        show: true,
 | 
			
		||||
        text: "Колонка с таким названием уже существует",
 | 
			
		||||
        type: "error"
 | 
			
		||||
      });
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    apiRequest("/project-column/create-column", {
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      data: {
 | 
			
		||||
@@ -123,9 +137,22 @@ export const TrackerModal = ({
 | 
			
		||||
          : 1,
 | 
			
		||||
        title: valueColumn
 | 
			
		||||
      }
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectBoard.id));
 | 
			
		||||
    });
 | 
			
		||||
    })
 | 
			
		||||
      .then(() => {
 | 
			
		||||
        dispatch(setProjectBoardFetch(projectBoard.id));
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Колонка успешно создана",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
      })
 | 
			
		||||
      .catch(() => {
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Ошибка при создании колонки",
 | 
			
		||||
          type: "error"
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    setValueColumn("");
 | 
			
		||||
    setActive(false);
 | 
			
		||||
  }
 | 
			
		||||
@@ -202,7 +229,7 @@ export const TrackerModal = ({
 | 
			
		||||
        setDeadLineDate("");
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Задача создана",
 | 
			
		||||
          text: "Задача успешно создана",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
@@ -219,6 +246,11 @@ export const TrackerModal = ({
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      setActive(false);
 | 
			
		||||
      dispatch(editProjectName({ id: projectId, name: projectName }));
 | 
			
		||||
      showNotification({
 | 
			
		||||
        show: true,
 | 
			
		||||
        text: "Название проекта успешно изменено",
 | 
			
		||||
        type: "success"
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -267,8 +299,25 @@ export const TrackerModal = ({
 | 
			
		||||
        title: columnName
 | 
			
		||||
      }
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      setActive(false);
 | 
			
		||||
      dispatch(editColumnName({ id: columnId, title: columnName }));
 | 
			
		||||
      const existingColumn = projectBoard.columns.find(
 | 
			
		||||
        (column) => column.title === columnName
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      if (existingColumn) {
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Колонка с таким названием уже существует",
 | 
			
		||||
          type: "error"
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        setActive(false);
 | 
			
		||||
        dispatch(editColumnName({ id: columnId, title: columnName }));
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Колонка успешно изменена",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -287,6 +336,11 @@ export const TrackerModal = ({
 | 
			
		||||
          dispatch(setProject(result));
 | 
			
		||||
          setActive(false);
 | 
			
		||||
          setNameProject("");
 | 
			
		||||
          showNotification({
 | 
			
		||||
            show: true,
 | 
			
		||||
            text: "Проект успешно создан",
 | 
			
		||||
            type: "success"
 | 
			
		||||
          });
 | 
			
		||||
        } else {
 | 
			
		||||
          showNotification({
 | 
			
		||||
            show: true,
 | 
			
		||||
@@ -310,21 +364,57 @@ export const TrackerModal = ({
 | 
			
		||||
      setActive(false);
 | 
			
		||||
      setSelectedWorker("");
 | 
			
		||||
      setSelectWorkersOpen(false);
 | 
			
		||||
      showNotification({
 | 
			
		||||
        show: true,
 | 
			
		||||
        text: "Приглашение отправлено",
 | 
			
		||||
        type: "success"
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function inviteUserByEmail() {
 | 
			
		||||
    apiRequest("/project/add-user-by-email", {
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      data: {
 | 
			
		||||
        email: emailWorker,
 | 
			
		||||
        project_id: projectBoard.id
 | 
			
		||||
      }
 | 
			
		||||
    }).then((el) => {
 | 
			
		||||
      setActive(false);
 | 
			
		||||
      setEmailWorker("");
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  const validateEmail = (email) => {
 | 
			
		||||
    // Простая валидация адреса электронной почты
 | 
			
		||||
    const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
 | 
			
		||||
    return emailPattern.test(email);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const inviteUserByEmail = () => {
 | 
			
		||||
    if (validateEmail(emailWorker)) {
 | 
			
		||||
      setEmailError("");
 | 
			
		||||
      apiRequest("/project/add-user-by-email", {
 | 
			
		||||
        method: "POST",
 | 
			
		||||
        data: {
 | 
			
		||||
          email: emailWorker,
 | 
			
		||||
          project_id: projectBoard.id
 | 
			
		||||
        }
 | 
			
		||||
      }).then((response) => {
 | 
			
		||||
        if (response.status === 400) {
 | 
			
		||||
          showNotification({
 | 
			
		||||
            show: true,
 | 
			
		||||
            text: "Участник уже добавлен в проект",
 | 
			
		||||
            type: "error"
 | 
			
		||||
          });
 | 
			
		||||
        } else if (response.status === 404) {
 | 
			
		||||
          showNotification({
 | 
			
		||||
            show: true,
 | 
			
		||||
            text: "Данной почты не существует",
 | 
			
		||||
            type: "error"
 | 
			
		||||
          });
 | 
			
		||||
        } else {
 | 
			
		||||
          setActive(false);
 | 
			
		||||
          setEmailWorker("");
 | 
			
		||||
          dispatch(addPersonToProject(response));
 | 
			
		||||
          showNotification({
 | 
			
		||||
            show: true,
 | 
			
		||||
            text: "Приглашение отправлено",
 | 
			
		||||
            type: "success"
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    } else {
 | 
			
		||||
      setEmailError("Некорректный e-mail адрес");
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    modalType === "add-worker"
 | 
			
		||||
@@ -406,8 +496,18 @@ export const TrackerModal = ({
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleModalClose = () => {
 | 
			
		||||
    setEmailError("");
 | 
			
		||||
    setEmailWorker("");
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <ModalLayout active={active} setActive={setActive} type={modalType}>
 | 
			
		||||
    <ModalLayout
 | 
			
		||||
      active={active}
 | 
			
		||||
      setActive={setActive}
 | 
			
		||||
      onClose={handleModalClose}
 | 
			
		||||
      type={modalType}
 | 
			
		||||
    >
 | 
			
		||||
      {modalType === "add-worker" && (
 | 
			
		||||
        <>
 | 
			
		||||
          <div className="select__person">
 | 
			
		||||
@@ -428,7 +528,7 @@ export const TrackerModal = ({
 | 
			
		||||
                  >
 | 
			
		||||
                    <p>
 | 
			
		||||
                      {selectedWorker
 | 
			
		||||
                        ? selectedWorker.employee.fio
 | 
			
		||||
                        ? removeLast(selectedWorker.employee.fio)
 | 
			
		||||
                        : "Выберите пользователя"}
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <img className="arrow" src={arrowDown} alt="arrow" />
 | 
			
		||||
@@ -447,7 +547,7 @@ export const TrackerModal = ({
 | 
			
		||||
                                  setSelectedWorker(worker);
 | 
			
		||||
                                }}
 | 
			
		||||
                              >
 | 
			
		||||
                                <span>{worker.employee.fio}</span>
 | 
			
		||||
                                <span>{removeLast(worker.employee.fio)}</span>
 | 
			
		||||
                                <img
 | 
			
		||||
                                  src={urlForLocal(worker.employee.avatar)}
 | 
			
		||||
                                  alt="avatar"
 | 
			
		||||
@@ -478,6 +578,7 @@ export const TrackerModal = ({
 | 
			
		||||
                      value={emailWorker}
 | 
			
		||||
                      onChange={(e) => setEmailWorker(e.target.value)}
 | 
			
		||||
                    />
 | 
			
		||||
                    <div className="email-error-message">{emailError}</div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <BaseButton
 | 
			
		||||
                    styles={"button-add add-person-btn"}
 | 
			
		||||
@@ -501,7 +602,6 @@ export const TrackerModal = ({
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className="create-task-body">
 | 
			
		||||
              <div className="create-task-body__left">
 | 
			
		||||
                <h4>Введите название и описание задачи</h4>
 | 
			
		||||
                <div className="input-container">
 | 
			
		||||
                  <input
 | 
			
		||||
                    maxLength="100"
 | 
			
		||||
@@ -524,7 +624,15 @@ export const TrackerModal = ({
 | 
			
		||||
                      "bulletedList",
 | 
			
		||||
                      "numberedList"
 | 
			
		||||
                    ],
 | 
			
		||||
                    removePlugins: ["BlockQuote"],
 | 
			
		||||
                    removePlugins: [
 | 
			
		||||
                      "CKFinderUploadAdapter",
 | 
			
		||||
                      "CKFinder",
 | 
			
		||||
                      "EasyImage",
 | 
			
		||||
                      "Image",
 | 
			
		||||
                      "ImageCaption",
 | 
			
		||||
                      "ImageUpload",
 | 
			
		||||
                      "MediaEmbed"
 | 
			
		||||
                    ],
 | 
			
		||||
                    placeholder: "Описание задачи"
 | 
			
		||||
                  }}
 | 
			
		||||
                  onChange={(event, editor) => {
 | 
			
		||||
@@ -653,7 +761,7 @@ export const TrackerModal = ({
 | 
			
		||||
                          src={urlForLocal(selectedExecutorTask.user.avatar)}
 | 
			
		||||
                          alt="avatar"
 | 
			
		||||
                        />
 | 
			
		||||
                        <span>{selectedExecutorTask.user.fio}</span>
 | 
			
		||||
                        <span>{removeLast(selectedExecutorTask.user.fio)}</span>
 | 
			
		||||
                      </>
 | 
			
		||||
                    ) : (
 | 
			
		||||
                      <span>{selectedExecutorTask}</span>
 | 
			
		||||
@@ -679,7 +787,7 @@ export const TrackerModal = ({
 | 
			
		||||
                                }
 | 
			
		||||
                                alt="avatar"
 | 
			
		||||
                              />
 | 
			
		||||
                              <span>{person.user.fio}</span>
 | 
			
		||||
                              <span>{removeLast(person.user.fio)}</span>
 | 
			
		||||
                            </div>
 | 
			
		||||
                          );
 | 
			
		||||
                        })
 | 
			
		||||
@@ -690,7 +798,7 @@ export const TrackerModal = ({
 | 
			
		||||
                  )}
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className="create-task-body__right__dead-line">
 | 
			
		||||
                  <img src={calendarImg} alt="calendar" />
 | 
			
		||||
                  <p>⌛</p>
 | 
			
		||||
                  <p onClick={() => setDatePickerOpen(!datePickerOpen)}>
 | 
			
		||||
                    {deadLineDate
 | 
			
		||||
                      ? getCorrectDate(deadLineDate)
 | 
			
		||||
@@ -714,7 +822,7 @@ export const TrackerModal = ({
 | 
			
		||||
              <Loader style={"green"} />
 | 
			
		||||
            ) : (
 | 
			
		||||
              <BaseButton styles={"button-add"} onClick={createTicket}>
 | 
			
		||||
                Создать
 | 
			
		||||
                Создать задачу
 | 
			
		||||
              </BaseButton>
 | 
			
		||||
            )}
 | 
			
		||||
          </div>
 | 
			
		||||
@@ -844,7 +952,14 @@ export const TrackerModal = ({
 | 
			
		||||
        </div>
 | 
			
		||||
      )}
 | 
			
		||||
 | 
			
		||||
      <span className="exit" onClick={() => setActive(false)}></span>
 | 
			
		||||
      <span
 | 
			
		||||
        className="exit"
 | 
			
		||||
        onClick={() => {
 | 
			
		||||
          setActive(false);
 | 
			
		||||
          setEmailError("");
 | 
			
		||||
          setEmailWorker("");
 | 
			
		||||
        }}
 | 
			
		||||
      ></span>
 | 
			
		||||
    </ModalLayout>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -227,6 +227,7 @@
 | 
			
		||||
    min-width: 240px;
 | 
			
		||||
    height: 42px;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    margin: 10px 0 10px 0;
 | 
			
		||||
 | 
			
		||||
    p {
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
@@ -262,7 +263,7 @@
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      padding: 9.5px 12px;
 | 
			
		||||
      top: 48px;
 | 
			
		||||
      top: 45px;
 | 
			
		||||
      left: 0;
 | 
			
		||||
      background: white;
 | 
			
		||||
      border-radius: 5px;
 | 
			
		||||
@@ -337,7 +338,7 @@
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .create-task-body {
 | 
			
		||||
    padding: 15px 20px;
 | 
			
		||||
    padding: 15px 30px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    column-gap: 20px;
 | 
			
		||||
 | 
			
		||||
@@ -373,8 +374,8 @@
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .ck-editor__editable.ck-rounded-corners {
 | 
			
		||||
        min-height: 150px;
 | 
			
		||||
        max-height: 150px;
 | 
			
		||||
        min-height: 180px;
 | 
			
		||||
        max-height: 180px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -383,6 +384,7 @@
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      align-items: start;
 | 
			
		||||
      justify-content: end;
 | 
			
		||||
      row-gap: 10px;
 | 
			
		||||
 | 
			
		||||
      &__owner {
 | 
			
		||||
        display: flex;
 | 
			
		||||
@@ -714,6 +716,10 @@
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .button-add {
 | 
			
		||||
    margin: 0 30px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.name-project {
 | 
			
		||||
 
 | 
			
		||||
@@ -29,10 +29,10 @@ export const Navigation = () => {
 | 
			
		||||
        path: "/tracker",
 | 
			
		||||
        name: "Трекер"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/payouts",
 | 
			
		||||
        name: "Выплаты"
 | 
			
		||||
      },
 | 
			
		||||
      // {
 | 
			
		||||
      //   path: "/payouts",
 | 
			
		||||
      //   name: "Выплаты"
 | 
			
		||||
      // },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/quiz",
 | 
			
		||||
        name: "Тесты"
 | 
			
		||||
@@ -43,14 +43,14 @@ export const Navigation = () => {
 | 
			
		||||
      }
 | 
			
		||||
    ],
 | 
			
		||||
    partner: [
 | 
			
		||||
      {
 | 
			
		||||
        path: "/catalog",
 | 
			
		||||
        active: "candidate",
 | 
			
		||||
        name: "Каталог"
 | 
			
		||||
      },
 | 
			
		||||
      // {
 | 
			
		||||
      //   path: "/catalog",
 | 
			
		||||
      //   active: "candidate",
 | 
			
		||||
      //   name: "Каталог"
 | 
			
		||||
      // },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/requests",
 | 
			
		||||
        name: "Запросы"
 | 
			
		||||
        name: "Мои вакансии"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/employees",
 | 
			
		||||
@@ -61,10 +61,10 @@ export const Navigation = () => {
 | 
			
		||||
        path: "/tracker",
 | 
			
		||||
        name: "Трекер"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/treaties",
 | 
			
		||||
        name: "Договоры"
 | 
			
		||||
      },
 | 
			
		||||
      // {
 | 
			
		||||
      //   path: "/treaties",
 | 
			
		||||
      //   name: "Договоры"
 | 
			
		||||
      // },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/settings",
 | 
			
		||||
        name: "Настройки"
 | 
			
		||||
@@ -81,7 +81,7 @@ export const Navigation = () => {
 | 
			
		||||
              <NavLink
 | 
			
		||||
                key={index}
 | 
			
		||||
                end
 | 
			
		||||
                to={link.path === "/Quiz" ? link.path : `/profile${link.path}`}
 | 
			
		||||
                to={`/profile${link.path}`}
 | 
			
		||||
                className={
 | 
			
		||||
                  currentPath.includes(link.path) ||
 | 
			
		||||
                  currentPath.includes(link.active)
 | 
			
		||||
@@ -97,7 +97,7 @@ export const Navigation = () => {
 | 
			
		||||
 | 
			
		||||
        <div className="profile-header__personal-info">
 | 
			
		||||
          <h3 className="profile-header__personal-info-name">
 | 
			
		||||
            {profileInfo?.fio ? profileInfo?.fio : profileInfo?.username}
 | 
			
		||||
            {profileInfo?.fio || profileInfo?.username}
 | 
			
		||||
          </h3>
 | 
			
		||||
          <NavLink end to={"/profile"}>
 | 
			
		||||
            <img
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,3 @@
 | 
			
		||||
.container {
 | 
			
		||||
  max-width: 1160px !important;
 | 
			
		||||
}
 | 
			
		||||
.catalog {
 | 
			
		||||
  background: #f1f1f1;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
@@ -14,6 +11,10 @@
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.container {
 | 
			
		||||
  max-width: 1160px !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.outstaffing-block__selected .outstaffing-block__img {
 | 
			
		||||
  background-color: #52b70999;
 | 
			
		||||
  color: #f9f9f9;
 | 
			
		||||
 
 | 
			
		||||
@@ -95,11 +95,21 @@ export const ProfileCalendar = () => {
 | 
			
		||||
              alt="avatar"
 | 
			
		||||
            />
 | 
			
		||||
            <p className="summary__name">
 | 
			
		||||
              {profileInfo?.fio ? profileInfo?.fio : profileInfo?.username},{" "}
 | 
			
		||||
              {profileInfo.specification} разработчик
 | 
			
		||||
              {profileInfo?.fio || profileInfo?.username}{" "}
 | 
			
		||||
              {profileInfo.specification}
 | 
			
		||||
            </p>
 | 
			
		||||
            <hr />
 | 
			
		||||
            <div className="summary__direction">Front End</div>
 | 
			
		||||
            <div className="summary__level">Middle+</div>
 | 
			
		||||
          </div>
 | 
			
		||||
          <Link to="/profile/calendar/report">
 | 
			
		||||
          <div className="summary__skill">
 | 
			
		||||
            <p>Ключевые навыки:</p>
 | 
			
		||||
            <div>Java</div>
 | 
			
		||||
            <div>Java</div>
 | 
			
		||||
            <div>Solid</div>
 | 
			
		||||
            <div>Java</div>
 | 
			
		||||
          </div>
 | 
			
		||||
          {/* <Link to="/profile/calendar/report">
 | 
			
		||||
            <button
 | 
			
		||||
              className="calendar__btn"
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
@@ -109,7 +119,7 @@ export const ProfileCalendar = () => {
 | 
			
		||||
            >
 | 
			
		||||
              Заполнить отчет
 | 
			
		||||
            </button>
 | 
			
		||||
          </Link>
 | 
			
		||||
          </Link> */}
 | 
			
		||||
        </div>
 | 
			
		||||
        {loader ? (
 | 
			
		||||
          <div className="loader__wrapper">
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,6 @@ import {
 | 
			
		||||
import {
 | 
			
		||||
  calendarHelper,
 | 
			
		||||
  correctDay,
 | 
			
		||||
  currentMonthAndDay,
 | 
			
		||||
  getCorrectDate,
 | 
			
		||||
  getReports,
 | 
			
		||||
  hourOfNum
 | 
			
		||||
@@ -26,9 +25,9 @@ import { apiRequest } from "@api/request";
 | 
			
		||||
import "@components/Calendar/calendarComponent.scss";
 | 
			
		||||
import BaseButton from "@components/Common/BaseButton/BaseButton";
 | 
			
		||||
 | 
			
		||||
import arrow from "assets/icons/arrows/arrowCalendar.png";
 | 
			
		||||
import arrowLeft from "assets/icons/arrows/arrowCalendar_left.png";
 | 
			
		||||
import arrowRight from "assets/icons/arrows/arrowCalendar_right.png";
 | 
			
		||||
import calendarIcon from "assets/icons/calendar.svg";
 | 
			
		||||
// import close from "assets/icons/closeProjectPersons.svg";
 | 
			
		||||
import rectangle from "assets/images/rectangle__calendar.png";
 | 
			
		||||
 | 
			
		||||
export const ProfileCalendarComponent = React.memo(
 | 
			
		||||
@@ -45,6 +44,7 @@ export const ProfileCalendarComponent = React.memo(
 | 
			
		||||
  }) => {
 | 
			
		||||
    const dispatch = useDispatch();
 | 
			
		||||
 | 
			
		||||
    // const [l, setL] = useState(1);
 | 
			
		||||
    const [calendar, setCalendar] = useState([]);
 | 
			
		||||
    const [month, setMonth] = useState("");
 | 
			
		||||
    const [endDate, setEndDate] = useState(null);
 | 
			
		||||
@@ -173,11 +173,18 @@ export const ProfileCalendarComponent = React.memo(
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const countHours = (day) => {
 | 
			
		||||
      let hours =
 | 
			
		||||
        reports
 | 
			
		||||
          .find((item) => moment(item.created_at).isSame(day, "date"))
 | 
			
		||||
          ?.task.reduce((acc, task) => acc + task.hours_spent, 0) || 0;
 | 
			
		||||
      return `${hours} ${hourOfNum(hours)}`;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <div className="calendar-component">
 | 
			
		||||
        <div className="calendar-component__header">
 | 
			
		||||
          <div className="calendar-component__header-info">
 | 
			
		||||
            {!userId && <h3>Мои отчеты за </h3>}
 | 
			
		||||
            <p className="calendar__hours">
 | 
			
		||||
              {month} 
 | 
			
		||||
              <span>
 | 
			
		||||
@@ -187,27 +194,26 @@ export const ProfileCalendarComponent = React.memo(
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className="calendar-component__header-switcher">
 | 
			
		||||
            <div
 | 
			
		||||
              className="calendar-component__header-box"
 | 
			
		||||
              className="calendar-component__header-arrow"
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                setValueHandler(prevMonth());
 | 
			
		||||
                dispatch(setRequestDate(getReports(prevMonth())));
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              <img src={arrow} alt="" />
 | 
			
		||||
              <span>{prevMonth().format("MMMM")}</span>
 | 
			
		||||
              <img src={arrowLeft} alt="" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className="calendar-component__header-box">
 | 
			
		||||
              <span>{value.format("YYYY")}</span>
 | 
			
		||||
              <img className={"calendar__icon"} src={calendarIcon} alt="" />
 | 
			
		||||
              <span>{value.format("MMMM, YYYY")}</span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div
 | 
			
		||||
              className="calendar-component__header-box"
 | 
			
		||||
              className="calendar-component__header-arrow"
 | 
			
		||||
              onClick={() => {
 | 
			
		||||
                setValueHandler(nextMonth());
 | 
			
		||||
                dispatch(setRequestDate(getReports(nextMonth())));
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              <span>{nextMonth().format("MMMM")}</span>
 | 
			
		||||
              <img src={arrow} alt="" />
 | 
			
		||||
              <img src={arrowRight} alt="" />
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
@@ -218,13 +224,13 @@ export const ProfileCalendarComponent = React.memo(
 | 
			
		||||
 | 
			
		||||
        <div className="calendar-component__body">
 | 
			
		||||
          <div>
 | 
			
		||||
            <p>Пн</p>
 | 
			
		||||
            <p>Вт</p>
 | 
			
		||||
            <p>Ср</p>
 | 
			
		||||
            <p>Чт</p>
 | 
			
		||||
            <p>Пт</p>
 | 
			
		||||
            <p>Сб</p>
 | 
			
		||||
            <p>Вс</p>
 | 
			
		||||
            <p>Понедельник</p>
 | 
			
		||||
            <p>Вторник</p>
 | 
			
		||||
            <p>Среда</p>
 | 
			
		||||
            <p>Четверг</p>
 | 
			
		||||
            <p>Пятница</p>
 | 
			
		||||
            <p>Суббота</p>
 | 
			
		||||
            <p>Воскресенье</p>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <div className="calendar-component__form">
 | 
			
		||||
@@ -260,12 +266,12 @@ export const ProfileCalendarComponent = React.memo(
 | 
			
		||||
                  id="btn"
 | 
			
		||||
                >
 | 
			
		||||
                  <Link to={startRangeDays ? "#" : correctRoute(day)}>
 | 
			
		||||
                    <img
 | 
			
		||||
                      className={"calendar__icon"}
 | 
			
		||||
                      src={calendarIcon}
 | 
			
		||||
                      alt=""
 | 
			
		||||
                    />
 | 
			
		||||
                    {currentMonthAndDay(day)}
 | 
			
		||||
                    <div className="form-date">{day.format("D")}</div>
 | 
			
		||||
                    <div className="form-box">
 | 
			
		||||
                      <div className="form-hours">
 | 
			
		||||
                        <span>{countHours(day)}</span>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </Link>
 | 
			
		||||
                </button>
 | 
			
		||||
              ))
 | 
			
		||||
@@ -286,15 +292,16 @@ export const ProfileCalendarComponent = React.memo(
 | 
			
		||||
                ? `${getCorrectDate(startDate)} - ${getCorrectDate(endDate)}`
 | 
			
		||||
                : `${getCorrectDate(endDate)} - ${getCorrectDate(startDate)}`
 | 
			
		||||
              : activePeriod
 | 
			
		||||
                ? "Выберите диапазон на календаре"
 | 
			
		||||
                : "Выбрать диапазон"}
 | 
			
		||||
              ? "Выберите диапазон на календаре"
 | 
			
		||||
              : "Выбрать диапазон"}
 | 
			
		||||
          </span>
 | 
			
		||||
 | 
			
		||||
          <span>
 | 
			
		||||
            {totalRangeHours
 | 
			
		||||
              ? `${totalRangeHours} ${hourOfNum(totalRangeHours)}`
 | 
			
		||||
              : endDate
 | 
			
		||||
                ? "0 часов"
 | 
			
		||||
                : ""}
 | 
			
		||||
              ? "0 часов"
 | 
			
		||||
              : ""}
 | 
			
		||||
          </span>
 | 
			
		||||
          {endDate && (
 | 
			
		||||
            <BaseButton
 | 
			
		||||
@@ -308,6 +315,7 @@ export const ProfileCalendarComponent = React.memo(
 | 
			
		||||
              Сбросить
 | 
			
		||||
            </BaseButton>
 | 
			
		||||
          )}
 | 
			
		||||
          <span className="hint">Для общего просчета - выберите диапазон</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,25 @@
 | 
			
		||||
    @media (max-width: 500px) {
 | 
			
		||||
      padding-right: 5px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .summary__skill {
 | 
			
		||||
      color: #6f6f6f;
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
      font-weight: 300;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: row;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      column-gap: 10px;
 | 
			
		||||
 | 
			
		||||
      div {
 | 
			
		||||
        font-size: 12px;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
 | 
			
		||||
        border: #8dc63f 0.5px solid;
 | 
			
		||||
        border-radius: 44px;
 | 
			
		||||
        padding: 3px 20px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .loader__wrapper {
 | 
			
		||||
@@ -36,7 +55,6 @@
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .calendar__wrapper {
 | 
			
		||||
 | 
			
		||||
    @media (max-width: 1000px) {
 | 
			
		||||
      min-height: auto;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -39,10 +39,10 @@ export const ProfileHeader = () => {
 | 
			
		||||
        path: "/tracker",
 | 
			
		||||
        name: "Трекер"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/payouts",
 | 
			
		||||
        name: "Выплаты"
 | 
			
		||||
      },
 | 
			
		||||
      // {
 | 
			
		||||
      //   path: "/payouts",
 | 
			
		||||
      //   name: "Выплаты"
 | 
			
		||||
      // },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/quiz",
 | 
			
		||||
        name: "Тесты"
 | 
			
		||||
@@ -59,7 +59,7 @@ export const ProfileHeader = () => {
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/requests",
 | 
			
		||||
        name: "Запросы"
 | 
			
		||||
        name: "Мои вакансии"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/employees",
 | 
			
		||||
@@ -69,10 +69,10 @@ export const ProfileHeader = () => {
 | 
			
		||||
        path: "/tracker",
 | 
			
		||||
        name: "Трекер"
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/treaties",
 | 
			
		||||
        name: "Договоры"
 | 
			
		||||
      },
 | 
			
		||||
      // {
 | 
			
		||||
      //   path: "/treaties",
 | 
			
		||||
      //   name: "Договоры"
 | 
			
		||||
      // },
 | 
			
		||||
      {
 | 
			
		||||
        path: "/settings",
 | 
			
		||||
        name: "Настройки"
 | 
			
		||||
@@ -91,11 +91,10 @@ export const ProfileHeader = () => {
 | 
			
		||||
      });
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  const handler = () => {
 | 
			
		||||
    setIsLoggingOut(true);
 | 
			
		||||
  const handler = (e) => {
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    localStorage.clear();
 | 
			
		||||
    dispatch(auth(false));
 | 
			
		||||
    setIsLoggingOut(false);
 | 
			
		||||
    navigate("/auth");
 | 
			
		||||
    dispatch(setProfileInfo({}));
 | 
			
		||||
  };
 | 
			
		||||
@@ -110,6 +109,10 @@ export const ProfileHeader = () => {
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const closeMenu = () => {
 | 
			
		||||
    setActive(false);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <header className="profile-header">
 | 
			
		||||
      <div className="auth-title">
 | 
			
		||||
@@ -140,13 +143,10 @@ export const ProfileHeader = () => {
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div className={active ? "auth-body active" : "auth-body"}>
 | 
			
		||||
        {/* <div className="auth-body__title">
 | 
			
		||||
          <img src={ITguild}></img>
 | 
			
		||||
        </div> */}
 | 
			
		||||
        <nav className="auth-body__navigation">
 | 
			
		||||
          <div className="profile-header__personal-info">
 | 
			
		||||
            <h3 className="profile-header__personal-info-name">
 | 
			
		||||
              {profileInfo?.fio ? profileInfo?.fio : profileInfo?.username}
 | 
			
		||||
              {profileInfo?.fio || profileInfo?.username}
 | 
			
		||||
            </h3>
 | 
			
		||||
            <NavLink end to={"/profile"}>
 | 
			
		||||
              <img
 | 
			
		||||
@@ -166,7 +166,7 @@ export const ProfileHeader = () => {
 | 
			
		||||
              <NavLink
 | 
			
		||||
                key={index}
 | 
			
		||||
                end
 | 
			
		||||
                to={link.path === "/Quiz" ? link.path : `/profile${link.path}`}
 | 
			
		||||
                to={link.path === "/quiz" ? link.path : `/profile${link.path}`}
 | 
			
		||||
                className={currentPath.includes(link.path) ? "active" : ""}
 | 
			
		||||
              >
 | 
			
		||||
                {link.name}
 | 
			
		||||
@@ -179,6 +179,7 @@ export const ProfileHeader = () => {
 | 
			
		||||
          </button>
 | 
			
		||||
        </nav>
 | 
			
		||||
      </div>
 | 
			
		||||
      {active && <div className="backdrop" onClick={closeMenu}></div>}
 | 
			
		||||
    </header>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,6 @@
 | 
			
		||||
    justify-content: space-between;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    z-index: 9;
 | 
			
		||||
    max-width: 1160px;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    margin: 0 auto;
 | 
			
		||||
@@ -36,6 +35,7 @@
 | 
			
		||||
 | 
			
		||||
        @media (max-width: 414px) {
 | 
			
		||||
          display: block;
 | 
			
		||||
          z-index: 9;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &__line {
 | 
			
		||||
@@ -64,9 +64,19 @@
 | 
			
		||||
    background: white;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .backdrop {
 | 
			
		||||
    position: fixed;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    background-color: rgba(0, 0, 0, 0.5);
 | 
			
		||||
    z-index: 7;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .auth-body {
 | 
			
		||||
    opacity: 0;
 | 
			
		||||
    z-index: 99;
 | 
			
		||||
    z-index: 8;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
@@ -99,7 +109,7 @@
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
 | 
			
		||||
      a {
 | 
			
		||||
        padding: 10px 0 0 0;
 | 
			
		||||
        padding: 15px 0 0 10px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      a,
 | 
			
		||||
@@ -134,7 +144,7 @@
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    overflow: visible;
 | 
			
		||||
    width: calc(100vw / 3);
 | 
			
		||||
    width: calc(100vw / 2.5);
 | 
			
		||||
    transition: width 0.3s;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
@@ -188,6 +198,7 @@
 | 
			
		||||
  &__logout-burger {
 | 
			
		||||
    background: none;
 | 
			
		||||
    border: none;
 | 
			
		||||
    padding: 15px 0 0 0;
 | 
			
		||||
    font-weight: 500;
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
    line-height: 32px;
 | 
			
		||||
 
 | 
			
		||||
@@ -68,6 +68,11 @@ export const ProjectTicket = ({ project, index }) => {
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  // showNotification({
 | 
			
		||||
  //   show: true,
 | 
			
		||||
  //   text: "Проект успешно удален",
 | 
			
		||||
  //   type: "success"
 | 
			
		||||
  // });
 | 
			
		||||
 | 
			
		||||
  function closeAcceptModal() {
 | 
			
		||||
    setAcceptModalOpen(false);
 | 
			
		||||
@@ -96,16 +101,16 @@ export const ProjectTicket = ({ project, index }) => {
 | 
			
		||||
            alt="avatar"
 | 
			
		||||
            className="project__avatar"
 | 
			
		||||
          />
 | 
			
		||||
          <span>{project.owner_info.fio}</span>
 | 
			
		||||
          <div>
 | 
			
		||||
            <p>Создатель проекта</p>
 | 
			
		||||
            <span>{project.owner_info.fio}</span>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </Link>
 | 
			
		||||
 | 
			
		||||
      {/* <Link
 | 
			
		||||
        to={`/profile/statistics/${project.id}`}
 | 
			
		||||
        className="project__statistics"
 | 
			
		||||
      >
 | 
			
		||||
      <Link to={`/profile/statistics/${project.id}`} className="project-stats">
 | 
			
		||||
        Посмотреть статистику
 | 
			
		||||
      </Link> */}
 | 
			
		||||
      </Link>
 | 
			
		||||
 | 
			
		||||
      <span
 | 
			
		||||
        className="menu-settings"
 | 
			
		||||
@@ -135,7 +140,16 @@ export const ProjectTicket = ({ project, index }) => {
 | 
			
		||||
            <img src={edit}></img>
 | 
			
		||||
            <p>редактировать</p>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div onClick={() => copyProjectLink(project.id)}>
 | 
			
		||||
          <div
 | 
			
		||||
            onClick={() => {
 | 
			
		||||
              copyProjectLink(project.id);
 | 
			
		||||
              showNotification({
 | 
			
		||||
                show: true,
 | 
			
		||||
                text: "Ссылка скопирована в буфер обмена",
 | 
			
		||||
                type: "copy"
 | 
			
		||||
              });
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <img src={link}></img>
 | 
			
		||||
            <p>скопировать ссылку</p>
 | 
			
		||||
          </div>
 | 
			
		||||
@@ -145,14 +159,14 @@ export const ProjectTicket = ({ project, index }) => {
 | 
			
		||||
              setAcceptModalOpen(true);
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <img src={archiveSet}></img>
 | 
			
		||||
            {/* <img src={archiveSet}></img>
 | 
			
		||||
            <p>в архив</p>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div
 | 
			
		||||
            onClick={() => {
 | 
			
		||||
              navigate(`/profile/statistics/${project.id}`);
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
          > */}
 | 
			
		||||
            <img src={archiveSet}></img>
 | 
			
		||||
            <p>статистика</p>
 | 
			
		||||
          </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,8 @@
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  width: 300px;
 | 
			
		||||
  width: 22%;
 | 
			
		||||
  height: 140px;
 | 
			
		||||
  background: #f1f1f1;
 | 
			
		||||
  border-radius: 12px;
 | 
			
		||||
 | 
			
		||||
@@ -29,7 +30,7 @@
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
    font-size: 18px;
 | 
			
		||||
    color: #111112;
 | 
			
		||||
    margin-bottom: 10px;
 | 
			
		||||
    margin: 0 0 15px 0;
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      color: black;
 | 
			
		||||
@@ -44,14 +45,15 @@
 | 
			
		||||
    p {
 | 
			
		||||
      color: #6f6f6f;
 | 
			
		||||
      margin-bottom: 0;
 | 
			
		||||
      font-size: 12px;
 | 
			
		||||
      font-weight: 500;
 | 
			
		||||
      font-size: 9px;
 | 
			
		||||
      font-weight: 300;
 | 
			
		||||
      line-height: 17px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    span {
 | 
			
		||||
      color: blue;
 | 
			
		||||
      font-size: 15px;
 | 
			
		||||
      font-weight: 400;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .count {
 | 
			
		||||
@@ -80,18 +82,29 @@
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &-stats {
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    font-weight: 300;
 | 
			
		||||
    line-height: 17px;
 | 
			
		||||
    text-decoration: underline;
 | 
			
		||||
    color: #678eda;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    left: 18px;
 | 
			
		||||
    bottom: 16px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .menu-settings {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    font-size: 30px;
 | 
			
		||||
    color: #6f6f6f;
 | 
			
		||||
    right: 15px;
 | 
			
		||||
    top: -10px;
 | 
			
		||||
    bottom: 10px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__avatar {
 | 
			
		||||
    width: 25px;
 | 
			
		||||
    height: 25px;
 | 
			
		||||
    margin-right: 10px;
 | 
			
		||||
    width: 30px;
 | 
			
		||||
    height: 30px;
 | 
			
		||||
    margin: 0 10px 0 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__open-tracker {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ import "./reportForm.scss";
 | 
			
		||||
 | 
			
		||||
registerLocale("ru", ru);
 | 
			
		||||
 | 
			
		||||
const ReportForm = () => {
 | 
			
		||||
export const ReportForm = () => {
 | 
			
		||||
  if (localStorage.getItem("role_status") === "18") {
 | 
			
		||||
    return <Navigate to="/profile" replace />;
 | 
			
		||||
  }
 | 
			
		||||
@@ -456,5 +456,3 @@ const ReportForm = () => {
 | 
			
		||||
    </section>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default ReportForm;
 | 
			
		||||
 
 | 
			
		||||
@@ -34,11 +34,15 @@
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      grid-column-gap: 30px;
 | 
			
		||||
      column-gap: 30px;
 | 
			
		||||
      column-gap: 10px;
 | 
			
		||||
      margin-top: 20px;
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
      text-decoration: none;
 | 
			
		||||
 | 
			
		||||
      img {
 | 
			
		||||
        width: 23px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      p {
 | 
			
		||||
        margin-bottom: 0;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
 
 | 
			
		||||
@@ -47,23 +47,23 @@ export const SideBar = () => {
 | 
			
		||||
        </div>
 | 
			
		||||
        <ul className="auth-body__navigation">
 | 
			
		||||
          <li>
 | 
			
		||||
            <Link to={"/auth"}>Вход для партнеров</Link>
 | 
			
		||||
            <Link to={"/auth"}>Вход</Link>
 | 
			
		||||
          </li>
 | 
			
		||||
          <li>
 | 
			
		||||
            <Link to={"/auth"}>Кабинет разработчика</Link>
 | 
			
		||||
            <Link to={"/profile"}>Личный кабинет</Link>
 | 
			
		||||
          </li>
 | 
			
		||||
          <li>
 | 
			
		||||
            <Link to={"/tracker-intro"}>Трекер</Link>
 | 
			
		||||
          </li>
 | 
			
		||||
          <li>
 | 
			
		||||
            <Link to={"/Quiz"}>Тесты</Link>
 | 
			
		||||
            <Link to={"/quiz"}>Тесты</Link>
 | 
			
		||||
          </li>
 | 
			
		||||
          <li>
 | 
			
		||||
            <Link to={"/forms"}>Формы</Link>
 | 
			
		||||
          </li>
 | 
			
		||||
          <li>
 | 
			
		||||
            <a href="#">Школа</a>
 | 
			
		||||
          </li>
 | 
			
		||||
          <li>
 | 
			
		||||
            <a href="#">Отрасли</a>
 | 
			
		||||
          </li>
 | 
			
		||||
          <li>
 | 
			
		||||
            <a href="#">Контакты</a>
 | 
			
		||||
          </li>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										193
									
								
								src/components/TrackerCardTask/TrackerCardTask.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,193 @@
 | 
			
		||||
import React, { useEffect, useState } from "react";
 | 
			
		||||
import { useDispatch } from "react-redux";
 | 
			
		||||
 | 
			
		||||
import { movePositionProjectTask } from "@redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import { getCorrectDate } from "@utils/calendarHelper";
 | 
			
		||||
import { removeLast, urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import TrackerSelectColumn from "@components/TrackerSelectColumn/TrackerSelectColumn";
 | 
			
		||||
 | 
			
		||||
import commentsBoard from "assets/icons/commentsBoard.svg";
 | 
			
		||||
import filesBoard from "assets/icons/filesBoard.svg";
 | 
			
		||||
import avatarMok from "assets/images/avatarMok.png";
 | 
			
		||||
 | 
			
		||||
import "./trackerCardTask.scss";
 | 
			
		||||
 | 
			
		||||
const TrackerCardTask = ({
 | 
			
		||||
  task,
 | 
			
		||||
  projectBoard,
 | 
			
		||||
  titleColor,
 | 
			
		||||
  column,
 | 
			
		||||
  openTicket,
 | 
			
		||||
  startWrapperIndexTest,
 | 
			
		||||
  setWrapperHover
 | 
			
		||||
}) => {
 | 
			
		||||
  const dispatch = useDispatch();
 | 
			
		||||
  const [taskHover, setTaskHover] = useState({});
 | 
			
		||||
 | 
			
		||||
  const priority = {
 | 
			
		||||
    2: "Высокий",
 | 
			
		||||
    1: "Средний",
 | 
			
		||||
    0: "Низкий"
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const priorityClass = {
 | 
			
		||||
    2: "high",
 | 
			
		||||
    1: "middle",
 | 
			
		||||
    0: "low"
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  function dragDropTaskHandler(e, task, column) {
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    if (task.id === startWrapperIndexTest.current.task.id) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const finishTask = column.tasks.indexOf(task);
 | 
			
		||||
 | 
			
		||||
    dispatch(
 | 
			
		||||
      movePositionProjectTask({
 | 
			
		||||
        startTask: startWrapperIndexTest.current.task,
 | 
			
		||||
        finishTask: task,
 | 
			
		||||
        finishIndex: finishTask
 | 
			
		||||
      })
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function dragOverTaskHandler(e, task) {
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    if (startWrapperIndexTest.current.task.id === task.id) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    setTaskHover((prevState) => ({ [prevState]: false, [task.id]: true }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function dragStartHandler(e, task, columnId) {
 | 
			
		||||
    startWrapperIndexTest.current = { task: task, index: columnId };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function dragLeaveTaskHandler() {
 | 
			
		||||
    setTaskHover((prevState) => ({ [prevState]: false }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function dragEndTaskHandler() {
 | 
			
		||||
    setTaskHover((prevState) => ({ [prevState]: false }));
 | 
			
		||||
    setWrapperHover((prevState) => ({
 | 
			
		||||
      [prevState]: false
 | 
			
		||||
    }));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    const tasksHover = {};
 | 
			
		||||
    const columnHover = {};
 | 
			
		||||
 | 
			
		||||
    if (Object.keys(projectBoard).length) {
 | 
			
		||||
      projectBoard.columns.forEach((column) => {
 | 
			
		||||
        columnHover[column.id] = false;
 | 
			
		||||
        column.tasks.forEach((task) => (tasksHover[task.id] = false));
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    setWrapperHover(columnHover);
 | 
			
		||||
    setTaskHover(tasksHover);
 | 
			
		||||
  }, [projectBoard]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div
 | 
			
		||||
      key={task.id}
 | 
			
		||||
      className={`tasks__board__item ${
 | 
			
		||||
        taskHover[task.id] ? "task__hover" : ""
 | 
			
		||||
      }`}
 | 
			
		||||
      draggable={true}
 | 
			
		||||
      onDragStart={(e) => dragStartHandler(e, task, column.id)}
 | 
			
		||||
      onDragOver={(e) => dragOverTaskHandler(e, task)}
 | 
			
		||||
      onDragLeave={(e) => dragLeaveTaskHandler(e)}
 | 
			
		||||
      onDragEnd={() => dragEndTaskHandler()}
 | 
			
		||||
      onDrop={(e) => dragDropTaskHandler(e, task, column)}
 | 
			
		||||
      onClick={(e) => openTicket(e, task)}
 | 
			
		||||
    >
 | 
			
		||||
      <div
 | 
			
		||||
        className="tasks__board__item__title"
 | 
			
		||||
        onClick={() => {
 | 
			
		||||
          if (window.innerWidth < 985) {
 | 
			
		||||
            window.location.replace(`/tracker/task/${task.id}`);
 | 
			
		||||
          }
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <p className="task__board__item__title">{task.title}</p>
 | 
			
		||||
      </div>
 | 
			
		||||
      <p
 | 
			
		||||
        dangerouslySetInnerHTML={{
 | 
			
		||||
          __html: task.description
 | 
			
		||||
        }}
 | 
			
		||||
        className="tasks__board__item__description"
 | 
			
		||||
      ></p>
 | 
			
		||||
      {Boolean(task.mark.length) && (
 | 
			
		||||
        <div className="tasks__board__item__tags">
 | 
			
		||||
          {task.mark.map((tag) => {
 | 
			
		||||
            return (
 | 
			
		||||
              <div
 | 
			
		||||
                className="tag-item"
 | 
			
		||||
                key={tag.id}
 | 
			
		||||
                style={{ background: tag.color }}
 | 
			
		||||
              >
 | 
			
		||||
                <p>{tag.slug}</p>
 | 
			
		||||
              </div>
 | 
			
		||||
            );
 | 
			
		||||
          })}
 | 
			
		||||
        </div>
 | 
			
		||||
      )}
 | 
			
		||||
      <div className="tasks__board__item__container">
 | 
			
		||||
        {typeof task.execution_priority === "number" && (
 | 
			
		||||
          <div className="tasks__board__item__priority">
 | 
			
		||||
            <p>⚡</p>
 | 
			
		||||
            <span className={priorityClass[task.execution_priority]}>
 | 
			
		||||
              {priority[task.execution_priority]}
 | 
			
		||||
            </span>
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
        {task.dead_line && (
 | 
			
		||||
          <div className="tasks__board__item__dead-line">
 | 
			
		||||
            <p>⌛</p>
 | 
			
		||||
            <span style={{ color: titleColor }}>
 | 
			
		||||
              {getCorrectDate(task.dead_line)}
 | 
			
		||||
            </span>
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div className="tasks__board__item__info">
 | 
			
		||||
        <div className="tasks__board__item__executor">
 | 
			
		||||
          <img
 | 
			
		||||
            src={
 | 
			
		||||
              task.executor?.avatar
 | 
			
		||||
                ? urlForLocal(task.executor?.avatar)
 | 
			
		||||
                : avatarMok
 | 
			
		||||
            }
 | 
			
		||||
            alt="avatar"
 | 
			
		||||
          />
 | 
			
		||||
          <span>
 | 
			
		||||
            {removeLast(task.executor?.fio) || "Исполнитель не назначен"}
 | 
			
		||||
          </span>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="tasks__board__item__info__tags">
 | 
			
		||||
          <div className="tasks__board__item__info__more">
 | 
			
		||||
            <img src={commentsBoard} alt="commentsImg" />
 | 
			
		||||
            <span>{task.comment_count}</span>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div className="tasks__board__item__info__more">
 | 
			
		||||
            <img src={filesBoard} alt="filesImg" />
 | 
			
		||||
            <span>{task.file_count}</span>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <TrackerSelectColumn
 | 
			
		||||
        columns={projectBoard.columns.filter((item) => item.id !== column.id)}
 | 
			
		||||
        currentColumn={column}
 | 
			
		||||
        task={task}
 | 
			
		||||
      />
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default TrackerCardTask;
 | 
			
		||||
							
								
								
									
										365
									
								
								src/components/TrackerCardTask/trackerCardTask.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,365 @@
 | 
			
		||||
.tasks {
 | 
			
		||||
  &__board {
 | 
			
		||||
    background: #f5f7f9;
 | 
			
		||||
    box-shadow: 0px 2px 5px rgba(60, 66, 87, 0.04),
 | 
			
		||||
      0px 0px 0px 1px rgba(60, 66, 87, 0.08), 0px 1px 1px rgba(0, 0, 0, 0.06);
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
    padding: 12px 10px 12px 8px;
 | 
			
		||||
    width: 360px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    row-gap: 10px;
 | 
			
		||||
    height: fit-content;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    transition: all 0.3s ease;
 | 
			
		||||
    transform: scaleY(-1);
 | 
			
		||||
    min-height: 815px;
 | 
			
		||||
 | 
			
		||||
    @media (max-width: 900px) {
 | 
			
		||||
      min-width: auto;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      max-width: none;
 | 
			
		||||
      transform: scaleX(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .tasks-container {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      row-gap: 8px;
 | 
			
		||||
      max-height: 750px;
 | 
			
		||||
      overflow: auto;
 | 
			
		||||
      padding: 5px;
 | 
			
		||||
 | 
			
		||||
      &::-webkit-scrollbar {
 | 
			
		||||
        width: 3px;
 | 
			
		||||
        border-radius: 10px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &::-webkit-scrollbar-thumb {
 | 
			
		||||
        background: #cbd9f9;
 | 
			
		||||
        border-radius: 20px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &::-webkit-scrollbar-track {
 | 
			
		||||
        background: #c5c0c6;
 | 
			
		||||
        border-radius: 20px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__hover {
 | 
			
		||||
      box-shadow: 0px 2px 10px #9cc480, 0px 0px 0px 1px rgba(60, 66, 87, 0.08),
 | 
			
		||||
        0px 1px 1px rgba(0, 0, 0, 0.06);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .task__hover {
 | 
			
		||||
      box-shadow: 0 0 5px gray;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__item {
 | 
			
		||||
      width: 328px;
 | 
			
		||||
      padding: 6px 10px 8px 10px;
 | 
			
		||||
      position: relative;
 | 
			
		||||
      box-shadow: 0px 3px 2px -2px rgba(0, 0, 0, 0.06),
 | 
			
		||||
        0px 5px 3px -2px rgba(0, 0, 0, 0.02);
 | 
			
		||||
      border-radius: 6px;
 | 
			
		||||
      background: #ffffff;
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
      transition: 0.4s;
 | 
			
		||||
 | 
			
		||||
      &:hover {
 | 
			
		||||
        transform: scale(1.025);
 | 
			
		||||
        transition: 0.3s;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @media (max-width: 900px) {
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        max-height: none;
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
          transform: none;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__hide {
 | 
			
		||||
        opacity: 0;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__title {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        justify-content: space-between;
 | 
			
		||||
        position: relative;
 | 
			
		||||
 | 
			
		||||
        p {
 | 
			
		||||
          color: #1a1919;
 | 
			
		||||
          font-weight: 500;
 | 
			
		||||
          font-size: 16px;
 | 
			
		||||
          line-height: 20px;
 | 
			
		||||
          margin-bottom: 0;
 | 
			
		||||
          max-height: 100px;
 | 
			
		||||
          overflow: hidden;
 | 
			
		||||
          text-overflow: ellipsis;
 | 
			
		||||
          -webkit-line-clamp: 3;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        span {
 | 
			
		||||
          cursor: pointer;
 | 
			
		||||
          display: flex;
 | 
			
		||||
          border-radius: 6px;
 | 
			
		||||
          align-items: center;
 | 
			
		||||
          justify-content: center;
 | 
			
		||||
          font-size: 20px;
 | 
			
		||||
          padding-bottom: 10px;
 | 
			
		||||
          width: 24px;
 | 
			
		||||
          height: 24px;
 | 
			
		||||
          border: 1px solid #dddddd;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__description {
 | 
			
		||||
        margin: 4px 0;
 | 
			
		||||
        color: #5c6165;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        line-height: 120%;
 | 
			
		||||
        max-height: 100px;
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
        text-overflow: ellipsis;
 | 
			
		||||
        display: -webkit-box;
 | 
			
		||||
        -webkit-line-clamp: 2;
 | 
			
		||||
        -webkit-box-orient: vertical;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__container {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        justify-content: space-between;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__info {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        column-gap: 10px;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        justify-content: space-between;
 | 
			
		||||
        pointer-events: none;
 | 
			
		||||
        margin-top: 5px;
 | 
			
		||||
 | 
			
		||||
        &__tags {
 | 
			
		||||
          display: flex;
 | 
			
		||||
          column-gap: 5px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &__more {
 | 
			
		||||
          cursor: pointer;
 | 
			
		||||
          display: flex;
 | 
			
		||||
          align-items: center;
 | 
			
		||||
          span {
 | 
			
		||||
            font-weight: 500;
 | 
			
		||||
            font-size: 12px;
 | 
			
		||||
            line-height: 15px;
 | 
			
		||||
            color: #6e7c87;
 | 
			
		||||
            margin-left: 5px;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &__avatars {
 | 
			
		||||
          position: relative;
 | 
			
		||||
          img {
 | 
			
		||||
            position: relative;
 | 
			
		||||
          }
 | 
			
		||||
          img:first-child {
 | 
			
		||||
            right: -15px;
 | 
			
		||||
            z-index: 2;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__priority {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        column-gap: 5px;
 | 
			
		||||
        margin-top: 3px;
 | 
			
		||||
 | 
			
		||||
        p {
 | 
			
		||||
          font-weight: 500;
 | 
			
		||||
          font-size: 14px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        span {
 | 
			
		||||
          font-weight: 500;
 | 
			
		||||
          font-size: 14px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .high {
 | 
			
		||||
          color: red;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .middle {
 | 
			
		||||
          color: #cece00;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .low {
 | 
			
		||||
          color: green;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__dead-line {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        column-gap: 5px;
 | 
			
		||||
 | 
			
		||||
        p {
 | 
			
		||||
          font-weight: 500;
 | 
			
		||||
          font-size: 14px;
 | 
			
		||||
          color: #1458dd;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        span {
 | 
			
		||||
          font-weight: 500;
 | 
			
		||||
          font-size: 14px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        img {
 | 
			
		||||
          margin-top: -2px;
 | 
			
		||||
          width: 18px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__executor {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        font-weight: 500;
 | 
			
		||||
        column-gap: 5px;
 | 
			
		||||
 | 
			
		||||
        span {
 | 
			
		||||
          max-width: 210px;
 | 
			
		||||
          overflow: hidden;
 | 
			
		||||
          text-overflow: ellipsis;
 | 
			
		||||
          white-space: nowrap;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        img {
 | 
			
		||||
          width: 25px;
 | 
			
		||||
          height: 25px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__tags {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-wrap: wrap;
 | 
			
		||||
        column-gap: 6px;
 | 
			
		||||
        row-gap: 3px;
 | 
			
		||||
        margin: 3px 0;
 | 
			
		||||
 | 
			
		||||
        .tag-item {
 | 
			
		||||
          padding: 3px 10px;
 | 
			
		||||
          border-radius: 10px;
 | 
			
		||||
          color: white;
 | 
			
		||||
          font-size: 12px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .open-items {
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
      border-radius: 44px;
 | 
			
		||||
      width: 33px;
 | 
			
		||||
      height: 33px;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      justify-content: center;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      bottom: -15px;
 | 
			
		||||
      font-size: 20px;
 | 
			
		||||
      left: 165px;
 | 
			
		||||
      color: white;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .more-items {
 | 
			
		||||
      background: #8bcc60;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .less-items {
 | 
			
		||||
      background: #f92828;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__more {
 | 
			
		||||
      padding-bottom: 50px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .column__select {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      padding: 15px;
 | 
			
		||||
      background: #e1fccf;
 | 
			
		||||
      border-radius: 12px;
 | 
			
		||||
      right: -20px;
 | 
			
		||||
      top: 5px;
 | 
			
		||||
      z-index: 7;
 | 
			
		||||
      row-gap: 10px;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
 | 
			
		||||
      @media (max-width: 910px) {
 | 
			
		||||
        right: 10px;
 | 
			
		||||
        top: 40px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &__item {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-content: center;
 | 
			
		||||
        img {
 | 
			
		||||
          margin-right: 5px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        span {
 | 
			
		||||
          font-size: 14px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__no-items {
 | 
			
		||||
      font-weight: 500;
 | 
			
		||||
      font-size: 25px;
 | 
			
		||||
      transform: scaleY(-1);
 | 
			
		||||
 | 
			
		||||
      @media (max-width: 900px) {
 | 
			
		||||
        transform: none;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__no-tasks {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      transform: scaleY(-1);
 | 
			
		||||
 | 
			
		||||
      &-info {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        margin-bottom: 15px;
 | 
			
		||||
        img {
 | 
			
		||||
          width: 27px;
 | 
			
		||||
          height: 27px;
 | 
			
		||||
          margin-right: 5px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        p {
 | 
			
		||||
          font-weight: 700;
 | 
			
		||||
          font-size: 22px;
 | 
			
		||||
          line-height: 32px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &-more {
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        line-height: 22px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @media (max-width: 900px) {
 | 
			
		||||
        transform: none;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										113
									
								
								src/components/TrackerSelectExecutor/TrackerSelectExecutor.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,113 @@
 | 
			
		||||
import React, { useEffect, useState } from "react";
 | 
			
		||||
import { useDispatch } from "react-redux";
 | 
			
		||||
 | 
			
		||||
import { filteredExecutorTasks } from "@redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import { removeLast, urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import arrowDown from "assets/icons/arrows/selectArrow.png";
 | 
			
		||||
import close from "assets/icons/close.png";
 | 
			
		||||
import avatarMok from "assets/images/avatarMok.png";
 | 
			
		||||
 | 
			
		||||
import "./trackerSelectExecutor.scss";
 | 
			
		||||
 | 
			
		||||
const TrackerSelectExecutor = ({
 | 
			
		||||
  selectedExecutor,
 | 
			
		||||
  setSelectedExecutor,
 | 
			
		||||
  deleteSelectedExecutor,
 | 
			
		||||
  projectBoard
 | 
			
		||||
}) => {
 | 
			
		||||
  const [selectExecutorOpen, setSelectedExecutorOpen] = useState(false);
 | 
			
		||||
  const dispatch = useDispatch();
 | 
			
		||||
 | 
			
		||||
  const initListeners = () => {
 | 
			
		||||
    document.addEventListener("click", closeByClickingOut);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const closeByClickingOut = (event) => {
 | 
			
		||||
    const path = event.path || (event.composedPath && event.composedPath());
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
      event &&
 | 
			
		||||
      !path.find(
 | 
			
		||||
        (div) =>
 | 
			
		||||
          div.classList &&
 | 
			
		||||
          (div.classList.contains("tasks__head__executor") ||
 | 
			
		||||
            div.classList.contains("tasks__head__executor-dropdown"))
 | 
			
		||||
      )
 | 
			
		||||
    ) {
 | 
			
		||||
      setSelectedExecutorOpen(false);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  function executorFilter(user) {
 | 
			
		||||
    dispatch(filteredExecutorTasks(user.user_id));
 | 
			
		||||
    setSelectedExecutor(user);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    initListeners();
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  if (selectedExecutor) {
 | 
			
		||||
    return (
 | 
			
		||||
      <div className="tasks__head__executor-selected">
 | 
			
		||||
        <p>{removeLast(selectedExecutor.user.fio)}</p>
 | 
			
		||||
        <img
 | 
			
		||||
          className="avatar"
 | 
			
		||||
          src={
 | 
			
		||||
            selectedExecutor.user?.avatar
 | 
			
		||||
              ? urlForLocal(selectedExecutor.user.avatar)
 | 
			
		||||
              : avatarMok
 | 
			
		||||
          }
 | 
			
		||||
          alt="avatar"
 | 
			
		||||
        />
 | 
			
		||||
        <img
 | 
			
		||||
          className="delete"
 | 
			
		||||
          src={close}
 | 
			
		||||
          alt="delete"
 | 
			
		||||
          onClick={deleteSelectedExecutor}
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  } else {
 | 
			
		||||
    return (
 | 
			
		||||
      <div
 | 
			
		||||
        className="tasks__head__executor"
 | 
			
		||||
        onClick={() => setSelectedExecutorOpen(!selectExecutorOpen)}
 | 
			
		||||
      >
 | 
			
		||||
        <p>Выберите исполнителя</p>
 | 
			
		||||
        <img
 | 
			
		||||
          className={selectExecutorOpen ? "open" : ""}
 | 
			
		||||
          src={arrowDown}
 | 
			
		||||
          alt="arrow"
 | 
			
		||||
        />
 | 
			
		||||
        {selectExecutorOpen && (
 | 
			
		||||
          <div className="tasks__head__executor-dropdown">
 | 
			
		||||
            {projectBoard.projectUsers.map((user) => {
 | 
			
		||||
              return (
 | 
			
		||||
                <div
 | 
			
		||||
                  className="executor-dropdown__person"
 | 
			
		||||
                  key={user.user_id}
 | 
			
		||||
                  onClick={() => executorFilter(user)}
 | 
			
		||||
                >
 | 
			
		||||
                  <p>{removeLast(user.user?.fio)}</p>
 | 
			
		||||
                  <img
 | 
			
		||||
                    src={
 | 
			
		||||
                      user.user?.avatar
 | 
			
		||||
                        ? urlForLocal(user.user.avatar)
 | 
			
		||||
                        : avatarMok
 | 
			
		||||
                    }
 | 
			
		||||
                    alt="avatar"
 | 
			
		||||
                  />
 | 
			
		||||
                </div>
 | 
			
		||||
              );
 | 
			
		||||
            })}
 | 
			
		||||
          </div>
 | 
			
		||||
        )}
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default TrackerSelectExecutor;
 | 
			
		||||
							
								
								
									
										129
									
								
								src/components/TrackerSelectExecutor/trackerSelectExecutor.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,129 @@
 | 
			
		||||
.tasks {
 | 
			
		||||
  &__head {
 | 
			
		||||
    &__executor {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
      margin-right: 10px;
 | 
			
		||||
      border-radius: 8px;
 | 
			
		||||
      border: 1px solid #e3e2e2;
 | 
			
		||||
      padding: 2px 6px;
 | 
			
		||||
      position: relative;
 | 
			
		||||
      max-width: 190px;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
 | 
			
		||||
      @media (max-width: 915px) {
 | 
			
		||||
        margin-right: 0;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        max-width: none;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @media (max-width: 650px) {
 | 
			
		||||
        border-color: gray;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &-selected {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        border-radius: 8px;
 | 
			
		||||
        max-width: 220px;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        margin-right: 10px;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
 | 
			
		||||
        p {
 | 
			
		||||
          color: #252c32;
 | 
			
		||||
          font-weight: 400;
 | 
			
		||||
          font-size: 14px;
 | 
			
		||||
          line-height: 24px;
 | 
			
		||||
          max-width: 155px;
 | 
			
		||||
          overflow: hidden;
 | 
			
		||||
          white-space: nowrap;
 | 
			
		||||
          text-overflow: ellipsis;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .avatar {
 | 
			
		||||
          margin: 0 5px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .delete {
 | 
			
		||||
          cursor: pointer;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        img {
 | 
			
		||||
          display: flex;
 | 
			
		||||
          width: 20px;
 | 
			
		||||
          height: 20px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @media (max-width: 915px) {
 | 
			
		||||
          width: 100%;
 | 
			
		||||
          max-width: none;
 | 
			
		||||
          justify-content: start;
 | 
			
		||||
 | 
			
		||||
          p {
 | 
			
		||||
            font-size: 16px;
 | 
			
		||||
            max-width: none;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      p {
 | 
			
		||||
        color: #252c32;
 | 
			
		||||
        font-weight: 400;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        line-height: 24px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      img {
 | 
			
		||||
        transition: all 0.15s ease;
 | 
			
		||||
        margin-left: 5px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .open {
 | 
			
		||||
        transform: rotate(180deg);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &-dropdown {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        top: 33px;
 | 
			
		||||
        left: 0;
 | 
			
		||||
        background: white;
 | 
			
		||||
        border-radius: 8px;
 | 
			
		||||
        z-index: 5;
 | 
			
		||||
        padding: 10px 10px;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        row-gap: 7px;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
 | 
			
		||||
        .executor-dropdown__person {
 | 
			
		||||
          display: flex;
 | 
			
		||||
          justify-content: space-between;
 | 
			
		||||
          align-items: center;
 | 
			
		||||
          p {
 | 
			
		||||
            max-width: 155px;
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
            white-space: nowrap;
 | 
			
		||||
            text-overflow: ellipsis;
 | 
			
		||||
 | 
			
		||||
            @media (max-width: 915px) {
 | 
			
		||||
              max-width: none;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          img {
 | 
			
		||||
            width: 20px;
 | 
			
		||||
            height: 20px;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &:hover {
 | 
			
		||||
            p {
 | 
			
		||||
              font-weight: 600;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										275
									
								
								src/components/TrackerTagList/TrackerTagList.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,275 @@
 | 
			
		||||
import React, { useEffect, useState } from "react";
 | 
			
		||||
import { HexColorPicker } from "react-colorful";
 | 
			
		||||
import { useDispatch } from "react-redux";
 | 
			
		||||
import { useParams } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  addNewTagToProject,
 | 
			
		||||
  deleteTagProject,
 | 
			
		||||
  setProjectBoardFetch
 | 
			
		||||
} from "@redux/projectsTrackerSlice";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import { useNotification } from "@hooks/useNotification";
 | 
			
		||||
 | 
			
		||||
import arrowDown from "assets/icons/arrows/selectArrow.png";
 | 
			
		||||
import close from "assets/icons/close.png";
 | 
			
		||||
import edit from "assets/icons/edit.svg";
 | 
			
		||||
 | 
			
		||||
import "./trackerTagList.scss";
 | 
			
		||||
 | 
			
		||||
const TrackerTagList = ({ projectBoard }) => {
 | 
			
		||||
  const dispatch = useDispatch();
 | 
			
		||||
  const projectId = useParams();
 | 
			
		||||
 | 
			
		||||
  const { showNotification } = useNotification();
 | 
			
		||||
  const [tagInfo, setTagInfo] = useState({ description: "", name: "" });
 | 
			
		||||
  const [color, setColor] = useState("#aabbcc");
 | 
			
		||||
  const [tags, setTags] = useState({
 | 
			
		||||
    open: false,
 | 
			
		||||
    add: false,
 | 
			
		||||
    edit: false
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  function deleteTag(tagId) {
 | 
			
		||||
    apiRequest("/mark/detach", {
 | 
			
		||||
      method: "DELETE",
 | 
			
		||||
      data: {
 | 
			
		||||
        mark_id: tagId,
 | 
			
		||||
        entity_type: 1,
 | 
			
		||||
        entity_id: projectId.id
 | 
			
		||||
      }
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      dispatch(deleteTagProject(tagId));
 | 
			
		||||
      showNotification({
 | 
			
		||||
        show: true,
 | 
			
		||||
        text: "Тег удален",
 | 
			
		||||
        type: "success"
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function addNewTag() {
 | 
			
		||||
    apiRequest("/mark/create", {
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      data: {
 | 
			
		||||
        title: tagInfo.description,
 | 
			
		||||
        slug: tagInfo.name,
 | 
			
		||||
        color: color,
 | 
			
		||||
        status: 1
 | 
			
		||||
      }
 | 
			
		||||
    }).then((data) => {
 | 
			
		||||
      apiRequest("/mark/attach", {
 | 
			
		||||
        method: "POST",
 | 
			
		||||
        data: {
 | 
			
		||||
          mark_id: data.id,
 | 
			
		||||
          entity_type: 1,
 | 
			
		||||
          entity_id: projectId.id
 | 
			
		||||
        }
 | 
			
		||||
      }).then((data) => {
 | 
			
		||||
        dispatch(addNewTagToProject(data.mark));
 | 
			
		||||
        setTags((prevState) => ({
 | 
			
		||||
          ...prevState,
 | 
			
		||||
          add: false
 | 
			
		||||
        }));
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Тег успешно создан",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function editTag() {
 | 
			
		||||
    apiRequest("/mark/update", {
 | 
			
		||||
      method: "PUT",
 | 
			
		||||
      data: {
 | 
			
		||||
        mark_id: tagInfo.editMarkId,
 | 
			
		||||
        title: tagInfo.description,
 | 
			
		||||
        slug: tagInfo.name,
 | 
			
		||||
        color: color
 | 
			
		||||
      }
 | 
			
		||||
    }).then(() => {
 | 
			
		||||
      dispatch(setProjectBoardFetch(projectId.id));
 | 
			
		||||
      setTags((prevState) => ({
 | 
			
		||||
        ...prevState,
 | 
			
		||||
        edit: false
 | 
			
		||||
      }));
 | 
			
		||||
      setTagInfo({ description: "", name: "" });
 | 
			
		||||
      setColor("#aabbcc");
 | 
			
		||||
      showNotification({
 | 
			
		||||
        show: true,
 | 
			
		||||
        text: "Тег успешно изменён",
 | 
			
		||||
        type: "success"
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const initListeners = () => {
 | 
			
		||||
    document.addEventListener("click", closeByClickingOut);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const closeByClickingOut = (event) => {
 | 
			
		||||
    const path = event.path || (event.composedPath && event.composedPath());
 | 
			
		||||
    if (
 | 
			
		||||
      event &&
 | 
			
		||||
      !path.find(
 | 
			
		||||
        (div) =>
 | 
			
		||||
          div.classList &&
 | 
			
		||||
          (div.classList.contains("tasks__head__tags") ||
 | 
			
		||||
            div.classList.contains("tags__list"))
 | 
			
		||||
      )
 | 
			
		||||
    ) {
 | 
			
		||||
      setTags({ open: false, add: false, edit: false });
 | 
			
		||||
      setTagInfo({ description: "", name: "" });
 | 
			
		||||
      setColor("#aabbcc");
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    initListeners();
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="tasks__head__tags">
 | 
			
		||||
      <div
 | 
			
		||||
        className="tags__add"
 | 
			
		||||
        onClick={() => {
 | 
			
		||||
          setTags((prevState) => ({
 | 
			
		||||
            ...prevState,
 | 
			
		||||
            open: !tags.open
 | 
			
		||||
          }));
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <p>Список тегов</p>
 | 
			
		||||
        <img className={tags.open ? "open" : ""} src={arrowDown} alt="arrow" />
 | 
			
		||||
      </div>
 | 
			
		||||
      {tags.open && (
 | 
			
		||||
        <div className="tags__list">
 | 
			
		||||
          {!tags.add && !tags.edit && (
 | 
			
		||||
            <div
 | 
			
		||||
              className="add-new-tag"
 | 
			
		||||
              onClick={() =>
 | 
			
		||||
                setTags((prevState) => ({
 | 
			
		||||
                  ...prevState,
 | 
			
		||||
                  add: true
 | 
			
		||||
                }))
 | 
			
		||||
              }
 | 
			
		||||
            >
 | 
			
		||||
              <p>Добавить новый тег</p>
 | 
			
		||||
              <span>+</span>
 | 
			
		||||
            </div>
 | 
			
		||||
          )}
 | 
			
		||||
          {!tags.add && !tags.edit && (
 | 
			
		||||
            <div className="tags__list__created">
 | 
			
		||||
              {projectBoard.mark.map((tag) => {
 | 
			
		||||
                return (
 | 
			
		||||
                  <div className="tag-item" key={tag.id}>
 | 
			
		||||
                    <div className="tag-item__info">
 | 
			
		||||
                      <span
 | 
			
		||||
                        className="tag-item__color"
 | 
			
		||||
                        style={{ background: tag.color }}
 | 
			
		||||
                      />
 | 
			
		||||
                      <div>
 | 
			
		||||
                        <span className="tag-item__info__name">{tag.slug}</span>
 | 
			
		||||
                        <p className="tag-item__description">{tag.title}</p>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div className="tag-item__images">
 | 
			
		||||
                      <img
 | 
			
		||||
                        src={edit}
 | 
			
		||||
                        alt="edit"
 | 
			
		||||
                        onClick={() => {
 | 
			
		||||
                          setTags((prevState) => ({
 | 
			
		||||
                            ...prevState,
 | 
			
		||||
                            edit: true
 | 
			
		||||
                          }));
 | 
			
		||||
                          setTagInfo({
 | 
			
		||||
                            description: tag.title,
 | 
			
		||||
                            name: tag.slug,
 | 
			
		||||
                            editMarkId: tag.id
 | 
			
		||||
                          });
 | 
			
		||||
                          setColor(tag.color);
 | 
			
		||||
                        }}
 | 
			
		||||
                      />
 | 
			
		||||
                      <img
 | 
			
		||||
                        onClick={() => deleteTag(tag.id)}
 | 
			
		||||
                        className="delete"
 | 
			
		||||
                        src={close}
 | 
			
		||||
                        alt="delete"
 | 
			
		||||
                      />
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                );
 | 
			
		||||
              })}
 | 
			
		||||
            </div>
 | 
			
		||||
          )}
 | 
			
		||||
          {(tags.add || tags.edit) && (
 | 
			
		||||
            <div className="form-tag">
 | 
			
		||||
              <input
 | 
			
		||||
                className="form-tag__input"
 | 
			
		||||
                placeholder="Описание метки"
 | 
			
		||||
                maxLength="25"
 | 
			
		||||
                value={tagInfo.description}
 | 
			
		||||
                onChange={(e) =>
 | 
			
		||||
                  setTagInfo((prevState) => ({
 | 
			
		||||
                    ...prevState,
 | 
			
		||||
                    description: e.target.value
 | 
			
		||||
                  }))
 | 
			
		||||
                }
 | 
			
		||||
              />
 | 
			
		||||
              <input
 | 
			
		||||
                className="form-tag__input"
 | 
			
		||||
                placeholder="Тег"
 | 
			
		||||
                value={tagInfo.name}
 | 
			
		||||
                maxLength="10"
 | 
			
		||||
                onChange={(e) =>
 | 
			
		||||
                  setTagInfo((prevState) => ({
 | 
			
		||||
                    ...prevState,
 | 
			
		||||
                    name: e.target.value
 | 
			
		||||
                  }))
 | 
			
		||||
                }
 | 
			
		||||
              />
 | 
			
		||||
              <HexColorPicker color={color} onChange={setColor} />
 | 
			
		||||
              <button
 | 
			
		||||
                onClick={() => {
 | 
			
		||||
                  tags.add ? addNewTag() : editTag();
 | 
			
		||||
                }}
 | 
			
		||||
                className={
 | 
			
		||||
                  tagInfo.name && tagInfo.description
 | 
			
		||||
                    ? "form-tag__btn"
 | 
			
		||||
                    : "form-tag__btn disable"
 | 
			
		||||
                }
 | 
			
		||||
              >
 | 
			
		||||
                {tags.add ? "Добавить" : "Изменить"}
 | 
			
		||||
              </button>
 | 
			
		||||
              {(tags.add || tags.edit) && (
 | 
			
		||||
                <button
 | 
			
		||||
                  className={"form-tag__btn"}
 | 
			
		||||
                  onClick={() => {
 | 
			
		||||
                    setTags((prevState) => ({
 | 
			
		||||
                      ...prevState,
 | 
			
		||||
                      add: false,
 | 
			
		||||
                      edit: false
 | 
			
		||||
                    }));
 | 
			
		||||
                    setTagInfo({
 | 
			
		||||
                      description: "",
 | 
			
		||||
                      name: ""
 | 
			
		||||
                    });
 | 
			
		||||
                    setColor("#aabbcc");
 | 
			
		||||
                  }}
 | 
			
		||||
                >
 | 
			
		||||
                  Отмена
 | 
			
		||||
                </button>
 | 
			
		||||
              )}
 | 
			
		||||
            </div>
 | 
			
		||||
          )}
 | 
			
		||||
        </div>
 | 
			
		||||
      )}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default TrackerTagList;
 | 
			
		||||
							
								
								
									
										208
									
								
								src/components/TrackerTagList/trackerTagList.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,208 @@
 | 
			
		||||
.tasks {
 | 
			
		||||
  &__head {
 | 
			
		||||
    &__tags {
 | 
			
		||||
      position: relative;
 | 
			
		||||
      img {
 | 
			
		||||
        transition: all 0.15s ease;
 | 
			
		||||
        margin-left: 5px;
 | 
			
		||||
      }
 | 
			
		||||
      .open {
 | 
			
		||||
        transform: rotate(180deg);
 | 
			
		||||
      }
 | 
			
		||||
      .tags {
 | 
			
		||||
        &__add {
 | 
			
		||||
          display: flex;
 | 
			
		||||
          align-items: center;
 | 
			
		||||
          margin: 0 10px;
 | 
			
		||||
          column-gap: 5px;
 | 
			
		||||
          cursor: pointer;
 | 
			
		||||
          padding: 5px;
 | 
			
		||||
          border-radius: 8px;
 | 
			
		||||
          border: 1px solid #e3e2e2;
 | 
			
		||||
          max-height: 30px;
 | 
			
		||||
 | 
			
		||||
          p {
 | 
			
		||||
            white-space: nowrap;
 | 
			
		||||
            font-weight: 400;
 | 
			
		||||
            font-size: 14px;
 | 
			
		||||
            line-height: 17px;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          span {
 | 
			
		||||
            width: 14px;
 | 
			
		||||
            height: 14px;
 | 
			
		||||
            font-weight: 400;
 | 
			
		||||
            line-height: 16px;
 | 
			
		||||
            border-radius: 50px;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
            justify-content: center;
 | 
			
		||||
            display: flex;
 | 
			
		||||
            background: #99b4f3;
 | 
			
		||||
            color: white;
 | 
			
		||||
            font-size: 14px;
 | 
			
		||||
            transition: all 0.15s ease;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        &__list {
 | 
			
		||||
          position: absolute;
 | 
			
		||||
          border-radius: 8px;
 | 
			
		||||
          background: #d9d9d9;
 | 
			
		||||
          z-index: 8;
 | 
			
		||||
          top: 30px;
 | 
			
		||||
          left: -35px;
 | 
			
		||||
          width: 216px;
 | 
			
		||||
          display: flex;
 | 
			
		||||
          flex-direction: column;
 | 
			
		||||
 | 
			
		||||
          @media (max-width: 900px) {
 | 
			
		||||
            left: 0px;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .close {
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
            width: 20px;
 | 
			
		||||
            height: 20px;
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            right: 10px;
 | 
			
		||||
            top: 2px;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &__created {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            flex-direction: column;
 | 
			
		||||
            row-gap: 8px;
 | 
			
		||||
            margin-top: 8px;
 | 
			
		||||
            padding: 0 8px 8px;
 | 
			
		||||
 | 
			
		||||
            .tag-item {
 | 
			
		||||
              display: flex;
 | 
			
		||||
              align-items: center;
 | 
			
		||||
              flex-direction: row;
 | 
			
		||||
              justify-content: space-between;
 | 
			
		||||
              column-gap: 5px;
 | 
			
		||||
              padding: 0px 8px;
 | 
			
		||||
              border-radius: 8px;
 | 
			
		||||
              height: 40px;
 | 
			
		||||
              max-height: 40px;
 | 
			
		||||
              background: #fff;
 | 
			
		||||
 | 
			
		||||
              &__description {
 | 
			
		||||
                font-size: 12px;
 | 
			
		||||
                word-break: break-word;
 | 
			
		||||
                max-width: 115px;
 | 
			
		||||
                max-height: 40px;
 | 
			
		||||
                overflow: hidden;
 | 
			
		||||
                text-wrap: wrap;
 | 
			
		||||
                text-overflow: ellipsis;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              &__color {
 | 
			
		||||
                width: 22.25px;
 | 
			
		||||
                height: 23.217px;
 | 
			
		||||
                border-radius: 8px;
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              &__images {
 | 
			
		||||
                display: flex;
 | 
			
		||||
                flex-direction: column-reverse;
 | 
			
		||||
                row-gap: 3px;
 | 
			
		||||
 | 
			
		||||
                img {
 | 
			
		||||
                  height: 14px;
 | 
			
		||||
                  width: 14px;
 | 
			
		||||
                  cursor: pointer;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                .delete {
 | 
			
		||||
                  width: 16px;
 | 
			
		||||
                  height: 16px;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              &__info {
 | 
			
		||||
                display: flex;
 | 
			
		||||
                align-items: center;
 | 
			
		||||
                column-gap: 10px;
 | 
			
		||||
 | 
			
		||||
                &__name {
 | 
			
		||||
                  font-size: 12px;
 | 
			
		||||
                  font-weight: 600;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .add-new-tag {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
            column-gap: 15px;
 | 
			
		||||
            border-radius: 8px;
 | 
			
		||||
            background: white;
 | 
			
		||||
            color: #252c32;
 | 
			
		||||
            height: 40px;
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
            justify-content: center;
 | 
			
		||||
            margin: 8px 8px 0px;
 | 
			
		||||
 | 
			
		||||
            p {
 | 
			
		||||
              font-size: 15px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            span {
 | 
			
		||||
              width: 19px;
 | 
			
		||||
              height: 19px;
 | 
			
		||||
              border-radius: 50px;
 | 
			
		||||
              align-items: center;
 | 
			
		||||
              justify-content: center;
 | 
			
		||||
              display: flex;
 | 
			
		||||
              background: #52b709;
 | 
			
		||||
              color: white;
 | 
			
		||||
              font-size: 16px;
 | 
			
		||||
              transition: all 0.15s ease;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .form-tag {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            flex-direction: column;
 | 
			
		||||
            padding: 8px;
 | 
			
		||||
            row-gap: 8px;
 | 
			
		||||
 | 
			
		||||
            .arrow {
 | 
			
		||||
              position: absolute;
 | 
			
		||||
              cursor: pointer;
 | 
			
		||||
              top: 5px;
 | 
			
		||||
              width: 15px;
 | 
			
		||||
              height: 15px;
 | 
			
		||||
              transform: rotate(180deg);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &__input {
 | 
			
		||||
              outline: none;
 | 
			
		||||
              border-radius: 8px;
 | 
			
		||||
              border: 1px solid #e3e2e2;
 | 
			
		||||
              font-size: 15px;
 | 
			
		||||
              padding: 5px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &__btn {
 | 
			
		||||
              outline: none;
 | 
			
		||||
              border: none;
 | 
			
		||||
              background: #252c32;
 | 
			
		||||
              color: whitesmoke;
 | 
			
		||||
              margin: 0 auto 0;
 | 
			
		||||
              border-radius: 10px;
 | 
			
		||||
              font-size: 15px;
 | 
			
		||||
              padding: 5px 12px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .disable {
 | 
			
		||||
              opacity: 0.5;
 | 
			
		||||
              pointer-events: none;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,7 +3,7 @@ import { CKEditor } from "@ckeditor/ckeditor5-react";
 | 
			
		||||
import React, { useState } from "react";
 | 
			
		||||
 | 
			
		||||
import { getCorrectDate } from "@utils/calendarHelper";
 | 
			
		||||
import { urlForLocal } from "@utils/helper";
 | 
			
		||||
import { removeLast, urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
@@ -93,7 +93,7 @@ export const TrackerTaskComment = ({
 | 
			
		||||
            }
 | 
			
		||||
            alt="avatar"
 | 
			
		||||
          />
 | 
			
		||||
          <p>{comment.user.fio}</p>
 | 
			
		||||
          <p>{removeLast(comment.user.fio)}</p>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="comments__list__item__date">
 | 
			
		||||
          <span>{getCorrectDate(comment.created_at)}</span>
 | 
			
		||||
@@ -127,11 +127,8 @@ export const TrackerTaskComment = ({
 | 
			
		||||
              "EasyImage",
 | 
			
		||||
              "Image",
 | 
			
		||||
              "ImageCaption",
 | 
			
		||||
              "ImageStyle",
 | 
			
		||||
              "ImageToolbar",
 | 
			
		||||
              "ImageUpload",
 | 
			
		||||
              "MediaEmbed",
 | 
			
		||||
              "BlockQuote"
 | 
			
		||||
              "MediaEmbed"
 | 
			
		||||
            ]
 | 
			
		||||
          }}
 | 
			
		||||
          onChange={(event, editor) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ export const HeaderPageTestsQuiz = ({ isVisibilityButton }) => {
 | 
			
		||||
        </div>
 | 
			
		||||
        {isVisibilityButton && (
 | 
			
		||||
          <Link
 | 
			
		||||
            to={"/Quiz/instruction"}
 | 
			
		||||
            to={"/quiz/instruction"}
 | 
			
		||||
            className="quiz-btn quiz-btn_restriction"
 | 
			
		||||
          >
 | 
			
		||||
            Пройти
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,8 @@ import { selectUserInfo } from "@redux/quizSlice";
 | 
			
		||||
 | 
			
		||||
import { urlForLocal } from "@utils/helper";
 | 
			
		||||
 | 
			
		||||
import { Loader } from "@components/common/Loader/Loader";
 | 
			
		||||
 | 
			
		||||
// import { apiRequest } from "@api/request";
 | 
			
		||||
import "./quiz.scss";
 | 
			
		||||
 | 
			
		||||
@@ -21,7 +23,7 @@ export const HeaderQuiz = ({ header }) => {
 | 
			
		||||
        <div className="header-quiz">
 | 
			
		||||
          <div className="header-quiz__container">
 | 
			
		||||
            {!userInfo ? (
 | 
			
		||||
              <h2>Loading...</h2>
 | 
			
		||||
              <Loader />
 | 
			
		||||
            ) : (
 | 
			
		||||
              <>
 | 
			
		||||
                {header && (
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,8 @@ import { selectedTest } from "@redux/quizSlice";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import { Loader } from "@components/common/Loader/Loader";
 | 
			
		||||
 | 
			
		||||
import comment from "assets/icons/comment.jpg";
 | 
			
		||||
 | 
			
		||||
import "./quiz.scss";
 | 
			
		||||
@@ -24,7 +26,7 @@ export const Instruction = () => {
 | 
			
		||||
    <div className="instruction">
 | 
			
		||||
      <div className="instruction__container">
 | 
			
		||||
        {!countQuestions ? (
 | 
			
		||||
          <h2>Loading...</h2>
 | 
			
		||||
          <Loader />
 | 
			
		||||
        ) : (
 | 
			
		||||
          <>
 | 
			
		||||
            <h3 className="instruction__title quiz-title_h3">
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@ export const MyTestsQuiz = ({ listTests }) => {
 | 
			
		||||
                    </h3>
 | 
			
		||||
                    <div className="item-test__body test-data">
 | 
			
		||||
                      <Link
 | 
			
		||||
                        to={"/Quiz/interjacent"}
 | 
			
		||||
                        to={"/quiz/interjacent"}
 | 
			
		||||
                        className="quiz-btn"
 | 
			
		||||
                        onClick={() => recordSelectedTest(item)}
 | 
			
		||||
                      >
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,11 @@ export const QuizPassingInformation = ({ setStartTest, uuid, timer }) => {
 | 
			
		||||
        }
 | 
			
		||||
        dispatch(setQuestions(res));
 | 
			
		||||
        setStartTest(true);
 | 
			
		||||
        showNotification({
 | 
			
		||||
          show: true,
 | 
			
		||||
          text: "Тест успешно запущен",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
        restart(
 | 
			
		||||
          moment()
 | 
			
		||||
            .add(res[0]?.time_limit.split(":")[0], "hours")
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,8 @@ import { fetchResultTest, selectResult, selectedTest } from "@redux/quizSlice";
 | 
			
		||||
 | 
			
		||||
import { apiRequest } from "@api/request";
 | 
			
		||||
 | 
			
		||||
import { Loader } from "@components/common/Loader/Loader";
 | 
			
		||||
 | 
			
		||||
export const Results = () => {
 | 
			
		||||
  const result = useSelector(selectResult);
 | 
			
		||||
  const test = useSelector(selectedTest);
 | 
			
		||||
@@ -21,7 +23,7 @@ export const Results = () => {
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={"result _container"}>
 | 
			
		||||
      {!result ? (
 | 
			
		||||
        <h1 style={{ display: "block" }}>Ожидайте результата...</h1>
 | 
			
		||||
        <Loader />
 | 
			
		||||
      ) : (
 | 
			
		||||
        <div className="result__body">
 | 
			
		||||
          <div className="result__text">Благодарим за прохождение теста</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@ export const TaskQuiz = ({ timer }) => {
 | 
			
		||||
          text: "Тест успешно пройден",
 | 
			
		||||
          type: "success"
 | 
			
		||||
        });
 | 
			
		||||
        navigate("/Quiz");
 | 
			
		||||
        navigate("/quiz");
 | 
			
		||||
        // if (String(res?.status)[0] !== "2") {
 | 
			
		||||
        //   showNotification({
 | 
			
		||||
        //     show: true,
 | 
			
		||||
@@ -566,7 +566,6 @@ $maxWidthContainer: 1123;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    flex-wrap: wrap;
 | 
			
		||||
    @media (max-width: 600px) {
 | 
			
		||||
      display: block;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
import React, { Component } from "react";
 | 
			
		||||
 | 
			
		||||
import { Fallback } from "./Fallback";
 | 
			
		||||
 | 
			
		||||
class ErrorBoundary extends Component {
 | 
			
		||||
  state = {
 | 
			
		||||
    error: null
 | 
			
		||||
@@ -13,7 +15,7 @@ class ErrorBoundary extends Component {
 | 
			
		||||
    const { error } = this.state;
 | 
			
		||||
 | 
			
		||||
    if (error) {
 | 
			
		||||
      return <div>Что-то пошло не так =( {error}</div>;
 | 
			
		||||
      return <Fallback />;
 | 
			
		||||
    }
 | 
			
		||||
    return this.props.children;
 | 
			
		||||
  }
 | 
			
		||||
							
								
								
									
										19
									
								
								src/hoc/Fallback.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,19 @@
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
import rightArrow from "assets/icons/arrows/arrowRight.svg";
 | 
			
		||||
import logo from "assets/images/logo/ITguild.svg";
 | 
			
		||||
 | 
			
		||||
import "./fallback.scss";
 | 
			
		||||
 | 
			
		||||
export const Fallback = () => {
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="fallback">
 | 
			
		||||
      <img src={logo} alt="logo" className="logo" />
 | 
			
		||||
      <h1>Произошла непредвиденная ошибка</h1>
 | 
			
		||||
      <a href="/profile">
 | 
			
		||||
        Вернуться назад
 | 
			
		||||
        <img src={rightArrow} alt="arrow" />
 | 
			
		||||
      </a>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										24
									
								
								src/hoc/fallback.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,24 @@
 | 
			
		||||
.fallback {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  padding: 100px;
 | 
			
		||||
  gap: 15px;
 | 
			
		||||
 | 
			
		||||
  img {
 | 
			
		||||
    max-width: 250px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  a {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    column-gap: 10px;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    font-size: 20px;
 | 
			
		||||
    color: black;
 | 
			
		||||
    transition: all 0.3s ease;
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
      scale: 1.1;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -7,7 +7,9 @@ export const useFormValidation = (
 | 
			
		||||
  fields,
 | 
			
		||||
  showNotificationError,
 | 
			
		||||
  showNotificationTrue,
 | 
			
		||||
  isPartner
 | 
			
		||||
  isPartner,
 | 
			
		||||
  setLoader,
 | 
			
		||||
  closeModal
 | 
			
		||||
) => {
 | 
			
		||||
  // Состояние формы, содержащее значения полей
 | 
			
		||||
  const [formData, setFormData] = useState(fields);
 | 
			
		||||
@@ -85,6 +87,7 @@ export const useFormValidation = (
 | 
			
		||||
    e.preventDefault();
 | 
			
		||||
    // Проверка валидации формы
 | 
			
		||||
    if (validateForm()) {
 | 
			
		||||
      setLoader(true);
 | 
			
		||||
      let newformData = { ...formData, is_partner: isPartner ? 1 : 0 };
 | 
			
		||||
      delete newformData.secondPassword;
 | 
			
		||||
 | 
			
		||||
@@ -93,12 +96,18 @@ export const useFormValidation = (
 | 
			
		||||
          method: "POST",
 | 
			
		||||
          data: newformData
 | 
			
		||||
        }).then((data) => {
 | 
			
		||||
          setLoader(false);
 | 
			
		||||
          if ("errors" in data) {
 | 
			
		||||
            showNotificationError();
 | 
			
		||||
          } else {
 | 
			
		||||
            handleClearForm();
 | 
			
		||||
            showNotificationTrue();
 | 
			
		||||
            return showNotificationError(
 | 
			
		||||
              "Аккаунт с таким логином или email уже существует"
 | 
			
		||||
            );
 | 
			
		||||
          }
 | 
			
		||||
          if (!data.id) {
 | 
			
		||||
            return showNotificationError("Ошибка");
 | 
			
		||||
          }
 | 
			
		||||
          handleClearForm();
 | 
			
		||||
          showNotificationTrue();
 | 
			
		||||
          closeModal();
 | 
			
		||||
        });
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        console.error("Error submitting form:", error);
 | 
			
		||||
 
 | 
			
		||||
@@ -3,11 +3,14 @@ import ReactDOM from "react-dom/client";
 | 
			
		||||
import { Provider } from "react-redux";
 | 
			
		||||
 | 
			
		||||
import App from "./App";
 | 
			
		||||
import ErrorBoundary from "./hoc/ErrorBoundary";
 | 
			
		||||
import "./index.css";
 | 
			
		||||
import { store } from "./store/store";
 | 
			
		||||
 | 
			
		||||
ReactDOM.createRoot(document.getElementById("root")).render(
 | 
			
		||||
  <Provider store={store}>
 | 
			
		||||
    <App />
 | 
			
		||||
  </Provider>
 | 
			
		||||
  <ErrorBoundary>
 | 
			
		||||
    <Provider store={store}>
 | 
			
		||||
      <App />
 | 
			
		||||
    </Provider>
 | 
			
		||||
  </ErrorBoundary>
 | 
			
		||||
);
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ import React, { useState } from "react";
 | 
			
		||||
import { Link } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
import CardArticle from "@components/CardArticle/CardArticle";
 | 
			
		||||
import AuthHeader from "@components/Common/AuthHeader/AuthHeader";
 | 
			
		||||
import { AuthHeader } from "@components/Common/AuthHeader/AuthHeader";
 | 
			
		||||
import { Footer } from "@components/Common/Footer/Footer";
 | 
			
		||||
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
 | 
			
		||||
import SideBar from "@components/SideBar/SideBar";
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,16 @@
 | 
			
		||||
.article-blog {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  min-height: 100vh;
 | 
			
		||||
  background: #f1f1f1;
 | 
			
		||||
 | 
			
		||||
  .container {
 | 
			
		||||
    max-width: 1160px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    flex: 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__breadcrumbs {
 | 
			
		||||
    margin-top: 30px;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,9 @@ import { useNavigate } from "react-router-dom";
 | 
			
		||||
import { selectAuth } from "@redux/outstaffingSlice";
 | 
			
		||||
 | 
			
		||||
import { AuthBox } from "@components/AuthBox/AuthBox";
 | 
			
		||||
import AuthHeader from "@components/Common/AuthHeader/AuthHeader";
 | 
			
		||||
import { AuthHeader } from "@components/Common/AuthHeader/AuthHeader";
 | 
			
		||||
import { Footer } from "@components/Common/Footer/Footer";
 | 
			
		||||
import SideBar from "@components/SideBar/SideBar";
 | 
			
		||||
import SliderWorkers from "@components/SliderWorkers/SliderWorkers";
 | 
			
		||||
 | 
			
		||||
import arrow from "assets/icons/arrows/arrow__login_page.png";
 | 
			
		||||
import text from "assets/images/Body_Text.png";
 | 
			
		||||
@@ -19,26 +18,21 @@ import cross from "assets/images/cross.png";
 | 
			
		||||
 | 
			
		||||
import "./auth.scss";
 | 
			
		||||
 | 
			
		||||
const Auth = () => {
 | 
			
		||||
  const isAuth = useSelector(selectAuth);
 | 
			
		||||
  let navigate = useNavigate();
 | 
			
		||||
export const Auth = () => {
 | 
			
		||||
  // const isAuth = useSelector(selectAuth);
 | 
			
		||||
  // let navigate = useNavigate();
 | 
			
		||||
  //
 | 
			
		||||
  // const getToken = localStorage.getItem("auth_token");
 | 
			
		||||
 | 
			
		||||
  const getToken = localStorage.getItem("auth_token");
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (isAuth || getToken) {
 | 
			
		||||
      navigate("/profile");
 | 
			
		||||
    }
 | 
			
		||||
  }, [getToken]);
 | 
			
		||||
  // useEffect(() => {
 | 
			
		||||
  //   if (isAuth || getToken) {
 | 
			
		||||
  //     navigate("/profile");
 | 
			
		||||
  //   }
 | 
			
		||||
  // }, [getToken]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <section className="auth-partners">
 | 
			
		||||
      <AuthHeader />
 | 
			
		||||
      <SliderWorkers
 | 
			
		||||
        title={"Свободные разработчики"}
 | 
			
		||||
        titleInfo={"для Вашей команды"}
 | 
			
		||||
        subTitle={true}
 | 
			
		||||
      />
 | 
			
		||||
      <div className="auth-partners__background">
 | 
			
		||||
        <img className="auth-partners__vector" src={vector} alt="" />
 | 
			
		||||
        <img className="auth-partners__vector-black" src={vectorBlack} alt="" />
 | 
			
		||||
@@ -98,5 +92,3 @@ const Auth = () => {
 | 
			
		||||
    </section>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default Auth;
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ import { selectAuth } from "@redux/outstaffingSlice";
 | 
			
		||||
 | 
			
		||||
import AuthBlock from "@components/AuthBlock/AuthBlock";
 | 
			
		||||
import CategoriesItem from "@components/CategoriesItem/CategoriesItem";
 | 
			
		||||
import AuthHeader from "@components/Common/AuthHeader/AuthHeader";
 | 
			
		||||
import { AuthHeader } from "@components/Common/AuthHeader/AuthHeader";
 | 
			
		||||
import { Footer } from "@components/Common/Footer/Footer";
 | 
			
		||||
import ModalResetPassword from "@components/Modal/ModalResetPassword/ModalResetPassword";
 | 
			
		||||
import SideBar from "@components/SideBar/SideBar";
 | 
			
		||||
@@ -111,13 +111,6 @@ export const AuthForCandidate = () => {
 | 
			
		||||
    <div className="auth-candidate">
 | 
			
		||||
      <AuthHeader />
 | 
			
		||||
      <div className="container">
 | 
			
		||||
        <AuthBlock
 | 
			
		||||
          resetModal={setModalReset}
 | 
			
		||||
          title="Войти, если есть доступ"
 | 
			
		||||
          description="Если вы получили доступ, пройдя
 | 
			
		||||
                   2 шага для входа, или хотите узнать
 | 
			
		||||
                  свои результаты в кабинете"
 | 
			
		||||
        />
 | 
			
		||||
        <div className="auth-candidate__start">
 | 
			
		||||
          <h2 className="auth-candidate__start__title">
 | 
			
		||||
            Хочу в команду <span>IT-специалистов</span>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,15 @@
 | 
			
		||||
.auth-candidate {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  background-color: #f1f1f1;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  min-height: 100vh;
 | 
			
		||||
  background: #f1f1f1;
 | 
			
		||||
 | 
			
		||||
  .container {
 | 
			
		||||
    max-width: 1160px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    flex: 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__start {
 | 
			
		||||
    margin-top: 60px;
 | 
			
		||||
 
 | 
			
		||||