This commit is contained in:
smanylov
2025-12-18 17:21:18 +07:00
parent a538fe1684
commit 7540dd57de
8 changed files with 201 additions and 46 deletions
+5 -3
View File
@@ -3,7 +3,7 @@ import { Suspense } from 'react';
import ProtectionOverview from '@/app/ui/dashboard/protection-overview';
import StatsGrid from '@/app/ui/dashboard/stats-grid';
import { useTranslations } from 'next-intl';
import FilesTable from '@/app/ui/dashboard/files-table';
import FilesTable from '@/app/ui/dashboard/files-table';
export const metadata: Metadata = {
title: 'Dashboard',
@@ -18,8 +18,10 @@ export default function Page() {
<h1 className="page-title">
{t("statistics")}
</h1>
<ProtectionOverview />
<StatsGrid />
<div className="flex justify-between flex-wrap gap-8">
<ProtectionOverview />
<StatsGrid />
</div>
<FilesTable />
</Suspense>
</div>
+32
View File
@@ -0,0 +1,32 @@
import React, { ReactNode } from 'react';
interface ModalWindowtProps {
children: ReactNode;
state: boolean;
callBack: (value: boolean) => void;
}
export default function ModalWindow({ children, state, callBack }: ModalWindowtProps) {
console.log(state);
return (
<>
{state && (
<div
className="modal-wrapper"
onClick={() => {
callBack(false);
}}
>
<div
className="modal-window"
onClick={(e) => e.stopPropagation()}
>
{children}
</div>
</div>
)
}
</>
)
}
+22
View File
@@ -126,3 +126,25 @@
margin: 0 auto;
}
}
.modal-wrapper {
position: fixed;
z-index: 101;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: #0000007a;
.modal-window {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 20px;
background: #fff;
color: #000;
border-radius: 20px;
box-shadow: rgba(0, 0, 0, 0.08) 0px 4px 20px;
}
}
+47 -2
View File
@@ -112,6 +112,10 @@
font-size: 28px;
font-weight: 700;
margin-bottom: 5px;
&.btn {
user-select: none;
}
}
&-label {
@@ -136,6 +140,38 @@
display: flex;
justify-content: center;
}
&-drop-down-list {
position: absolute;
left: 80%;
top: 50%;
max-height: 0;
color: #fff;
font-size: 16px;
border-radius: 20px;
padding: 0;
border: none;
width: 200px;
z-index: 1;
font-weight: 500;
background: #ffffff00;
overflow: hidden;
transition: all 0.5s ease;
transform: translateY(-50%);
&.opened {
max-height: 500px;
padding: 20px;
box-shadow: 0 4px 20px #ffffff34;
background: #7165b6;
}
a:hover {
font-size: 17px;
transition: all 0.3s ease;
}
}
}
&-switch {
@@ -156,6 +192,8 @@
display: grid;
grid-template-columns: repeat(5, 1fr);
--boder-collor: #f3f4f6;
border-bottom: 1px solid var(--boder-collor);
align-items: center;
.stats-item.images {
--card-color-1: #f08c00;
@@ -199,8 +237,8 @@
}
}
&.last-row {
border-bottom: 1px solid var(--boder-collor);
&.second-row {
border-top: none;
}
&.left-top-corner {
@@ -652,3 +690,10 @@
margin-left: 5px;
}
}
.page-row {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
gap: 20px;
}
+83 -33
View File
@@ -1,8 +1,10 @@
'use client'
import { useState } from 'react';
import { useState, useRef } from 'react';
import { PieChartComponent } from '@/app/components/PieChartComponent';
import { useTranslations } from 'next-intl';
import Link from 'next/link';
import { useClickOutside } from '@/app/hooks/useClickOutside';
const data = [
@@ -11,30 +13,76 @@ const data = [
{ name: 'audios', value: 25, color: '#1971c2' },
];
/* нужно что бы включать выключать кнопки добавления маркировок */
const totalFiles = 1;
export default function ProtectionOverview() {
const [isOpen, setIsOpen] = useState(false);
const t = useTranslations('Global');
const [openDropDownList, setOpenDropDownList] = useState(false);
const dropDownList = useRef(null);
useClickOutside(dropDownList, () => {
setOpenDropDownList(false)
});
return (
<div className="protection-overview">
<div className="protection-overview grow">
<h3>{t('protecting-your-content')}</h3>
<p>{t('current-status-of')}</p>
<div className={`protection-stats ${isOpen ? "opened" : ""}`}>
<div className="protection-stat total-files">
<div className="protection-stat-value">0</div>
<div className="protection-stat-label">{t('total-files')}</div>
</div>
<div className="protection-stat total-checks">
<div className="protection-stat-row">
<div className="protection-stat-value">0</div>
<div className="protection-stat-label">{t('check')}</div>
{totalFiles ? (
<>
<div className="protection-stat total-files">
<div className="protection-stat-value">0</div>
<div className="protection-stat-label">{t('total-files')}</div>
</div>
<div className="protection-stat total-checks">
<div className="protection-stat-row">
<div className="protection-stat-value">0</div>
<div className="protection-stat-label">{t('check')}</div>
</div>
<div className="protection-stat-row">
<div className="protection-stat-value">0</div>
<div className="protection-stat-label">{t('violations')}</div>
</div>
</div>
</>
) : (
<div className="protection-stat total-files relative">
<div className="protection-stat-label">
{t('there-are-no-files-yet')}
</div>
<div
className="protection-stat-value btn"
onClick={() => {
setOpenDropDownList(!openDropDownList);
}}
ref={dropDownList}
>
{t('add')}
<div
className={`protection-stat-drop-down-list ${openDropDownList ? 'opened' : ''}`}
>
<div
className="flex flex-col text-center"
>
<Link href='/pages/marking-photo'>
{t('photo-marking')}
</Link>
<Link href='/pages/marking-video'>
{t('video-marking')}
</Link>
<Link href='/pages/marking-audio'>
{t('audio-marking')}
</Link>
</div>
</div>
</div>
</div>
<div className="protection-stat-row">
<div className="protection-stat-value">0</div>
<div className="protection-stat-label">{t('violations')}</div>
</div>
</div>
)}
{isOpen ? (
<div className="protection-stat total-usage">
<PieChartComponent data={data} />
@@ -48,25 +96,27 @@ export default function ProtectionOverview() {
</div>
)}
</div>
<button
className="protection-overview-switch cursor-pointer"
onClick={() => {
setIsOpen(!isOpen);
}}
>
<svg
className={`w-5 h-5 ml-2 transition-transform ${isOpen ? 'rotate-180' : ''}`}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
{!!totalFiles && (
<button
className="protection-overview-switch cursor-pointer"
onClick={() => {
setIsOpen(!isOpen);
}}
>
<path
fillRule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button>
<svg
className={`w-5 h-5 ml-2 transition-transform ${isOpen ? 'rotate-180' : ''}`}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button>
)}
</div>
)
}
+6 -6
View File
@@ -4,7 +4,7 @@ export default function StatsGrid() {
const t = useTranslations("Global");
return (
<div className="block-wrapper stats-wrapper">
<div className="block-wrapper stats-wrapper grow">
<h3>
{t('your-content')}
</h3>
@@ -25,20 +25,20 @@ export default function StatsGrid() {
{t('checks')}
</div>
<div className="stats-item first-column images">
<div className="stats-item first-column second-row images">
<IconImageFile />
{t('images')}
</div>
<div className="stats-item">
<div className="stats-item second-row">
0
</div>
<div className="stats-item">
<div className="stats-item second-row">
0
</div>
<div className="stats-item">
<div className="stats-item second-row">
0
</div>
<div className="stats-item last-column">
<div className="stats-item second-row last-column">
0
</div>
+3 -1
View File
@@ -114,7 +114,9 @@
"added": "Added",
"no-data": "No data",
"view-all": "View all",
"days-ago": "days ago"
"days-ago": "days ago",
"there-are-no-files-yet": "There are no files yet",
"add": "Add"
},
"Login-register-form": {
"and": "and",
+3 -1
View File
@@ -114,7 +114,9 @@
"added": "Добавлено",
"no-data": "Нет данных",
"view-all": "Посмотреть все",
"days-ago": "дней назад"
"days-ago": "дней назад",
"there-are-no-files-yet": "Файлов пока нет",
"add": "Добавить"
},
"Login-register-form": {
"and": "и",