import 'dart:async'; import 'dart:collection'; import 'package:aitrainer_app/model/cache.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/dialog_premium.dart'; import 'package:aitrainer_app/widgets/treeview_parent_widget.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/bloc/development_by_muscle/development_by_muscle_bloc.dart'; import 'package:aitrainer_app/model/workout_menu_tree.dart'; import 'package:aitrainer_app/library/tree_view.dart'; import 'package:aitrainer_app/widgets/bottom_nav.dart'; import 'package:flurry/flurry.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_form_bloc/flutter_form_bloc.dart'; class MyDevelopmentMusclePage extends StatefulWidget { @override _MyDevelopmentMuscleState createState() => _MyDevelopmentMuscleState(); } class _MyDevelopmentMuscleState extends State with Common, Trans { // ignore: close_sinks DevelopmentByMuscleBloc bloc; double cWidth; @override void initState() { super.initState(); Flurry.logEvent("myDevelopmentMuscle"); if (!Cache().hasPurchased) { Timer( Duration(milliseconds: 2000), () => { showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return DialogPremium( unlocked: false, unlockRound: 1, function: "Development Of Muscles", unlockedText: "", onTap: () => {Navigator.of(context).pop(), Navigator.of(context).pop()}, onCancel: () => {Navigator.of(context).pop(), Navigator.of(context).pop()}, ); }) }); } /// We require the initializers to run after the loading screen is rendered SchedulerBinding.instance.addPostFrameCallback((_) { BlocProvider.of(context).add(DevelopmentByMuscleLoad()); }); } @override Widget build(BuildContext context) { bloc = BlocProvider.of(context); cWidth = mediaSizeWidth(context); setContext(context); return Scaffold( appBar: AppBarNav(depth: 1), body: Container( padding: EdgeInsets.all(20), decoration: BoxDecoration( image: DecorationImage( image: AssetImage('asset/image/WT_menu_dark.png'), fit: BoxFit.cover, alignment: Alignment.center, ), ), child: BlocConsumer( listener: (context, state) { if (state is DevelopmentByMuscleErrorState) { Scaffold.of(context).showSnackBar(SnackBar( content: Text( state.message, ), backgroundColor: Colors.orange, )); } else if (state is DevelopmentByMuscleLoadingState) { //LoadingDialog.show(context); } }, builder: (context, state) { if (state is DevelopmentByMuscleStateInitial) { return Container(); } else { //LoadingDialog.hide(context); return TreeView( startExpanded: false, children: _getTreeChildren(bloc.workoutTreeRepository.sortedTree, bloc), ); } }, ), ), bottomNavigationBar: BottomNavigator(bottomNavIndex: 1), ); } List _getTreeChildren(SplayTreeMap tree, DevelopmentByMuscleBloc bloc) { List exerciseTypes = List(); Card explanation = Card( color: Colors.white60, child: Container( padding: EdgeInsets.only(left: 10, right: 5, top: 12), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Row( children: [ Icon( Icons.info, color: Colors.orangeAccent, ), Text(" "), Text( t("My Development By Muscle"), style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), ], ), Divider( color: Colors.transparent, ), Text( t("Here you see you development in the last period."), style: TextStyle(fontSize: 12, fontWeight: FontWeight.normal), ), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ChoiceChip( avatar: Icon( Icons.bubble_chart, ), label: Text(t('Sum Of Mass')), labelStyle: TextStyle(fontSize: 9, color: Colors.black), selectedColor: Colors.lightBlueAccent, selected: bloc.diagramType == DiagramType.sumMass, onSelected: (value) => {bloc.add(DevelopmentByMuscleDiagramTypeChange(diagramType: DiagramType.sumMass))}, ), ChoiceChip( avatar: Icon(Icons.accessibility_new), label: Text(t('One Rep Max')), labelStyle: TextStyle(fontSize: 9, color: Colors.black), selectedColor: Colors.lightBlueAccent, selected: bloc.diagramType == DiagramType.oneRepMax, onSelected: (value) => {bloc.add(DevelopmentByMuscleDiagramTypeChange(diagramType: DiagramType.oneRepMax))}, ), ChoiceChip( avatar: Icon(Icons.perm_device_information), label: Text(t('Percent')), labelStyle: TextStyle(fontSize: 9, color: Colors.black), selectedColor: Colors.lightBlueAccent, selected: bloc.diagramType == DiagramType.percent, onSelected: (value) => {bloc.add(DevelopmentByMuscleDiagramTypeChange(diagramType: DiagramType.percent))}, ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ChoiceChip( labelPadding: EdgeInsets.only(right: 5), avatar: Icon(Icons.timer), label: Text(t('Detailed')), labelStyle: TextStyle(fontSize: 9, color: Colors.black), disabledColor: Colors.black26, selectedColor: Colors.greenAccent, selected: bloc.dateRate == DateRate.daily, onSelected: (value) => {bloc.add(DevelopmentByMuscleDateRateChange(dateRate: DateRate.daily))}, ), ChoiceChip( labelPadding: EdgeInsets.only(right: 5), avatar: Icon(Icons.timer), label: Text(t('Weekly')), labelStyle: TextStyle(fontSize: 9, color: Colors.black), selectedColor: Colors.greenAccent, disabledColor: Colors.white12, tooltip: "Heti bontás", selected: bloc.dateRate == DateRate.weekly, onSelected: (value) => {bloc.add(DevelopmentByMuscleDateRateChange(dateRate: DateRate.weekly))}, ), ChoiceChip( labelPadding: EdgeInsets.only(right: 5), avatar: Icon(Icons.timer), label: Text(t('Monthly')), labelStyle: TextStyle(fontSize: 9, color: Colors.black), selectedColor: Colors.greenAccent, disabledColor: Colors.black26, selected: bloc.dateRate == DateRate.monthly, onSelected: (value) => {bloc.add(DevelopmentByMuscleDateRateChange(dateRate: DateRate.monthly))}, ), ChoiceChip( labelPadding: EdgeInsets.only(right: 5), avatar: Icon(Icons.timer), label: Text(t('Yearly')), labelStyle: TextStyle(fontSize: 9, color: Colors.black), selectedColor: Colors.greenAccent, disabledColor: Colors.white70, selected: bloc.dateRate == DateRate.yearly, onSelected: (value) => {bloc.add(DevelopmentByMuscleDateRateChange(dateRate: DateRate.yearly))}, ), ], ) ], ))); exerciseTypes.add(explanation); tree.forEach((name, list) { exerciseTypes.add(Container( margin: const EdgeInsets.only(left: 4.0), child: TreeViewChild( startExpanded: false, parent: _getExerciseWidget(exerciseTypeName: name), children: _getChildList(list, bloc), ))); }); return exerciseTypes; } Widget _getExerciseWidget({@required String exerciseTypeName, List list}) { return TreeviewParentWidget(text: exerciseTypeName); } List _getChildList(List listWorkoutTree, DevelopmentByMuscleBloc bloc) { List list = List(); listWorkoutTree.forEach((element) { bool hasNoData = (bloc.listChartData[element.exerciseTypeId] == null); String unit = " kg"; if (bloc.diagramType == DiagramType.percent) { unit = " %"; } list.add(SizedBox( width: cWidth * 0.85, height: hasNoData ? 0 : 200, child: Container( padding: const EdgeInsets.only(left: 5, top: 5, right: 5, bottom: 5), color: Colors.white70, child: Column(mainAxisSize: MainAxisSize.min, children: [ hasNoData ? Container() : Text( element.exerciseType.nameTranslation, style: TextStyle(color: Colors.deepOrange), ), hasNoData ? Container( //child: Text("no data for " + element.exerciseType.nameTranslation), ) : Expanded( //fit: FlexFit.loose, child: BarChart( BarChartData( alignment: BarChartAlignment.spaceAround, barTouchData: BarTouchData( touchTooltipData: BarTouchTooltipData( tooltipBgColor: Colors.white70, getTooltipItem: (group, groupIndex, rod, rodIndex) { return BarTooltipItem( rod.y.toStringAsFixed(0) + unit, TextStyle(color: Colors.black54, fontSize: 12, fontWeight: FontWeight.bold), ); }), ), titlesData: FlTitlesData( show: true, bottomTitles: SideTitles( showTitles: true, getTextStyles: (_) => TextStyle(fontSize: 8, color: Colors.blueGrey), getTitles: (double value) { var date = new DateTime.fromMillisecondsSinceEpoch(value.toInt()); //String strDate = DateFormat('MM.dd.', AppLanguage().appLocal.toString()).format(date); String strDate = getDatePart(date, bloc.dateRate); return strDate; }, ), leftTitles: SideTitles( showTitles: true, getTextStyles: (_) => TextStyle(fontSize: 8, color: Colors.blueGrey), interval: bloc.listChartData[element.exerciseTypeId] == null ? 100 : bloc.listChartData[element.exerciseTypeId].interval, margin: 10, getTitles: (double value) { return value.toStringAsFixed(0) + unit; })), borderData: FlBorderData( show: false, ), gridData: FlGridData( show: true, checkToShowHorizontalLine: (value) => value % bloc.listChartData[element.exerciseTypeId].gridInterval == 0, getDrawingHorizontalLine: (value) { return FlLine( color: Colors.black26, strokeWidth: 0.5, ); }, ), groupsSpace: 2, barGroups: bloc.listChartData[element.exerciseTypeId] == null ? [] : bloc.listChartData[element.exerciseTypeId].data, ), swapAnimationDuration: Duration(milliseconds: 1200), ), ) ]), ), )); }); return list; } }