import 'package:diameter/components/detail.dart'; import 'package:diameter/components/dialogs.dart'; import 'package:diameter/components/dropdown.dart'; import 'package:diameter/components/forms.dart'; import 'package:diameter/models/accuracy.dart'; import 'package:diameter/models/meal_category.dart'; import 'package:diameter/models/meal_portion_type.dart'; import 'package:diameter/models/meal_source.dart'; import 'package:diameter/models/settings.dart'; import 'package:diameter/navigation.dart'; import 'package:diameter/screens/accuracy_detail.dart'; import 'package:diameter/screens/meal/meal_category_detail.dart'; import 'package:diameter/screens/meal/meal_portion_type_detail.dart'; import 'package:flutter/material.dart'; class MealSourceDetailScreen extends StatefulWidget { static const String routeName = '/meal-source'; final int id; const MealSourceDetailScreen({Key? key, this.id = 0}) : super(key: key); @override _MealSourceDetailScreenState createState() => _MealSourceDetailScreenState(); } class _MealSourceDetailScreenState extends State { MealSource? _mealSource; bool _isNew = true; List _portionSizeAccuracies = []; List _carbsRatioAccuracies = []; List _mealCategories = []; List _mealPortionTypes = []; final GlobalKey _mealSourceForm = GlobalKey(); final ScrollController _scrollController = ScrollController(); final _valueController = TextEditingController(text: ''); final _notesController = TextEditingController(text: ''); Accuracy? _defaultCarbsRatioAccuracy; Accuracy? _defaultPortionSizeAccuracy; MealCategory? _defaultMealCategory; MealPortionType? _defaultMealPortionType; final _defaultCarbsRatioAccuracyController = TextEditingController(text: ''); final _defaultPortionSizeAccuracyController = TextEditingController(text: ''); final _defaultMealCategoryController = TextEditingController(text: ''); final _defaultMealPortionTypeController = TextEditingController(text: ''); @override void initState() { super.initState(); reload(); _portionSizeAccuracies = Accuracy.getAllForPortionSize(); _carbsRatioAccuracies = Accuracy.getAllForCarbsRatio(); _mealCategories = MealCategory.getAll(); _mealPortionTypes = MealPortionType.getAll(); if (_mealSource != null) { _valueController.text = _mealSource!.value; _notesController.text = _mealSource!.notes ?? ''; _defaultPortionSizeAccuracy = _mealSource!.defaultPortionSizeAccuracy.target; _defaultPortionSizeAccuracyController.text = (_defaultPortionSizeAccuracy ?? '').toString(); _defaultCarbsRatioAccuracy = _mealSource!.defaultCarbsRatioAccuracy.target; _defaultCarbsRatioAccuracyController.text = (_defaultCarbsRatioAccuracy ?? '').toString(); _defaultMealCategory = _mealSource!.defaultMealCategory.target; _defaultMealCategoryController.text = (_defaultMealCategory ?? '').toString(); _defaultMealPortionType = _mealSource!.defaultMealPortionType.target; _defaultMealPortionTypeController.text = (_defaultMealPortionType ?? '').toString(); } } void reload({String? message}) { if (widget.id != 0) { setState(() { _mealSource = MealSource.get(widget.id); }); } _isNew = _mealSource == null; setState(() { if (message != null) { var snackBar = SnackBar( content: Text(message), duration: const Duration(seconds: 2), ); ScaffoldMessenger.of(context) ..removeCurrentSnackBar() ..showSnackBar(snackBar); } }); } void handleSaveAction() async { MealSource mealSource = MealSource( id: widget.id, value: _valueController.text, notes: _notesController.text, ); mealSource.defaultCarbsRatioAccuracy.target = _defaultCarbsRatioAccuracy; mealSource.defaultPortionSizeAccuracy.target = _defaultPortionSizeAccuracy; mealSource.defaultMealCategory.target = _defaultMealCategory; mealSource.defaultMealPortionType.target = _defaultMealPortionType; MealSource.put(mealSource); Navigator.pop(context, ['${_isNew ? 'New' : ''} Meal Source saved', mealSource]); } void handleCancelAction() { if (Settings.get().showConfirmationDialogOnCancel && ((_isNew && (_valueController.text != '' || _defaultCarbsRatioAccuracy != null || _defaultPortionSizeAccuracy != null || _defaultMealCategory != null || _defaultMealPortionType != null || _notesController.text != '')) || (!_isNew && (_valueController.text != _mealSource!.value || _defaultCarbsRatioAccuracy != _mealSource!.defaultCarbsRatioAccuracy.target || _defaultPortionSizeAccuracy != _mealSource!.defaultPortionSizeAccuracy.target || _defaultMealCategory != _mealSource!.defaultMealCategory.target || _defaultMealPortionType != _mealSource!.defaultMealPortionType.target || _notesController.text != (_mealSource!.notes ?? ''))))) { Dialogs.showCancelConfirmationDialog( context: context, isNew: _isNew, onSave: handleSaveAction, ); } else { Navigator.pop(context); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(_isNew ? 'New Meal Source' : _mealSource!.value), ), drawer: const Navigation(currentLocation: MealSourceDetailScreen.routeName), body: Scrollbar( controller: _scrollController, child: SingleChildScrollView( controller: _scrollController, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ FormWrapper( formState: _mealSourceForm, fields: [ TextFormField( controller: _valueController, decoration: const InputDecoration( labelText: 'Name', ), validator: (value) { if (value!.trim().isEmpty) { return 'Empty name'; } return null; }, ), Row( children: [ Expanded( child: AutoCompleteDropdownButton( selectedItem: _defaultCarbsRatioAccuracy, controller: _defaultCarbsRatioAccuracyController, label: 'Default Carbs Ratio Accuracy', items: _carbsRatioAccuracies, onChanged: (value) { setState(() { _defaultCarbsRatioAccuracy = value; _defaultCarbsRatioAccuracyController.text = (_defaultCarbsRatioAccuracy ?? '').toString(); }); }, ), ), IconButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => _defaultCarbsRatioAccuracy == null ? const AccuracyDetailScreen() : AccuracyDetailScreen( id: _defaultCarbsRatioAccuracy!.id), ), ).then((result) { setState(() { _defaultCarbsRatioAccuracy = result?[1]; _defaultCarbsRatioAccuracyController.text = (_defaultCarbsRatioAccuracy ?? '').toString(); }); reload(message: result?[0]); }); }, icon: Icon(_defaultCarbsRatioAccuracy == null ? Icons.add : Icons.edit), ), ], ), Row( children: [ Expanded( child: AutoCompleteDropdownButton( selectedItem: _defaultPortionSizeAccuracy, controller: _defaultPortionSizeAccuracyController, label: 'Default Portion Size Accuracy', items: _portionSizeAccuracies, onChanged: (value) { setState(() { _defaultPortionSizeAccuracy = value; _defaultPortionSizeAccuracyController.text = (_defaultPortionSizeAccuracy ?? '') .toString(); }); }, ), ), IconButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => _defaultPortionSizeAccuracy == null ? const AccuracyDetailScreen() : AccuracyDetailScreen( id: _defaultPortionSizeAccuracy!.id), ), ).then((result) { setState(() { _defaultPortionSizeAccuracy = result?[1]; _defaultPortionSizeAccuracyController.text = (_defaultPortionSizeAccuracy ?? '') .toString(); }); reload(message: result?[0]); }); }, icon: Icon(_defaultPortionSizeAccuracy == null ? Icons.add : Icons.edit), ), ], ), Row( children: [ Expanded( child: AutoCompleteDropdownButton( selectedItem: _defaultMealCategory, controller: _defaultMealCategoryController, label: 'Default Meal Category', items: _mealCategories, onChanged: (value) { setState(() { _defaultMealCategory = value; _defaultMealCategoryController.text = (_defaultMealCategory ?? '').toString(); }); }, ), ), IconButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => _defaultMealCategory == null ? const MealCategoryDetailScreen() : MealCategoryDetailScreen( id: _defaultMealCategory!.id), ), ).then((result) { setState(() { _defaultMealCategory = result?[1]; _defaultMealCategoryController.text = (_defaultMealCategory ?? '').toString(); }); reload(message: result?[0]); }); }, icon: Icon(_defaultMealCategory == null ? Icons.add : Icons.edit), ), ], ), Row( children: [ Expanded( child: AutoCompleteDropdownButton( selectedItem: _defaultMealPortionType, controller: _defaultMealPortionTypeController, label: 'Default Meal Portion Type', items: _mealPortionTypes, onChanged: (value) { setState(() { _defaultMealPortionType = value; _defaultMealPortionTypeController.text = (_defaultMealPortionType ?? '').toString(); }); }, ), ), IconButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => _defaultMealPortionType == null ? const MealPortionTypeDetailScreen() : MealPortionTypeDetailScreen( id: _defaultMealPortionType!.id), ), ).then((result) { setState(() { _defaultMealPortionType = result?[1]; _defaultMealPortionTypeController.text = (_defaultMealPortionType ?? '').toString(); }); reload(message: result?[0]); }); }, icon: Icon(_defaultMealPortionType == null ? Icons.add : Icons.edit), ), ], ), TextFormField( controller: _notesController, decoration: const InputDecoration( labelText: 'Notes', ), keyboardType: TextInputType.multiline, minLines: 2, maxLines: 5, ) ], ), ], ), ), ), bottomNavigationBar: DetailBottomRow( onCancel: handleCancelAction, onSave: handleSaveAction, ), ); } }