rework violation table and violation actions

This commit is contained in:
smanylov
2026-04-29 15:15:04 +07:00
parent c0fe6cce48
commit c274cb134d
6 changed files with 341 additions and 449 deletions
@@ -10,7 +10,6 @@ import DashboardFilesInfo from '@/app/ui/dashboard/new/dashboard-files-info';
import DahboardLimitsSection from '@/app/ui/dashboard/new/dashborad-limits-section';
import DahboardGeographySection from '@/app/ui/dashboard/new/dashboard-geography-section';
import DashboardLastCheck from '@/app/ui/dashboard/new/dashboard-last-check';
import ViolationsCarousel from '@/app/ui/dashboard/new/violations-carousel';
import DashboardUserViolations from '@/app/ui/dashboard/new/dashboard-user-violations';
export const metadata: Metadata = {
+25 -6
View File
@@ -80,24 +80,41 @@ export async function startGlobalMonitoring(monitoringType: 'monitoring' | 'all_
}
}
export async function getViolationFilesArray() {
export async function getViolationFilesArray(props: {
page?: number,
size?: number,
start_date?: string,
end_date?: string,
file_name?: string
}) {
const token = await getSessionData('token');
console.log('getViolationFilesArray');
const { page, size, start_date, end_date, file_name } = props;
try {
const body: Record<string, any> = {
token: token
};
const response = await fetch(`${API_BASE_URL}/api/v1/global-search/violation-summary`, {
method: 'GET',
if (page !== undefined) body.page = page;
if (size !== undefined) body.size = size;
if (start_date !== undefined) body.start_date = start_date;
if (end_date !== undefined) body.end_date = end_date;
if (file_name !== undefined) body.file_name = file_name;
const response = await fetch(`${API_BASE_URL}/api/v1/global-search/violation-summary-with-files`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': `Bearer ${token}`,
}
},
body: JSON.stringify(body),
});
if (response.ok) {
let parsed = await response.json();
if (parsed.length) {
if (parsed.content.length) {
return parsed;
} else {
throw parsed;
@@ -310,6 +327,7 @@ export async function createComplaint(
formData: FormData
): Promise<complainBody> {
const email = await getSessionData('email');
const token = await getSessionData('token');
const violationId = formData.get('violationId') as string || '';
const textArea = formData.get('note') as string || '';
@@ -345,6 +363,7 @@ export async function createComplaint(
version: 1,
msg_id: 30013,
message_body: {
token: token,
action: 'create',
violation_id: violationId,
text: textArea,
@@ -912,6 +912,21 @@ export default function TanstakFilesTable({ fileType, showFileLink }: { fileType
))}
</thead>
<tbody className={`tanstak-table-body ${isFetching ? 'loading' : ''}`}>
{isLoading && (
<tr>
<td colSpan={columns.length} className="text-center relative h-12.5">
<div
className="loading-animation"
>
<div
className="global-spinner"
>
</div>
</div>
</td>
</tr>
)}
{table.getRowModel().rows.length > 0 ? (
table.getRowModel().rows.map(row => (
<tr key={row.id}>
@@ -926,9 +941,11 @@ export default function TanstakFilesTable({ fileType, showFileLink }: { fileType
))
) : (
<tr>
{!isLoading && (
<td colSpan={columns.length} className="text-center">
{t('no-data-for-selected-filters')}
</td>
)}
</tr>
)}
</tbody>
@@ -11,7 +11,7 @@ import Link from 'next/link';
import { getViolationFilesArray } from '@/app/actions/violationActions';
import { IconEye } from '@/app/ui/icons/icons';
interface ViolationFile {
interface FileViolation {
createdAt: string;
fileId: string;
fileName: string;
@@ -23,20 +23,26 @@ interface ViolationFile {
violationCount: number;
}
interface ViolationData {
content: FileViolation[];
}
export default function DashboardUserViolations() {
const {
data: violationData,
isLoading,
isError,
error,
} = useQuery<ViolationFile[]>({
queryKey: ['violationData'],
queryFn: () => getViolationFilesArray(),
} = useQuery<ViolationData>({
queryKey: ['violationData', { page: 0, size: 5 }],
queryFn: () => getViolationFilesArray({
page: 0,
size: 5,
}),
select: (data) => {
return data?.slice(0, 5) || [];
},
/* refetchInterval: 30000 */
return data;
}
});
const t = useTranslations('Global');
@@ -76,8 +82,8 @@ export default function DashboardUserViolations() {
</div>
)}
{violationData?.length ? (
violationData?.map((file) => {
{violationData?.content.length ? (
violationData?.content.map((file) => {
return (
<div
key={file.fileId}
@@ -1,173 +0,0 @@
'use client'
import { Swiper, SwiperSlide } from 'swiper/react';
import { Pagination, Autoplay } from 'swiper/modules';
import Image from 'next/image';
import 'swiper/css';
import 'swiper/css/pagination';
import testImage from '@/app/src/image-preview.png'
import { useEffect, useRef } from 'react';
import { useTranslations } from 'next-intl';
import Link from 'next/link';
import { useQuery } from '@tanstack/react-query';
import { getViolationFilesArray } from '@/app/actions/violationActions';
interface ViolationFile {
createdAt: string;
fileId: string;
fileName: string;
fileSize: number;
latestViolationDate: string;
mimeType: string;
status: string;
supportId: number;
violationCount: number;
}
export default function ViolationsCarousel() {
const {
data: violationData,
isLoading,
isError,
error,
} = useQuery<ViolationFile[]>({
queryKey: ['violationData'],
queryFn: () => getViolationFilesArray(),
select: (data) => {
return data;
},
/* refetchInterval: 30000 */
});
const paginationRef = useRef(null);
const t = useTranslations('Global');
useEffect(() => {
console.log(violationData);
}, [violationData])
return (
<div className="content-section">
<div className="section-header">
<h3 className="section-title">{t('violation')}</h3>
<Link
href="violations"
className="view-all-link"
>
Смотреть все
</Link>
</div>
<div>
{t('are-no-violations')}
</div>
<div className="violations-carousel">
<Swiper
spaceBetween={50}
slidesPerView={1}
modules={[Pagination, Autoplay]}
pagination={{
clickable: true,
el: '.custon-swiper-pagination'
}}
loop={true}
autoplay={{
delay: 3000,
disableOnInteraction: false,
}}
>
{/* {violationData?.map(item => {
return (
<SwiperSlide>
<div
className="violation-slide"
>
</div>
</SwiperSlide>
)
})} */}
{/* <SwiperSlide>
<div className="violation-slide">
<div className="violation-image-container">
<Image src={testImage} alt="Preview" className="violation-image" />
<div className="violation-badge">НАРУШЕНИЕ</div>
<div className="violation-status-badge">ОБРАБОТАНО</div>
</div>
<div className="violation-content">
<div className="violation-title-row">
<div className="violation-filename">
🖼️banner111.png</div>
<div className="violation-type-badge photo">
Фото
</div>
</div>
<div className="violation-info-grid">
<div className="violation-info-item">
<div className="violation-info-label">
🌍 Регион
</div>
<div className="violation-info-value">
<span className="region-flag">🇺🇸</span>
<span>США</span>
</div>
</div>
<div className="violation-info-item">
<div className="violation-info-label">📅 Обнаружено</div>
<div className="violation-info-value">
17.10.2025</div>
</div>
<div className="violation-info-item">
<div className="violation-info-label">🌐 Домен</div>
<div className="violation-info-value">
m.apkpure.com </div>
</div>
<div className="violation-info-item">
<div className="violation-info-label">📊 Категория</div>
<div className="violation-info-value">
Единичное
</div>
</div>
<div className="violation-info-item">
<div className="violation-info-label">📁 Тип</div>
<div className="violation-info-value">
Изображение</div>
</div>
<div className="violation-info-item">
<div className="violation-info-label">⚡ Статус</div>
<div className="violation-info-value">
✅ Обработано</div>
</div>
</div>
<div className="violation-actions-row">
<button className="btn-visit-site">
🔗 Перейти на сайт
</button>
<button className="violation-action">
🚨 Открыть дело
</button>
</div>
</div>
</div>
</SwiperSlide> */}
</Swiper>
<div
className="flex justify-center mt-6"
>
<div
ref={paginationRef}
className="flex justify-center gap-2 custon-swiper-pagination"
>
</div>
</div>
</div>
</div>
)
}
+221 -197
View File
@@ -1,6 +1,6 @@
'use client'
import { useMemo, useState } from 'react';
import { useMemo, useState, useEffect } 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, IconEye } from '@/app/ui/icons/icons';
@@ -9,8 +9,10 @@ import { getViolationFilesArray } from '@/app/actions/violationActions';
import { useViewport } from '@/app/hooks/useViewport';
import { formatDate, formatDateTime } from '@/app/lib/formatDate';
import Link from 'next/link';
import DropDownList from '@/app/components/DropDownList';
import { useDebounce } from 'use-debounce';
interface ViolationFile {
interface FileViolation {
createdAt: string;
fileId: string;
fileName: string;
@@ -22,32 +24,103 @@ interface ViolationFile {
violationCount: number;
}
interface ViolationData {
content: FileViolation[];
totalPages: number;
totalElements: number;
size: number;
number: number;
}
export default function ViolationsTable() {
const {
data: violationData,
isLoading,
isError,
error,
} = useQuery<ViolationFile[]>({
queryKey: ['violationData'],
queryFn: () => getViolationFilesArray(),
select: (data) => {
return data;
},
/* refetchInterval: 30000 */
});
const t = useTranslations('Global');
const viewport = useViewport();
// Состояния
const [sorting, setSorting] = useState<SortingState>([]);
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
const [fileNameFilter, setFileNameFilter] = useState<string>('');
const [dateFilter, setDateFilter] = useState<string>('all');
const [pagination, setPagination] = useState({
pageIndex: 0,
pageSize: 10,
});
const [sorting, setSorting] = useState<SortingState>([]);
const [debouncedFileName] = useDebounce(fileNameFilter, 500);
const getDateRange = (filter: string): { start_date?: string; end_date?: string } => {
const now = new Date();
const end_date = formatDateTimeForAPI(now);
switch (filter) {
case 'today': {
const start_date = formatDateTimeForAPI(new Date(now.setHours(0, 0, 0, 0)));
return { start_date, end_date };
}
case 'week': {
const weekAgo = new Date(now);
weekAgo.setDate(weekAgo.getDate() - 7);
weekAgo.setHours(0, 0, 0, 0);
return { start_date: formatDateTimeForAPI(weekAgo), end_date };
}
case 'month': {
const monthAgo = new Date(now);
monthAgo.setMonth(monthAgo.getMonth() - 1);
monthAgo.setHours(0, 0, 0, 0);
return { start_date: formatDateTimeForAPI(monthAgo), end_date };
}
case 'older': {
const monthAgo = new Date(now);
monthAgo.setMonth(monthAgo.getMonth() - 1);
monthAgo.setHours(0, 0, 0, 0);
return { end_date: formatDateTimeForAPI(monthAgo) };
}
default:
return {};
}
};
const formatDateTimeForAPI = (date: Date): string => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
const dateRange = getDateRange(dateFilter);
const {
data: violationData,
isLoading,
isFetching,
isError,
error,
refetch,
} = useQuery<ViolationData>({
queryKey: ['violationData', pagination.pageIndex, pagination.pageSize, debouncedFileName, dateFilter],
queryFn: () => getViolationFilesArray({
page: pagination.pageIndex,
size: pagination.pageSize,
file_name: debouncedFileName || undefined,
start_date: dateRange.start_date,
end_date: dateRange.end_date,
}),
select: (data) => {
console.log(data);
return data;
},
placeholderData: (previousData) => previousData,
});
useEffect(() => {
if (violationData) {
setPagination(prev => ({
...prev,
pageIndex: violationData.number || 0,
}));
}
}, [violationData]);
const viewport = useViewport();
const getMaxLengthByWidth = (): number => {
if (viewport.device === 'MOBILE') return 26;
if (viewport.device === 'TABLET') return 32;
@@ -73,115 +146,83 @@ export default function ViolationsTable() {
const maxNameLength = MAX_FILE_NAME_LENGTH - extension.length - 3;
if (maxNameLength <= 0) {
return '...' /* + extension */;
return '...';
}
return nameWithoutExtension.substring(0, maxNameLength) + '...' /* + extension */;
}
return nameWithoutExtension.substring(0, maxNameLength) + '...';
};
const columns = useMemo<ColumnDef<ViolationFile>[]>(
const columns = useMemo<ColumnDef<FileViolation>[]>(
() => [
{
accessorKey: 'supportId',
header: ({ column }) => (
<div className="column">
<span>
ID
</span>
<span>ID</span>
<button
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
className="sort-button"
>
{
column.getIsSorted() === 'asc' ?
<span>
{column.getIsSorted() === 'asc' ? (
<IconArrowUp />
</span>
: column.getIsSorted() === 'desc' ?
<span>
) : column.getIsSorted() === 'desc' ? (
<IconArrowDown />
</span>
: <span>
) : (
<IconFilter />
</span>
}
)}
</button>
</div>
),
cell: ({ row }) => {
return (
<div>
cell: ({ row }) => (
<div className="text-center table-item table-item-id">
{row.original.supportId}
</div>
</div>
)
}
),
},
{
accessorKey: 'fileName',
header: ({ column }) => (
<div className="column start">
<span>
{t('file')}
</span>
<span>{t('file')}</span>
<button
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
className="sort-button"
>
{
column.getIsSorted() === 'asc' ?
<span>
{column.getIsSorted() === 'asc' ? (
<IconArrowUp />
</span>
: column.getIsSorted() === 'desc' ?
<span>
) : column.getIsSorted() === 'desc' ? (
<IconArrowDown />
</span>
: <span>
) : (
<IconFilter />
</span>
}
)}
</button>
</div>
),
cell: ({ row }) => {
return (
<div>
cell: ({ row }) => (
<div
className="flex items-center space-x-2 table-item table-item-file-name"
title={row.original.fileName}
>
{cutFileName(row.original.fileName)}
</div>
</div>
)
}
),
},
{
accessorKey: 'violationCount',
header: ({ column }) => (
<div className="column">
<span>
{t('matches')}
</span>
<span>{t('matches')}</span>
<button
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
className="sort-button"
>
{
column.getIsSorted() === 'asc' ?
<span>
{column.getIsSorted() === 'asc' ? (
<IconArrowUp />
</span>
: column.getIsSorted() === 'desc' ?
<span>
) : column.getIsSorted() === 'desc' ? (
<IconArrowDown />
</span>
: <span>
) : (
<IconFilter />
</span>
}
)}
</button>
</div>
),
@@ -195,26 +236,18 @@ export default function ViolationsTable() {
accessorKey: 'latestViolationDate',
header: ({ column }) => (
<div className="column">
<span>
{t('date')}
</span>
<span>{t('date')}</span>
<button
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
className="sort-button"
>
{
column.getIsSorted() === 'asc' ?
<span>
{column.getIsSorted() === 'asc' ? (
<IconArrowUp />
</span>
: column.getIsSorted() === 'desc' ?
<span>
) : column.getIsSorted() === 'desc' ? (
<IconArrowDown />
</span>
: <span>
) : (
<IconFilter />
</span>
}
)}
</button>
</div>
),
@@ -228,28 +261,14 @@ export default function ViolationsTable() {
},
{
accessorKey: 'actions',
header: ({ column }) => (
header: () => (
<div className="column">
<span>
{t('actions')}
</span>
<span>{t('actions')}</span>
</div>
),
cell: ({ row }) => {
return (
cell: ({ row }) => (
<div className="actions">
<div
className="actions-group"
>
{/* <button
onClick={() => {
console.log(row.original.fileId);
}}
className="bg-violet-500 hover:bg-violet-600"
title={t('view')}
>
<IconEye />
</button> */}
<div className="actions-group">
<Link
href={`/pages/file/${row.original.fileId}`}
className="bg-violet-500 hover:bg-violet-600"
@@ -259,62 +278,57 @@ export default function ViolationsTable() {
</Link>
</div>
</div>
)
}
),
},
],
[]
)
const filteredData = useMemo(() => {
let result = violationData;
if (!result) {
return [];
}
return result
}, [violationData])
[t, viewport]
);
const table = useReactTable({
data: filteredData,
data: violationData?.content || [],
columns,
state: {
sorting,
columnFilters,
pagination
pagination,
},
pageCount: violationData?.totalPages || -1,
autoResetPageIndex: false,
manualPagination: true, // Пагинация с бека
manualSorting: false, // сортировка локально так как эндпоинт не поддерживает сортировку.
manualFiltering: true, // Фильтрация с бека
onPaginationChange: setPagination,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getFilteredRowModel: getFilteredRowModel(),
initialState: {
pagination: {
pageSize: 10,
},
},
});
const handleFileNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setFileNameFilter(e.target.value);
setPagination(prev => ({ ...prev, pageIndex: 0 }));
};
const handleDateFilterChange = (value: string) => {
setDateFilter(value);
setPagination(prev => ({ ...prev, pageIndex: 0 }));
};
if (isError) {
return <div className="block-wrapper">Error: {error?.message || t('error')}</div>;
}
return (
<div
className="block-wrapper"
>
<div className="block-wrapper">
<div className="tab-content">
<div
className="tanstak-table-wrapper"
>
<h3
className="tanstak-table-title"
>
<div className="tanstak-table-wrapper">
<h3 className="tanstak-table-title">
{t('matches-detected')}
</h3>
{/* Фильтры */}
{/* <div className="tanstak-table-filtres">
<div className="tanstak-table-filtres">
<div className="table-filtres-wrapper">
{/* Фильтр по дате */}
<div className="table-filtres-item">
<div className="table-filtres-label">{t('date-filter')}:</div>
<DropDownList
@@ -322,48 +336,50 @@ export default function ViolationsTable() {
translatedValue={(() => {
switch (dateFilter) {
case 'all':
return t('all-dates')
return t('all-dates');
case 'week':
return t('for-a-week')
return t('for-a-week');
case 'month':
return t('for-a-month')
return t('for-a-month');
case 'older':
return t('older-than-a-month')
return t('older-than-a-month');
default:
return t('today')
return t('today');
}
})()}
callBack={setDateFilter}
callBack={handleDateFilterChange}
>
<li value="all">
{t('all-dates')}
</li>
<li value="today">
{t('today')}
</li>
<li value="week">
{t('for-a-week')}
</li>
<li value="month">
{t('for-a-month')}
</li>
<li value="older">
{t('older-than-a-month')}
</li>
<li value="all">{t('all-dates')}</li>
<li value="today">{t('today')}</li>
<li value="week">{t('for-a-week')}</li>
<li value="month">{t('for-a-month')}</li>
<li value="older">{t('older-than-a-month')}</li>
</DropDownList>
</div>
{/* Фильтр по имени файла */}
<div className="table-filtres-item">
<div className="table-filtres-label">{t('file-name')}:</div>
<input
type="text"
value={fileNameFilter}
onChange={handleFileNameChange}
placeholder={t('search')}
className="table-filtres-text-filter"
/>
</div>
</div>
<div
className="table-filtres-wrapper"
>
<div className="table-filtres-wrapper">
<div className="table-filtres-item">
<div className="table-filtres-label">{t('items-per-page')}:</div>
<DropDownList
value={table.getState().pagination.pageSize}
//@ts-ignore сделал так потому что для table.setPageSize нужна цифра
callBack={table.setPageSize}
//@ts-ignore
callBack={(value: number) => {
table.setPageSize(value);
setPagination(prev => ({ ...prev, pageSize: value, pageIndex: 0 }));
}}
>
{[5, 10, 20, 50, 100].map(pageSize => (
<li key={pageSize} value={pageSize}>
@@ -373,8 +389,7 @@ export default function ViolationsTable() {
</DropDownList>
</div>
</div>
</div> */}
</div>
{/* Таблица */}
<div className="tanstak-table-block">
@@ -383,20 +398,32 @@ export default function ViolationsTable() {
{table.getHeaderGroups().map(headerGroup => (
<tr key={headerGroup.id}>
{headerGroup.headers.map(header => (
<th
key={header.id}
>
<th key={header.id}>
{header.isPlaceholder
? null
: typeof header.column.columnDef.header === 'function'
? header.column.columnDef.header(header.getContext())
: header.column.columnDef.header as string}
: (header.column.columnDef.header as string)}
</th>
))}
</tr>
))}
</thead>
<tbody className="tanstak-table-body">
<tbody className={`tanstak-table-body ${isFetching ? 'loading' : ''}`}>
{isLoading && (
<tr>
<td colSpan={columns.length} className="text-center relative h-12.5">
<div
className="loading-animation"
>
<div
className="global-spinner"
>
</div>
</div>
</td>
</tr>
)}
{table.getRowModel().rows.length > 0 ? (
table.getRowModel().rows.map(row => (
<tr key={row.id}>
@@ -404,16 +431,18 @@ export default function ViolationsTable() {
<td key={cell.id}>
{typeof cell.column.columnDef.cell === 'function'
? cell.column.columnDef.cell(cell.getContext())
: cell.getValue() as string}
: (cell.getValue() as string)}
</td>
))}
</tr>
))
) : (
<tr>
{!isLoading && (
<td colSpan={columns.length} className="text-center">
{t('no-data-for-selected-filters')}
</td>
)}
</tr>
)}
</tbody>
@@ -426,16 +455,15 @@ export default function ViolationsTable() {
<span className="pagination-info-pages">
{t('page')}{' '}
<strong>
{table.getState().pagination.pageIndex + 1} {t('out-of')} {table.getPageCount() ? table.getPageCount() : 1}
{table.getState().pagination.pageIndex + 1} {t('out-of')} {violationData?.totalPages || 1}
</strong>
</span>
<span className="pagination-info-files">
| {t('shown')} {table.getRowModel().rows.length} {t('out-of')} {filteredData.length}
| {t('shown')} {violationData?.content?.length || 0} {t('out-of')} {violationData?.totalElements || 0}
</span>
</div>
<div className="pagination-controls">
{table.getCanPreviousPage() && (
<button
className="arrow"
onClick={() => table.firstPage()}
@@ -443,8 +471,6 @@ export default function ViolationsTable() {
>
<IconDoubleArrowLeft />
</button>
)}
{table.getCanPreviousPage() && (
<button
className="arrow"
onClick={() => table.previousPage()}
@@ -452,26 +478,28 @@ export default function ViolationsTable() {
>
<IconArrowLeft />
</button>
)}
<div className="pagination-controls-pages">
{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;
{Array.from({ length: Math.min(5, violationData?.totalPages || 0) }, (_, i) => {
const totalPages = violationData?.totalPages || 0;
const currentPage = table.getState().pagination.pageIndex;
let pageIndex = 0;
if (pageIndex < table.getPageCount()) {
if (totalPages <= 5) {
pageIndex = i;
} else if (currentPage <= 2) {
pageIndex = i;
} else if (currentPage >= totalPages - 3) {
pageIndex = totalPages - 5 + i;
} else {
pageIndex = currentPage - 2 + i;
}
if (pageIndex < totalPages) {
return (
<button
key={pageIndex}
className={`${table.getState().pagination.pageIndex === pageIndex
? 'current'
: 'other'
}`}
className={table.getState().pagination.pageIndex === pageIndex ? 'current' : 'other'}
onClick={() => table.setPageIndex(pageIndex)}
>
{pageIndex + 1}
@@ -482,7 +510,6 @@ export default function ViolationsTable() {
})}
</div>
{table.getCanNextPage() && (
<button
className="arrow"
onClick={() => table.nextPage()}
@@ -490,8 +517,6 @@ export default function ViolationsTable() {
>
<IconArrowRight />
</button>
)}
{table.getCanNextPage() && (
<button
className="arrow"
onClick={() => table.lastPage()}
@@ -499,11 +524,10 @@ export default function ViolationsTable() {
>
<IconDoubleArrowRight />
</button>
)}
</div>
</div>
</div>
</div>
</div>
)
);
}