diameter/lib/screens/log/log_entry/log_bolus_detail.dart

227 lines
7.7 KiB
Dart

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/config.dart';
import 'package:diameter/models/bolus.dart';
import 'package:diameter/models/log_bolus.dart';
import 'package:diameter/models/log_entry.dart';
import 'package:diameter/models/log_meal.dart';
import 'package:diameter/navigation.dart';
import 'package:diameter/settings.dart';
import 'package:flutter/material.dart';
class LogBolusDetailScreen extends StatefulWidget {
static const String routeName = '/log-bolus';
final int logEntryId;
final int id;
const LogBolusDetailScreen({Key? key, this.logEntryId = 0, this.id = 0})
: super(key: key);
@override
_LogBolusDetailScreenState createState() => _LogBolusDetailScreenState();
}
class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
LogEntry? _logEntry;
LogBolus? _logBolus;
bool _isNew = true;
bool _isSaving = false;
final GlobalKey<FormState> _logBolusForm = GlobalKey<FormState>();
final _unitsController = TextEditingController(text: '');
final _carbsController = TextEditingController(text: '');
final _mgPerDlController = TextEditingController(text: '');
final _mmolPerLController = TextEditingController(text: '');
final _delayController = TextEditingController(text: '');
final _notesController = TextEditingController(text: '');
bool _manuallyAdjusted = false;
LogMeal? _meal;
Bolus? _rate;
List<LogMeal> _logMeals = [];
@override
void initState() {
super.initState();
reload();
_logEntry = LogEntry.get(widget.logEntryId);
_logMeals = _logEntry?.meals ?? [];
if (widget.id != 0) {
_unitsController.text = _logBolus!.units.toString();
_carbsController.text = (_logBolus!.carbs ?? '').toString();
_mgPerDlController.text = (_logBolus!.mgPerDl ?? '').toString();
_mmolPerLController.text = (_logBolus!.mmolPerL ?? '').toString();
_delayController.text = (_logBolus!.delay ?? '').toString();
_notesController.text = _logBolus!.notes ?? '';
_manuallyAdjusted = _logBolus!.manuallyAdjusted;
_meal = _logBolus!.meal.target;
_rate = _logBolus!.rate.target ?? Bolus.getRateForTime(_logEntry?.time);
}
}
void reload() {
if (widget.id != 0) {
setState(() {
_logBolus = LogBolus.get(widget.id);
});
}
_isNew = _logBolus == null;
}
Future<void> onSelectMeal(LogMeal meal) async {
setState(() {
_meal = meal;
if (meal.carbsPerPortion != null) {
_carbsController.text = meal.carbsPerPortion.toString();
if (_rate != null) {
_unitsController.text =
(meal.carbsPerPortion ?? 0 / (_rate!.carbs / _rate!.units))
.toString();
}
}
});
}
void handleSaveAction() async {
setState(() {
_isSaving = true;
});
if (_logBolusForm.currentState!.validate()) {
LogBolus logBolus = LogBolus(
id: widget.id,
units: double.tryParse(_unitsController.text) ?? 0,
carbs: double.tryParse(_carbsController.text),
mgPerDl: int.tryParse(_mgPerDlController.text),
mmolPerL: double.tryParse(_mmolPerLController.text),
delay: int.tryParse(_delayController.text),
manuallyAdjusted: _manuallyAdjusted,
notes: _notesController.text,
);
logBolus.logEntry.target = _logEntry;
logBolus.meal.target = _meal;
logBolus.rate.target = _rate;
LogBolus.put(logBolus);
Navigator.pop(context, '${_isNew ? 'New' : ''} Bolus Saved');
}
setState(() {
_isSaving = false;
});
}
void handleCancelAction() {
if (showConfirmationDialogOnCancel &&
((_isNew &&
(_unitsController.text != '' ||
_carbsController.text != '' ||
_mgPerDlController.text != '' ||
_mmolPerLController.text != '' ||
_delayController.text != '' ||
_manuallyAdjusted ||
_notesController.text != '')) ||
(!_isNew &&
(double.tryParse(_unitsController.text) != _logBolus!.units ||
double.tryParse(_carbsController.text) != _logBolus!.carbs ||
int.tryParse(_mgPerDlController.text) != _logBolus!.mgPerDl ||
double.tryParse(_mmolPerLController.text) != _logBolus!.mmolPerL ||
int.tryParse(_delayController.text) != _logBolus!.delay ||
_manuallyAdjusted != _logBolus!.manuallyAdjusted ||
_notesController.text != (_logBolus!.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 Bolus' : 'Edit Bolus'),
),
drawer: const Navigation(currentLocation: LogBolusDetailScreen.routeName),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
FormWrapper(
formState: _logBolusForm,
fields: [
TextFormField(
decoration: const InputDecoration(
labelText: 'Bolus Units',
suffixText: ' U',
),
controller: _unitsController,
keyboardType:
const TextInputType.numberWithOptions(decimal: true),
),
AutoCompleteDropdownButton<LogMeal>(
selectedItem: _meal,
label: 'Meal',
items: _logMeals,
renderItem: (item) => item.value,
onChanged: (value) {
if (value != null) {
onSelectMeal(value);
}
},
),
Expanded(
child: TextFormField(
decoration: InputDecoration(
labelText: 'Carbs',
suffixText:
nutritionMeasurement == NutritionMeasurement.grams
? 'g'
: nutritionMeasurement ==
NutritionMeasurement.ounces
? 'oz'
: '',
),
controller: _carbsController,
keyboardType: const TextInputType.numberWithOptions(
decimal: true),
),
),
TextFormField(
decoration: const InputDecoration(
labelText: 'Delayed Bolus Duration',
suffixText: ' min',
),
controller: _delayController,
keyboardType: const TextInputType.numberWithOptions(),
),
TextFormField(
controller: _notesController,
decoration: const InputDecoration(
labelText: 'Notes',
alignLabelWithHint: true,
),
keyboardType: TextInputType.multiline,
),
],
),
],
),
),
bottomNavigationBar: DetailBottomRow(
onCancel: handleCancelAction,
onSave: _isSaving ? null : handleSaveAction,
),
);
}
}