Flutter-Ernaehrungsapp/lib/android/pages/nav_pages/progress_page.dart

340 lines
14 KiB
Dart
Raw Normal View History

2023-05-29 12:08:46 +02:00
import 'package:ernaehrung/android/components/meal_page_text/secondary_big_text_component.dart';
import 'package:ernaehrung/android/components/meal_page_text/secondary_text_component.dart';
import 'package:ernaehrung/android/components/meal_page_text/title_component.dart';
import 'package:ernaehrung/android/config/statistics.dart';
2023-05-29 12:08:46 +02:00
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import '../../config/format_helper.dart';
2023-05-29 12:08:46 +02:00
class ProgressPage extends StatelessWidget {
final String title;
final Color backgroundColor = const Color(0xff47a44b);
const ProgressPage({Key? key, required this.title}) : super(key: key);
String get getTitle => title;
@override
String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) {
return getTitle;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
2023-06-02 01:42:56 +02:00
child: Column(
children: [
Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(8))),
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: Column(
children: [
ValueListenableBuilder(
valueListenable: StatisticsService
.instance.dailyAverageForCurrentWeek,
builder: (context, value, child) {
return SizedBox(
height: 100,
width: 400,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const TitleComponent("Kalorien"),
const SizedBox(
height: 10,
),
const SecondaryTextComponent(
"Durchschnittlich"),
SecondaryBigTextComponent(
"${value.toString()} kcal/Tag"),
],
),
);
},
),
ValueListenableBuilder(
valueListenable:
StatisticsService.instance.barChartData,
builder: (context, value, child) {
return SizedBox(
height: 300,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 15,
// Adjust the height of the legend as needed
2023-06-01 13:19:55 +02:00
child: Row(
2023-06-02 01:42:56 +02:00
mainAxisAlignment: MainAxisAlignment.center,
2023-06-01 13:19:55 +02:00
children: [
Container(
2023-06-02 01:42:56 +02:00
margin: const EdgeInsets.symmetric(
horizontal: 8.0),
// Adjust the spacing between legend items
child: Row(
children: [
Container(
width: 12,
height: 12,
decoration: const BoxDecoration(
color: Colors.red,
// Use the color of the first bar rod for the legend item
shape: BoxShape.circle,
),
),
const SizedBox(width: 4.0),
// Adjust the spacing between the color indicator and the legend label
const Text(
'Frühstück',
// Replace with your desired legend label
style: TextStyle(
fontSize:
12), // Adjust the font size of the legend labels
),
],
),
),
Container(
margin: const EdgeInsets.symmetric(
horizontal: 8.0),
// Adjust the spacing between legend items
child: Row(
children: [
Container(
width: 12,
height: 12,
decoration: const BoxDecoration(
color: Colors.green,
// Use the color of the first bar rod for the legend item
shape: BoxShape.circle,
),
),
const SizedBox(width: 4.0),
// Adjust the spacing between the color indicator and the legend label
const Text(
'Mittagessen',
// Replace with your desired legend label
style: TextStyle(
fontSize:
12), // Adjust the font size of the legend labels
),
],
2023-06-01 13:19:55 +02:00
),
),
2023-06-02 01:42:56 +02:00
Container(
margin: const EdgeInsets.symmetric(
horizontal: 8.0),
// Adjust the spacing between legend items
child: Row(
children: [
Container(
width: 12,
height: 12,
decoration: const BoxDecoration(
color: Colors.yellow,
// Use the color of the first bar rod for the legend item
shape: BoxShape.circle,
),
),
const SizedBox(width: 4.0),
// Adjust the spacing between the color indicator and the legend label
const Text(
'Abendessen',
// Replace with your desired legend label
style: TextStyle(
fontSize:
12), // Adjust the font size of the legend labels
),
],
),
2023-06-01 13:19:55 +02:00
),
],
),
),
2023-06-02 01:42:56 +02:00
Container(
margin:
const EdgeInsets.fromLTRB(0, 24, 0, 0),
height: 250,
child: BarChart(
BarChartData(
barTouchData: barTouchData,
titlesData: titlesData,
borderData: borderData,
barGroups: value,
gridData: FlGridData(show: false),
alignment: BarChartAlignment.spaceAround,
2023-06-01 13:19:55 +02:00
),
2023-06-02 01:42:56 +02:00
),
2023-06-01 13:19:55 +02:00
),
2023-06-02 01:42:56 +02:00
],
),
2023-06-02 01:42:56 +02:00
);
},
),
],
2023-06-02 01:42:56 +02:00
),
)),
Container(
margin: const EdgeInsets.fromLTRB(0, 16, 0, 0),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(8))),
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: ValueListenableBuilder(
valueListenable:
StatisticsService.instance.weeklyCaloryRanking,
builder: (context, value, child) {
return Column(
children: [
const TitleComponent(
"Lebensmittel mit dem höchsten Kaloriengehalt"),
const SizedBox(
height: 24,
),
for (var item in value.toSet())
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SecondaryTextComponent(
getWeeklyRankingString(item.name)),
SecondaryTextComponent(
item.calories.toString()),
],
),
],
);
},
),
))
],
2023-05-29 12:08:46 +02:00
),
),
);
}
BarTouchData get barTouchData => BarTouchData(
enabled: false,
touchTooltipData: BarTouchTooltipData(
tooltipBgColor: Colors.transparent,
tooltipPadding: EdgeInsets.zero,
tooltipMargin: 4,
getTooltipItem: (
BarChartGroupData group,
int groupIndex,
BarChartRodData rod,
int rodIndex,
) {
return BarTooltipItem(
rod.toY.round().toString(),
const TextStyle(
2023-06-01 13:19:55 +02:00
color: Colors.transparent,
2023-05-29 12:08:46 +02:00
fontWeight: FontWeight.bold,
),
);
},
),
);
Widget getTitles(double value, TitleMeta meta) {
const style = TextStyle(
2023-06-01 13:19:55 +02:00
color: Colors.orange,
2023-05-29 12:08:46 +02:00
fontWeight: FontWeight.bold,
fontSize: 14,
);
String text;
switch (value.toInt()) {
case 0:
2023-06-01 12:14:23 +02:00
text = 'M';
2023-05-29 12:08:46 +02:00
break;
case 1:
2023-06-01 12:14:23 +02:00
text = 'T';
2023-05-29 12:08:46 +02:00
break;
case 2:
2023-06-01 12:14:23 +02:00
text = 'W';
2023-05-29 12:08:46 +02:00
break;
case 3:
2023-06-01 12:14:23 +02:00
text = 'T';
2023-05-29 12:08:46 +02:00
break;
case 4:
2023-06-01 12:14:23 +02:00
text = 'F';
2023-05-29 12:08:46 +02:00
break;
case 5:
2023-06-01 12:14:23 +02:00
text = 'S';
2023-05-29 12:08:46 +02:00
break;
case 6:
2023-06-01 12:14:23 +02:00
text = 'S';
2023-05-29 12:08:46 +02:00
break;
default:
text = '';
break;
}
return SideTitleWidget(
axisSide: meta.axisSide,
space: 4,
child: Text(text, style: style),
);
}
FlTitlesData get titlesData => FlTitlesData(
2023-06-02 01:42:56 +02:00
show: true,
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 30,
getTitlesWidget: getTitles,
2023-05-29 12:08:46 +02:00
),
2023-06-02 01:42:56 +02:00
),
topTitles: AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
rightTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
2023-05-29 12:08:46 +02:00
),
2023-06-02 01:42:56 +02:00
),
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, _) {
// Return a custom widget for each axis value
return Container(
constraints:
const BoxConstraints.tightFor(width: double.infinity),
child: Padding(
padding: const EdgeInsets.only(right: 3.0),
// Adjust the margin value as needed
child: FittedBox(
fit: BoxFit.scaleDown,
alignment: Alignment.centerLeft,
child: Text(
value.toInt().toString(),
style: const TextStyle(
color: Colors.orange,
fontWeight: FontWeight.bold,
2023-06-01 13:19:55 +02:00
),
),
),
2023-06-02 01:42:56 +02:00
),
);
},
),
));
2023-05-29 12:08:46 +02:00
FlBorderData get borderData => FlBorderData(
2023-06-02 01:42:56 +02:00
show: true, // Set to true to display the chart border
border: const Border(
bottom: BorderSide(color: Colors.black, width: 1),
left:
BorderSide(color: Colors.black, width: 1), // Hide the left border
),
);
2023-05-29 12:08:46 +02:00
}