workouttest_app/lib/view/test_set_edit.dart
2021-04-19 00:16:07 +02:00

290 lines
12 KiB
Dart

import 'dart:collection';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/bloc/test_set_edit/test_set_edit_bloc.dart';
import 'package:aitrainer_app/library/custom_icon_icons.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:aitrainer_app/model/workout_menu_tree.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:aitrainer_app/widgets/menu_image.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/cupertino.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';
// ignore: must_be_immutable
class TestSetEdit extends StatelessWidget with Trans {
@override
Widget build(BuildContext context) {
HashMap args = ModalRoute.of(context)!.settings.arguments as HashMap;
final String templateName = args['templateName'];
final String templateNameTranslation = args['templateNameTranslation'];
// ignore: close_sinks
final MenuBloc menuBloc = BlocProvider.of<MenuBloc>(context);
late TestSetEditBloc? bloc;
final bool activeExercisePlan = Cache().activeExercisePlan != null;
setContext(context);
return Scaffold(
appBar: AppBarNav(
depth: 0,
),
body: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('asset/image/WT_black_background.jpg'),
fit: BoxFit.cover,
alignment: Alignment.center,
),
),
child: BlocProvider(
create: (context) => TestSetEditBloc(
templateName: templateName,
templateNameTranslation: templateNameTranslation,
workoutTreeRepository: menuBloc.menuTreeRepository,
menuBloc: menuBloc),
child: BlocConsumer<TestSetEditBloc, TestSetEditState>(listener: (context, state) {
if (state is TestSetEditError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
} else if (state is TestSetEditSaved) {
Navigator.of(context).pop();
Navigator.of(context).pushNamed("testSetExecute");
}
}, builder: (context, state) {
bloc = BlocProvider.of<TestSetEditBloc>(context);
return ModalProgressHUD(
child: getTestSetWidget(bloc!, templateNameTranslation),
inAsyncCall: state is TestSetEditLoading,
opacity: 0.5,
color: Colors.black54,
progressIndicator: CircularProgressIndicator(),
);
}))),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
if (activeExercisePlan) {
showCupertinoDialog(
useRootNavigator: true,
context: context,
builder: (_) => CupertinoAlertDialog(
title: Text(t("You have an active Test Set!") + "\n" + Cache().activeExercisePlan!.name),
content: Column(children: [
Divider(),
Text(t("Do you want to override it?"), style: GoogleFonts.inter(color: Colors.black, fontSize: 16)),
]),
actions: [
TextButton(
child: Text(t("No, bring me there"), textAlign: TextAlign.center),
onPressed: () => {
Navigator.pop(context),
Navigator.pop(context),
Navigator.of(context).pushNamed("testSetExecute"),
},
),
TextButton(
child: Text(t("Yes")),
onPressed: () {
Navigator.pop(context);
startTrainingDialog(bloc);
},
)
],
));
} else {
startTrainingDialog(bloc);
}
},
backgroundColor: Colors.orange[800],
icon: Icon(CustomIcon.clock),
label: Text(
t("Start training"),
style: GoogleFonts.inter(fontWeight: FontWeight.bold, fontSize: 16),
),
),
);
}
void startTrainingDialog(TestSetEditBloc? bloc) {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return DialogCommon(
title: "Start!",
descriptions: t("Enjoy the exercises, good luck with the testing!"),
text: "OK",
onTap: () => {
Navigator.of(context).pop(),
if (bloc != null)
{
bloc.add(TestSetEditSubmit()),
}
},
onCancel: () => {Navigator.of(context).pop()},
);
});
}
Widget getTestSetWidget(TestSetEditBloc bloc, String templateName) {
return Container(
padding: EdgeInsets.only(left: 10, right: 10),
child: CustomScrollView(scrollDirection: Axis.vertical, slivers: [
SliverAppBar(
toolbarHeight: 135,
automaticallyImplyLeading: false,
backgroundColor: Colors.transparent,
title: Column(mainAxisAlignment: MainAxisAlignment.start, children: [
RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: GoogleFonts.archivoBlack(
fontSize: 18,
fontWeight: FontWeight.bold,
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,
),
],
),
children: [
TextSpan(text: t("Edit Your Training Test Set"), style: GoogleFonts.inter(color: Colors.white, fontSize: 18)),
TextSpan(text: "\n", style: GoogleFonts.inter(color: Colors.white, fontSize: 18)),
TextSpan(text: t(templateName), style: GoogleFonts.archivoBlack(color: Colors.yellow[300], fontSize: 18)),
])),
Divider(
color: Colors.transparent,
),
GestureDetector(
onTap: () => showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return DialogCommon(
title: bloc.templateNameTranslation,
descriptions: bloc.templateDescription,
text: "OK",
onTap: () => {Navigator.of(context).pop()},
onCancel: () => {Navigator.of(context).pop()},
);
}),
child: Icon(
CustomIcon.question_circle,
color: Colors.orange[400],
size: 40,
)),
]),
centerTitle: true,
),
SliverList(delegate: SliverChildListDelegate(getExerciseTypeWidgets(bloc))),
]));
}
List<Widget> imageSliders(int index, WorkoutMenuTree? workoutTree, TestSetEditBloc bloc) {
final List<Widget> list = [];
bool deleted = workoutTree == null;
bloc.displayPlanDetails[index].forEach((value) {
ExerciseType alternative = value;
final WorkoutMenuTree? workoutTreeAlternative =
bloc.menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(alternative.exerciseTypeId);
list.add(getImageStack(workoutTreeAlternative!, bloc, index, deleted));
});
return list;
}
Stack getImageStack(WorkoutMenuTree element, TestSetEditBloc bloc, int index, bool deleted) {
return Stack(alignment: Alignment.topRight, children: [
Stack(alignment: Alignment.bottomLeft, children: [
deleted
? Opacity(opacity: 0.2, child: MenuImage(imageName: element.imageName, workoutTreeId: element.id))
: MenuImage(imageName: element.imageName, workoutTreeId: element.id),
Container(
padding: EdgeInsets.only(left: 15, bottom: 15, right: 15),
child: Text(
element.name,
maxLines: 4,
style: GoogleFonts.archivoBlack(color: deleted ? element.color.withOpacity(0.2) : element.color, fontSize: 16, height: 1.1),
),
),
]),
deleted == false
? Container(
width: 40,
height: 40,
child: ClipRRect(
borderRadius: BorderRadius.circular(24.0),
child: GestureDetector(
onTap: () => bloc.add(TestSetEditDeleteExerciseType(indexKey: index)),
child: Container(
color: Colors.red[600],
child: Center(
child: Text(
"X",
style: GoogleFonts.archivoBlack(
color: Colors.white,
fontSize: 28,
),
),
)))))
: Container(
width: 40,
height: 40,
child: ClipRRect(
borderRadius: BorderRadius.circular(24.0),
child: GestureDetector(
onTap: () => bloc.add(TestSetEditAddExerciseType(indexKey: index)),
child: Container(
color: Colors.yellow[700],
child: Center(
child: Icon(
Icons.undo_sharp,
size: 40,
color: Colors.white,
)),
))))
]);
}
List<Widget> getExerciseTypeWidgets(TestSetEditBloc bloc) {
final List<Widget> widgets = [];
bloc.exercisePlanDetails.forEach((key, element) {
WorkoutMenuTree? workoutTree;
if (element != null) {
workoutTree = bloc.menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(element.exerciseTypeId);
}
final Widget widget = CarouselSlider(
options: CarouselOptions(
viewportFraction: 0.80,
reverse: false,
enableInfiniteScroll: false,
autoPlay: false,
aspectRatio: 2,
enlargeCenterPage: true,
onPageChanged: (index, reason) => bloc.add(TestSetEditChangeExerciseType(index: index, indexKey: key)),
enlargeStrategy: CenterPageEnlargeStrategy.scale),
items: imageSliders(key, workoutTree, bloc),
);
widgets.add(widget);
});
return widgets;
}
}