'use client'; import { useState, useEffect, useMemo } from 'react'; import { PageLayout, StatusBadge } from '@/components/ui'; import ActivityTimeline from '@/components/ActivityTimeline'; interface AuditEntry { id: string; action: string; entity_type: string; user_name?: string; description?: string; created_at: string; } interface Stats { total: number; byAction: Record; byEntity: Record; byDay: Record; } export default function AnalyticsPage() { const [entries, setEntries] = useState([]); const [loading, setLoading] = useState(true); const [days, setDays] = useState(7); useEffect(() => { setLoading(true); fetch(`/api/v1/audit-log?page=1&per_page=500`) .then(r => r.json()).then(d => setEntries(d.items || [])) .catch(() => {}).finally(() => setLoading(false)); }, []); const stats = useMemo(() => { const cutoff = new Date(); cutoff.setDate(cutoff.getDate() - days); const filtered = entries.filter(e => new Date(e.created_at) >= cutoff); const byAction: Record = {}; const byEntity: Record = {}; const byDay: Record = {}; for (const e of filtered) { byAction[e.action] = (byAction[e.action] || 0) + 1; byEntity[e.entity_type] = (byEntity[e.entity_type] || 0) + 1; const day = new Date(e.created_at).toLocaleDateString('ru-RU'); byDay[day] = (byDay[day] || 0) + 1; } return { total: filtered.length, byAction, byEntity, byDay }; }, [entries, days]); const topActions = Object.entries(stats.byAction).sort((a, b) => b[1] - a[1]).slice(0, 8); const topEntities = Object.entries(stats.byEntity).sort((a, b) => b[1] - a[1]).slice(0, 8); const maxAction = Math.max(...topActions.map(([, v]) => v), 1); return ( {[7, 30, 90].map(d => ( ))} }> {loading ?
Загрузка...
: (
{/* Summary cards */}
{stats.total}
Всего действий
{stats.byAction['create'] || 0}
Создано
{stats.byAction['update'] || 0}
Обновлено
{stats.byAction['delete'] || 0}
Удалено
{/* Top actions bar chart */}

По типу действия

{topActions.map(([action, count]) => (
{action}
{count}
))}
{/* Top entities */}

По объектам

{topEntities.map(([entity, count]) => (
{entity} {count}
))}
{/* Recent activity */}

Последняя активность

)} ); }