227 lines
7.7 KiB
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,
|
|
),
|
|
);
|
|
}
|
|
}
|