feat(app): страница здоровья вместо разрозненных /sync и data quality
/sync и блок data quality на дашборде сведены в один /health с двумя вкладками (Источники, Качество данных); дашборд ссылается на неё вместо собственного bottom sheet. Список находок вынесен в общий виджет DataQualityList, чтобы не дублировать рендер.
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import 'package:fintracker_api/fintracker_api.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
|
||||
/// Maps a `/metrics/data-quality` row's severity string to a color. Shared by
|
||||
/// the Здоровье page's findings list and the dashboard's summary chip so the
|
||||
/// two surfaces never disagree on what a severity looks like.
|
||||
Color severityColor(String severity) {
|
||||
final s = severity.toLowerCase();
|
||||
if (s.contains('crit') || s.contains('err')) return const Color(0xFFD03B3B);
|
||||
if (s.contains('warn')) return const Color(0xFFFAB219);
|
||||
if (s.contains('info') || s.contains('low')) return const Color(0xFF0CA30C);
|
||||
return const Color(0xFFEC835A);
|
||||
}
|
||||
|
||||
/// Renders `DataQualityRow`s as a colored-dot list: one implementation used
|
||||
/// by both the Здоровье page and (if reused) the dashboard's quick peek.
|
||||
class DataQualityList extends StatelessWidget {
|
||||
const DataQualityList({required this.rows, super.key});
|
||||
|
||||
final List<DataQualityRow> rows;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (rows.isEmpty) {
|
||||
return const EmptyState(
|
||||
icon: Icons.check_circle_outline,
|
||||
message: 'Проблем не найдено.',
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
children: [for (final row in rows) _DataQualityTile(row: row)],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DataQualityTile extends StatelessWidget {
|
||||
const _DataQualityTile({required this.row});
|
||||
|
||||
final DataQualityRow row;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 4, right: 10),
|
||||
width: 10,
|
||||
height: 10,
|
||||
decoration: BoxDecoration(color: severityColor(row.severity), shape: BoxShape.circle),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('${row.checkName} (${row.count})',
|
||||
style: Theme.of(context).textTheme.titleSmall),
|
||||
const SizedBox(height: 2),
|
||||
Text(row.detail),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user