mirror of
https://gitlab.com/megazordpobeda/DataRush.git
synced 2026-05-23 02:47:10 +00:00
Merge branch 'master' of https://gitlab.prodcontest.ru/team-15/project
This commit is contained in:
+46
-34
@@ -12,6 +12,7 @@
|
||||
"autoprefixer": "^10.4.20",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"katex": "^0.16.21",
|
||||
"lucide-react": "^0.476.0",
|
||||
"monaco-editor": "^0.52.2",
|
||||
@@ -28,9 +29,12 @@
|
||||
"tailwindcss": "^4.0.9",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"vaul": "^1.1.2",
|
||||
"zod": "^3.24.2",
|
||||
"zustand": "^5.0.3",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^22.13.5",
|
||||
"@types/react": "^19.0.10",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
@@ -173,69 +177,69 @@
|
||||
|
||||
"@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="],
|
||||
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.34.8", "", { "os": "android", "cpu": "arm" }, "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw=="],
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.34.9", "", { "os": "android", "cpu": "arm" }, "sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA=="],
|
||||
|
||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.34.8", "", { "os": "android", "cpu": "arm64" }, "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q=="],
|
||||
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.34.9", "", { "os": "android", "cpu": "arm64" }, "sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg=="],
|
||||
|
||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.34.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q=="],
|
||||
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.34.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ=="],
|
||||
|
||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.34.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw=="],
|
||||
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.34.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q=="],
|
||||
|
||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.34.8", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA=="],
|
||||
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.34.9", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw=="],
|
||||
|
||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.34.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q=="],
|
||||
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.34.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.34.8", "", { "os": "linux", "cpu": "arm" }, "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g=="],
|
||||
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.34.9", "", { "os": "linux", "cpu": "arm" }, "sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg=="],
|
||||
|
||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.34.8", "", { "os": "linux", "cpu": "arm" }, "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA=="],
|
||||
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.34.9", "", { "os": "linux", "cpu": "arm" }, "sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.34.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A=="],
|
||||
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.34.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw=="],
|
||||
|
||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.34.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q=="],
|
||||
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.34.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A=="],
|
||||
|
||||
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.34.8", "", { "os": "linux", "cpu": "none" }, "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ=="],
|
||||
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.34.9", "", { "os": "linux", "cpu": "none" }, "sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg=="],
|
||||
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.34.8", "", { "os": "linux", "cpu": "ppc64" }, "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw=="],
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": ["@rollup/rollup-linux-powerpc64le-gnu@4.34.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA=="],
|
||||
|
||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.34.8", "", { "os": "linux", "cpu": "none" }, "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw=="],
|
||||
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.34.9", "", { "os": "linux", "cpu": "none" }, "sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg=="],
|
||||
|
||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.34.8", "", { "os": "linux", "cpu": "s390x" }, "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA=="],
|
||||
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.34.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.34.8", "", { "os": "linux", "cpu": "x64" }, "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA=="],
|
||||
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.34.9", "", { "os": "linux", "cpu": "x64" }, "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A=="],
|
||||
|
||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.34.8", "", { "os": "linux", "cpu": "x64" }, "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ=="],
|
||||
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.34.9", "", { "os": "linux", "cpu": "x64" }, "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA=="],
|
||||
|
||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.34.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ=="],
|
||||
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.34.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q=="],
|
||||
|
||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.34.8", "", { "os": "win32", "cpu": "ia32" }, "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w=="],
|
||||
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.34.9", "", { "os": "win32", "cpu": "ia32" }, "sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w=="],
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.34.8", "", { "os": "win32", "cpu": "x64" }, "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g=="],
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.34.9", "", { "os": "win32", "cpu": "x64" }, "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw=="],
|
||||
|
||||
"@swc/core": ["@swc/core@1.11.1", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.18" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.11.1", "@swc/core-darwin-x64": "1.11.1", "@swc/core-linux-arm-gnueabihf": "1.11.1", "@swc/core-linux-arm64-gnu": "1.11.1", "@swc/core-linux-arm64-musl": "1.11.1", "@swc/core-linux-x64-gnu": "1.11.1", "@swc/core-linux-x64-musl": "1.11.1", "@swc/core-win32-arm64-msvc": "1.11.1", "@swc/core-win32-ia32-msvc": "1.11.1", "@swc/core-win32-x64-msvc": "1.11.1" }, "peerDependencies": { "@swc/helpers": "*" }, "optionalPeers": ["@swc/helpers"] }, "sha512-67+lBHZ1lAJQKoOhBHl9DE2iugPYAulRVArZjoF+DnIY3G9wLXCXxw5It0IaCnzvJVvUPxGmr0rHViXKBDP5Vg=="],
|
||||
"@swc/core": ["@swc/core@1.11.5", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.19" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.11.5", "@swc/core-darwin-x64": "1.11.5", "@swc/core-linux-arm-gnueabihf": "1.11.5", "@swc/core-linux-arm64-gnu": "1.11.5", "@swc/core-linux-arm64-musl": "1.11.5", "@swc/core-linux-x64-gnu": "1.11.5", "@swc/core-linux-x64-musl": "1.11.5", "@swc/core-win32-arm64-msvc": "1.11.5", "@swc/core-win32-ia32-msvc": "1.11.5", "@swc/core-win32-x64-msvc": "1.11.5" }, "peerDependencies": { "@swc/helpers": "*" }, "optionalPeers": ["@swc/helpers"] }, "sha512-EVY7zfpehxhTZXOfy508gb3D78ihoGGmvyiTWtlBPjgIaidP1Xw0naHMD78CWiFlZmeDjKXJufGtsEGOnZdmNA=="],
|
||||
|
||||
"@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bJbqZ51JghEZ8WaFetofkfkS3MWsS/V3vDvY+0r+SlLeocZwf8q8/GqcafnElHcU+zLV6yTi13fJwUce6ULiUQ=="],
|
||||
"@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.11.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GEd1hzEx0mSGkJYMFMGLnrGgjL2rOsOsuYWyjyiA3WLmhD7o+n/EWBDo6mzD/9aeF8dzSPC0TnW216gJbvrNzA=="],
|
||||
|
||||
"@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-9GGEoN0uxkLg3KocOVzMfe9c9/DxESXclsL/U2xVLa3pTFB5YnXhiCP5YBT/3Q7nSGLD+R2ALqkNlDoueUjvPw=="],
|
||||
"@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.11.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-toz04z9wAClVvQSEY3xzrgyyeWBAfMWcKG4K0ugNvO56h/wczi2ZHRlnAXZW1tghKBk3z6MXqa/srfXgNhffKw=="],
|
||||
|
||||
"@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Lt7l/l0nfSTUzsWcVY3dtOPl5RtgCJ+Ya8IG4Aa3l6c7kLc6Sx4JpylpEIY9yhGidDy/uQ8KUg5kqUPtUrXrvQ=="],
|
||||
"@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.11.5", "", { "os": "linux", "cpu": "arm" }, "sha512-5SjmKxXdwbBpsYGTpgeXOXMIjS563/ntRGn8Zc12H/c4VfPrRLGhgbJ/48z2XVFyBLcw7BCHZyFuVX1+ZI3W0Q=="],
|
||||
|
||||
"@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-oe826cfuGukctTSpDjk7RJRDEJihQMAzvO5tdWK0wcy+zvMPFyH5Fg6cW0X4ST3M7fcV91/1T/iuiiD2SVamYw=="],
|
||||
"@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.11.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-pydIlInHRzRIwB0NHblz3Dx58H/bsi0I5F2deLf9iOmwPNuOGcEEZF1Qatc7YIjP5DFbXK+Dcz+pMUZb2cc2MQ=="],
|
||||
|
||||
"@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-ABb4pnYeQp/JBJS5Qd2apTwOzpzrTebQFUiFjk0WgTKIr9T6SL3tLXMjgvbSXIath+1HnbCKFUwDXNQhgGFFTg=="],
|
||||
"@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.11.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-LhBHKjkZq5tJF1Lh0NJFpx7ROnCWLckrlIAIdSt9XfOV+zuEXJQOj+NFcM1eNk17GFfFyUMOZyGZxzYq5dveEQ=="],
|
||||
|
||||
"@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-E09TcHv40bV0mOHTKquZw0IOcQ+lzzpQjyOhCa7+GBpbS3eg5/35Gu7DfToN2bomz74LPKW/l7jZRG+ZNOYNHQ=="],
|
||||
"@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.11.5", "", { "os": "linux", "cpu": "x64" }, "sha512-dCi4xkxXlsk5sQYb3i413Cfh7+wMJeBYTvBZTD5xh+/DgRtIcIJLYJ2tNjWC4/C2i5fj+Ze9bKNSdd8weRWZ3A=="],
|
||||
|
||||
"@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-cuW4r7GbvQt9uv+rGdYLHUjDvGjHmr1nYE7iFVk6r4i+byZuXBK6M7P1p+/dTzacshOc05I9n/eUV+Hfjp9a3A=="],
|
||||
"@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.11.5", "", { "os": "linux", "cpu": "x64" }, "sha512-K0AC4TreM5Oo/tXNXnE/Gf5+5y/HwUdd7xvUjOpZddcX/RlsbYOKWLgOtA3fdFIuta7XC+vrGKmIhm5l70DSVQ=="],
|
||||
|
||||
"@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-H8Q78GwaKnCL4isHx8JRTRi6vUU6iMLbpegS2jzWWC1On7EePhkLx2eR8nEsaRIQB6rc3WqdIj74OgOpNoPi7g=="],
|
||||
"@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.11.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-wzum8sYUsvPY7kgUfuqVYTgIPYmBC8KPksoNM1fz5UfhudU0ciQuYvUBD47GIGOevaoxhLkjPH4CB95vh1mJ9w=="],
|
||||
|
||||
"@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.11.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-Rx7cZ0OvqMb16fgmUSlPWQbH1+X355IDJhVQpUlpL+ezD/kkWmJix+4u2GVE/LHrfbdyZ4sjjIzSsCQxJV05Mw=="],
|
||||
"@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.11.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-lco7mw0TPRTpVPR6NwggJpjdUkAboGRkLrDHjIsUaR+Y5+0m5FMMkHOMxWXAbrBS5c4ph7QErp4Lma4r9Mn5og=="],
|
||||
|
||||
"@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-6bEEC/XU1lwYzUXY7BXj3nhe7iBF9+i9dVo+hbiVxXZMrD0LUd+7urOBM3NtVnDsUaR6Ge/g7aR+OfpgYscKOg=="],
|
||||
"@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.11.5", "", { "os": "win32", "cpu": "x64" }, "sha512-E+DApLSC6JRK8VkDa4bNsBdD7Qoomx1HvKVZpOXl9v94hUZI5GMExl4vU5isvb+hPWL7rZ0NeI7ITnVLgLJRbA=="],
|
||||
|
||||
"@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
|
||||
|
||||
"@swc/types": ["@swc/types@0.1.18", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-NZghLaQvF3eFdj2DUjGkpwaunbZYaRcxciHINnwA4n3FrLAI8hKFOBqs2wkcOiLQfWkIdfuG6gBkNFrkPNji5g=="],
|
||||
"@swc/types": ["@swc/types@0.1.19", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-WkAZaAfj44kh/UFdAQcrMP1I0nwRqpt27u+08LMBYMqmQfwwMofYoMh/48NGkMMRfC4ynpfwRbJuu8ErfNloeA=="],
|
||||
|
||||
"@tailwindcss/node": ["@tailwindcss/node@4.0.9", "", { "dependencies": { "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "tailwindcss": "4.0.9" } }, "sha512-tOJvdI7XfJbARYhxX+0RArAhmuDcczTC46DGCEziqxzzbIaPnfYaIyRT31n4u8lROrsO7Q6u/K9bmQHL2uL1bQ=="],
|
||||
|
||||
@@ -275,6 +279,8 @@
|
||||
|
||||
"@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
|
||||
|
||||
"@types/js-cookie": ["@types/js-cookie@3.0.6", "", {}, "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ=="],
|
||||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/katex": ["@types/katex@0.16.7", "", {}, "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ=="],
|
||||
@@ -283,7 +289,7 @@
|
||||
|
||||
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
||||
|
||||
"@types/node": ["@types/node@22.13.5", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg=="],
|
||||
"@types/node": ["@types/node@22.13.8", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-G3EfaZS+iOGYWLLRCEAXdWK9my08oHNZ+FHluRiggIYJPOXzhOiDgpVCUHaUvyIC5/fj7C/p637jdzC666AOKQ=="],
|
||||
|
||||
"@types/react": ["@types/react@19.0.10", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g=="],
|
||||
|
||||
@@ -401,7 +407,7 @@
|
||||
|
||||
"eslint": ["eslint@9.21.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.2", "@eslint/core": "^0.12.0", "@eslint/eslintrc": "^3.3.0", "@eslint/js": "9.21.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg=="],
|
||||
|
||||
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.1.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw=="],
|
||||
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
|
||||
|
||||
"eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.4.19", "", { "peerDependencies": { "eslint": ">=8.40" } }, "sha512-eyy8pcr/YxSYjBoqIFSrlbn9i/xvxUFa8CjzAYo9cFjgGXqq1hyjihcpZvxRLalpaWmueWR81xn7vuKmAFijDQ=="],
|
||||
|
||||
@@ -511,6 +517,8 @@
|
||||
|
||||
"jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
|
||||
|
||||
"js-cookie": ["js-cookie@3.0.5", "", {}, "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
||||
|
||||
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
|
||||
@@ -703,7 +711,7 @@
|
||||
|
||||
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
||||
|
||||
"rollup": ["rollup@4.34.8", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.34.8", "@rollup/rollup-android-arm64": "4.34.8", "@rollup/rollup-darwin-arm64": "4.34.8", "@rollup/rollup-darwin-x64": "4.34.8", "@rollup/rollup-freebsd-arm64": "4.34.8", "@rollup/rollup-freebsd-x64": "4.34.8", "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", "@rollup/rollup-linux-arm-musleabihf": "4.34.8", "@rollup/rollup-linux-arm64-gnu": "4.34.8", "@rollup/rollup-linux-arm64-musl": "4.34.8", "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", "@rollup/rollup-linux-riscv64-gnu": "4.34.8", "@rollup/rollup-linux-s390x-gnu": "4.34.8", "@rollup/rollup-linux-x64-gnu": "4.34.8", "@rollup/rollup-linux-x64-musl": "4.34.8", "@rollup/rollup-win32-arm64-msvc": "4.34.8", "@rollup/rollup-win32-ia32-msvc": "4.34.8", "@rollup/rollup-win32-x64-msvc": "4.34.8", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ=="],
|
||||
"rollup": ["rollup@4.34.9", "", { "dependencies": { "@types/estree": "1.0.6" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.34.9", "@rollup/rollup-android-arm64": "4.34.9", "@rollup/rollup-darwin-arm64": "4.34.9", "@rollup/rollup-darwin-x64": "4.34.9", "@rollup/rollup-freebsd-arm64": "4.34.9", "@rollup/rollup-freebsd-x64": "4.34.9", "@rollup/rollup-linux-arm-gnueabihf": "4.34.9", "@rollup/rollup-linux-arm-musleabihf": "4.34.9", "@rollup/rollup-linux-arm64-gnu": "4.34.9", "@rollup/rollup-linux-arm64-musl": "4.34.9", "@rollup/rollup-linux-loongarch64-gnu": "4.34.9", "@rollup/rollup-linux-powerpc64le-gnu": "4.34.9", "@rollup/rollup-linux-riscv64-gnu": "4.34.9", "@rollup/rollup-linux-s390x-gnu": "4.34.9", "@rollup/rollup-linux-x64-gnu": "4.34.9", "@rollup/rollup-linux-x64-musl": "4.34.9", "@rollup/rollup-win32-arm64-msvc": "4.34.9", "@rollup/rollup-win32-ia32-msvc": "4.34.9", "@rollup/rollup-win32-x64-msvc": "4.34.9", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ=="],
|
||||
|
||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||
|
||||
@@ -807,6 +815,10 @@
|
||||
|
||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
"zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="],
|
||||
|
||||
"zustand": ["zustand@5.0.3", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg=="],
|
||||
|
||||
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
|
||||
|
||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
|
||||
@@ -1,10 +1,31 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="/dr.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>мегазордпобеда.рф</title>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/HSESans-Regular.otf"
|
||||
as="font"
|
||||
type="font/otf"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/HSESans-SemiBold.otf"
|
||||
as="font"
|
||||
type="font/otf"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="/fonts/HSESans-Bold.otf"
|
||||
as="font"
|
||||
type="font/otf"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<title>DATARUSH</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"autoprefixer": "^10.4.20",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"js-cookie": "^3.0.5",
|
||||
"katex": "^0.16.21",
|
||||
"lucide-react": "^0.476.0",
|
||||
"monaco-editor": "^0.52.2",
|
||||
@@ -33,10 +34,13 @@
|
||||
"tailwind-merge": "^3.0.2",
|
||||
"tailwindcss": "^4.0.9",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"vaul": "^1.1.2"
|
||||
"vaul": "^1.1.2",
|
||||
"zod": "^3.24.2",
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/node": "^22.13.5",
|
||||
"@types/react": "^19.0.10",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg width="52" height="52" viewBox="0 0 52 52" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="52" height="52" fill="#333333"/>
|
||||
<path d="M25.796 26.6C25.796 31.352 22.532 35 17.372 35H11.06V18.2H17.372C22.532 18.2 25.796 21.848 25.796 26.6ZM21.764 26.624C21.764 24.056 20.012 22.208 17.3 22.208H15.092V30.992H17.3C20.012 30.992 21.764 29.168 21.764 26.624Z" fill="#FFDD2D"/>
|
||||
<path d="M28.2631 18.2H34.5031C37.7671 18.2 40.3591 20.792 40.3591 24.032C40.3591 26.336 38.9431 28.304 36.9031 29.144C37.9831 29.456 38.7751 31.52 40.2631 31.52C40.5271 31.52 40.7911 31.472 41.1031 31.352V35C40.3831 35.192 39.7351 35.288 39.1591 35.288C35.1031 35.288 34.4551 30.32 33.1351 29.744H32.2951V35H28.2631V18.2ZM32.2951 21.848V26.096H34.0951C35.2951 26.096 36.3271 25.232 36.3271 23.984C36.3271 22.76 35.2951 21.848 34.0951 21.848H32.2951Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 863 B |
@@ -1,93 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
|
||||
sodipodi:docname="logo.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="183"
|
||||
inkscape:cy="182.5"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" /><defs
|
||||
id="defs1"><linearGradient
|
||||
id="linearGradient35"
|
||||
inkscape:collect="always"><stop
|
||||
style="stop-color:#ffc265;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop35" /><stop
|
||||
style="stop-color:#ff6933;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop36" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient35"
|
||||
id="linearGradient36"
|
||||
x1="1.0752909"
|
||||
y1="67.795866"
|
||||
x2="99.798593"
|
||||
y2="67.795866"
|
||||
gradientUnits="userSpaceOnUse" /></defs><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"><path
|
||||
style="font-weight:bold;font-size:77.6829px;font-family:'Adobe Gothic Std';-inkscape-font-specification:'Adobe Gothic Std, Bold';fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.37228;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 38.059464,33.814916 -6.188593,23.94974 c -1.849465,7.624138 -3.485531,15.331149 -4.765929,22.45806 H 26.891544 C 25.682277,72.930062 24.117345,65.471666 22.339015,57.764656 L 16.434954,33.814916 H 3.4175691 L -0.28136,97.542768 H 9.3216293 L 10.388628,73.012933 c 0.355666,-7.872752 0.711333,-17.320054 0.853599,-25.358547 h 0.213399 c 1.2804,7.789879 2.987597,16.408472 4.765929,23.618255 l 6.046326,25.358548 h 7.966925 l 6.686526,-25.772904 c 1.849464,-7.126912 3.841195,-15.579761 5.406127,-23.203899 h 0.213399 c -0.07113,6.463943 0.284533,16.739956 0.569067,25.109934 L 44.10579,97.542768 H 54.135579 L 51.005715,33.814916 Z m 23.829679,0 V 44.09093 h 21.83791 v 0.331483 L 59.755145,90.664471 v 6.878297 H 97.028967 V 87.183886 H 73.341597 V 86.852402 L 96.815576,41.439055 v -7.624139 z"
|
||||
id="text1"
|
||||
aria-label="MZ " /><path
|
||||
style="font-weight:bold;font-size:77.6829px;font-family:'Adobe Gothic Std';-inkscape-font-specification:'Adobe Gothic Std, Bold';fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.37228;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 38.58037,34.344171 -6.188593,23.94974 c -1.849465,7.624138 -3.485531,15.331148 -4.765929,22.45806 H 27.41245 C 26.203183,73.459317 24.638251,66.00092 22.859921,58.293911 L 16.95586,34.344171 H 3.9384748 L 0.23954565,98.072025 H 9.8425353 L 10.909534,73.542187 C 11.2652,65.669435 11.620866,56.222134 11.763133,48.183641 h 0.213399 c 1.2804,7.789879 2.987597,16.408471 4.765929,23.618255 l 6.046326,25.358547 h 7.966925 l 6.686526,-25.772904 c 1.849464,-7.126912 3.841195,-15.579761 5.406127,-23.203898 h 0.213399 c -0.07113,6.463943 0.284533,16.739955 0.569067,25.109933 l 0.995865,24.778451 H 54.656485 L 51.526621,34.344171 Z m 23.829679,0 v 10.276013 h 21.83791 v 0.331483 L 60.276051,91.193726 v 6.878299 H 97.549873 V 87.713141 H 73.862503 V 87.381656 L 97.336482,41.96831 v -7.624139 z"
|
||||
id="path21"
|
||||
aria-label="MZ " /><path
|
||||
style="font-weight:bold;font-size:77.6829px;font-family:'Adobe Gothic Std';-inkscape-font-specification:'Adobe Gothic Std, Bold';fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.37228;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 39.101276,34.873425 -6.188593,23.94974 c -1.849465,7.624138 -3.485531,15.331149 -4.765929,22.45806 H 27.933355 C 26.724089,73.988571 25.159157,66.530175 23.380827,58.823165 L 17.476766,34.873425 H 4.4593805 L 0.76045133,98.601283 H 10.363441 L 11.43044,74.071442 c 0.355666,-7.872752 0.711332,-17.320053 0.853599,-25.358547 h 0.213399 c 1.2804,7.789879 2.987597,16.408472 4.765929,23.618255 l 6.046326,25.358548 h 7.966925 l 6.686526,-25.772904 c 1.849464,-7.126912 3.841195,-15.579761 5.406127,-23.203899 h 0.213399 c -0.07113,6.463943 0.284533,16.739956 0.569067,25.109934 l 0.995865,24.778454 H 55.177391 L 52.047527,34.873425 Z m 23.829679,0 v 10.276014 h 21.83791 v 0.331483 L 60.796957,91.72298 v 6.878303 H 98.070775 V 88.242395 H 74.383409 V 87.910911 L 97.857388,42.497564 v -7.624139 z"
|
||||
id="path22"
|
||||
aria-label="MZ " /><path
|
||||
style="font-weight:bold;font-size:77.6829px;font-family:'Adobe Gothic Std';-inkscape-font-specification:'Adobe Gothic Std, Bold';fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.37228;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 39.622182,35.40268 33.433589,59.35242 C 31.584124,66.976558 29.948058,74.683568 28.66766,81.81048 H 28.454261 C 27.244995,74.517826 25.680063,67.059429 23.901733,59.35242 L 17.997672,35.40268 H 4.9802861 L 1.281357,99.13054 h 9.60299 l 1.066999,-24.529844 c 0.355666,-7.872752 0.711332,-17.320053 0.853599,-25.358546 h 0.213399 c 1.2804,7.789879 2.987597,16.408471 4.765929,23.618255 l 6.046326,25.358544 h 7.966925 L 38.48405,72.446048 c 1.849464,-7.126912 3.841195,-15.57976 5.406127,-23.203898 h 0.213399 c -0.07113,6.463943 0.284533,16.739955 0.569067,25.109933 L 45.668508,99.13054 H 55.698297 L 52.568433,35.40268 Z m 23.829679,0 v 10.276013 h 21.83791 v 0.331483 L 61.317863,92.252235 V 99.13054 H 98.591684 V 88.77165 H 74.904315 V 88.440165 L 98.378289,43.026819 V 35.40268 Z"
|
||||
id="path23"
|
||||
aria-label="MZ " /><path
|
||||
style="font-weight:bold;font-size:77.6829px;font-family:'Adobe Gothic Std';-inkscape-font-specification:'Adobe Gothic Std, Bold';fill:url(#linearGradient36);fill-opacity:1;stroke:#000000;stroke-width:1.372;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 40.143088,35.931934 -6.188593,23.94974 c -1.849465,7.624138 -3.485531,15.331149 -4.765929,22.45806 H 28.975167 C 27.765901,75.04708 26.200969,67.588684 24.422639,59.881674 L 18.518578,35.931934 H 5.5011918 L 1.8022627,99.659798 h 9.6029903 l 1.066999,-24.529847 c 0.355666,-7.872752 0.711332,-17.320053 0.853599,-25.358547 h 0.213399 c 1.2804,7.789879 2.987597,16.408472 4.765929,23.618255 l 6.046326,25.358548 h 7.966925 l 6.686525,-25.772904 c 1.849465,-7.126912 3.841196,-15.579761 5.406128,-23.203899 h 0.213399 c -0.07113,6.463943 0.284533,16.739956 0.569067,25.109934 l 0.995865,24.77846 H 56.219203 L 53.089339,35.931934 Z m 23.829679,0 v 10.276014 h 21.83791 v 0.331483 L 61.838769,92.781489 v 6.878309 H 99.112593 V 89.300904 H 75.425221 V 88.96942 L 98.899198,43.556073 v -7.624139 z"
|
||||
id="path24"
|
||||
aria-label="MZ " /><g
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:6.78629989;stroke-dasharray:none"
|
||||
id="g25"
|
||||
transform="matrix(0.14638629,0,0,0.16509671,32.014583,-5.942102)"><path
|
||||
d="m 237.09324,93.929616 c 0.041,0.736 -0.013,1.485 -0.198,2.229 l -16.5,66.000004 c -0.832,3.325 -3.812,5.663 -7.238,5.681 l -99,0.5 c -0.013,0 -0.025,0 -0.038,0 H 15.118243 c -3.444,0 -6.4450002,-2.346 -7.2770002,-5.688 L -8.6587571,96.401616 c -0.19,-0.764 -0.245,-1.534 -0.197,-2.289 -6.3829999,-2.011 -11.0259999,-7.984 -11.0259999,-15.023 0,-8.685 7.065,-15.75 15.7499998,-15.75 8.6850001,0 15.7500002,7.065 15.7500002,15.75 0,4.891 -2.2410002,9.267 -5.7500002,12.158 L 26.526243,112.06162 c 5.221,5.261 12.466,8.277 19.878,8.277 8.764,0 17.12,-4.162 22.382,-11.135 L 102.73624,64.219616 c -2.851997,-2.85 -4.617997,-6.788 -4.617997,-11.13 0,-8.685 7.064997,-15.75 15.749997,-15.75 8.685,0 15.75,7.065 15.75,15.75 0,4.212 -1.672,8.035 -4.375,10.864 0.009,0.012 0.02,0.022 0.029,0.035 l 33.704,45.108004 c 5.26,7.04 13.646,11.243 22.435,11.243 7.48,0 14.514,-2.913 19.803,-8.203 l 20.788,-20.788004 c -3.583,-2.89 -5.884,-7.308 -5.884,-12.259 0,-8.685 7.065,-15.75 15.75,-15.75 8.685,0 15.75,7.065 15.75,15.75 0,6.851 -4.405,12.678 -10.525,14.84 z m -18.308,97.910004 c 0,-4.142 -3.358,-7.5 -7.5,-7.5 H 17.285243 c -4.142,0 -7.5000002,3.358 -7.5000002,7.5 v 18 c 0,4.142 3.3580002,7.5 7.5000002,7.5 H 211.28524 c 4.142,0 7.5,-3.358 7.5,-7.5 z"
|
||||
id="path1"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:6.7863;stroke-dasharray:none;stroke-opacity:1" /><path
|
||||
d="m 240.7081,97.134808 c 0.041,0.736 -0.013,1.485 -0.198,2.229 l -16.5,66.000002 c -0.832,3.325 -3.812,5.663 -7.238,5.681 l -99,0.5 c -0.013,0 -0.025,0 -0.038,0 H 18.733108 c -3.444,0 -6.445,-2.346 -7.277,-5.688 L -5.0438922,99.606808 c -0.19,-0.764 -0.245,-1.534 -0.197,-2.289 -6.3829998,-2.011 -11.0259998,-7.984 -11.0259998,-15.023 0,-8.685 7.0649999,-15.75 15.74999973,-15.75 8.68500007,0 15.75000027,7.065 15.75000027,15.75 0,4.891 -2.241,9.267 -5.7500003,12.158 L 30.141108,115.26681 c 5.221,5.261 12.466,8.277 19.878,8.277 8.764,0 17.12,-4.162 22.382,-11.135 L 106.3511,67.424808 c -2.85199,-2.85 -4.61799,-6.788 -4.61799,-11.13 0,-8.685 7.06499,-15.75 15.74999,-15.75 8.685,0 15.75,7.065 15.75,15.75 0,4.212 -1.672,8.035 -4.375,10.864 0.009,0.012 0.02,0.022 0.029,0.035 l 33.704,45.108002 c 5.26,7.04 13.646,11.243 22.435,11.243 7.48,0 14.514,-2.913 19.803,-8.203 l 20.788,-20.788002 c -3.583,-2.89 -5.884,-7.308 -5.884,-12.259 0,-8.685 7.065,-15.75 15.75,-15.75 8.685,0 15.75,7.065 15.75,15.75 0,6.851 -4.405,12.678 -10.525,14.84 z m -18.308,97.910002 c 0,-4.142 -3.358,-7.5 -7.5,-7.5 H 20.900108 c -4.142,0 -7.5,3.358 -7.5,7.5 v 18 c 0,4.142 3.358,7.5 7.5,7.5 H 214.9001 c 4.142,0 7.5,-3.358 7.5,-7.5 z"
|
||||
id="path32"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:6.7863;stroke-dasharray:none;stroke-opacity:1" /><path
|
||||
d="m 244.32296,100.34 c 0.041,0.736 -0.013,1.485 -0.198,2.229 l -16.5,66 c -0.832,3.325 -3.812,5.663 -7.238,5.681 l -99,0.5 c -0.013,0 -0.025,0 -0.038,0 H 22.347973 c -3.444,0 -6.445,-2.346 -7.277,-5.688 l -16.5000003,-66.25 c -0.19,-0.764 -0.245,-1.534 -0.197,-2.289 C -8.0090271,98.512 -12.652027,92.539 -12.652027,85.5 c 0,-8.685 7.0649998,-15.75 15.7499997,-15.75 8.6850003,0 15.7500003,7.065 15.7500003,15.75 0,4.891 -2.241,9.267 -5.75,12.158 l 20.658,20.814 c 5.221,5.261 12.466,8.277 19.878,8.277 8.764,0 17.12,-4.162 22.382,-11.135 L 109.96596,70.63 c -2.85199,-2.85 -4.61799,-6.788 -4.61799,-11.13 0,-8.685 7.06499,-15.75 15.74999,-15.75 8.685,0 15.75,7.065 15.75,15.75 0,4.212 -1.672,8.035 -4.375,10.864 0.009,0.012 0.02,0.022 0.029,0.035 l 33.704,45.108 c 5.26,7.04 13.646,11.243 22.435,11.243 7.48,0 14.514,-2.913 19.803,-8.203 l 20.788,-20.788 c -3.583,-2.89 -5.884,-7.308 -5.884,-12.259 0,-8.685 7.065,-15.75 15.75,-15.75 8.685,0 15.75,7.065 15.75,15.75 0,6.851 -4.405,12.678 -10.525,14.84 z m -18.308,97.91 c 0,-4.142 -3.358,-7.5 -7.5,-7.5 H 24.514973 c -4.142,0 -7.5,3.358 -7.5,7.5 v 18 c 0,4.142 3.358,7.5 7.5,7.5 H 218.51496 c 4.142,0 7.5,-3.358 7.5,-7.5 z"
|
||||
id="path33"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:6.7863;stroke-dasharray:none;stroke-opacity:1" /><path
|
||||
d="m 244.32296,100.34 c 0.041,0.736 -0.013,1.485 -0.198,2.229 l -16.5,66 c -0.832,3.325 -3.812,5.663 -7.238,5.681 l -99,0.5 c -0.013,0 -0.025,0 -0.038,0 H 22.347973 c -3.444,0 -6.445,-2.346 -7.277,-5.688 l -16.5000003,-66.25 c -0.19,-0.764 -0.245,-1.534 -0.197,-2.289 C -8.0090271,98.512 -12.652027,92.539 -12.652027,85.5 c 0,-8.685 7.0649998,-15.75 15.7499997,-15.75 8.6850003,0 15.7500003,7.065 15.7500003,15.75 0,4.891 -2.241,9.267 -5.75,12.158 l 20.658,20.814 c 5.221,5.261 12.466,8.277 19.878,8.277 8.764,0 17.12,-4.162 22.382,-11.135 L 109.96596,70.63 c -2.85199,-2.85 -4.61799,-6.788 -4.61799,-11.13 0,-8.685 7.06499,-15.75 15.74999,-15.75 8.685,0 15.75,7.065 15.75,15.75 0,4.212 -1.672,8.035 -4.375,10.864 0.009,0.012 0.02,0.022 0.029,0.035 l 33.704,45.108 c 5.26,7.04 13.646,11.243 22.435,11.243 7.48,0 14.514,-2.913 19.803,-8.203 l 20.788,-20.788 c -3.583,-2.89 -5.884,-7.308 -5.884,-12.259 0,-8.685 7.065,-15.75 15.75,-15.75 8.685,0 15.75,7.065 15.75,15.75 0,6.851 -4.405,12.678 -10.525,14.84 z m -18.308,97.91 c 0,-4.142 -3.358,-7.5 -7.5,-7.5 H 24.514973 c -4.142,0 -7.5,3.358 -7.5,7.5 v 18 c 0,4.142 3.358,7.5 7.5,7.5 H 218.51496 c 4.142,0 7.5,-3.358 7.5,-7.5 z"
|
||||
id="path34"
|
||||
style="fill:#f8ff43;fill-opacity:1;stroke:#000000;stroke-width:6.7863;stroke-dasharray:none;stroke-opacity:1" /></g><g
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:6.78629989;stroke-dasharray:none"
|
||||
id="g27"
|
||||
transform="matrix(0.14638629,0,0,0.16509671,32.014583,-5.942102)" /></g></svg>
|
||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,21 +1,30 @@
|
||||
import { Routes, Route } from "react-router";
|
||||
import "./styles/globals.css";
|
||||
import Competitions from "./pages/Competitions";
|
||||
import CompetitionPreview from './pages/CompetitionPreview'
|
||||
import CompetitionSession from "./pages/CompetitionSession";
|
||||
|
||||
import { NavbarLayout } from "./widgets/navbar-layout";
|
||||
|
||||
import Competitions from "./pages/Competitions";
|
||||
import CompetitionPreview from "./pages/CompetitionPreview";
|
||||
import CompetitionSession from "./pages/CompetitionSession";
|
||||
import LoginPage from "./pages/Login";
|
||||
import { AuthLayout } from "./widgets/auth-layout";
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Routes>
|
||||
<Route element={<NavbarLayout />}>
|
||||
<Route path="/" element={<Competitions />} />
|
||||
<Route path="/competition/:id" element={<CompetitionPreview />} />
|
||||
</Route>
|
||||
<Route
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
|
||||
<Route element={<AuthLayout />}>
|
||||
<Route element={<NavbarLayout />}>
|
||||
<Route path="/" element={<Competitions />} />
|
||||
<Route path="/competition/:id" element={<CompetitionPreview />} />
|
||||
</Route>
|
||||
|
||||
<Route
|
||||
path="/competition/:id/tasks/:taskId"
|
||||
element={<CompetitionSession />}
|
||||
/>
|
||||
</Route>
|
||||
</Routes>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,71 +1,77 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState } from "react";
|
||||
import { DataRush } from "@/components/ui/icons/datarush";
|
||||
import { ChevronDown, User, Settings, BarChart2, LogOut } from "lucide-react";
|
||||
import { Link } from "react-router";
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
SheetClose
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
SheetClose,
|
||||
} from "@/components/ui/sheet";
|
||||
import { useUserStore } from "@/shared/stores/user";
|
||||
|
||||
const Header = () => {
|
||||
const user = useUserStore((state) => state.user);
|
||||
const [isProfileOpen, setIsProfileOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<header className="bg-card sticky top-0 z-30 flex h-[72px] w-full items-center justify-center">
|
||||
<header className="bg-card sticky top-0 z-30 flex h-[72px] w-full items-center justify-center px-4 sm:px-6">
|
||||
<div className="flex w-full max-w-5xl items-center justify-between">
|
||||
<Link to="/">
|
||||
<DataRush />
|
||||
</Link>
|
||||
<div
|
||||
className="flex items-center gap-1 cursor-pointer hover:opacity-80 transition-opacity px-2 py-1 rounded-md"
|
||||
<div
|
||||
className="flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 transition-opacity hover:opacity-80"
|
||||
onClick={() => setIsProfileOpen(true)}
|
||||
>
|
||||
<span className="text-lg font-semibold font-hse-sans">itqdev</span>
|
||||
<span className="font-hse-sans text-lg font-semibold">
|
||||
{user?.username}
|
||||
</span>
|
||||
<ChevronDown size={20} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Sheet open={isProfileOpen} onOpenChange={setIsProfileOpen}>
|
||||
<SheetContent className="w-[300px] sm:w-[350px] p-0">
|
||||
<SheetHeader className="border-b py-4 px-5">
|
||||
<SheetTitle className="font-hse-sans text-lg font-medium">Профиль</SheetTitle>
|
||||
<SheetContent className="w-[300px] p-0 sm:w-[350px]">
|
||||
<SheetHeader className="border-b px-5 py-4">
|
||||
<SheetTitle className="font-hse-sans text-lg font-medium">
|
||||
Профиль
|
||||
</SheetTitle>
|
||||
</SheetHeader>
|
||||
|
||||
<div className="py-4 px-2">
|
||||
<ProfileOption
|
||||
icon={<User size={18} />}
|
||||
label="Ваш профиль"
|
||||
|
||||
<div className="px-2 py-4">
|
||||
<ProfileOption
|
||||
icon={<User size={18} />}
|
||||
label="Ваш профиль"
|
||||
onClick={() => {
|
||||
setIsProfileOpen(false);
|
||||
}}
|
||||
}}
|
||||
/>
|
||||
|
||||
<ProfileOption
|
||||
icon={<Settings size={18} />}
|
||||
label="Настройки"
|
||||
|
||||
<ProfileOption
|
||||
icon={<Settings size={18} />}
|
||||
label="Настройки"
|
||||
onClick={() => {
|
||||
setIsProfileOpen(false);
|
||||
}}
|
||||
}}
|
||||
/>
|
||||
|
||||
<ProfileOption
|
||||
icon={<BarChart2 size={18} />}
|
||||
label="Статистика"
|
||||
|
||||
<ProfileOption
|
||||
icon={<BarChart2 size={18} />}
|
||||
label="Статистика"
|
||||
onClick={() => {
|
||||
setIsProfileOpen(false);
|
||||
}}
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="border-t mt-2 pt-2">
|
||||
<ProfileOption
|
||||
icon={<LogOut size={18} />}
|
||||
label="Выйти"
|
||||
|
||||
<div className="mt-2 border-t pt-2">
|
||||
<ProfileOption
|
||||
icon={<LogOut size={18} />}
|
||||
label="Выйти"
|
||||
onClick={() => {
|
||||
setIsProfileOpen(false);
|
||||
}}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -82,11 +88,16 @@ interface ProfileOptionProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const ProfileOption: React.FC<ProfileOptionProps> = ({ icon, label, onClick, className }) => {
|
||||
const ProfileOption: React.FC<ProfileOptionProps> = ({
|
||||
icon,
|
||||
label,
|
||||
onClick,
|
||||
className,
|
||||
}) => {
|
||||
return (
|
||||
<SheetClose asChild>
|
||||
<button
|
||||
className={`flex items-center gap-3 w-full px-3 py-2.5 rounded-md text-left transition-colors hover:bg-gray-100 ${className || ''}`}
|
||||
<button
|
||||
className={`flex w-full items-center gap-3 rounded-md px-3 py-2.5 text-left transition-colors hover:bg-gray-100 ${className || ""}`}
|
||||
onClick={onClick}
|
||||
>
|
||||
<span className="text-gray-600">{icon}</span>
|
||||
@@ -96,4 +107,4 @@ const ProfileOption: React.FC<ProfileOptionProps> = ({ icon, label, onClick, cla
|
||||
);
|
||||
};
|
||||
|
||||
export { Header };
|
||||
export { Header };
|
||||
|
||||
@@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/shared/lib/utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
@@ -20,9 +20,9 @@ const buttonVariants = cva(
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-12 px-5 py-3 has-[>svg]:px-3 text-lg font-semibold",
|
||||
default: "h-11 px-4 text-base font-semibold rounded-xl",
|
||||
lg: "h-12 px-5 py-3 has-[>svg]:px-3 text-lg font-semibold",
|
||||
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
||||
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
||||
icon: "size-9",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Loader } from "lucide-react";
|
||||
|
||||
export const Spinner = (props: React.ComponentProps<typeof Loader>) => (
|
||||
<Loader className="animate-spin" {...props} />
|
||||
);
|
||||
@@ -2,7 +2,7 @@ import { useState } from "react";
|
||||
import { useParams, Link, useNavigate } from "react-router-dom";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import { Competition } from "@/shared/types";
|
||||
import { mockCompetitions, mockTasks } from "@/shared/mocks/mocks";
|
||||
|
||||
@@ -14,7 +14,7 @@ const CompetitionPage = () => {
|
||||
);
|
||||
|
||||
const handleContinue = () => {
|
||||
if (competition?.id) {
|
||||
if (competition?.id) {
|
||||
if (mockTasks && mockTasks.length > 0) {
|
||||
const firstTaskId = mockTasks[0].id;
|
||||
navigate(`/competition/${competition.id}/tasks/${firstTaskId}`);
|
||||
@@ -43,19 +43,19 @@ const CompetitionPage = () => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-8">
|
||||
<div className="flex flex-col-reverse gap-8 md:flex-row">
|
||||
<div className="flex flex-1 flex-col gap-5">
|
||||
<h1 className="text-[34px] leading-11 font-semibold text-balance">
|
||||
{competition.name}
|
||||
</h1>
|
||||
<div className="text-xl leading-10 font-normal prose prose-lg max-w-none">
|
||||
<ReactMarkdown>
|
||||
{competition.description || ''}
|
||||
</ReactMarkdown>
|
||||
<div className="prose prose-lg max-w-none text-xl leading-10 font-normal">
|
||||
<ReactMarkdown>{competition.description || ""}</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-96 *:w-full">
|
||||
<Button onClick={handleContinue}>Продолжить</Button>
|
||||
<div className="w-full *:w-full md:w-96">
|
||||
<Button size={"lg"} onClick={handleContinue}>
|
||||
Продолжить
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -63,4 +63,4 @@ const CompetitionPage = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default CompetitionPage;
|
||||
export default CompetitionPage;
|
||||
|
||||
@@ -11,13 +11,9 @@ export function CompetitionCard({
|
||||
competition,
|
||||
className,
|
||||
}: CompetitionCardProps) {
|
||||
|
||||
return (
|
||||
<Card
|
||||
className={cn(
|
||||
"aspect-square h-full max-h-80 w-auto overflow-hidden",
|
||||
className,
|
||||
)}
|
||||
className={cn("aspect-square h-full w-auto overflow-hidden", className)}
|
||||
>
|
||||
<div className="relative h-full overflow-hidden">
|
||||
<img
|
||||
@@ -40,7 +36,9 @@ export function CompetitionCard({
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<h3 className="text-xl font-semibold">{competition.name}</h3>
|
||||
<h3 className="line-clamp-2 text-xl font-semibold">
|
||||
{competition.name}
|
||||
</h3>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -25,7 +25,7 @@ const CompetitionsPage = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex flex-col gap-6 sm:gap-8">
|
||||
<Section>
|
||||
<SectionHeader>
|
||||
<SectionTitle>Мои события</SectionTitle>
|
||||
@@ -50,11 +50,15 @@ const CompetitionsPage = () => {
|
||||
};
|
||||
|
||||
const Section = ({ children }: { children: React.ReactNode }) => {
|
||||
return <div className="flex flex-col gap-8">{children}</div>;
|
||||
return <div className="flex flex-col gap-6 sm:gap-8">{children}</div>;
|
||||
};
|
||||
|
||||
const SectionHeader = ({ children }: { children: React.ReactNode }) => {
|
||||
return <div className="flex h-[58px] items-center gap-2">{children}</div>;
|
||||
return (
|
||||
<div className="flex min-h-[58px] flex-col items-center justify-center gap-4 sm:flex-row sm:gap-2">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SectionTitle = ({ children }: { children: React.ReactNode }) => {
|
||||
|
||||
@@ -8,7 +8,7 @@ interface CompetitionGridProps {
|
||||
|
||||
export function CompetitionGrid({ competitions }: CompetitionGridProps) {
|
||||
return (
|
||||
<div className="grid grid-cols-3 gap-9">
|
||||
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2 md:grid-cols-3 md:gap-7 lg:gap-9">
|
||||
{competitions.map((competition) => (
|
||||
<Link key={competition.id} to={`/competition/${competition.id}`}>
|
||||
<CompetitionCard competition={competition} />
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||||
label?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export const Input = ({ label, error, id, ...props }: InputProps) => {
|
||||
return (
|
||||
<div className="flex w-full flex-col items-stretch gap-2">
|
||||
{label && (
|
||||
<label htmlFor={id} className="text-base font-semibold">
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<input
|
||||
id={id}
|
||||
className="bg-card h-12 rounded-xl border px-4 text-base"
|
||||
{...props}
|
||||
/>
|
||||
{error && <span className="text-red-500">{error}</span>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
import { DataRush } from "@/components/ui/icons/datarush";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { LoginTab } from "./modules/LoginTab";
|
||||
import { SignupTab } from "./modules/SignupTab";
|
||||
import React from "react";
|
||||
import { getToken } from "@/shared/token";
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
const LoginPage = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
React.useEffect(() => {
|
||||
const token = getToken();
|
||||
if (token) {
|
||||
navigate("/");
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="flex h-screen flex-col items-center gap-10 px-4 py-10 sm:gap-18 sm:py-18">
|
||||
<DataRush size={52} />
|
||||
<div className="flex w-full max-w-96 flex-col items-center gap-7">
|
||||
<h1 className="text-center text-4xl font-semibold">
|
||||
Добро пожаловать!
|
||||
</h1>
|
||||
<Tabs
|
||||
defaultValue="login"
|
||||
className="flex w-full flex-col items-center gap-7"
|
||||
>
|
||||
<TabsList>
|
||||
<TabsTrigger value="login">Вход</TabsTrigger>
|
||||
<TabsTrigger value="signup">Регистрация</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="login" asChild>
|
||||
<LoginTab />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="signup" asChild>
|
||||
<SignupTab />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginPage;
|
||||
@@ -0,0 +1,74 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "../components/input";
|
||||
import { login } from "@/shared/api/auth";
|
||||
import { saveToken } from "@/shared/token";
|
||||
import { useNavigate } from "react-router";
|
||||
import { useState } from "react";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { ApiError } from "@/shared/api";
|
||||
|
||||
export const LoginTab = () => {
|
||||
const navigate = useNavigate();
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const loginAction = async (
|
||||
formData: FormData,
|
||||
e: React.FormEvent<HTMLFormElement>,
|
||||
) => {
|
||||
e.preventDefault();
|
||||
|
||||
setLoading(true);
|
||||
|
||||
const email = formData.get("email");
|
||||
const password = formData.get("password");
|
||||
|
||||
if (!email || !password) {
|
||||
setError("Неверное имя пользователя или пароль");
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const token = await login({
|
||||
email: email.toString(),
|
||||
password: password.toString(),
|
||||
});
|
||||
saveToken(token.token);
|
||||
navigate("/");
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError && (e.status === 400 || e.status === 401)) {
|
||||
setError("Неверное имя пользователя или пароль");
|
||||
} else {
|
||||
setError("Произошла непредвиденная ошибка");
|
||||
}
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<form
|
||||
className="flex w-full flex-col items-stretch gap-8"
|
||||
onSubmit={(e) => loginAction(new FormData(e.currentTarget), e)}
|
||||
>
|
||||
<div className="flex flex-col items-stretch gap-5">
|
||||
<Input
|
||||
id="email"
|
||||
name="email"
|
||||
label="Почта"
|
||||
placeholder="vdeniske@megazord.pobeda"
|
||||
/>
|
||||
<Input
|
||||
id="password"
|
||||
name="password"
|
||||
label="Пароль"
|
||||
placeholder="Введите пароль"
|
||||
type="password"
|
||||
/>
|
||||
</div>
|
||||
{error && <span className="text-red-500">{error}</span>}
|
||||
<Button type="submit">{loading ? <Spinner size={16} /> : "Войти"}</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,134 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "../components/input";
|
||||
import { z } from "zod";
|
||||
import React from "react";
|
||||
import { signup } from "@/shared/api/auth";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { saveToken } from "@/shared/token";
|
||||
import { useNavigate } from "react-router";
|
||||
import { ApiError } from "@/shared/api";
|
||||
|
||||
const signupSchema = z.object({
|
||||
email: z.string().email({ message: "Некорректная почта" }).trim(),
|
||||
username: z
|
||||
.string()
|
||||
.min(1, { message: "Имя пользователя должно быть не меньше 1 знака" })
|
||||
.max(50, { message: "Имя пользователя должно быть не больше 50 знаков" })
|
||||
.trim(),
|
||||
password: z
|
||||
.string()
|
||||
.min(8, { message: "Пароль должен быть не меньше 8 знаков" })
|
||||
.regex(/[a-zA-Z]/, {
|
||||
message: "Пароль должен содержать хотя бы одну букву",
|
||||
})
|
||||
.regex(/[0-9]/, { message: "Пароль должен содержать хотя бы одну цифру" })
|
||||
.regex(/[^a-zA-Z0-9]/, {
|
||||
message: "Пароль должен содержать хотя бы один специальный символ",
|
||||
})
|
||||
.trim(),
|
||||
});
|
||||
|
||||
interface SignupFormErrors {
|
||||
username?: string[];
|
||||
email?: string[];
|
||||
password?: string[];
|
||||
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export const SignupTab = () => {
|
||||
const navigate = useNavigate();
|
||||
const [errors, setErrors] = React.useState<SignupFormErrors | null>(null);
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
|
||||
const signupAction = async (
|
||||
formData: FormData,
|
||||
e: React.FormEvent<HTMLFormElement>,
|
||||
) => {
|
||||
e.preventDefault();
|
||||
|
||||
setLoading(true);
|
||||
|
||||
const validatedFields = signupSchema.safeParse({
|
||||
email: formData.get("email"),
|
||||
username: formData.get("username"),
|
||||
password: formData.get("password"),
|
||||
});
|
||||
|
||||
if (!validatedFields.success) {
|
||||
setErrors(validatedFields.error.flatten().fieldErrors);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const token = await signup({
|
||||
...validatedFields.data,
|
||||
});
|
||||
saveToken(token.token);
|
||||
navigate("/");
|
||||
} catch (e) {
|
||||
if (e instanceof ApiError) {
|
||||
if (e.status === 400) {
|
||||
setErrors({ message: "Неверные данные" });
|
||||
} else if (e.status === 409) {
|
||||
setErrors({
|
||||
message:
|
||||
"Пользователь с такой почтой или именем пользователя уже существует",
|
||||
});
|
||||
} else {
|
||||
setErrors({ message: "Произошла непредвиденная ошибка" });
|
||||
}
|
||||
} else {
|
||||
setErrors({ message: "Произошла непредвиденная ошибка" });
|
||||
}
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<form
|
||||
className="flex w-full flex-col items-stretch gap-8"
|
||||
onSubmit={(e) => signupAction(new FormData(e.currentTarget), e)}
|
||||
>
|
||||
<div className="flex flex-col items-stretch gap-5">
|
||||
<Input
|
||||
id="email"
|
||||
name="email"
|
||||
label="Почта"
|
||||
placeholder="vdeniske@megazord.pobeda"
|
||||
error={errors?.email?.at(0)}
|
||||
onChange={() => setErrors(null)}
|
||||
/>
|
||||
|
||||
<Input
|
||||
id="username"
|
||||
name="username"
|
||||
label="Имя пользователя"
|
||||
placeholder="Введите имя пользователя"
|
||||
error={errors?.username?.at(0)}
|
||||
onChange={() => setErrors(null)}
|
||||
/>
|
||||
|
||||
<Input
|
||||
id="password"
|
||||
name="password"
|
||||
label="Пароль"
|
||||
placeholder="Введите пароль"
|
||||
type="password"
|
||||
error={errors?.password?.at(0)}
|
||||
onChange={() => setErrors(null)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{errors?.message && (
|
||||
<span className="text-red-500">{errors.message}</span>
|
||||
)}
|
||||
|
||||
<Button type="submit" onClick={() => setErrors(null)}>
|
||||
{loading ? <Spinner size={16} /> : "Зарегистрироваться"}
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import { authFetch } from ".";
|
||||
|
||||
interface AuthResponse {
|
||||
token: string;
|
||||
}
|
||||
|
||||
export const signup = async (body: {
|
||||
email: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}) => {
|
||||
return await authFetch<AuthResponse>("/sign-up", {
|
||||
method: "POST",
|
||||
body,
|
||||
});
|
||||
};
|
||||
|
||||
export const login = async (body: { email: string; password: string }) => {
|
||||
return await authFetch<AuthResponse>("/sign-in", {
|
||||
method: "POST",
|
||||
body,
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
import { ofetch } from "ofetch";
|
||||
import { getToken, removeToken } from "../token";
|
||||
|
||||
const BASE_URL = import.meta.env.VITE_API_ENDPOINT;
|
||||
|
||||
export class ApiError extends Error {
|
||||
response: Response;
|
||||
status: number;
|
||||
|
||||
constructor(response: Response) {
|
||||
super(response.statusText);
|
||||
this.response = response;
|
||||
this.status = response.status;
|
||||
}
|
||||
}
|
||||
|
||||
export const authFetch = ofetch.create({
|
||||
baseURL: BASE_URL,
|
||||
async onResponseError({ response }) {
|
||||
throw new ApiError(response);
|
||||
},
|
||||
});
|
||||
|
||||
export const apiFetch = ofetch.create({
|
||||
baseURL: BASE_URL,
|
||||
headers: {
|
||||
Authorization: "Bearer " + getToken(),
|
||||
},
|
||||
async onResponseError({ response }) {
|
||||
if (response.status === 401) {
|
||||
removeToken();
|
||||
window.location.href = "/login";
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ApiError(response);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
import { apiFetch } from ".";
|
||||
import { User } from "../types/user";
|
||||
|
||||
export const getCurrentUser = async () => {
|
||||
return await apiFetch<User>("/me");
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import { create } from "zustand";
|
||||
import { User } from "../types/user";
|
||||
import { getCurrentUser } from "../api/user";
|
||||
|
||||
interface UserState {
|
||||
user: User | null;
|
||||
loading: boolean;
|
||||
|
||||
fetchUser: () => Promise<void>;
|
||||
}
|
||||
|
||||
const useUserStore = create<UserState>((set) => ({
|
||||
user: null,
|
||||
loading: true,
|
||||
|
||||
fetchUser: async () => {
|
||||
set({ loading: true });
|
||||
const user = await getCurrentUser();
|
||||
set({ user, loading: false });
|
||||
},
|
||||
}));
|
||||
|
||||
export { useUserStore };
|
||||
@@ -0,0 +1,17 @@
|
||||
import Cookie from "js-cookie";
|
||||
|
||||
export const getToken = () => {
|
||||
return Cookie.get("token");
|
||||
};
|
||||
|
||||
export const saveToken = (token: string) => {
|
||||
Cookie.set("token", token, {
|
||||
secure: true,
|
||||
sameSite: "Strict",
|
||||
expires: 30,
|
||||
});
|
||||
};
|
||||
|
||||
export const removeToken = () => {
|
||||
Cookie.remove("token");
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
username: string;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { useUserStore } from "@/shared/stores/user";
|
||||
import React from "react";
|
||||
import { Outlet } from "react-router";
|
||||
|
||||
export const AuthLayout = () => {
|
||||
const fetchUser = useUserStore((state) => state.fetchUser);
|
||||
|
||||
React.useEffect(() => {
|
||||
async function fetchData() {
|
||||
await fetchUser();
|
||||
}
|
||||
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return <Outlet />;
|
||||
};
|
||||
@@ -5,8 +5,10 @@ const NavbarLayout = () => {
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<div className="m-auto mt-6 w-full max-w-5xl">
|
||||
<Outlet />
|
||||
<div className="px-4 sm:px-6">
|
||||
<div className="m-auto mt-6 w-full max-w-5xl">
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user