Untitled

 avatar
unknown
plain_text
2 years ago
19 kB
4
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...