import 'package:flutter/material.dart'; import 'package:xp_models/xp_models.dart'; import '../theme/app_theme.dart'; class LogsCard extends StatefulWidget { final SystemLogResponse? logs; final Future Function({int count, LogLevel? level}) onRefresh; const LogsCard({ super.key, required this.logs, required this.onRefresh, }); @override State createState() => _LogsCardState(); } class _LogsCardState extends State { LogLevel? _selectedLevel; bool _isRefreshing = false; Future _refreshLogs() async { setState(() { _isRefreshing = true; }); try { await widget.onRefresh(count: 50, level: _selectedLevel); } finally { if (mounted) { setState(() { _isRefreshing = false; }); } } } @override Widget build(BuildContext context) { return Card( child: Padding( padding: const EdgeInsets.all(20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(Icons.article, color: AppTheme.primaryColor), const SizedBox(width: 8), Expanded( child: Text( 'System Logs', style: Theme.of(context).textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, ), ), ), DropdownButton( value: _selectedLevel, hint: const Text('All'), items: [ const DropdownMenuItem( value: null, child: Text('All'), ), ...LogLevel.values.map((level) => DropdownMenuItem( value: level, child: Text(level.name.toUpperCase()), )), ], onChanged: (LogLevel? newLevel) { setState(() { _selectedLevel = newLevel; }); _refreshLogs(); }, ), const SizedBox(width: 8), IconButton( icon: _isRefreshing ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.refresh), onPressed: _isRefreshing ? null : _refreshLogs, tooltip: 'Refresh Logs', ), ], ), const SizedBox(height: 16), Container( height: 300, decoration: BoxDecoration( color: Colors.grey.shade50, borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.grey.shade300), ), child: widget.logs == null ? const Center(child: CircularProgressIndicator()) : widget.logs!.logs.isEmpty ? const Center(child: Text('No logs available')) : ListView.builder( padding: const EdgeInsets.all(8), itemCount: widget.logs!.logs.length, itemBuilder: (context, index) { final log = widget.logs!.logs[index]; return _LogEntry(log: log); }, ), ), ], ), ), ); } } class _LogEntry extends StatelessWidget { final String log; const _LogEntry({required this.log}); @override Widget build(BuildContext context) { final color = _getLogColor(log); return Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: Text( log, style: TextStyle( fontFamily: 'monospace', fontSize: 12, color: color, ), ), ); } Color _getLogColor(String logEntry) { if (logEntry.contains('[ERROR]')) return AppTheme.errorColor; if (logEntry.contains('[WARN]')) return AppTheme.warningColor; if (logEntry.contains('[INFO]')) return AppTheme.infoColor; if (logEntry.contains('[DEBUG]')) return Colors.grey; return Colors.black87; } }