import 'dart:collection'; import 'package:aitrainer_app/bloc/development_diagram/development_diagram_bloc.dart'; import 'package:aitrainer_app/model/property.dart'; import 'package:aitrainer_app/repository/exercise_repository.dart'; import 'package:aitrainer_app/repository/workout_tree_repository.dart'; import 'package:aitrainer_app/util/common.dart'; import 'package:aitrainer_app/util/diagram_data.dart'; import 'package:aitrainer_app/util/trans.dart'; import 'package:aitrainer_app/widgets/app_bar.dart'; import 'package:aitrainer_app/widgets/dialog_common.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart'; import 'package:syncfusion_flutter_charts/charts.dart'; import '../repository/customer_repository.dart'; // ignore: must_be_immutable class DevelopmentDiagram extends StatelessWidget with Common, Trans { CustomerRepository? customerRepository; ExerciseRepository? exerciseRepository; WorkoutTreeRepository? workoutTreeRepository; int? exerciseTypeId; Property? property; late String title; @override Widget build(BuildContext context) { setContext(context); final HashMap args = ModalRoute.of(context)!.settings.arguments as HashMap; this.customerRepository = args['customerRepository']; this.exerciseRepository = args['exerciseRepository']; this.exerciseTypeId = args['exerciseTypeId']; this.property = args['property']; this.title = args['title']; return Scaffold( appBar: AppBarNav(depth: 1), body: Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, decoration: BoxDecoration( image: DecorationImage( image: AssetImage('asset/image/WT_plainblack_background.jpg'), fit: BoxFit.fill, alignment: Alignment.center, ), ), child: BlocProvider( create: (context) => customerRepository == null ? DevelopmentDiagramBloc(diagramTitle: title, exerciseRepository: exerciseRepository, exerciseTypeId: exerciseTypeId) : DevelopmentDiagramBloc( diagramTitle: title, customerRepository: customerRepository, propertyName: property!.propertyName, ), child: BlocConsumer( listener: (context, state) { if (state is DevelopmentDiagramError) { showDialog( context: context, builder: (BuildContext context) { return DialogCommon( warning: true, title: t("Warning"), descriptions: t(state.message), text: "OK", onTap: () => Navigator.of(context).pop(), onCancel: () => { Navigator.of(context).pop(), }, ); }); } }, builder: (context, state) { final DevelopmentDiagramBloc bloc = BlocProvider.of(context); return ModalProgressHUD( child: getDiagramWidget(bloc), inAsyncCall: state is DevelopmentDiagramLoading, opacity: 0.5, color: Colors.black54, progressIndicator: CircularProgressIndicator(), ); }, ), ))); } Widget getExplanation(DevelopmentDiagramBloc bloc) { return Container( color: Colors.white54, padding: EdgeInsets.all(5), child: Wrap( direction: Axis.horizontal, runSpacing: 5, children: [ Icon( Icons.info, color: Colors.orangeAccent, ), Text(" "), Text( bloc.diagramTitle, style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), ], ), ); } Widget getFilterData(DevelopmentDiagramBloc bloc) { return bloc.isGroup ? Container( color: Colors.transparent, // padding: EdgeInsets.all(5), child: Wrap( direction: Axis.horizontal, spacing: 10, runSpacing: 5, 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.group == DiagramGroup.sumMass, onSelected: (value) => {bloc.add(DevelopmentDiagramChangeGroup(group: DiagramGroup.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.group == DiagramGroup.oneRepMax, onSelected: (value) => {bloc.add(DevelopmentDiagramChangeGroup(group: DiagramGroup.oneRepMax))}, ), ChoiceChip( avatar: Icon(Icons.perm_device_information), label: Text(t('Percent')), labelStyle: TextStyle(fontSize: 9, color: Colors.black), selectedColor: Colors.lightBlueAccent, selected: bloc.group == DiagramGroup.percent, onSelected: (value) => {bloc.add(DevelopmentDiagramChangeGroup(group: DiagramGroup.percent))}, ), ], ), ) : Offstage(); } Widget getGroupDate(DevelopmentDiagramBloc bloc) { return Container( color: Colors.transparent, //padding: EdgeInsets.all(5), child: Wrap( direction: Axis.horizontal, spacing: 10, runSpacing: 5, 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.dateFilter == DiagramDateFilter.daily, onSelected: (value) => {bloc.add(DevelopmentDiagramChangeDateFormat(dateFilter: DiagramDateFilter.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, selected: bloc.dateFilter == DiagramDateFilter.weekly, onSelected: (value) => {bloc.add(DevelopmentDiagramChangeDateFormat(dateFilter: DiagramDateFilter.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.dateFilter == DiagramDateFilter.monthly, onSelected: (value) => {bloc.add(DevelopmentDiagramChangeDateFormat(dateFilter: DiagramDateFilter.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.dateFilter == DiagramDateFilter.yearly, onSelected: (value) => {bloc.add(DevelopmentDiagramChangeDateFormat(dateFilter: DiagramDateFilter.yearly))}, ), ], ), ); } Widget getDiagramWidget(DevelopmentDiagramBloc bloc) { double cHeight = MediaQuery.of(context).size.height; return SingleChildScrollView( child: Column(children: [ getExplanation(bloc), getFilterData(bloc), getGroupDate(bloc), Container( height: cHeight * .70, child: SfCartesianChart( /* title: ChartTitle( text: property.propertyNameTranslation, textStyle: TextStyle(color: Colors.white, fontFamily: 'Roboto', fontSize: 20, fontWeight: FontWeight.w800)), */ plotAreaBorderColor: Colors.amber[50], primaryXAxis: CategoryAxis( borderColor: Colors.white12, axisLine: AxisLine(color: Colors.deepOrange, width: 2, dashArray: [5, 5]), labelStyle: TextStyle(color: Colors.deepOrange, fontFamily: 'Roboto', fontSize: 14, fontStyle: FontStyle.italic, fontWeight: FontWeight.w500), //title: AxisTitle(text: t('Date'), textStyle: TextStyle(color: Colors.white, fontFamily: 'Roboto', fontSize: 20, fontWeight: FontWeight.w800)) ), primaryYAxis: CategoryAxis( borderColor: Colors.white12, labelStyle: TextStyle(color: Colors.deepOrange, fontFamily: 'Roboto', fontSize: 14, fontStyle: FontStyle.italic, fontWeight: FontWeight.w500), axisLine: AxisLine(color: Colors.deepOrange, width: 2, dashArray: [15, 5]), ), palette: [Colors.white, Colors.orange, Colors.yellow], zoomPanBehavior: ZoomPanBehavior( // Performs zooming on double tap enableDoubleTapZooming: true), /* trackballBehavior: TrackballBehavior( // Enables the trackball enable: true, activationMode: ActivationMode.singleTap, tooltipSettings: InteractiveTooltip( enable: true, color: Colors.white, format: 'point.x : point.y', )), */ annotations: [ /* CartesianChartAnnotation( coordinateUnit: CoordinateUnit.percentage, verticalAlignment: ChartAlignment.center, horizontalAlignment: ChartAlignment.center, widget: getExplanation(bloc), x: '50%', y: '3%'), */ CartesianChartAnnotation( coordinateUnit: CoordinateUnit.percentage, verticalAlignment: ChartAlignment.center, horizontalAlignment: ChartAlignment.center, widget: Text(t("Double Tap: Zoom"), style: GoogleFonts.inter(color: Colors.yellow, fontSize: 12)), x: '55%', y: '85%') ], series: [ SplineSeries( markerSettings: MarkerSettings(isVisible: true, shape: DataMarkerType.diamond), dataSource: bloc.diagramData, dataLabelSettings: DataLabelSettings(isVisible: true, color: Colors.white), xValueMapper: (DiagramData data, _) => data.x, yValueMapper: (DiagramData data, _) => data.y, dataLabelMapper: (DiagramData data, _) => data.y!.toStringAsFixed(1)) ], )) ])); } }