diff --git a/src/app/[locale]/pages/my-content/page.tsx b/src/app/[locale]/pages/my-content/page.tsx
index fbbab98..d7393ba 100644
--- a/src/app/[locale]/pages/my-content/page.tsx
+++ b/src/app/[locale]/pages/my-content/page.tsx
@@ -1,14 +1,18 @@
import MyContentInfoBlock from '@/app/ui/my-content/my-content-info-block';
import FilesTable from '@/app/ui/dashboard/files-table';
import MyContentPieChart from '@/app/ui/my-content/my-content-pie-chart';
+import MyContentPageTitleColorFrame from '@/app/ui/my-content/new/my-content-page-title';
+import MyContentStatsOverview from '@/app/ui/my-content/new/my-content-stats-overview';
export default function Page() {
return (
<>
-
*/}
>
)
diff --git a/src/app/components/StackedBarChart.tsx b/src/app/components/StackedBarChart.tsx
index 208f6a0..d72a634 100644
--- a/src/app/components/StackedBarChart.tsx
+++ b/src/app/components/StackedBarChart.tsx
@@ -1,6 +1,6 @@
'use client'
-import { useTranslations } from 'next-intl';
+import { useTranslations, useLocale } from 'next-intl';
import { useMemo } from 'react';
import { BarChart, Bar, Cell, XAxis, Tooltip } from 'recharts';
import { pluralize } from '@/app/lib/pluralize';
@@ -24,6 +24,7 @@ interface BarShapeProps {
}
export const StackedBarChart = ({ data }: Files) => {
+ const locale = useLocale();
const t = useTranslations('Global');
const CHECKS_COLOR = '#6366f1';
@@ -154,12 +155,12 @@ export const StackedBarChart = ({ data }: Files) => {
const pluralizeCheks = (number: number) => {
const translate = [t('check'), t('checks-few'), t('checks')];
- return pluralize(number, translate[0], translate[1], translate[2]);
+ return pluralize(number, translate[0], translate[1], translate[2], locale);
};
const pluralizeViolations = (number: number) => {
const translate = [t('violation'), t('violations-few'), t('violations')];
- return pluralize(number, translate[0], translate[1], translate[2]);
+ return pluralize(number, translate[0], translate[1], translate[2], locale);
};
return (
diff --git a/src/app/components/tanstakTable.tsx b/src/app/components/tanstakTable.tsx
index 9abc0c7..6cc116f 100644
--- a/src/app/components/tanstakTable.tsx
+++ b/src/app/components/tanstakTable.tsx
@@ -12,7 +12,7 @@ import {
ColumnFiltersState,
} from '@tanstack/react-table';
import { IconImageFile, IconVideoFile, IconAudioFile, IconEye, IconDoubleArrowRight, IconArrowRight, IconDoubleArrowLeft, IconArrowLeft, IconArrowUp, IconArrowDown, IconFilter, IconFileDownload, IconShieldExclamation, IconDelete } from '@/app/ui/icons/icons';
-import { useTranslations } from 'next-intl';
+import { useTranslations, useLocale } from 'next-intl';
import DropDownList from '@/app/components/dropDownList';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { getUserFilesData, removeUserFile } from '@/app/actions/fileEntity';
@@ -156,6 +156,7 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
const [isFileLoading, setIsFileLoading] = useState(false);
const t = useTranslations("Global");
+ const locale = useLocale();
// Определение колонок
const columns = useMemo[]>(
@@ -606,7 +607,7 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
const pluralizeFiles = (number: number) => {
const translate = [t('file'), t('files-few'), t('files')];
- return pluralize(number, translate[0], translate[1], translate[2]);
+ return pluralize(number, translate[0], translate[1], translate[2], locale);
};
return (
diff --git a/src/app/lib/pluralize.ts b/src/app/lib/pluralize.ts
index 4efe7fd..12a5131 100644
--- a/src/app/lib/pluralize.ts
+++ b/src/app/lib/pluralize.ts
@@ -1,14 +1,6 @@
'use client'
-export const pluralize = (number: number, one: string, few: string, many: string) => {
- const getCurrentLang = () => {
- if (typeof window !== 'undefined') {
- return document?.documentElement?.getAttribute('lang') || 'ru';
- }
- return 'ru'; // значение по умолчанию для сервера
- }
- const currentLang = getCurrentLang();
-
+export const pluralize = (number: number, one: string, few: string, many: string, currentLang: string) => {
if (currentLang === 'ru') {
const n = Math.abs(number) % 100;
const n1 = n % 10;
diff --git a/src/app/styles/global-styles.scss b/src/app/styles/global-styles.scss
index 8e8c23a..c25c771 100644
--- a/src/app/styles/global-styles.scss
+++ b/src/app/styles/global-styles.scss
@@ -38,9 +38,9 @@
border-radius: 16px;
margin-bottom: 2rem;
box-shadow: 0 10px 40px rgba(102, 126, 234, 0.2);
+ color: v.$white;
h1 {
- color: v.$white;
font-size: 2rem;
font-weight: 700;
margin: 0 0 0.5rem 0;
@@ -50,10 +50,43 @@
}
p {
- color: rgba(255, 255, 255, 0.9);
font-size: 1rem;
margin: 0;
}
+
+ .header-content {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 40px;
+
+ .header-main {
+ flex: 1;
+ }
+
+ .header-stats {
+ display: flex;
+ gap: 28px;
+ align-items: center;
+ }
+
+ .header-stat-item {
+ text-align: center;
+ }
+
+ .header-stat-value {
+ font-size: 28px;
+ font-weight: 700;
+ margin-bottom: 4px;
+ }
+
+ .header-stat-label {
+ font-size: 13px;
+ opacity: 0.85;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ }
+ }
}
.main-containter-wrapper {
diff --git a/src/app/styles/pages-styles.scss b/src/app/styles/pages-styles.scss
index aefb378..b917c06 100644
--- a/src/app/styles/pages-styles.scss
+++ b/src/app/styles/pages-styles.scss
@@ -1856,4 +1856,85 @@
color: #6b7280;
font-weight: 500;
}
+}
+
+.my-content-stats-overview {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 20px;
+ margin-bottom: 30px;
+
+ @media (max-width: 1400px) {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ .stat-card.files {
+ --card-color-1: #ff6b8a;
+ --card-color-2: #ff8da1;
+ }
+
+ .stat-card.protected {
+ --card-color-1: #8b5cf6;
+ --card-color-2: #a78bfa;
+ }
+
+ .stat-card.checks {
+ --card-color-1: #10b981;
+ --card-color-2: #34d399;
+ }
+
+ .stat-card.storage {
+ --card-color-1: #f59e0b;
+ --card-color-2: #fbbf24;
+ }
+
+ .stat-card {
+ background: linear-gradient(135deg, var(--card-color-1), var(--card-color-2));
+ border-radius: 20px;
+ padding: 32px 28px;
+ color: white;
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
+ transition: all 0.4s ease;
+ cursor: pointer;
+ position: relative;
+ overflow: hidden;
+
+ &:hover {
+ transform: translateY(-8px);
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.2);
+ }
+ }
+
+ .stat-icon {
+ font-size: 36px;
+ }
+
+ .stat-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 16px;
+ position: relative;
+ z-index: 1;
+ }
+
+ .stat-value {
+ font-size: 32px;
+ font-weight: 700;
+ color: white;
+ margin-bottom: 6px;
+ position: relative;
+ z-index: 1;
+ }
+
+ .stat-label {
+ font-size: 13px;
+ color: white;
+ opacity: 0.9;
+ font-weight: 500;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ position: relative;
+ z-index: 1;
+ }
}
\ No newline at end of file
diff --git a/src/app/ui/dashboard/protection-overview.tsx b/src/app/ui/dashboard/protection-overview.tsx
index da7b402..6441268 100644
--- a/src/app/ui/dashboard/protection-overview.tsx
+++ b/src/app/ui/dashboard/protection-overview.tsx
@@ -2,7 +2,7 @@
import { useState, useRef, useEffect } from 'react';
import { PieChartComponent } from '@/app/components/PieChartComponent';
-import { useTranslations } from 'next-intl';
+import {useTranslations, useLocale} from 'next-intl';
import Link from 'next/link';
import { useClickOutside } from '@/app/hooks/useClickOutside';
import { useQuery } from '@tanstack/react-query';
@@ -30,6 +30,7 @@ export default function ProtectionOverview() {
{ name: 'videos', value: 0, color: '#2f9e44' },
{ name: 'audios', value: 0, color: '#1971c2' },
]);
+ const locale = useLocale();
const t = useTranslations('Global');
const [openDropDownList, setOpenDropDownList] = useState(false);
const dropDownList = useRef(null);
@@ -106,17 +107,17 @@ export default function ProtectionOverview() {
const pluralizeFiles = (number: number) => {
const translate = [t('file'), t('files-few'), t('files')];
- return pluralize(number, translate[0], translate[1], translate[2]);
+ return pluralize(number, translate[0], translate[1], translate[2], locale);
};
const pluralizeCheks = (number: number) => {
const translate = [t('check'), t('checks-few'), t('checks')];
- return pluralize(number, translate[0], translate[1], translate[2]);
+ return pluralize(number, translate[0], translate[1], translate[2], locale);
};
const pluralizeViolations = (number: number) => {
const translate = [t('violation'), t('violations-few'), t('violations')];
- return pluralize(number, translate[0], translate[1], translate[2]);
+ return pluralize(number, translate[0], translate[1], translate[2], locale);
};
const CHECKS = 6;
diff --git a/src/app/ui/marking-page/protection-summary.tsx b/src/app/ui/marking-page/protection-summary.tsx
index de90622..8e2d41b 100644
--- a/src/app/ui/marking-page/protection-summary.tsx
+++ b/src/app/ui/marking-page/protection-summary.tsx
@@ -1,6 +1,6 @@
'use client'
-import { useTranslations } from 'next-intl';
+import {useTranslations, useLocale} from 'next-intl';
import { useQuery } from '@tanstack/react-query';
import { getUserFilesInfo } from '@/app/actions/action';
import { convertBytes } from '@/app/lib/convertBytes';
@@ -72,19 +72,21 @@ export default function ProtectionSummary({ fileType }: { fileType: string }) {
}
});
+ const locale = useLocale();
+
const pluralizeFilesName = (number: number) => {
const translate = [t(`${fileType}`), t(`${fileType}s-few`), t(`${fileType}s`)];
- return pluralize(number, translate[0], translate[1], translate[2]);
+ return pluralize(number, translate[0], translate[1], translate[2], locale);
};
const pluralizeCheks = (number: number) => {
const translate = [t('check'), t('checks-few'), t('checks')];
- return pluralize(number, translate[0], translate[1], translate[2]);
+ return pluralize(number, translate[0], translate[1], translate[2], locale);
};
const pluralizeViolations = (number: number) => {
const translate = [t('violation'), t('violations-few'), t('violations')];
- return pluralize(number, translate[0], translate[1], translate[2]);
+ return pluralize(number, translate[0], translate[1], translate[2], locale);
};
return (
diff --git a/src/app/ui/my-content/my-content-info-block.tsx b/src/app/ui/my-content/my-content-info-block.tsx
index 28f2a24..8820ae1 100644
--- a/src/app/ui/my-content/my-content-info-block.tsx
+++ b/src/app/ui/my-content/my-content-info-block.tsx
@@ -3,11 +3,12 @@
import { IconDocument, IconImageFile, IconVideoFile, IconAudioFile } from '@/app/ui/icons/icons';
import { useQuery } from '@tanstack/react-query';
import { getUserFilesInfo } from '@/app/actions/action';
-import { useTranslations } from 'next-intl';
+import {useTranslations, useLocale} from 'next-intl';
import { convertBytes } from '@/app/lib/convertBytes';
import { pluralize } from '@/app/lib/pluralize';
export default function MyContentInfoBlock() {
+ const locale = useLocale();
const t = useTranslations('Global');
const {
@@ -70,7 +71,7 @@ export default function MyContentInfoBlock() {
const pluralizeFiles = (number: number) => {
const translate = [t('file'), t('files-few'), t('files')];
- return pluralize(number, translate[0], translate[1], translate[2]);
+ return pluralize(number, translate[0], translate[1], translate[2], locale);
};
return (
diff --git a/src/app/ui/my-content/new/my-content-page-title.tsx b/src/app/ui/my-content/new/my-content-page-title.tsx
new file mode 100644
index 0000000..fba6b62
--- /dev/null
+++ b/src/app/ui/my-content/new/my-content-page-title.tsx
@@ -0,0 +1,50 @@
+'use client'
+
+import { useTranslations } from 'next-intl';
+import { useQuery } from '@tanstack/react-query';
+import { getUserFilesInfo } from '@/app/actions/action';
+import { convertBytes } from '@/app/lib/convertBytes';
+
+export default function MyContentPageTitleColorFrame({ title, description }: { title: string, description: string }) {
+ const t = useTranslations('Global');
+ const {
+ data: filesInfo,
+ isLoading,
+ isError,
+ error,
+ } = useQuery({
+ queryKey: ['userFilesInfo'],
+ queryFn: getUserFilesInfo,
+ });
+
+ return (
+
+
+
+
+ {t(title)}
+
+
+ {t(description)}
+
+
+
+
+
{filesInfo?.all_files_quantity}
+
Файлов
+
+
+
+
+
+
{filesInfo.all_files_size ? convertBytes(filesInfo.all_files_size) : 0}
+
Хранилище
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/ui/my-content/new/my-content-stats-overview.tsx b/src/app/ui/my-content/new/my-content-stats-overview.tsx
new file mode 100644
index 0000000..97a0c70
--- /dev/null
+++ b/src/app/ui/my-content/new/my-content-stats-overview.tsx
@@ -0,0 +1,59 @@
+'use client'
+
+import { useTranslations } from 'next-intl';
+import { useQuery } from '@tanstack/react-query';
+import { getUserFilesInfo } from '@/app/actions/action';
+import {convertBytes} from '@/app/lib/convertBytes';
+
+export default function MyContentStatsOverview() {
+ const t = useTranslations('Global');
+ const {
+ data: filesInfo,
+ isLoading,
+ isError,
+ error,
+ } = useQuery({
+ queryKey: ['userFilesInfo'],
+ queryFn: getUserFilesInfo,
+ });
+
+ return (
+
+
+
+
{filesInfo?.all_files_quantity}
+
Всего файлов
+
+
+
+
+
0
+
Защищено файлов
+
+
+
+
+
0
+
Проверок защиты
+
+
+
+
+
{filesInfo.all_files_size ? convertBytes(filesInfo.all_files_size) : 0}
+
Хранилище
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json
index 6125f2f..8565b16 100644
--- a/src/i18n/messages/en.json
+++ b/src/i18n/messages/en.json
@@ -169,7 +169,8 @@
"your-documents": "Your documents",
"multi-layered-protection-for-your-images": "Multi-layered image content protection with invisible watermarks",
"multi-layered-protection-for-your-audios": "Multi-layered audio content protection with invisible watermarks",
- "multi-layered-protection-for-your-videos": "Multi-layered video content protection with invisible watermarks"
+ "multi-layered-protection-for-your-videos": "Multi-layered video content protection with invisible watermarks",
+ "my-content-description": "Managing protected files and copyright control"
},
"Login-register-form": {
"and": "and",
diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json
index 4f071a5..a4e0c94 100644
--- a/src/i18n/messages/ru.json
+++ b/src/i18n/messages/ru.json
@@ -169,7 +169,8 @@
"your-documents": "Ваши документы",
"multi-layered-protection-for-your-images": "Многослойная защита изображений с невидимыми водяными знаками",
"multi-layered-protection-for-your-audios": "Многослойная защита аудиоконтента с невидимыми водяными знаками",
- "multi-layered-protection-for-your-videos": "Многослойная защита видеоконтента с невидимыми водяными знаками"
+ "multi-layered-protection-for-your-videos": "Многослойная защита видеоконтента с невидимыми водяными знаками",
+ "my-content-description": "Управление защищенными файлами и контролем авторских прав"
},
"Login-register-form": {
"and": "и",