diff --git a/src/app/[locale]/pages/marking-audio/page.tsx b/src/app/[locale]/pages/marking-audio/page.tsx
index 9669682..17774ed 100644
--- a/src/app/[locale]/pages/marking-audio/page.tsx
+++ b/src/app/[locale]/pages/marking-audio/page.tsx
@@ -4,6 +4,8 @@ import PageTitle from '@/app/ui/page-title';
import UploadSectionFile from '@/app/components/upload-section-file';
import { getAllowedFilesExtensions } from '@/app/actions/fileUpload';
import { StackedBarChart } from '@/app/components/StackedBarChart';
+import PageTitleColorFrame from '@/app/ui/page-title-color-frame';
+import ProtectionStatistic from '@/app/ui/marking-page/new/protection-statistic';
const data = [
{
@@ -44,9 +46,13 @@ export default async function Page() {
return (
-
+
+
-
+
diff --git a/src/app/[locale]/pages/marking-photo/page.tsx b/src/app/[locale]/pages/marking-photo/page.tsx
index aeed655..c3fbce1 100644
--- a/src/app/[locale]/pages/marking-photo/page.tsx
+++ b/src/app/[locale]/pages/marking-photo/page.tsx
@@ -3,8 +3,10 @@ import FilesTable from '@/app/ui/dashboard/files-table';
import PageTitle from '@/app/ui/page-title';
import UploadSectionFile from '@/app/components/upload-section-file';
import { getAllowedFilesExtensions } from '@/app/actions/fileUpload';
-import {StackedBarChart} from '@/app/components/StackedBarChart';
-import {TestComponent} from '@/app/components/test-component';
+import { StackedBarChart } from '@/app/components/StackedBarChart';
+import { TestComponent } from '@/app/components/test-component';
+import PageTitleColorFrame from '@/app/ui/page-title-color-frame';
+import ProtectionStatistic from '@/app/ui/marking-page/new/protection-statistic';
const data = [
{
@@ -40,10 +42,14 @@ export default async function Page() {
return (
-
-
+
+
+
-
+
diff --git a/src/app/[locale]/pages/marking-video/page.tsx b/src/app/[locale]/pages/marking-video/page.tsx
index 9f7b121..bb89d72 100644
--- a/src/app/[locale]/pages/marking-video/page.tsx
+++ b/src/app/[locale]/pages/marking-video/page.tsx
@@ -4,6 +4,8 @@ import PageTitle from '@/app/ui/page-title';
import UploadSectionFile from '@/app/components/upload-section-file';
import { getAllowedFilesExtensions } from '@/app/actions/fileUpload';
import { StackedBarChart } from '@/app/components/StackedBarChart';
+import PageTitleColorFrame from '@/app/ui/page-title-color-frame';
+import ProtectionStatistic from '@/app/ui/marking-page/new/protection-statistic';
const data = [
{
@@ -44,9 +46,13 @@ export default async function Page() {
return (
-
+
+
-
+
diff --git a/src/app/components/tanstakTable.tsx b/src/app/components/tanstakTable.tsx
index e240be3..9abc0c7 100644
--- a/src/app/components/tanstakTable.tsx
+++ b/src/app/components/tanstakTable.tsx
@@ -18,6 +18,7 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { getUserFilesData, removeUserFile } from '@/app/actions/fileEntity';
import ModalWindow from '@/app/components/modalWindow';
import { toast } from 'sonner';
+import { pluralize } from '@/app/lib/pluralize';
type FileType = 'image' | 'video' | 'audio';
@@ -603,6 +604,11 @@ 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 (
@@ -755,7 +761,7 @@ export default function TanstakFilesTable({ fileType }: { fileType: string }) {
- | {t('shown')} {table.getRowModel().rows.length} {t('out-of')} {filteredData.length} {t('files')}
+ | {t('shown')} {table.getRowModel().rows.length} {t('out-of')} {filteredData.length} {pluralizeFiles(filteredData.length || 0)}
diff --git a/src/app/lib/pluralize.ts b/src/app/lib/pluralize.ts
index 9f10a51..4efe7fd 100644
--- a/src/app/lib/pluralize.ts
+++ b/src/app/lib/pluralize.ts
@@ -1,5 +1,13 @@
+'use client'
+
export const pluralize = (number: number, one: string, few: string, many: string) => {
- const currentLang = document.documentElement.getAttribute('lang') || 'ru';
+ const getCurrentLang = () => {
+ if (typeof window !== 'undefined') {
+ return document?.documentElement?.getAttribute('lang') || 'ru';
+ }
+ return 'ru'; // значение по умолчанию для сервера
+ }
+ const currentLang = getCurrentLang();
if (currentLang === 'ru') {
const n = Math.abs(number) % 100;
diff --git a/src/app/styles/global-styles.scss b/src/app/styles/global-styles.scss
index 9235c26..8e8c23a 100644
--- a/src/app/styles/global-styles.scss
+++ b/src/app/styles/global-styles.scss
@@ -32,6 +32,30 @@
}
}
+.page-title-color-frame {
+ background: linear-gradient(135deg, v.$p-color 0%, v.$s-color 100%);
+ padding: 2rem;
+ border-radius: 16px;
+ margin-bottom: 2rem;
+ box-shadow: 0 10px 40px rgba(102, 126, 234, 0.2);
+
+ h1 {
+ color: v.$white;
+ font-size: 2rem;
+ font-weight: 700;
+ margin: 0 0 0.5rem 0;
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ }
+
+ p {
+ color: rgba(255, 255, 255, 0.9);
+ font-size: 1rem;
+ margin: 0;
+ }
+}
+
.main-containter-wrapper {
margin-left: var(--side-bar-width);
;
@@ -399,4 +423,8 @@
}
}
}
+}
+
+.yaPreloadingSuggestBlockContainer {
+ height: 52px !important;
}
\ No newline at end of file
diff --git a/src/app/styles/pages-styles.scss b/src/app/styles/pages-styles.scss
index b32f128..aefb378 100644
--- a/src/app/styles/pages-styles.scss
+++ b/src/app/styles/pages-styles.scss
@@ -1825,6 +1825,35 @@
}
}
-.yaPreloadingSuggestBlockContainer {
- height: 52px !important;
+.protection-statistic {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+ gap: 1.5rem;
+ margin-bottom: 2rem;
+
+ &-stat-card {
+ background: white;
+ padding: 1.5rem;
+ border-radius: 12px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.07);
+ border: 2px solid #f3f4f6;
+ text-align: center;
+ transition: all 0.3s;
+ }
+
+ &-stat-number {
+ font-size: 2rem;
+ font-weight: 700;
+ /* background: linear-gradient(135deg, #667eea, #764ba2);
+ background-clip: text;
+ -webkit-text-fill-color: transparent; */
+ color: v.$p-color;
+ margin-bottom: 0.5rem;
+ }
+
+ &-stat-label {
+ font-size: 0.9rem;
+ color: #6b7280;
+ font-weight: 500;
+ }
}
\ No newline at end of file
diff --git a/src/app/ui/marking-page/new/protection-statistic.tsx b/src/app/ui/marking-page/new/protection-statistic.tsx
new file mode 100644
index 0000000..dab0d3d
--- /dev/null
+++ b/src/app/ui/marking-page/new/protection-statistic.tsx
@@ -0,0 +1,91 @@
+'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';
+
+type FilesInfo = {
+ totalSize: number;
+ totalCount: number;
+};
+
+export default function ProtectionStatistic({ fileType }: { fileType: string }) {
+ const t = useTranslations('Global');
+
+ const getFileTypeFields = (fileType: string): { totalSize: string, totalCount: string } => {
+ switch (fileType) {
+ case 'image':
+ return {
+ totalSize: 'images_size',
+ totalCount: 'images_quantity'
+ };
+ case 'video':
+ return {
+ totalSize: 'videos_size',
+ totalCount: 'videos_quantity'
+ };
+ case 'audio':
+ return {
+ totalSize: 'audios_size',
+ totalCount: 'audios_quantity'
+ };
+ default:
+ return {
+ totalSize: 'all_files_size',
+ totalCount: 'all_files_quantity'
+ };
+ }
+ };
+
+ const {
+ data: filesInfo,
+ isLoading,
+ isError,
+ error,
+ } = useQuery<{
+ all_files_size: number,
+ all_files_quantity: number
+ }, Error, FilesInfo>({
+ queryKey: ['userFilesInfo'],
+ queryFn: getUserFilesInfo,
+ select: (data): FilesInfo => {
+ if (!data) {
+ return {
+ totalSize: 0,
+ totalCount: 0
+ }
+ }
+
+ const fields = getFileTypeFields(fileType);
+
+ return {
+ totalSize: data[fields.totalSize as keyof typeof data],
+ totalCount: data[fields.totalCount as keyof typeof data]
+ }
+ }
+ });
+
+ return (
+
+
+
+
0
+
Видео проверялось
+
+
+
+ {filesInfo?.totalSize ? convertBytes(filesInfo?.totalSize) : 0}
+
+
Занимают видео
+
+
+
0
+
Найдено нарушений
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/app/ui/page-title-color-frame.tsx b/src/app/ui/page-title-color-frame.tsx
new file mode 100644
index 0000000..cbf3d4b
--- /dev/null
+++ b/src/app/ui/page-title-color-frame.tsx
@@ -0,0 +1,16 @@
+import { useTranslations } from 'next-intl';
+
+export default function PageTitleColorFrame({ title, description }: { title: string, description: string }) {
+ const t = useTranslations('Global');
+
+ return (
+
+
+ {t(title)}
+
+
+ {t(description)}
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json
index 304e07e..cdd4560 100644
--- a/src/i18n/messages/en.json
+++ b/src/i18n/messages/en.json
@@ -166,7 +166,10 @@
"your-image": "Your images",
"your-videos": "Your videos",
"your-audios": "Your audios",
- "your-documents": "Your documents"
+ "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"
},
"Login-register-form": {
"and": "and",
diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json
index 4e45131..ffcaa34 100644
--- a/src/i18n/messages/ru.json
+++ b/src/i18n/messages/ru.json
@@ -166,7 +166,10 @@
"your-image": "Ваши изображения",
"your-videos": "Ваш видео",
"your-audios": "Ваш аудио",
- "your-documents": "Ваши документы"
+ "your-documents": "Ваши документы",
+ "multi-layered-protection-for-your-images": "Многослойная защита изображений с невидимыми водяными знаками",
+ "multi-layered-protection-for-your-audios": "Многослойная защита аудиоконтента с невидимыми водяными знаками",
+ "multi-layered-protection-for-your-videos": "Многослойная защита видеоконтента с невидимыми водяными знаками"
},
"Login-register-form": {
"and": "и",