import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../app/load_state.dart'; import '../models/stats_summary.dart'; import '../providers/providers.dart'; import '../widgets/load_error_view.dart'; /// Экран просмотра статистики. /// Показывает сводку по группам за выбранный период. class StatsScreen extends ConsumerStatefulWidget { const StatsScreen({super.key}); @override ConsumerState createState() => _StatsScreenState(); } class _StatsScreenState extends ConsumerState { int _days = 7; @override void initState() { super.initState(); _load(); } Future _load() async { await ref.read(statsProvider.notifier).load(days: _days); } @override Widget build(BuildContext context) { final statsState = ref.watch(statsProvider); final stats = statsState.data; return Scaffold( appBar: AppBar(title: const Text('СТАТИСТИКА')), body: Column( children: [ // ─── Переключатель периода ─── Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( children: [ const Text('Период:', style: TextStyle(color: Colors.white54)), const SizedBox(width: 12), ...[1, 7, 14, 30].map( (d) => Padding( padding: const EdgeInsets.only(right: 8), child: ChoiceChip( label: Text('$d д.'), selected: _days == d, selectedColor: Colors.deepOrange, onSelected: (_) { setState(() => _days = d); _load(); }, ), ), ), ], ), ), // ─── Содержимое ─── Expanded(child: _buildContent(statsState, stats.groups)), ], ), ); } Widget _buildContent( LoadState statsState, List groups, ) { if ((statsState.isIdle || statsState.isLoading) && groups.isEmpty) { return const Center( child: CircularProgressIndicator(color: Colors.deepOrange), ); } if (statsState.hasError && groups.isEmpty) { return LoadErrorView( title: 'Не удалось загрузить статистику', message: statsState.errorMessage, icon: Icons.bar_chart, onRetry: _load, ); } if (groups.isEmpty) { return const Center( child: Text('Нет данных', style: TextStyle(color: Colors.white54)), ); } final hasStatusHeader = statsState.isLoading || statsState.hasError; final statusHeaderCount = hasStatusHeader ? 1 : 0; return RefreshIndicator( color: Colors.deepOrange, onRefresh: _load, child: ListView.builder( physics: const AlwaysScrollableScrollPhysics(), padding: const EdgeInsets.all(12), itemCount: groups.length + statusHeaderCount, itemBuilder: (context, index) { if (hasStatusHeader && index == 0) { if (statsState.isLoading) { return const Padding( padding: EdgeInsets.only(bottom: 12), child: LinearProgressIndicator(color: Colors.deepOrange), ); } return LoadErrorBanner( title: 'Не удалось обновить статистику', message: statsState.errorMessage, onRetry: _load, ); } final groupIndex = index - statusHeaderCount; return _StatsCard(data: groups[groupIndex]); }, ), ); } } /// Карточка статистики одной группы class _StatsCard extends StatelessWidget { final GroupStats data; const _StatsCard({required this.data}); @override Widget build(BuildContext context) { return Card( margin: const EdgeInsets.only(bottom: 8), child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( data.name, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), const SizedBox(height: 12), _StatRow( icon: Icons.touch_app, label: 'Всего команд', value: data.totalCommands.toString(), ), const SizedBox(height: 4), _StatRow( icon: Icons.power_settings_new, label: 'Включений', value: data.togglesOn.toString(), color: Colors.green, ), const SizedBox(height: 4), _StatRow( icon: Icons.power_off, label: 'Выключений', value: data.togglesOff.toString(), color: Colors.redAccent, ), if (data.estimatedHours != null) ...[ const SizedBox(height: 4), _StatRow( icon: Icons.access_time, label: 'Примерное время работы', value: data.formattedEstimatedHours, color: Colors.amber, ), ], ], ), ), ); } } /// Строка с иконкой, меткой и значением class _StatRow extends StatelessWidget { final IconData icon; final String label; final String value; final Color? color; const _StatRow({ required this.icon, required this.label, required this.value, this.color, }); @override Widget build(BuildContext context) { return Row( children: [ Icon(icon, size: 16, color: color ?? Colors.white38), const SizedBox(width: 8), Expanded( child: Text( label, style: const TextStyle(fontSize: 13, color: Colors.white54), ), ), Text( value, style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: color ?? Colors.white70, ), ), ], ); } }