feat: type stats and event log models
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
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';
|
||||
|
||||
@@ -30,7 +31,6 @@ class _StatsScreenState extends ConsumerState<StatsScreen> {
|
||||
Widget build(BuildContext context) {
|
||||
final statsState = ref.watch(statsProvider);
|
||||
final stats = statsState.data;
|
||||
final groups = (stats['groups'] as List<dynamic>?) ?? [];
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('СТАТИСТИКА')),
|
||||
@@ -62,15 +62,15 @@ class _StatsScreenState extends ConsumerState<StatsScreen> {
|
||||
),
|
||||
|
||||
// ─── Содержимое ───
|
||||
Expanded(child: _buildContent(statsState, groups)),
|
||||
Expanded(child: _buildContent(statsState, stats.groups)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildContent(
|
||||
LoadState<Map<String, dynamic>> statsState,
|
||||
List<dynamic> groups,
|
||||
LoadState<StatsSummary> statsState,
|
||||
List<GroupStats> groups,
|
||||
) {
|
||||
if ((statsState.isIdle || statsState.isLoading) && groups.isEmpty) {
|
||||
return const Center(
|
||||
@@ -120,8 +120,7 @@ class _StatsScreenState extends ConsumerState<StatsScreen> {
|
||||
}
|
||||
|
||||
final groupIndex = index - statusHeaderCount;
|
||||
final g = groups[groupIndex];
|
||||
return _StatsCard(data: g is Map ? Map<String, dynamic>.from(g) : {});
|
||||
return _StatsCard(data: groups[groupIndex]);
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -130,20 +129,12 @@ class _StatsScreenState extends ConsumerState<StatsScreen> {
|
||||
|
||||
/// Карточка статистики одной группы
|
||||
class _StatsCard extends StatelessWidget {
|
||||
final Map<String, dynamic> data;
|
||||
final GroupStats data;
|
||||
|
||||
const _StatsCard({required this.data});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final targetId = (data['target_id'] ?? data['group_id'] ?? data['id'] ?? '')
|
||||
.toString();
|
||||
final name = (data['name'] ?? targetId).toString();
|
||||
final totalCommands = data['total_commands'] ?? 0;
|
||||
final togglesOn = data['toggles_on'] ?? 0;
|
||||
final togglesOff = data['toggles_off'] ?? 0;
|
||||
final estimatedHours = data['estimated_hours'];
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
child: Padding(
|
||||
@@ -152,35 +143,35 @@ class _StatsCard extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
name,
|
||||
data.name,
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_StatRow(
|
||||
icon: Icons.touch_app,
|
||||
label: 'Всего команд',
|
||||
value: totalCommands.toString(),
|
||||
value: data.totalCommands.toString(),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
_StatRow(
|
||||
icon: Icons.power_settings_new,
|
||||
label: 'Включений',
|
||||
value: togglesOn.toString(),
|
||||
value: data.togglesOn.toString(),
|
||||
color: Colors.green,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
_StatRow(
|
||||
icon: Icons.power_off,
|
||||
label: 'Выключений',
|
||||
value: togglesOff.toString(),
|
||||
value: data.togglesOff.toString(),
|
||||
color: Colors.redAccent,
|
||||
),
|
||||
if (estimatedHours != null) ...[
|
||||
if (data.estimatedHours != null) ...[
|
||||
const SizedBox(height: 4),
|
||||
_StatRow(
|
||||
icon: Icons.access_time,
|
||||
label: 'Примерное время работы',
|
||||
value: _formatHours(estimatedHours),
|
||||
value: data.formattedEstimatedHours,
|
||||
color: Colors.amber,
|
||||
),
|
||||
],
|
||||
@@ -189,12 +180,6 @@ class _StatsCard extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _formatHours(dynamic hours) {
|
||||
final h = (hours is num) ? hours.toDouble() : 0.0;
|
||||
if (h < 1) return '${(h * 60).round()} мин';
|
||||
return '${h.toStringAsFixed(1)} ч';
|
||||
}
|
||||
}
|
||||
|
||||
/// Строка с иконкой, меткой и значением
|
||||
|
||||
Reference in New Issue
Block a user