447 lines
17 KiB
Dart
447 lines
17 KiB
Dart
import 'dart:collection';
|
|
|
|
import 'package:aitrainer_app/bloc/training_evaluation/training_evaluation_bloc.dart';
|
|
import 'package:aitrainer_app/bloc/training_plan/training_plan_bloc.dart';
|
|
import 'package:aitrainer_app/library/custom_icon_icons.dart';
|
|
import 'package:aitrainer_app/model/cache.dart';
|
|
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
|
|
import 'package:aitrainer_app/model/training_evaluation_exercise.dart';
|
|
import 'package:aitrainer_app/util/trans.dart';
|
|
import 'package:aitrainer_app/widgets/app_bar_min.dart';
|
|
import 'package:aitrainer_app/widgets/bottom_nav.dart';
|
|
import 'package:aitrainer_app/widgets/menu_image.dart';
|
|
import 'package:aitrainer_app/widgets/victory_widget.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:timeline_tile/timeline_tile.dart';
|
|
|
|
// ignore: must_be_immutable
|
|
class TrainingEvaluationPage extends StatelessWidget with Trans {
|
|
TrainingEvaluationPage({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
setContext(context);
|
|
String imageUrl = "";
|
|
if (Cache().userLoggedIn == null) {
|
|
imageUrl = 'asset/image/WT_Results_for_men.jpg';
|
|
} else if (Cache().userLoggedIn!.sex == "m") {
|
|
imageUrl = 'asset/image/WT_Results_for_men.jpg';
|
|
} else {
|
|
imageUrl = 'asset/image/WT_Results_for_female.jpg';
|
|
}
|
|
final HashMap args = ModalRoute.of(context)!.settings.arguments as HashMap;
|
|
final TrainingPlanBloc trainingPlanBloc = args["bloc"];
|
|
final dayName = args["day"];
|
|
return Scaffold(
|
|
appBar: AppBarMin(
|
|
back: true,
|
|
),
|
|
body: Container(
|
|
height: double.infinity,
|
|
width: double.infinity,
|
|
alignment: Alignment.center,
|
|
decoration: BoxDecoration(
|
|
image: DecorationImage(
|
|
image: AssetImage(imageUrl),
|
|
fit: BoxFit.cover,
|
|
alignment: Alignment.topCenter,
|
|
),
|
|
),
|
|
child: BlocProvider(
|
|
create: (context) =>
|
|
TrainingEvaluationBloc(trainingPlanBloc: trainingPlanBloc, day: dayName)..add(TrainingEvaluationLoad()),
|
|
child: BlocConsumer<TrainingEvaluationBloc, TrainingEvaluationState>(listener: (context, state) {
|
|
if (state is TrainingEvaluationError) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
|
|
} else if (state is TrainingEvaluationVictoryReady) {
|
|
showDialog(
|
|
context: context,
|
|
barrierDismissible: true,
|
|
builder: (BuildContext context) {
|
|
return Victory(
|
|
victory: true,
|
|
);
|
|
});
|
|
}
|
|
}, builder: (context, state) {
|
|
final bloc = BlocProvider.of<TrainingEvaluationBloc>(context);
|
|
return ModalProgressHUD(
|
|
child: getEvaluationWidgets(bloc, dayName),
|
|
inAsyncCall: state is TrainingEvaluationLoading,
|
|
opacity: 0.5,
|
|
color: Colors.black54,
|
|
progressIndicator: CircularProgressIndicator(),
|
|
);
|
|
}))),
|
|
bottomNavigationBar: BottomNavigator(bottomNavIndex: 0));
|
|
}
|
|
|
|
Widget getEvaluationWidgets(TrainingEvaluationBloc bloc, String dayName) {
|
|
return Container(
|
|
padding: EdgeInsets.only(left: 10, right: 10),
|
|
child: CustomScrollView(scrollDirection: Axis.vertical, slivers: [
|
|
SliverAppBar(
|
|
pinned: true,
|
|
backgroundColor: Colors.transparent,
|
|
expandedHeight: 130.0,
|
|
collapsedHeight: 130,
|
|
toolbarHeight: 40,
|
|
automaticallyImplyLeading: false,
|
|
flexibleSpace: FlexibleSpaceBar(
|
|
title: Column(children: [
|
|
Divider(),
|
|
Text(bloc.trainingPlanBloc.getMyPlan()!.name!,
|
|
textAlign: TextAlign.center,
|
|
maxLines: 4,
|
|
style: GoogleFonts.archivoBlack(
|
|
fontSize: 24,
|
|
color: Colors.orange[300],
|
|
shadows: <Shadow>[
|
|
Shadow(
|
|
offset: Offset(5.0, 5.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
Shadow(
|
|
offset: Offset(-3.0, 3.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
],
|
|
)),
|
|
Text(t("Training Summary"),
|
|
textAlign: TextAlign.center,
|
|
maxLines: 3,
|
|
style: GoogleFonts.archivoBlack(
|
|
fontSize: 20,
|
|
color: Colors.white,
|
|
shadows: <Shadow>[
|
|
Shadow(
|
|
offset: Offset(5.0, 5.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
Shadow(
|
|
offset: Offset(-3.0, 3.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
],
|
|
)),
|
|
]),
|
|
),
|
|
),
|
|
|
|
//getResultSummary(resultBloc),
|
|
SliverList(
|
|
delegate: SliverChildListDelegate([
|
|
summaryRow("asset/image/pict_time_h.png", "Duration", bloc.duration + " " + t("mins")),
|
|
Divider(color: Colors.transparent),
|
|
summaryRow("asset/image/pict_weight_volumen_tonna.png", "Total Lift", bloc.totalLift + " " + t("kg")),
|
|
Divider(color: Colors.transparent),
|
|
summaryRow("asset/image/pict_hypertrophy.png", "Maximum Repeats", "${bloc.maxRepeats}" + " " + t("reps")),
|
|
Divider(color: Colors.transparent),
|
|
//summaryRow("asset/image/pict_reps_volumen_db.png", "Total Lift Ever", "100 kg"),
|
|
//Divider(color: Colors.transparent),
|
|
Text(t("Details"),
|
|
textAlign: TextAlign.center,
|
|
maxLines: 3,
|
|
style: GoogleFonts.archivoBlack(
|
|
fontSize: 20,
|
|
color: Colors.white,
|
|
shadows: <Shadow>[
|
|
Shadow(
|
|
offset: Offset(5.0, 5.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
Shadow(
|
|
offset: Offset(-3.0, 3.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
],
|
|
)),
|
|
])),
|
|
SliverList(
|
|
delegate: SliverChildListDelegate(
|
|
getExerciseLists(bloc, dayName),
|
|
))
|
|
]));
|
|
}
|
|
|
|
Widget summaryRow(String imageUrl, String title, String data) {
|
|
return Row(
|
|
children: [
|
|
Image.asset(
|
|
imageUrl,
|
|
height: 40,
|
|
),
|
|
SizedBox(
|
|
width: 10,
|
|
),
|
|
Flexible(
|
|
fit: FlexFit.tight,
|
|
flex: 1,
|
|
child: Text(t(title),
|
|
textAlign: TextAlign.start,
|
|
maxLines: 2,
|
|
softWrap: true,
|
|
style: GoogleFonts.archivoBlack(
|
|
fontSize: 18,
|
|
color: Colors.orange[400],
|
|
shadows: <Shadow>[
|
|
Shadow(
|
|
offset: Offset(5.0, 5.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
Shadow(
|
|
offset: Offset(-3.0, 3.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
],
|
|
))),
|
|
SizedBox(
|
|
width: 10,
|
|
),
|
|
Text(t(data),
|
|
textAlign: TextAlign.center,
|
|
maxLines: 2,
|
|
softWrap: true,
|
|
style: GoogleFonts.archivoBlack(
|
|
fontSize: 20,
|
|
color: Colors.white,
|
|
shadows: <Shadow>[
|
|
Shadow(
|
|
offset: Offset(5.0, 5.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
Shadow(
|
|
offset: Offset(-3.0, 3.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
],
|
|
))
|
|
],
|
|
);
|
|
}
|
|
|
|
List<Widget> getExerciseLists(TrainingEvaluationBloc bloc, String dayName) {
|
|
List<Widget> list = [];
|
|
bloc.evaluationList.forEach((element) {
|
|
list.add(ExerciseTile(bloc: bloc, exercise: element));
|
|
});
|
|
return list;
|
|
}
|
|
}
|
|
|
|
// ignore: must_be_immutable
|
|
class ExerciseTile extends StatelessWidget with Trans {
|
|
final TrainingEvaluationBloc bloc;
|
|
final TrainingEvaluationExercise exercise;
|
|
|
|
ExerciseTile({required this.bloc, required this.exercise});
|
|
|
|
Widget getIndicator(ExercisePlanDetailState state) {
|
|
if (state.equalsTo(ExercisePlanDetailState.inProgress)) {
|
|
return ClipRRect(
|
|
borderRadius: BorderRadius.circular(24.0),
|
|
child: Container(
|
|
color: Colors.green,
|
|
child: Icon(
|
|
CustomIcon.calendar_2,
|
|
size: 28,
|
|
color: Colors.white,
|
|
)));
|
|
} else if (state.equalsTo(ExercisePlanDetailState.finished)) {
|
|
return ClipRRect(
|
|
borderRadius: BorderRadius.circular(24.0),
|
|
child: Container(
|
|
color: Colors.white,
|
|
child: Icon(
|
|
CustomIcon.ok_circled,
|
|
size: 40,
|
|
color: Colors.green,
|
|
)));
|
|
} else if (state.equalsTo(ExercisePlanDetailState.skipped)) {
|
|
return ClipRRect(
|
|
borderRadius: BorderRadius.circular(24.0),
|
|
child: Container(
|
|
color: Colors.white,
|
|
child: Icon(
|
|
CustomIcon.stop_1,
|
|
size: 40,
|
|
color: Colors.grey,
|
|
)));
|
|
} else if (state.equalsTo(ExercisePlanDetailState.extra)) {
|
|
return ClipRRect(
|
|
borderRadius: BorderRadius.circular(24.0),
|
|
child: Container(
|
|
color: Colors.white,
|
|
child: Icon(
|
|
CustomIcon.stopwatch_20,
|
|
size: 40,
|
|
color: Colors.blue[800],
|
|
)));
|
|
} else {
|
|
return Image.asset(
|
|
"asset/image/pict_reps_volumen_db.png",
|
|
);
|
|
}
|
|
}
|
|
|
|
Widget build(BuildContext context) {
|
|
setContext(context);
|
|
bool hasWeight = exercise.type.equalsTo(TrainingEvaluationExerciseType.weightBased);
|
|
bool skipped = exercise.state.equalsTo(ExercisePlanDetailState.skipped);
|
|
bool extra = exercise.state.equalsTo(ExercisePlanDetailState.extra);
|
|
|
|
return Container(
|
|
color: Colors.transparent,
|
|
child: TimelineTile(
|
|
alignment: TimelineAlign.manual,
|
|
lineXY: 0.1,
|
|
beforeLineStyle: const LineStyle(
|
|
color: Color(0xffb4f500),
|
|
thickness: 6,
|
|
),
|
|
afterLineStyle: const LineStyle(
|
|
color: Color(0xffb4f500),
|
|
thickness: 6,
|
|
),
|
|
indicatorStyle: IndicatorStyle(
|
|
width: 40,
|
|
height: 40,
|
|
indicator: getIndicator(exercise.state),
|
|
),
|
|
endChild: Container(
|
|
padding: EdgeInsets.only(left: 10),
|
|
child: Row(children: [
|
|
Container(
|
|
width: 120,
|
|
height: 80,
|
|
child: MenuImage(
|
|
imageName: bloc.trainingPlanBloc.getActualImageName(exercise.exerciseTypeId),
|
|
workoutTreeId: bloc.trainingPlanBloc.getActualWorkoutTreeId(exercise.exerciseTypeId)!,
|
|
radius: 12,
|
|
),
|
|
),
|
|
SizedBox(
|
|
width: 10,
|
|
),
|
|
Expanded(
|
|
child: RichText(
|
|
text: TextSpan(
|
|
style: GoogleFonts.inter(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.white,
|
|
),
|
|
children: [
|
|
TextSpan(
|
|
text: exercise.name,
|
|
style: GoogleFonts.inter(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.orange[500],
|
|
shadows: <Shadow>[
|
|
Shadow(
|
|
offset: Offset(5.0, 5.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
Shadow(
|
|
offset: Offset(-3.0, 3.0),
|
|
blurRadius: 12.0,
|
|
color: Colors.black54,
|
|
),
|
|
],
|
|
)),
|
|
TextSpan(text: "\n"),
|
|
hasWeight
|
|
? skipped
|
|
? extra
|
|
? TextSpan(
|
|
text: "-", style: GoogleFonts.inter(fontSize: 12, color: Colors.grey[400], fontWeight: FontWeight.bold))
|
|
: TextSpan(
|
|
text: t("skipped") + "!",
|
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.grey[400], fontWeight: FontWeight.bold))
|
|
: TextSpan(
|
|
text: t("One Rep Max") + ": ",
|
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[400], fontWeight: FontWeight.bold))
|
|
: TextSpan(),
|
|
hasWeight
|
|
? skipped || extra
|
|
? TextSpan()
|
|
: TextSpan(
|
|
text: exercise.oneRepMax!.toStringAsFixed(0) +
|
|
" " +
|
|
t("kg") +
|
|
" (Max: " +
|
|
exercise.max1RM!.toStringAsFixed(0) +
|
|
" " +
|
|
t("kg") +
|
|
")",
|
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold))
|
|
: TextSpan(),
|
|
TextSpan(text: "\n"),
|
|
hasWeight
|
|
? skipped || extra
|
|
? TextSpan()
|
|
: TextSpan(
|
|
text: t("Total Lift") + ": ",
|
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[400], fontWeight: FontWeight.bold))
|
|
: TextSpan(),
|
|
hasWeight
|
|
? skipped || extra
|
|
? TextSpan()
|
|
: TextSpan(
|
|
text: exercise.totalLift!.toStringAsFixed(0) +
|
|
" " +
|
|
t("kg") +
|
|
" (Max: " +
|
|
exercise.maxTotalLift!.toStringAsFixed(0) +
|
|
" " +
|
|
t("kg") +
|
|
")",
|
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold))
|
|
: skipped || extra
|
|
? TextSpan()
|
|
: TextSpan(
|
|
text: exercise.repeats!.toStringAsFixed(0) +
|
|
" " +
|
|
t("reps") +
|
|
" (Max: " +
|
|
exercise.maxRepeats!.toStringAsFixed(0) +
|
|
" " +
|
|
t("reps") +
|
|
")",
|
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.white, fontWeight: FontWeight.bold)),
|
|
TextSpan(text: "\n"),
|
|
skipped || extra
|
|
? TextSpan()
|
|
: TextSpan(
|
|
text: t("Trend") + ": ",
|
|
style: GoogleFonts.inter(fontSize: 12, color: Colors.yellow[400], fontWeight: FontWeight.bold)),
|
|
skipped || extra
|
|
? TextSpan()
|
|
: TextSpan(
|
|
text: t(exercise.trendText),
|
|
style: GoogleFonts.inter(fontSize: 12, color: exercise.trendColor, fontWeight: FontWeight.bold)),
|
|
]),
|
|
)),
|
|
]),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|