Untitled
unknown
plain_text
3 years ago
19 kB
7
Indexable
import 'package:client/enums.dart';
import 'package:client/services/training_services.dart';
import 'package:client/states/user_state.dart';
import 'package:client/utils/other_utils.dart';
import 'package:client/widgets/commons.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import '../../../../models/training_model.dart';
import '../../../../styles.dart';
class ExerciseSetTile extends StatefulWidget {
final String number;
final bool? withDivider;
final BlockExerciseSetsModel exerciseSetsModel;
final BlockType? blocktype;
const ExerciseSetTile({
required this.number,
this.withDivider,
this.blocktype = BlockType.strenght,
required this.exerciseSetsModel,
Key? key,
}) : super(key: key);
@override
State<ExerciseSetTile> createState() => _ExerciseSetTileState();
}
//TODO re order by set
//finds next editable text focus to focus on it
extension Utility on BuildContext {
void nextEditableTextFocus() {
do {
FocusScope.of(this).nextFocus();
} while (FocusScope.of(this).focusedChild!.context == null);
}
}
class _ExerciseSetTileState extends State<ExerciseSetTile> {
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
children: [
RowSpace(),
//**numbering
Container(
height: 30,
width: 30,
decoration: BoxDecoration(
color: mainColor,
borderRadius: const BorderRadius.all(Radius.circular(5)),
),
child: Center(
child: Text(
widget.number,
style: textStyleCustom(
color: Colors.white, fontSize: defaultFontSizeMinus),
),
),
),
RowSpace(
width: 10,
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
//weight / sec /mins / meters / cals */
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ExerciseEditableField(
set: widget.exerciseSetsModel.repType == RepTypes.reps
? ExerciseSetFields.weight
: widget.exerciseSetsModel.repType ==
RepTypes.secs
? ExerciseSetFields.time
: widget.exerciseSetsModel.repType ==
RepTypes.mins
? ExerciseSetFields.time
: widget.exerciseSetsModel.repType ==
RepTypes.meters
? ExerciseSetFields.distance
: widget.exerciseSetsModel.repType ==
RepTypes.cals
? ExerciseSetFields.cals
: ExerciseSetFields
.weight, //todo here change on what field is it
id: widget.exerciseSetsModel.id,
val: widget.exerciseSetsModel.repType == RepTypes.reps
? widget.exerciseSetsModel.weight
: widget.exerciseSetsModel.repType ==
RepTypes.secs
? widget.exerciseSetsModel.time
: widget.exerciseSetsModel.repType ==
RepTypes.mins
? widget.exerciseSetsModel.time
: widget.exerciseSetsModel.repType ==
RepTypes.meters
? widget.exerciseSetsModel.distance
: widget.exerciseSetsModel.repType ==
RepTypes.cals
? widget.exerciseSetsModel.cals
: widget
.exerciseSetsModel.weight),
RowSpace(
width: 5,
),
Text(
widget.exerciseSetsModel.unit != ""
? widget.exerciseSetsModel.unit
: widget.exerciseSetsModel.repType == RepTypes.cals
? "cals"
: "",
style: textStyleCustom(
fontSize: defaultFontSizeMinus - 2,
fontWeight: FontWeight.bold),
),
],
),
//**Reps, Rounds, Total Reps, Total Cals */
// Strength & EMOM: repType==reps
// AMRAP: make reps as Total Reps, Cals - Total Cals
// RFT: Rounds
if (((widget.blocktype == BlockType.strenght ||
widget.blocktype == BlockType.emom) &&
widget.exerciseSetsModel.repType == RepTypes.reps) ||
(widget.blocktype == BlockType.amrap ||
widget.blocktype == BlockType.rft) &&
(((widget.blocktype == BlockType.strenght ||
widget.blocktype == BlockType.emom) &&
widget.exerciseSetsModel.repType ==
RepTypes.meters) ==
false))
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ExerciseEditableField(
set: widget.blocktype == BlockType.rft
? ExerciseSetFields.rounds
: ExerciseSetFields.reps,
id: widget.exerciseSetsModel.id,
//for RFT get rounds for Streight get Reps
val: widget.blocktype == BlockType.rft
? widget.exerciseSetsModel.rounds
: widget.blocktype == BlockType.strenght
? widget.exerciseSetsModel.reps
: widget.exerciseSetsModel.repType ==
RepTypes.reps
? widget.exerciseSetsModel.reps
: widget.exerciseSetsModel.reps,
),
RowSpace(
width: 5,
),
Text(
widget.blocktype == BlockType.rft
? "rounds"
: widget.blocktype == BlockType.amrap
? widget.exerciseSetsModel.repType ==
RepTypes.cals
? "Total Cals"
: "Total Reps"
: "reps",
style: textStyleCustom(
fontSize: defaultFontSizeMinus - 2,
fontWeight: FontWeight.bold),
),
],
),
//** TIME field */
// only for Strength and EMOM with repytpe of meters
if ((widget.blocktype == BlockType.strenght ||
widget.blocktype == BlockType.emom) &&
widget.exerciseSetsModel.repType == RepTypes.meters)
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ExerciseEditableField(
set: ExerciseSetFields.time,
id: widget.exerciseSetsModel.id,
val: widget.exerciseSetsModel.time,
),
RowSpace(
width: 5,
),
Text(
"sec",
style: textStyleCustom(
fontSize: defaultFontSizeMinus - 2,
fontWeight: FontWeight.bold),
),
],
),
//**RPE/
//** all Strength and EMOM */
if (widget.blocktype == BlockType.strenght ||
widget.blocktype == BlockType.emom)
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ExerciseEditableField(
set: ExerciseSetFields.rpe,
id: widget.exerciseSetsModel.id,
val: widget.exerciseSetsModel.rpe,
),
RowSpace(
width: 5,
),
Text(
"RPE",
style: textStyleCustom(
fontSize: defaultFontSizeMinus - 2,
fontWeight: FontWeight.bold),
),
],
),
//**Spacer
if ((widget.blocktype == BlockType.rft ||
widget.blocktype == BlockType.amrap) ||
((widget.blocktype == BlockType.strenght ||
widget.blocktype == BlockType.emom)) &&
(widget.exerciseSetsModel.repType == RepTypes.cals ||
widget.exerciseSetsModel.repType ==
RepTypes.mins ||
widget.exerciseSetsModel.repType ==
RepTypes.secs))
Row(
children: [
Container(
width: 40,
),
RowSpace(
width: 5,
),
RowSpace(
width: 20,
)
],
)
],
),
),
],
),
widget.withDivider != null && widget.withDivider == true
? const Divider(thickness: 1)
: Container()
],
);
}
}
class ExerciseEditableField extends StatefulWidget {
final String? val;
final double? width;
final int id;
final ExerciseSetFields set;
const ExerciseEditableField(
{required this.set, required this.id, this.width, this.val, super.key});
@override
State<ExerciseEditableField> createState() => _ExerciseEditableFieldState();
}
class _ExerciseEditableFieldState extends State<ExerciseEditableField> {
final FocusNode _focusNode = FocusNode();
TextEditingController controller = TextEditingController();
bool selected = false;
@override
void initState() {
controller.text = widget.val ?? "";
controller.addListener(() {
if (_focusNode.hasFocus && !selected) {
final newText = controller.text;
controller.value = controller.value.copyWith(
text: newText,
selection: TextSelection(baseOffset: 0, extentOffset: newText.length),
);
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
void save() {
if (widget.set == ExerciseSetFields.weight) {
TrainingServices().saveExerciseSet(
accessToken:
Provider.of<UserState>(context, listen: false).accessToken,
setId: widget.id,
set: widget.set,
weight: convert2Double(controller.text),
reps: 0,
rpe: 0,
cals: 0,
distance: 0,
rounds: 0,
time: 0);
}
if (widget.set == ExerciseSetFields.reps) {
TrainingServices().saveExerciseSet(
accessToken:
Provider.of<UserState>(context, listen: false).accessToken,
setId: widget.id,
set: widget.set,
weight: 0,
reps: convert2Int(controller.text),
rpe: 0,
cals: 0,
distance: 0,
rounds: 0,
time: 0);
}
if (widget.set == ExerciseSetFields.rpe) {
TrainingServices().saveExerciseSet(
accessToken:
Provider.of<UserState>(context, listen: false).accessToken,
setId: widget.id,
set: widget.set,
weight: 0,
reps: 0,
cals: 0,
distance: 0,
rounds: 0,
time: 0,
rpe: convert2Int(controller.text));
}
if (widget.set == ExerciseSetFields.cals) {
TrainingServices().saveExerciseSet(
accessToken:
Provider.of<UserState>(context, listen: false).accessToken,
setId: widget.id,
set: widget.set,
weight: 0,
reps: 0,
cals: convert2Double(controller.text),
distance: 0,
rounds: 0,
time: 0,
rpe: 0);
}
if (widget.set == ExerciseSetFields.distance) {
TrainingServices().saveExerciseSet(
accessToken:
Provider.of<UserState>(context, listen: false).accessToken,
setId: widget.id,
set: widget.set,
weight: 0,
reps: 0,
cals: 0,
distance: convert2Double(controller.text),
rounds: 0,
time: 0,
rpe: 0);
}
if (widget.set == ExerciseSetFields.rounds) {
TrainingServices().saveExerciseSet(
accessToken:
Provider.of<UserState>(context, listen: false).accessToken,
setId: widget.id,
set: widget.set,
weight: 0,
reps: 0,
cals: 0,
distance: 0,
rounds: convert2Int(controller.text),
time: 0,
rpe: 0);
}
if (widget.set == ExerciseSetFields.time) {
TrainingServices().saveExerciseSet(
accessToken:
Provider.of<UserState>(context, listen: false).accessToken,
setId: widget.id,
set: widget.set,
weight: 0,
reps: 0,
cals: 0,
distance: 0,
rounds: 0,
time: convert2Int(controller.text),
rpe: 0);
}
}
return SizedBox(
width: widget.width ?? 60,
child: Center(
child: Focus(
focusNode: _focusNode,
onKey: (node, event) {
//trigger selected so it wont be selected again
selected = true;
return KeyEventResult.ignored;
},
onFocusChange: (value) {},
child: CupertinoTextField(
onChanged: (value) {
selected = true;
controller.selection = TextSelection(
baseOffset: controller.text.length,
extentOffset: controller.text.length);
},
textInputAction: TextInputAction.done,
controller: controller,
onTap: () {
controller.selection = TextSelection(
baseOffset: 0, extentOffset: controller.text.length);
},
onSubmitted: (value) {
save();
context.nextEditableTextFocus();
},
onEditingComplete: () {
save();
context.nextEditableTextFocus();
},
keyboardType:
TextInputType.numberWithOptions(signed: true, decimal: false),
textAlign: TextAlign.center,
inputFormatters: [
RegExInputFormatter.withRegex(
'^\$|^(0|([1-9][0-9]{0,}))(\\[0-9]{0,})?\$'),
],
maxLines: 1,
style: textStyleDefaultSmallerBold,
// decoration: InputDecoration(
// isCollapsed: true,
// contentPadding: const EdgeInsets.all(8),
// fillColor: trainingEditableFiledColor,
// filled: true,
// focusedBorder: const OutlineInputBorder(
// borderSide: BorderSide(color: Colors.blueAccent, width: 1),
// ),
// border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(5),
// borderSide: BorderSide.none,
// ),
// ),
),
),
),
);
}
}
class RegExInputFormatter implements TextInputFormatter {
final RegExp _regExp;
RegExInputFormatter._(this._regExp);
factory RegExInputFormatter.withRegex(String regexString) {
try {
final regex = RegExp(regexString);
return RegExInputFormatter._(regex);
} catch (e) {
// Something not right with regex string.
assert(false, e.toString());
final regex = RegExp(regexString);
return RegExInputFormatter._(regex);
}
}
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
final oldValueValid = _isValid(oldValue.text);
final newValueValid = _isValid(newValue.text);
if (oldValueValid && !newValueValid) {
return oldValue;
}
return newValue;
}
bool _isValid(String value) {
try {
final matches = _regExp.allMatches(value);
for (Match match in matches) {
if (match.start == 0 && match.end == value.length) {
return true;
}
}
return false;
} catch (e) {
// Invalid regex
assert(false, e.toString());
return true;
}
}
}
Editor is loading...