import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/providers.dart'; /// Экран просмотра лога событий. class EventLogScreen extends ConsumerStatefulWidget { const EventLogScreen({super.key}); @override ConsumerState createState() => _EventLogScreenState(); } class _EventLogScreenState extends ConsumerState { bool _loading = true; int _limit = 100; @override void initState() { super.initState(); _load(); } Future _load() async { setState(() => _loading = true); await ref.read(eventLogProvider.notifier).load(limit: _limit); if (mounted) setState(() => _loading = false); } @override Widget build(BuildContext context) { final events = ref.watch(eventLogProvider); return Scaffold( appBar: AppBar( title: const Text('ЛОГ СОБЫТИЙ'), actions: [ PopupMenuButton( icon: const Icon(Icons.filter_list), tooltip: 'Количество записей', onSelected: (v) { _limit = v; _load(); }, itemBuilder: (_) => [50, 100, 200, 500] .map((n) => PopupMenuItem(value: n, child: Text('$n записей'))) .toList(), ), ], ), body: _loading ? const Center( child: CircularProgressIndicator(color: Colors.deepOrange), ) : events.isEmpty ? const Center( child: Text( 'Нет событий', style: TextStyle(color: Colors.white54), ), ) : RefreshIndicator( color: Colors.deepOrange, onRefresh: _load, child: ListView.builder( padding: const EdgeInsets.all(8), itemCount: events.length, itemBuilder: (context, index) { final event = events[index]; return _EventRow( event: event is Map ? Map.from(event) : {}, ); }, ), ), ); } } class _EventRow extends StatelessWidget { final Map event; const _EventRow({required this.event}); @override Widget build(BuildContext context) { final timestamp = event['timestamp'] ?? event['time'] ?? event['created_at'] ?? ''; final action = event['action'] ?? event['command'] ?? event['type'] ?? ''; final targetId = event['target_id'] ?? event['target'] ?? event['group_id'] ?? ''; final params = event['params'] ?? event['details'] ?? ''; final actor = event['actor'] ?? event['user'] ?? event['key_name'] ?? ''; final formattedTime = _formatTime(timestamp.toString()); return Card( margin: const EdgeInsets.only(bottom: 4), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Время SizedBox( width: 80, child: Text( formattedTime, style: const TextStyle( fontSize: 11, color: Colors.white38, fontFamily: 'monospace', ), ), ), const SizedBox(width: 8), // Контент Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '$action - $targetId', style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500, ), ), if (params.toString().isNotEmpty) Text( params.toString(), style: const TextStyle( fontSize: 11, color: Colors.white38, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), if (actor.toString().isNotEmpty) Text( actor.toString(), style: const TextStyle( fontSize: 10, color: Colors.white24, ), ), ], ), ), ], ), ), ); } String _formatTime(String iso) { if (iso.isEmpty) return ''; try { final d = DateTime.parse(iso); String pad(int n) => n.toString().padLeft(2, '0'); return '${pad(d.day)}.${pad(d.month)} ${pad(d.hour)}:${pad(d.minute)}:${pad(d.second)}'; } catch (_) { return iso; } } }