From 67c6d07e4d4b61040bf438bb651768d7408152a3 Mon Sep 17 00:00:00 2001 From: smanylov Date: Thu, 11 Dec 2025 18:28:35 +0700 Subject: [PATCH] change dashboard layout --- package-lock.json | 396 +++++++++++- package.json | 1 + src/app/[locale]/page.tsx | 9 +- src/app/[locale]/pages/dashboard/page.tsx | 10 +- src/app/[locale]/pages/layout.tsx | 4 +- src/app/actions/action.ts | 8 +- src/app/actions/auth.ts | 25 +- src/app/actions/definitions.ts | 8 +- src/app/components/LanguageSwitcher.tsx | 2 - src/app/components/PieChartComponent.tsx | 51 ++ src/app/styles/dashboard.scss | 598 ++++-------------- src/app/styles/page.module.scss | 7 +- src/app/ui/dashboard/chart-container.tsx | 147 +++++ src/app/ui/dashboard/files-table.tsx | 7 + src/app/ui/dashboard/protection-overview.tsx | 66 +- src/app/ui/dashboard/stats-grid.tsx | 105 ++- src/app/ui/dashboard/storage-breakdown.tsx | 97 +++ src/app/ui/dashboard/violations-table.tsx | 107 ++++ .../ui/dashboard/violations-type-table.tsx | 60 ++ src/app/ui/header/userMenuButton.tsx | 2 +- src/i18n/messages/en.json | 12 +- src/i18n/messages/ru.json | 12 +- 22 files changed, 1185 insertions(+), 549 deletions(-) create mode 100644 src/app/components/PieChartComponent.tsx create mode 100644 src/app/ui/dashboard/files-table.tsx diff --git a/package-lock.json b/package-lock.json index 0b7e3d3..d5d876c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "next-intl": "^4.5.8", "react": "19.2.0", "react-dom": "19.2.0", + "recharts": "^3.5.1", "tailwindcss": "^4.1.17", "zod": "^4.1.13" }, @@ -1646,6 +1647,42 @@ "node": ">=0.10" } }, + "node_modules/@reduxjs/toolkit": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.11.1.tgz", + "integrity": "sha512-HjhlEREguAyBTGNzRlGNiDHGQ2EjLSPWwdhhpoEqHYy8hWak3Dp6/fU72OfqVsiMb8S6rbfPsWUF24fxpilrVA==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^11.0.0", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@reduxjs/toolkit/node_modules/immer": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.0.1.tgz", + "integrity": "sha512-naDCyggtcBWANtIrjQEajhhBEuL9b0Zg4zmlWK2CzS6xCWSE39/vvf4LqnMjUAWHBhot4m9MHCM/Z+mfWhUkiA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1659,6 +1696,18 @@ "integrity": "sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==", "license": "MIT" }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, "node_modules/@swc/core-darwin-arm64": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.3.tgz", @@ -2163,6 +2212,69 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -2198,7 +2310,7 @@ "version": "19.2.7", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -2214,6 +2326,12 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.47.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.47.0.tgz", @@ -3326,9 +3444,130 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -3414,6 +3653,12 @@ "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", "license": "MIT" }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3698,6 +3943,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-toolkit": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.42.0.tgz", + "integrity": "sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -4145,6 +4400,12 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4607,6 +4868,16 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/immutable": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", @@ -4656,6 +4927,15 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/intl-messageformat": { "version": "10.7.18", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.18.tgz", @@ -6257,9 +6537,31 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, "license": "MIT" }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -6274,6 +6576,51 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/recharts": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.5.1.tgz", + "integrity": "sha512-+v+HJojK7gnEgG6h+b2u7k8HH7FhyFUzAc4+cPrsjL4Otdgqr/ecXzAnHciqlzV1ko064eNcsdzrYOM78kankA==", + "license": "MIT", + "workspaces": [ + "www" + ], + "dependencies": { + "@reduxjs/toolkit": "1.x.x || 2.x.x", + "clsx": "^2.1.1", + "decimal.js-light": "^2.5.1", + "es-toolkit": "^1.39.3", + "eventemitter3": "^5.0.1", + "immer": "^10.1.1", + "react-redux": "8.x.x || 9.x.x", + "reselect": "5.1.1", + "tiny-invariant": "^1.3.3", + "use-sync-external-store": "^1.2.2", + "victory-vendor": "^37.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -6318,6 +6665,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", @@ -6926,6 +7279,12 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -7277,6 +7636,37 @@ "react": "^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/victory-vendor": { + "version": "37.3.6", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", + "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 59f7b32..26f4079 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "next-intl": "^4.5.8", "react": "19.2.0", "react-dom": "19.2.0", + "recharts": "^3.5.1", "tailwindcss": "^4.1.17", "zod": "^4.1.13" }, diff --git a/src/app/[locale]/page.tsx b/src/app/[locale]/page.tsx index 0ac4b69..23e9edc 100644 --- a/src/app/[locale]/page.tsx +++ b/src/app/[locale]/page.tsx @@ -1,4 +1,3 @@ -import styles from "@/app/styles/page.module.scss"; import { Metadata } from 'next'; import Link from 'next/link'; import { useTranslations } from 'next-intl'; @@ -11,12 +10,8 @@ export default function Home() { const t = useTranslations('HomePage'); return ( -
-
-
- Home page - {t('title')} -
+
+
dash board diff --git a/src/app/[locale]/pages/dashboard/page.tsx b/src/app/[locale]/pages/dashboard/page.tsx index 78cf0d5..a6019e0 100644 --- a/src/app/[locale]/pages/dashboard/page.tsx +++ b/src/app/[locale]/pages/dashboard/page.tsx @@ -2,11 +2,8 @@ import { Metadata } from 'next'; import { Suspense } from 'react'; import ProtectionOverview from '@/app/ui/dashboard/protection-overview'; import StatsGrid from '@/app/ui/dashboard/stats-grid'; -import StorageBreakdown from '@/app/ui/dashboard/storage-breakdown'; -import ChartContainer from '@/app/ui/dashboard/chart-container'; -import ViolationsTable from '@/app/ui/dashboard/violations-table'; -import ViolationsTypeTable from '@/app/ui/dashboard/violations-type-table'; import { useTranslations } from 'next-intl'; +import FilesTable from '@/app/ui/dashboard/files-table'; export const metadata: Metadata = { title: 'Dashboard', @@ -23,10 +20,7 @@ export default function Page() { - - - - +
); diff --git a/src/app/[locale]/pages/layout.tsx b/src/app/[locale]/pages/layout.tsx index 795f79d..c5cb136 100644 --- a/src/app/[locale]/pages/layout.tsx +++ b/src/app/[locale]/pages/layout.tsx @@ -19,9 +19,9 @@ export default async function Layout({ children }: { children: React.ReactNode }
-
+
-
+
{children}
diff --git a/src/app/actions/action.ts b/src/app/actions/action.ts index 7bee890..cbeafc2 100644 --- a/src/app/actions/action.ts +++ b/src/app/actions/action.ts @@ -1,6 +1,6 @@ 'use server' import { getSessionData } from '@/app/actions/session'; -import { localDevelopmentUrl } from '@/app/actions/definitions'; +import { localDevelopmentUrl, testUserData } from '@/app/actions/definitions'; const API_BASE_URL = process.env.NODE_ENV === 'development' ? localDevelopmentUrl @@ -35,6 +35,12 @@ export async function getUserData() { const userEmail = await getSessionData('email'); const token = await getSessionData('token'); + /* для теста */ + if (userEmail === "test" && token === "1111") { + return testUserData; + } + /* для теста */ + try { const response = await fetch(`${API_BASE_URL}/v1/api/user?email=${userEmail}`, { method: 'GET', diff --git a/src/app/actions/auth.ts b/src/app/actions/auth.ts index 347ed36..36b3901 100644 --- a/src/app/actions/auth.ts +++ b/src/app/actions/auth.ts @@ -40,6 +40,13 @@ export async function authorization( const email = formData.get('email') as string || ''; const password = formData.get('password'); + /* для теста */ + if (email === "test" && password === "test") { + await createSession("1111", "test"); + redirect('/pages/dashboard'); + } + /* для теста */ + const validatedFields = loginFormSchema.safeParse({ email, password @@ -168,9 +175,19 @@ export async function registration( try { const { full_name, email, password, phone } = validatedFields.data; - const response = await fetch(`${API_BASE_URL}/v1/api/auth/register1`, { + const response = await fetch(`${API_BASE_URL}/api/v1/data`, { method: 'POST', - body: JSON.stringify({ fullName: full_name, email, password, companyName: company, phone: phone }), + body: JSON.stringify({ + version: 1, + msg_id: 20002, + message_body: { + fullName: full_name, + email, + phone: phone, + password, + companyName: company, + } + }), headers: { "Content-Type": "application/json", "Accept": "application/json" @@ -179,7 +196,9 @@ export async function registration( if (response.ok) { let parsed = await response.json(); - await createSession(parsed.token, email); + console.log('--parsed--'); + console.log(parsed); + await createSession(parsed.message_body.token, email); } else { throw (`${response.status}`); } diff --git a/src/app/actions/definitions.ts b/src/app/actions/definitions.ts index ea31844..01e09a7 100644 --- a/src/app/actions/definitions.ts +++ b/src/app/actions/definitions.ts @@ -55,4 +55,10 @@ export const loginFormSchema = z .trim(), }) -export const localDevelopmentUrl = 'http://localhost:80'; \ No newline at end of file +export const localDevelopmentUrl = 'http://localhost:80'; + +export const testUserData = { + fullName: 'test', + email: 'test@mail.com', + subscriptionType: 'base' +} \ No newline at end of file diff --git a/src/app/components/LanguageSwitcher.tsx b/src/app/components/LanguageSwitcher.tsx index 3dab9e0..d00df7b 100644 --- a/src/app/components/LanguageSwitcher.tsx +++ b/src/app/components/LanguageSwitcher.tsx @@ -36,8 +36,6 @@ export default function LanguageSwitcher() {
) } \ No newline at end of file diff --git a/src/app/ui/dashboard/stats-grid.tsx b/src/app/ui/dashboard/stats-grid.tsx index f989102..13ab89f 100644 --- a/src/app/ui/dashboard/stats-grid.tsx +++ b/src/app/ui/dashboard/stats-grid.tsx @@ -1,35 +1,82 @@ +import { useTranslations } from 'next-intl'; +import { IconImageFile, IconVideoFile, IconAudioFile } from '@/app/ui/icons/icons'; export default function StatsGrid() { - return ( -
-
-
ИЗОБРАЖЕНИЯ
-
0 шт.
-
Ваши изображения
-
- 0 МБ
-
-
-
ВИДЕО
-
0 шт.
-
Ваш видео контент
-
- 0 МБ
-
+ const t = useTranslations("Global"); -
-
АУДИО
-
0 шт.
-
Ваш аудио контент
-
- 0 МБ
-
-
-
PDF-ФАЙЛЫ
-
0 шт.
-
Ваши PDF-файлы
-
- 0 КБ
+ return ( +
+

+ {t('your-content')} +

+
+
+ {t('content-type')} +
+
+ {t('quantity')} +
+
+ {t('size')} +
+
+ {t('violations')} +
+
+ {t('checks')} +
+ +
+ + {t('images')} +
+
+ 0 +
+
+ 0 +
+
+ 0 +
+
+ 0 +
+ +
+ + {t('videos')} +
+
+ 0 +
+
+ 0 +
+
+ 0 +
+
+ 0 +
+ +
+ + {t('audios')} +
+
+ 0 +
+
+ 0 +
+
+ 0 +
+
+ 0 +
+ ) } \ No newline at end of file diff --git a/src/app/ui/dashboard/storage-breakdown.tsx b/src/app/ui/dashboard/storage-breakdown.tsx index b4f712a..5e53cee 100644 --- a/src/app/ui/dashboard/storage-breakdown.tsx +++ b/src/app/ui/dashboard/storage-breakdown.tsx @@ -1,3 +1,100 @@ +/* deleted */ + +/* .storage-breakdown { + .storage-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 0; + border-bottom: 1px solid #f1f5f9; + } + + .storage-icon { + width: 24px; + height: 24px; + border-radius: 6px; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + + &.storage-icon.photos { + background: #dbeafe; + color: #1d4ed8; + } + + &.storage-icon.videos { + background: #f3e8ff; + color: #7c3aed; + } + + &.storage-icon.audio { + background: #d1fae5; + color: #059669; + } + + &.storage-icon.documents { + background: #fed7d7; + color: #dc2626; + } + + &.storage-icon.code { + background: #e0e7ff; + color: #4f46e5; + } + + &.storage-icon.text { + background: #fef3c7; + color: #d97706; + } + } + + .storage-type { + display: flex; + align-items: center; + gap: 10px; + } + + .storage-footer { + margin-top: 15px; + padding-top: 15px; + border-top: 2px solid #e2e8f0; + } + + .storage-footer-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 8px; + } + + .storage-footer-title { + font-weight: 600; + color: #1e293b; + } + + .storage-footer-weight { + font-weight: 600; + color: #6366f1; + font-size: 16px; + } + + .progress-bar { + background: #f1f5f9; + border-radius: 10px; + height: 8px; + overflow: hidden; + margin: 15px 0; + } + + .progress-fill { + height: 100%; + background: linear-gradient(90deg, #10b981, #059669); + border-radius: 10px; + transition: width 0.8s ease; + } +} */ + export default function StorageBreakdown() { return (
diff --git a/src/app/ui/dashboard/violations-table.tsx b/src/app/ui/dashboard/violations-table.tsx index ad9e0d5..dd301f3 100644 --- a/src/app/ui/dashboard/violations-table.tsx +++ b/src/app/ui/dashboard/violations-table.tsx @@ -1,3 +1,110 @@ +/* deleted */ + +/* .violations-table { + background: white; + border-radius: 20px; + overflow: hidden; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08); + border: 1px solid #f1f5f9; + + .violation-main { + flex: 1; + display: flex; + align-items: center; + gap: 15px; + } + + .violation-card { + padding: 20px 25px; + border-bottom: 1px solid #f1f5f9; + transition: all 0.3s ease; + display: flex; + align-items: center; + justify-content: space-between; + gap: 15px; + + &:hover { + background: linear-gradient(90deg, #f8fafc 0%, #f1f5f9 100%); + } + } + + .violation-icon-wrapper { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 12px; + width: 48px; + height: 48px; + border-radius: 12px; + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + flex-shrink: 0; + + &.photo { + background: linear-gradient(135deg, #dbeafe, #bfdbfe); + + img { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 12px; + } + } + } + + .btn-primary { + padding: 10px 20px; + } + + .violation-content-info { + flex: 1; + } + + .violation-filename { + font-weight: 600; + color: #1e293b; + font-size: 15px; + margin-bottom: 5px; + display: block; + } + + .violation-meta { + display: flex; + gap: 15px; + font-size: 13px; + color: #64748b; + flex-wrap: wrap; + } + + .violation-meta-item { + display: flex; + align-items: center; + gap: 5px; + } + + .violation-status-badge { + padding: 6px 12px; + border-radius: 20px; + font-size: 12px; + font-weight: 600; + background: linear-gradient(135deg, #fee2e2, #fecaca); + color: #dc2626; + white-space: nowrap; + } + + .violation-sources-badge { + padding: 6px 12px; + border-radius: 20px; + font-size: 12px; + font-weight: 600; + background: linear-gradient(135deg, #fef3c7, #fde68a); + color: #d97706; + white-space: nowrap; + } +} */ + import Link from 'next/link'; import Image from 'next/image'; diff --git a/src/app/ui/dashboard/violations-type-table.tsx b/src/app/ui/dashboard/violations-type-table.tsx index 6f941f5..4e2dd54 100644 --- a/src/app/ui/dashboard/violations-type-table.tsx +++ b/src/app/ui/dashboard/violations-type-table.tsx @@ -1,3 +1,63 @@ +/* deleted */ +/* +.violations-type-table { + .data-table { + width: 100%; + border-collapse: collapse; + margin-top: 15px; + } + + .data-table th { + font-weight: 600; + color: #374151; + background: #f9fafb; + font-size: 12px; + text-transform: uppercase; + letter-spacing: 1px; + } + + .data-table td { + color: #6b7280; + font-size: 14px; + font-weight: 600; + } + + .data-table th, + .data-table td { + text-align: left; + padding: 15px; + border-bottom: 1px solid #f3f4f6; + } + + .type-violations { + text-transform: uppercase; + } + + .total-violations { + span { + color: #dc2626; + } + + } + + .new-violations { + span { + color: #f59e0b; + } + } + + .status-violations { + span { + background: #fef2f2; + color: #dc2626; + padding: 4px 8px; + border-radius: 6px; + font-size: 12px; + font-weight: 600; + } + } +} */ + export default function ViolationsTypeTable() { return (
diff --git a/src/app/ui/header/userMenuButton.tsx b/src/app/ui/header/userMenuButton.tsx index 7acfdf7..98336d6 100644 --- a/src/app/ui/header/userMenuButton.tsx +++ b/src/app/ui/header/userMenuButton.tsx @@ -1,6 +1,6 @@ 'use client' -import { useState, useRef } from 'react'; +import { useState, useRef, useEffect } from 'react'; import { useClickOutside } from '@/app/hooks/useClickOutside'; import Link from 'next/link'; import { getUserData } from '@/app/actions/action'; diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index d4a32cc..83daf4e 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -4,7 +4,17 @@ "description": "This is a demo application with i18n support" }, "Global": { - "statistics": "Statistik" + "statistics": "Statistics", + "your-content": "Your content", + "fail": "Fail", + "content-type": "Content type", + "quantity": "Quantity", + "size": "Size", + "violations": "Violations", + "checks": "Checks", + "videos": "Videos", + "audios": "Audio", + "images": "Images" }, "Login-register-form": { "already-have-an-account": "Already have an account", diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index 1b87b17..0c2524c 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -4,7 +4,17 @@ "description": "Это демонстрационное приложение с поддержкой i18n" }, "Global": { - "statistics": "Статистика" + "statistics": "Статистика", + "your-content": "Ваш контент", + "fail": "Фаил", + "content-type": "Тип контента", + "quantity": "Количество", + "size": "Размер", + "violations": "Нарушения", + "checks": "Проверки", + "videos": "Видео", + "audios": "Аудио", + "images": "Изображения" }, "Login-register-form": { "already-have-an-account": "Уже есть аккаунт",