import 'package:flutter/material.dart'; import 'package:flutter/material.dart' as material; import 'package:flutter/services.dart'; import 'package:fmassive/database.dart'; import 'package:fmassive/edit_plan.dart'; import 'package:fmassive/main.dart'; import 'package:moor_flutter/moor_flutter.dart'; class StartPlan extends StatefulWidget { final PlansCompanion plan; const StartPlan({required this.plan, super.key}); @override createState() => _StartPlanState(); } class _StartPlanState extends State { late List exercises; List counts = []; List totals = []; int selectedExercise = 0; final repsController = TextEditingController(); final repsNode = FocusNode(); final weightController = TextEditingController(); final weightNode = FocusNode(); Future getTotals() async { final query = await (db.selectOnly(db.gymSets) ..addColumns([db.gymSets.name, db.gymSets.sets]) ..where(db.gymSets.name.isIn(exercises)) ..groupBy([db.gymSets.name, db.gymSets.sets])) .map((row) => MapEntry(row.read(db.gymSets.name), row.read(db.gymSets.sets))) .get(); final map = Map.fromIterables( query.map((entry) => entry.key), query.map((entry) => entry.value)); setState(() { totals = []; for (var exercise in exercises) { totals.add(map[exercise] ?? 0); } }); print("totals=$totals"); } Future getCounts() async { var countExp = db.gymSets.name.count(); final today = DateTime.now().toIso8601String().split('T')[0]; final query = await (db.selectOnly(db.gymSets) ..addColumns([countExp, db.gymSets.name]) ..where(db.gymSets.created.contains(today)) ..groupBy([db.gymSets.name])) .map((row) => MapEntry(row.read(db.gymSets.name), row.read(countExp))) .get(); final map = Map.fromIterables( query.map((entry) => entry.key), query.map((entry) => entry.value)); setState(() { counts = []; for (var exercise in exercises) { counts.add(map[exercise] ?? 0); } }); print("counts=$counts"); } Future focus(int index) async { final name = exercises[index]; final sets = await (db.gymSets.select() ..where((gymSet) => gymSet.name.contains(name)) ..orderBy([ (u) => OrderingTerm(expression: u.created, mode: OrderingMode.desc), ]) ..limit(1)) .get(); final firstSet = sets.first; repsController.text = firstSet.reps.toString(); repsController.selection = TextSelection( baseOffset: 0, extentOffset: firstSet.reps.toString().length); weightController.text = firstSet.weight.toString(); } @override void initState() { super.initState(); exercises = widget.plan.exercises.value.split(','); repsNode.requestFocus(); getCounts(); getTotals(); focus(selectedExercise); } @override dispose() { super.dispose(); } @override Widget build(BuildContext context) { List actions = []; if (widget.plan.id.present) actions.add(IconButton( onPressed: () async { await Navigator.push( context, MaterialPageRoute( builder: (context) => EditPlanPage(plan: widget.plan), ), ); }, icon: const Icon(Icons.edit))); if (totals.isEmpty || counts.isEmpty) return const CircularProgressIndicator(); return SafeArea( child: Scaffold( appBar: AppBar(title: const Text('Start plan'), actions: actions), body: Padding( padding: const EdgeInsets.all(16.0), child: material.Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: ListView.builder( itemBuilder: ((context, index) { return ListTile( title: Text(exercises[index]), subtitle: Text("${counts[index]}/${totals[index]}"), onTap: () { setState(() { selectedExercise = index; focus(index); }); }, leading: Radio( value: index, groupValue: selectedExercise, onChanged: (value) { print("onChanged $value"); if (value == null) return; setState(() { selectedExercise = value; focus(index); }); }, ), ); }), itemCount: exercises.length, ), ), TextFormField( decoration: const InputDecoration(labelText: 'Reps'), controller: repsController, focusNode: repsNode, ), TextFormField( decoration: const InputDecoration(labelText: 'Weight'), controller: weightController, focusNode: weightNode, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: () async { final gymSet = GymSetsCompanion( created: Value(DateTime.now().toIso8601String()), name: Value(exercises[selectedExercise]), reps: Value(int.tryParse(repsController.text) ?? 0), weight: Value(double.tryParse(weightController.text) ?? 0)); await db.into(db.gymSets).insert(gymSet); const platform = MethodChannel('com.massive/android'); platform.invokeMethod('timer', [180000]); await getCounts(); }, child: const Icon(Icons.check), ), )); } }