277 lines
12 KiB
Dart
277 lines
12 KiB
Dart
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<String, dynamic> args = ModalRoute.of(context)!.settings.arguments as HashMap<String, dynamic>;
|
|
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<DevelopmentDiagramBloc, DevelopmentDiagramState>(
|
|
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<DevelopmentDiagramBloc>(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: <double>[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: <double>[15, 5]),
|
|
),
|
|
palette: <Color>[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>[
|
|
/* 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: <ChartSeries>[
|
|
SplineSeries<DiagramData, String>(
|
|
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))
|
|
],
|
|
))
|
|
]));
|
|
}
|
|
}
|