update report page

This commit is contained in:
smanylov
2026-03-18 15:21:49 +07:00
parent 75874ab46f
commit 89e288c591
11 changed files with 207 additions and 72 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "no-copy-frontend", "name": "no-copy-frontend",
"version": "0.63.0", "version": "0.64.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev -p 2999", "dev": "next dev -p 2999",
+1 -3
View File
@@ -1,5 +1,4 @@
import StatsGrid from '@/app/ui/dashboard/stats-grid'; import ViolationsTable from '@/app/ui/violations/violations-table';
import ViolationsTable from '@/app/ui/dashboard/violations-table';
import FinalSummary from '@/app/ui/reports/final-summary'; import FinalSummary from '@/app/ui/reports/final-summary';
import AnalyticsCardMonth from '@/app/ui/reports/analytics-card-month'; import AnalyticsCardMonth from '@/app/ui/reports/analytics-card-month';
import AnalyticsCardGeography from '@/app/ui/reports/analytics-carв-geography'; import AnalyticsCardGeography from '@/app/ui/reports/analytics-carв-geography';
@@ -11,7 +10,6 @@ export default function Page() {
return ( return (
<div> <div>
<PageTitle title="reports-and-analytics" /> <PageTitle title="reports-and-analytics" />
{/* <StatsGrid /> */}
<ReportsInfo /> <ReportsInfo />
<ActivityByContentType /> <ActivityByContentType />
<div className="analytics-grid"> <div className="analytics-grid">
+14 -7
View File
@@ -14,12 +14,7 @@
color: white; color: white;
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 20px;
&::before {
content: '🔍';
margin-right: 12px;
font-size: 28px;
}
} }
.search-stats-grid { .search-stats-grid {
@@ -49,7 +44,13 @@
.search-stat-icon { .search-stat-icon {
font-size: 32px; font-size: 32px;
margin-bottom: 15px; margin-bottom: 15px;
display: block; display: flex;
justify-content: center;
.icon {
width: 50px;
height: 50px;
}
} }
.search-stat-value { .search-stat-value {
@@ -190,6 +191,7 @@
.summary-stats { .summary-stats {
display: grid; display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
grid-template-columns: 1fr 2fr 1fr;
gap: 30px; gap: 30px;
position: relative; position: relative;
z-index: 2; z-index: 2;
@@ -204,6 +206,11 @@
border: 2px solid rgba(255, 255, 255, 0.2); border: 2px solid rgba(255, 255, 255, 0.2);
transition: all 0.4s ease; transition: all 0.4s ease;
&.center {
display: flex;
justify-content: space-around;
}
&:hover { &:hover {
transform: translateY(-8px) scale(1.02); transform: translateY(-8px) scale(1.02);
background: rgba(255, 255, 255, 0.2); background: rgba(255, 255, 255, 0.2);
+3 -1
View File
@@ -2,7 +2,9 @@
export function IconImageFile() { export function IconImageFile() {
return ( return (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="m14 2l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2zm4 18V9h-5V4H6v16zm-1-7v6H7l5-5l2 2m-4-5.5A1.5 1.5 0 0 1 8.5 12A1.5 1.5 0 0 1 7 10.5A1.5 1.5 0 0 1 8.5 9a1.5 1.5 0 0 1 1.5 1.5" /></svg> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" className="icon">
<path fill="currentColor" d="m14 2l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2zm4 18V9h-5V4H6v16zm-1-7v6H7l5-5l2 2m-4-5.5A1.5 1.5 0 0 1 8.5 12A1.5 1.5 0 0 1 7 10.5A1.5 1.5 0 0 1 8.5 9a1.5 1.5 0 0 1 1.5 1.5" />
</svg>
) )
} }
+38 -13
View File
@@ -1,31 +1,56 @@
'use client'
import { useUserFilesInfo } from '@/app/hooks/react-query/useUserFilesInfo';
import { useTranslations } from 'next-intl';
import { IconImageFile, IconVideoFile, IconAudioFile, IconDocument } from '@/app/ui/icons/icons';
export default function ActivityByContentType() { export default function ActivityByContentType() {
const t = useTranslations('Global');
const { data: filesInfo, isLoading, isError, error } = useUserFilesInfo();
return ( return (
<div className="enhanced-chart-container"> <div className="enhanced-chart-container">
<div className="enhanced-chart-header"> <div className="enhanced-chart-header">
<h3 className="enhanced-chart-title"> <h3 className="enhanced-chart-title">
Активность проверок по типам контента {t('check-activity-by-content-type')}
</h3> </h3>
</div> </div>
<div className="search-stats-grid"> <div className="search-stats-grid">
<div className="search-stat-item"> <div className="search-stat-item">
<div className="search-stat-icon">📸</div> <div className="search-stat-icon">
<div className="search-stat-value">0</div> <IconImageFile />
<div className="search-stat-label">Изображения</div> </div>
<div className="search-stat-value">{filesInfo?.images.check ? filesInfo?.images.check : 0}</div>
<div className="search-stat-label">
{t('images')}
</div>
</div> </div>
<div className="search-stat-item"> <div className="search-stat-item">
<div className="search-stat-icon">🎬</div> <div className="search-stat-icon">
<div className="search-stat-value">0</div> <IconVideoFile />
<div className="search-stat-label">Видеофайлы</div> </div>
<div className="search-stat-value">{filesInfo?.videos.check ? filesInfo?.videos.check : 0}</div>
<div className="search-stat-label">
{t('videos')}
</div>
</div> </div>
<div className="search-stat-item"> <div className="search-stat-item">
<div className="search-stat-icon">🎵</div> <div className="search-stat-icon">
<div className="search-stat-value">0</div> <IconAudioFile />
<div className="search-stat-label">Аудиозаписи</div> </div>
<div className="search-stat-value">{filesInfo?.audios.check ? filesInfo?.audios.check : 0}</div>
<div className="search-stat-label">
{t('audios')}
</div>
</div> </div>
<div className="search-stat-item"> <div className="search-stat-item">
<div className="search-stat-icon">📄</div> <div className="search-stat-icon">
<div className="search-stat-value">0</div> <IconDocument />
<div className="search-stat-label">Документы</div> </div>
<div className="search-stat-value">{filesInfo?.documents.check ? filesInfo?.documents.check : 0}</div>
<div className="search-stat-label">
{t('documents')}
</div>
</div> </div>
</div> </div>
</div> </div>
+25 -16
View File
@@ -1,55 +1,64 @@
'use client'
import { useTranslations } from 'next-intl';
export default function AnalyticsCardMonth() { export default function AnalyticsCardMonth() {
const t = useTranslations('Global');
return ( return (
<div className="analytics-card"> <div className="analytics-card">
<div className="analytics-header"> <div className="analytics-header">
<div className="analytics-icon">📊</div> <div className="analytics-icon"></div>
<h3 className="analytics-title">Активность по месяцам</h3> <h3 className="analytics-title">
{t('activity-by-month')}
</h3>
</div> </div>
<div className="storage-timeline"> <div className="storage-timeline">
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">📅 Июль</span> <span className="timeline-month">{t('july')}</span>
<div className="timeline-stats"> <div className="timeline-stats">
<span>0 файлов</span> <span>0 {t('files')}</span>
<span></span> <span></span>
<span>0 Б</span> <span>0 Б</span>
</div> </div>
</div> </div>
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">📅 Август</span> <span className="timeline-month">{t('august')}</span>
<div className="timeline-stats"> <div className="timeline-stats">
<span>0 файлов</span> <span>0 {t('files')}</span>
<span></span> <span></span>
<span>0 Б</span> <span>0 Б</span>
</div> </div>
</div> </div>
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">📅 Сентябрь</span> <span className="timeline-month">{t('september')}</span>
<div className="timeline-stats"> <div className="timeline-stats">
<span>0 файлов</span> <span>0 {t('files')}</span>
<span></span> <span></span>
<span>0 Б</span> <span>0 Б</span>
</div> </div>
</div> </div>
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">📅 Октябрь</span> <span className="timeline-month">{t('october')}</span>
<div className="timeline-stats"> <div className="timeline-stats">
<span>3 файлов</span> <span>0 {t('files')}</span>
<span></span> <span></span>
<span>2.42 МБ</span> <span>0 Б</span>
</div> </div>
</div> </div>
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">📅 Ноябрь</span> <span className="timeline-month">{t('november')}</span>
<div className="timeline-stats"> <div className="timeline-stats">
<span>14 файлов</span> <span>0 {t('files')}</span>
<span></span> <span></span>
<span>43.53 МБ</span> <span>0 Б</span>
</div> </div>
</div> </div>
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">📅 Декабрь</span> <span className="timeline-month">{t('december')}</span>
<div className="timeline-stats"> <div className="timeline-stats">
<span>0 файлов</span> <span>0 {t('files')}</span>
<span></span> <span></span>
<span>0 Б</span> <span>0 Б</span>
</div> </div>
@@ -1,33 +1,53 @@
'use client'
import { useTranslations } from 'next-intl'
export default function AnalyticsCardGeography() { export default function AnalyticsCardGeography() {
const t = useTranslations('Global');
return ( return (
<div className="analytics-card"> <div className="analytics-card">
<div className="analytics-header"> <div className="analytics-header">
<div className="analytics-icon">🌍</div> <div className="analytics-icon"></div>
<h3 className="analytics-title">География нарушений</h3> <h3 className="analytics-title">
{t('geography-of-violations')}
</h3>
</div> </div>
<div className="storage-timeline"> <div className="storage-timeline">
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">🇷🇺 Россия</span> <span className="timeline-month">
{t('russia')}
</span>
<span className="method-count">0</span> <span className="method-count">0</span>
</div> </div>
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">🇺🇸 США</span> <span className="timeline-month">
{t('usa')}
</span>
<span className="method-count">0</span> <span className="method-count">0</span>
</div> </div>
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">🇩🇪 Германия</span> <span className="timeline-month">
{t('germany')}
</span>
<span className="method-count">0</span> <span className="method-count">0</span>
</div> </div>
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">🇫🇷 Франция</span> <span className="timeline-month">
{t('france')}
</span>
<span className="method-count">0</span> <span className="method-count">0</span>
</div> </div>
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">🇬🇧 Великобритания</span> <span className="timeline-month">
{t('uk')}
</span>
<span className="method-count">0</span> <span className="method-count">0</span>
</div> </div>
<div className="timeline-item"> <div className="timeline-item">
<span className="timeline-month">🇨🇳 Китай</span> <span className="timeline-month">
{t('china')}
</span>
<span className="method-count">0</span> <span className="method-count">0</span>
</div> </div>
</div> </div>
+40 -16
View File
@@ -1,32 +1,56 @@
'use client'
import { useUserFilesInfo } from '@/app/hooks/react-query/useUserFilesInfo';
import { useTranslations } from 'next-intl';
import { useEffect } from 'react';
export default function FinalSummary() { export default function FinalSummary() {
const t = useTranslations('Global');
const { data: filesInfo, isLoading, isError, error } = useUserFilesInfo();
return ( return (
<div className="final-summary"> <div className="final-summary">
<div className="summary-header"> <div className="summary-header">
<h2 className="summary-title"> <h2 className="summary-title">
📈 Итоговая статистика за Декабрь 2025 {t('summary-statistics')} {/* за Декабрь 2025 */}
</h2> </h2>
<p className="summary-subtitle"> <p className="summary-subtitle">
Общие показатели эффективности системы защиты {t('general-indicators-of-the-protection-system')}
</p> </p>
</div> </div>
<div className="summary-stats"> <div className="summary-stats">
<div className="summary-stat"> <div className="summary-stat">
<div className="summary-stat-icon">🔍</div> {/* <div className="summary-stat-icon">🔍</div> */}
<div className="summary-stat-value">0</div> <div className="summary-stat-value">{filesInfo?.total.check ? filesInfo?.total.check : 0}</div>
<div className="summary-stat-label">Всего проверок</div> <div className="summary-stat-label">
<div className="summary-stat-change">+15% к прошлому месяцу</div> {t('total-number-of-checks')}
</div>
{/* <div className="summary-stat-change">+15% к прошлому месяцу</div> */}
</div>
<div className="summary-stat center">
{/* <div className="summary-stat-icon">🚨</div> */}
<div>
<div className="summary-stat-value">{filesInfo?.total.violation ? filesInfo?.total.violation : 0}</div>
<div className="summary-stat-label">
{t('violations-found')}
</div>
</div>
<div>
<div className="summary-stat-value">0</div>
<div className="summary-stat-label">
{t('violations-registered')}
</div>
</div>
{/* <div className="summary-stat-change">Отличный результат!</div> */}
</div> </div>
<div className="summary-stat"> <div className="summary-stat">
<div className="summary-stat-icon">🚨</div> {/* <div className="summary-stat-icon">🛡️</div> */}
<div className="summary-stat-value">0</div> <div className="summary-stat-value">{filesInfo?.total.quantity ? filesInfo?.total.quantity : 0}</div>
<div className="summary-stat-label">Нарушений найдено</div> <div className="summary-stat-label">
<div className="summary-stat-change">Отличный результат!</div> {t('protected-content')}
</div> </div>
<div className="summary-stat"> {/* <div className="summary-stat-change">+0 за период</div> */}
<div className="summary-stat-icon">🛡</div>
<div className="summary-stat-value">0</div>
<div className="summary-stat-label">Защищенного контента</div>
<div className="summary-stat-change">+0 за период</div>
</div> </div>
</div> </div>
</div> </div>
-2
View File
@@ -6,8 +6,6 @@ import {IconDocument, IconSearch, IconWarning, IconGraph} from '@/app/ui/icons/i
export default function ReportsInfo() { export default function ReportsInfo() {
const t = useTranslations("Global"); const t = useTranslations("Global");
const { data: filesInfo, isLoading, isError, error } = useUserFilesInfo(); const { data: filesInfo, isLoading, isError, error } = useUserFilesInfo();
return ( return (
+29 -3
View File
@@ -203,6 +203,7 @@
"document-occupy": "Occupied by Documents", "document-occupy": "Occupied by Documents",
"violations-found": "Violations found", "violations-found": "Violations found",
"total-violations": "Total violations", "total-violations": "Total violations",
"violations-registered": "Violations registered",
"new": "new", "new": "new",
"in-progress": "In progress", "in-progress": "In progress",
"it-decided": "It's decided", "it-decided": "It's decided",
@@ -312,10 +313,35 @@
"open": "Open", "open": "Open",
"file-type": "File type", "file-type": "File type",
"file-not-found": "File not found", "file-not-found": "File not found",
"all-file-violations" : "All file violations", "all-file-violations": "All file violations",
"previous" : "Previous", "previous": "Previous",
"next": "Next", "next": "Next",
"source": "Source" "source": "Source",
"check-activity-by-content-type": "Check activity by content type",
"summary-statistics": "Summary statistics",
"general-indicators-of-the-protection-system": "General indicators of the protection system",
"total-number-of-checks": "Total number of checks",
"protected-content": "Protected content",
"geography-of-violations": "Geography of violations",
"activity-by-month": "Activity by month",
"january": "January",
"february": "February",
"march": "March",
"april": "April",
"may": "May",
"june": "June",
"july": "July",
"august": "August",
"september": "September",
"october": "October",
"november": "November",
"december": "December",
"russia": "Russia",
"usa": "USA",
"germany": "Germany",
"france": "France",
"uk": "United Kingdom",
"china": "China"
}, },
"Login-register-form": { "Login-register-form": {
"and": "and", "and": "and",
+28 -2
View File
@@ -203,6 +203,7 @@
"document-occupy": "Занимают документы", "document-occupy": "Занимают документы",
"violations-found": "Найдено нарушений", "violations-found": "Найдено нарушений",
"total-violations": "Всего нарушений", "total-violations": "Всего нарушений",
"violations-registered": "Нарушений зарегистрированно",
"new": "Новые", "new": "Новые",
"in-progress": "В работе", "in-progress": "В работе",
"it-decided": "Решено", "it-decided": "Решено",
@@ -313,9 +314,34 @@
"file-type": "Тип файла", "file-type": "Тип файла",
"file-not-found": "Файл не найден", "file-not-found": "Файл не найден",
"all-file-violations": "Все нарушения файла", "all-file-violations": "Все нарушения файла",
"previous" : "Предыдущая", "previous": "Предыдущая",
"next": "Следующая", "next": "Следующая",
"source": "Источник" "source": "Источник",
"check-activity-by-content-type": "Активность проверок по типам контента",
"summary-statistics": "Итоговая статистика",
"general-indicators-of-the-protection-system": "Общие показатели системы защиты",
"total-number-of-checks": "Всего проверок",
"protected-content": "Защищенного контента",
"geography-of-violations": "География нарушений",
"activity-by-month": "Активность по месяцам",
"january": "Январь",
"february": "Февраль",
"march": "Март",
"april": "Апрель",
"may": "Май",
"june": "Июнь",
"july": "Июль",
"august": "Август",
"september": "Сентябрь",
"october": "Октябрь",
"november": "Ноябрь",
"december": "Декабрь",
"russia": "Россия",
"usa": "США",
"germany": "Германия",
"france": "Франция",
"uk": "Великобритания",
"china": "Китай"
}, },
"Login-register-form": { "Login-register-form": {
"and": "и", "and": "и",