diff --git a/src/app/actions/fileEntity.ts b/src/app/actions/fileEntity.ts index 8e26813..3c5f387 100644 --- a/src/app/actions/fileEntity.ts +++ b/src/app/actions/fileEntity.ts @@ -120,7 +120,7 @@ export async function viewFileInfo(fileId: string) { } export async function downloadFile(fileId: string, fileName: string) { - const token = await getSessionData('token') + const token = await getSessionData('token'); const response = await fetch(`${API_BASE_URL}/api/v1/files/download/${fileId}`, { headers: { diff --git a/src/app/actions/violationActions.ts b/src/app/actions/violationActions.ts new file mode 100644 index 0000000..91be8a2 --- /dev/null +++ b/src/app/actions/violationActions.ts @@ -0,0 +1,67 @@ +'use server' + +import { getSessionData } from '@/app/actions/session'; +import { API_BASE_URL } from '@/app/actions/definitions'; + +export async function getViolationSearchStatus() { + const token = await getSessionData('token'); + console.log('getViolationSearchStatus'); + + try { + const response = await fetch(`${API_BASE_URL}/api/v1/global-search/actual-task`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': `Bearer ${token}`, + } + }); + /* console.log(response); */ + + if (response.ok) { + console.log('parsed'); + const parsed = await response.json(); + console.log(parsed); + + return parsed + } else { + return null + } + } catch (error) { + return null + } +} + +export async function startGlobalMonitoring(monitoringType: 'monitoring' | 'all_files') { + const token = await getSessionData('token'); + console.log('startGlobalMonitoring'); + + try { + const response = await fetch(`${API_BASE_URL}/api/v1/global-search/start`, { + method: 'POST', + body: JSON.stringify({ + searchType: monitoringType + }), + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}`, + } + }); + console.log(response); + + if (response.ok) { + const parsed = await response.json(); + console.log(parsed); + if (parsed?.message_code === 0) { + return parsed + } else { + return null + } + + } else { + return null + } + } catch (error) { + return null + } +} \ No newline at end of file diff --git a/src/app/styles/pages-styles.scss b/src/app/styles/pages-styles.scss index e621be0..a665a8b 100644 --- a/src/app/styles/pages-styles.scss +++ b/src/app/styles/pages-styles.scss @@ -4074,6 +4074,10 @@ background: transparent; border: 2px solid #6366f1; color: #6366f1; + + &:disabled { + opacity: 0.5; + } } &.btn-confirm:disabled, diff --git a/src/app/ui/violations/violations-check-all-section.tsx b/src/app/ui/violations/violations-check-all-section.tsx index ff82a37..2f721fc 100644 --- a/src/app/ui/violations/violations-check-all-section.tsx +++ b/src/app/ui/violations/violations-check-all-section.tsx @@ -1,18 +1,112 @@ +'use client' + +import { useQuery } from '@tanstack/react-query'; +import { useTranslations } from 'next-intl'; +import { getViolationSearchStatus, startGlobalMonitoring } from '@/app/actions/violationActions'; +import { useState } from 'react'; +import ModalWindow from '@/app/components/ModalWindow'; +import { fa } from 'zod/v4/locales'; + export default function ViolationsCheckAllSection() { - return ( -
-
-
-
🔍
-
Глобальная проверка контента
+ const { + data: violationSearchStatus, + isLoading, + isError, + error + } = useQuery({ + queryKey: ['violationSearchStatus'], + queryFn: () => { + return getViolationSearchStatus(); + }, + select: (data) => { + /* console.log(data); */ + if (data) { + return data; + } else { + return null + } + } + }); + const t = useTranslations('Global'); + const [isProcessing, setIsProcessing] = useState(false); + const [openWindow, setOpenWindow] = useState(false); + + function openModalWindow() { + setOpenWindow(true); + } + + async function handlerStartMonitoring(type: 'monitoring' | 'all_files') { + setIsProcessing(true); + + try { + const response = await startGlobalMonitoring(type); + } catch (error) { + console.error(error); + } finally { + setIsProcessing(false); + setOpenWindow(false); + } + } + + function ConfirmationModal() { + return ( +
+

+ Поиск нарушений во всех ваших изображениях +

+
+
Варианты проверки.
-
- Поиск нарушений во всех ваших изображениях. Проверка только точных совпадений (95%+). +
+ +
- -
+ ); + } + + return ( + <> + + + +
+ +
+
+ {/*
🔍
*/} +
Глобальная проверка контента
+
+
+ Поиск нарушений во всех ваших изображениях. Проверка только точных совпадений (95%+). +
+
+ +
+ ) } \ No newline at end of file diff --git a/src/app/ui/violations/violations-table.tsx b/src/app/ui/violations/violations-table.tsx index 73d182f..da2b555 100644 --- a/src/app/ui/violations/violations-table.tsx +++ b/src/app/ui/violations/violations-table.tsx @@ -1,79 +1,495 @@ +'use client' + +import { useMemo, useState } from 'react'; +import { useReactTable, getCoreRowModel, getSortedRowModel, getPaginationRowModel, getFilteredRowModel, ColumnDef, SortingState, ColumnFiltersState } from '@tanstack/react-table'; +import { useTranslations } from 'next-intl'; +import { IconArrowUp, IconArrowDown, IconFilter, IconDoubleArrowRight, IconArrowRight, IconDoubleArrowLeft, IconArrowLeft } from '@/app/ui/icons/icons'; +import DropDownList from '@/app/components/DropDownList'; +import { useQuery } from '@tanstack/react-query'; +import { getUserFilesData } from '@/app/actions/fileEntity'; + + export default function ViolationsTable() { + const { + data: violationData, + isLoading, + isError, + error, + } = useQuery({ + queryKey: ['violationData', 1, 10000], + queryFn: () => getUserFilesData(1, 10000), + + select: (data) => { + if (!data?.files) return []; + + return data.files.map((item: any) => { + /* const newDate = new Date(item.updatedAt).getTime(); */ + + return { + id: item.id, + }; + }); + }, + refetchInterval: 30000 + }); + const t = useTranslations('Global'); + + // Состояния + const [sorting, setSorting] = useState([]); + const [columnFilters, setColumnFilters] = useState([]); + const [dateFilter, setDateFilter] = useState('all'); + const [pagination, setPagination] = useState({ + pageIndex: 0, + pageSize: 10, + }); + + const columns = useMemo[]>( + () => [ + { + accessorKey: 'file', + header: ({ column }) => ( +
+ + Файл + + +
+ ), + cell: ({ row }) => { + return ( +
+
+ {/* {row.original} */} + Файл +
+
+ ) + } + }, + { + accessorKey: 'violationUrl', + header: ({ column }) => ( +
+ + violationUrl + + +
+ ), + cell: ({ row }) => ( +
+ {/* {row.original.amount} */} + violationUrl +
+ ), + }, + { + accessorKey: 'statistic', + header: ({ column }) => ( +
+ + Статистика + + +
+ ), + cell: ({ row }) => ( +
+ Статистика +
+ ), + }, + { + accessorKey: 'DMCA', + header: ({ column }) => ( +
+ + DMCA жалоба + + +
+ ), + cell: ({ row }) => { + return ( +
+

+ DMCA жалоба +

+
+ ) + }, + }, + { + accessorKey: 'actions', + header: ({ column }) => ( +
+ + actions + +
+ ), + cell: ({ row }) => { + return ( +
+ actions +
+ ) + } + }, + ], + [] + ) + + const filteredData = useMemo(() => { + let result = violationData?.payments; + if (!result) { + return []; + } + + // Фильтр по дате + if (dateFilter !== 'all') { + const now = Date.now(); + const oneDay = 24 * 60 * 60 * 1000; + const sevenDays = 7 * oneDay; + const thirtyDays = 30 * oneDay; + + switch (dateFilter) { + case 'today': + const todayStart = new Date().setHours(0, 0, 0, 0); + result = result.filter((item: any) => { + if (item.createdAt) { + return new Date(item.createdAt).getTime() >= todayStart + } else { + return 0 + } + }); + break; + case 'week': + const weekAgo = now - sevenDays; + result = result.filter((item: any) => { + if (item.createdAt) { + return new Date(item.createdAt).getTime() >= weekAgo; + } + }); + break; + case 'month': + const monthAgo = now - thirtyDays; + result = result.filter((item: any) => { + if (item.createdAt) { + return new Date(item.createdAt).getTime() >= monthAgo; + } + }); + break; + case 'older': + const monthAgo2 = now - thirtyDays; + result = result.filter((item: any) => { + if (item.createdAt) { + return new Date(item.createdAt).getTime() < monthAgo2; + } + }); + break; + } + } + + return result + }, [violationData?.payments, dateFilter]) + + const table = useReactTable({ + data: filteredData, + columns, + state: { + sorting, + columnFilters, + pagination + }, + autoResetPageIndex: false, + onPaginationChange: setPagination, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getFilteredRowModel: getFilteredRowModel(), + initialState: { + pagination: { + pageSize: 10, + }, + }, + }); + return ( -
-
-
Обнаруженные нарушения (17)
-
+
+
+
+

+ Обнаруженные нарушения +

-
- - - - - - - - - - - - - + {/* Фильтры */} + {/*
+
+
+
{t('date-filter')}:
+ { + switch (dateFilter) { + case 'all': + return t('all-dates') + case 'week': + return t('for-a-week') + case 'month': + return t('for-a-month') + case 'older': + return t('older-than-a-month') + default: + return t('today') + } + })()} + callBack={setDateFilter} + > +
  • + {t('all-dates')} +
  • +
  • + {t('today')} +
  • +
  • + {t('for-a-week')} +
  • +
  • + {t('for-a-month')} +
  • +
  • + {t('older-than-a-month')} +
  • +
    +
    -
    + +
    +
    +
    {t('items-per-page')}:
    + + {[5, 10, 20, 50, 100].map(pageSize => ( +
  • + {t('show')} {pageSize} +
  • + ))} +
    +
    +
    - + */} + {/* Таблица */} +
    +
    ФайлURL нарушенияСтатистикаDMCA ЖалобаДействия
    -
    - Preview -
    -
    -
    - banner111.png
    -
    - 📅 17.10.2025
    -
    + + {table.getHeaderGroups().map(headerGroup => ( + + {headerGroup.headers.map(header => ( + + ))} + + ))} + + + {table.getRowModel().rows.length > 0 ? ( + table.getRowModel().rows.map(row => ( + + {row.getVisibleCells().map(cell => ( + + ))} + + )) + ) : ( + + + + )} + +
    + {header.isPlaceholder + ? null + : typeof header.column.columnDef.header === 'function' + ? header.column.columnDef.header(header.getContext()) + : header.column.columnDef.header as string} +
    + {typeof cell.column.columnDef.cell === 'function' + ? cell.column.columnDef.cell(cell.getContext()) + : cell.getValue() as string} +
    + {t('no-data-for-selected-filters')} +
    +
    - - - https://m.apkpure.com/th/4k-wallpapers/com.starwalls.BACKGROUND.wallpapers4K.starwall - + {/* Пагинация */} +
    +
    + + {t('page')}{' '} + + {table.getState().pagination.pageIndex + 1} {t('out-of')} {table.getPageCount() ? table.getPageCount() : 1} + + + + | {t('shown')} {table.getRowModel().rows.length} {t('out-of')} {filteredData.length} + +
    - - -
    - 📊 85% -
    -
    - 🔗 2 источников -
    - - - - - - + )} + {table.getCanPreviousPage() && ( + + )} +
    + {Array.from({ length: Math.min(5, table.getPageCount()) }, (_, i) => { + const pageIndex = Math.max( + 0, + Math.min( + table.getPageCount() - 5, + table.getState().pagination.pageIndex - 2 + ) + ) + i; - -
    - - - -
    - - - - + if (pageIndex < table.getPageCount()) { + return ( + + ); + } + return null; + })} +
    + + {table.getCanNextPage() && ( + + )} + {table.getCanNextPage() && ( + + )} +
    +
    +
    )