forked from eatvio/eatvio_app
feat(insights): first isights impemetation
This commit is contained in:
84
lib/features/insights/presentation/charts/bmi_chart.dart
Normal file
84
lib/features/insights/presentation/charts/bmi_chart.dart
Normal file
@@ -0,0 +1,84 @@
|
||||
import 'package:eatvio_app/features/insights/models/insights_payload_model.dart';
|
||||
import 'package:eatvio_app/features/insights/presentation/charts/insights_chart_common.dart';
|
||||
import 'package:eatvio_app/features/insights/presentation/widgets/insights_colors.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||
|
||||
/// График ИМТ с цветными зонами: норма 18.5–25, избыточная масса 25–30, ожирение 30–40.
|
||||
class BmiChart extends StatelessWidget {
|
||||
const BmiChart({super.key, required this.model});
|
||||
|
||||
final BmiChartModel model;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final points = buildPoints(model.labels, model.values);
|
||||
if (points.isEmpty) {
|
||||
return InsightsChartPlaceholder(text: model.deltaText);
|
||||
}
|
||||
final s = S.of(context);
|
||||
final range = paddedRange(points.map((e) => e.value), minPadding: 2);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: insightsChartHeight,
|
||||
child: SfCartesianChart(
|
||||
key: const Key('insights_bmi_chart'),
|
||||
margin: EdgeInsets.zero,
|
||||
plotAreaBorderWidth: 0,
|
||||
primaryXAxis: buildInsightsCategoryAxis(),
|
||||
primaryYAxis: buildInsightsValueAxis(
|
||||
unit: s.insights_unit_bmi,
|
||||
min: range.min,
|
||||
max: range.max,
|
||||
plotBands: const [
|
||||
PlotBand(
|
||||
start: 18.5,
|
||||
end: 25,
|
||||
color: InsightsColors.bmiNormalZone,
|
||||
),
|
||||
PlotBand(
|
||||
start: 25,
|
||||
end: 30,
|
||||
color: InsightsColors.bmiOverweightZone,
|
||||
),
|
||||
PlotBand(
|
||||
start: 30,
|
||||
end: 40,
|
||||
color: InsightsColors.bmiObesityZone,
|
||||
),
|
||||
],
|
||||
),
|
||||
trackballBehavior: buildInsightsTrackball(),
|
||||
series: <CartesianSeries<InsightsPoint, String>>[
|
||||
SplineAreaSeries<InsightsPoint, String>(
|
||||
name: s.insights_tab_bmi,
|
||||
dataSource: points,
|
||||
xValueMapper: (point, _) => point.label,
|
||||
yValueMapper: (point, _) => point.value,
|
||||
borderColor: InsightsColors.blue,
|
||||
borderWidth: 3,
|
||||
gradient: buildInsightsAreaGradient(InsightsColors.blue),
|
||||
markerSettings: buildInsightsMarker(InsightsColors.blue),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (model.hint.isNotEmpty) ...[
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
model.hint,
|
||||
key: const Key('insights_bmi_hint'),
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
color: InsightsColors.subtitle,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user