fix objectbox meta model, update todo list, add date picker to log entry
This commit is contained in:
parent
f7d727e070
commit
ab0839bff3
34
TODO
34
TODO
@ -1,7 +1,37 @@
|
||||
|
||||
Todo:
|
||||
General/Framework:
|
||||
☐ add active/deleted flag to all data models
|
||||
☐ account for deleted/disabled elements in dropdowns
|
||||
☐ place dropdown items right below their input
|
||||
✔ use local database instead of back4app @done(21-11-07 18:53)
|
||||
☐ find a general way to deal with duration fields
|
||||
☐ add explanations to each section
|
||||
☐ use ids instead of passing entities around where possible
|
||||
|
||||
Accuracies:
|
||||
☐ implement reordering
|
||||
|
||||
Basal/Bolus:
|
||||
☐ create distinct visual mode for picking the active profile
|
||||
|
||||
Meal:
|
||||
none
|
||||
|
||||
Log Overview:
|
||||
☐ add active events view
|
||||
☐ adjust/debug active events view
|
||||
☐ display more information
|
||||
☐ apply target color settings to glucose
|
||||
☐ total bolus and carbs per entry
|
||||
|
||||
Log Entry:
|
||||
☐ add tab for bolus overview
|
||||
☐ calculate bolus suggestions according to active profile
|
||||
☐ add time picker for entry date/time
|
||||
|
||||
Event Types:
|
||||
☐ add option to change bolus/basal profile for event duration
|
||||
|
||||
Settings:
|
||||
☐ add objectbox class and use instead of shared preferences
|
||||
☐ add fields for date and time formats
|
||||
☐ add fields for glucose target
|
@ -1,43 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class DataTableContent {
|
||||
bool selected = false;
|
||||
List<DataCell> asDataTableCells(List<Widget> actions) => [];
|
||||
static List<DataColumn> asDataTableColumns() => [];
|
||||
}
|
||||
|
||||
class DataTableSourceBuilder extends DataTableSource {
|
||||
final List<DataTableContent> data;
|
||||
final BuildContext context;
|
||||
|
||||
DataTableSourceBuilder(this.context, this.data);
|
||||
|
||||
@override
|
||||
bool get isRowCountApproximate => false;
|
||||
|
||||
@override
|
||||
int get rowCount => data.length;
|
||||
|
||||
@override
|
||||
int get selectedRowCount {
|
||||
int count = 0;
|
||||
for (var element in data) {
|
||||
if (element.selected) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@override
|
||||
DataRow? getRow(int index) {
|
||||
assert(index >= 0);
|
||||
if (index >= data.length) return null;
|
||||
final rowData = data[index];
|
||||
return DataRow.byIndex(
|
||||
index: index,
|
||||
selected: rowData.selected,
|
||||
cells: rowData.asDataTableCells([]),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,19 +1,18 @@
|
||||
import 'package:diameter/components/progress_indicator.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StyledForm extends StatefulWidget {
|
||||
class FormWrapper extends StatefulWidget {
|
||||
final List<Widget>? fields;
|
||||
final List<Widget>? buttons;
|
||||
final GlobalKey<FormState>? formState;
|
||||
|
||||
const StyledForm({Key? key, this.formState, this.fields, this.buttons})
|
||||
const FormWrapper({Key? key, this.formState, this.fields, this.buttons})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_StyledFormState createState() => _StyledFormState();
|
||||
_FormWrapperState createState() => _FormWrapperState();
|
||||
}
|
||||
|
||||
class _StyledFormState extends State<StyledForm> {
|
||||
class _FormWrapperState extends State<FormWrapper> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
@ -45,13 +44,13 @@ class _StyledFormState extends State<StyledForm> {
|
||||
}
|
||||
}
|
||||
|
||||
class StyledBooleanFormField extends StatefulWidget {
|
||||
class BooleanFormField extends StatefulWidget {
|
||||
final bool value;
|
||||
final String label;
|
||||
final void Function(bool) onChanged;
|
||||
final bool? enabled;
|
||||
|
||||
const StyledBooleanFormField(
|
||||
const BooleanFormField(
|
||||
{Key? key,
|
||||
required this.value,
|
||||
required this.label,
|
||||
@ -60,10 +59,10 @@ class StyledBooleanFormField extends StatefulWidget {
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_StyledBooleanFormFieldState createState() => _StyledBooleanFormFieldState();
|
||||
_BooleanFormFieldState createState() => _BooleanFormFieldState();
|
||||
}
|
||||
|
||||
class _StyledBooleanFormFieldState extends State<StyledBooleanFormField> {
|
||||
class _BooleanFormFieldState extends State<BooleanFormField> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FormField<bool>(builder: (context) {
|
||||
@ -80,13 +79,58 @@ class _StyledBooleanFormFieldState extends State<StyledBooleanFormField> {
|
||||
}
|
||||
}
|
||||
|
||||
class StyledTimeOfDayFormField extends StatefulWidget {
|
||||
class DateTimeFormField extends StatefulWidget {
|
||||
final DateTime date;
|
||||
final DateTime? minDate;
|
||||
final DateTime? maxDate;
|
||||
final TextEditingController controller;
|
||||
final String label;
|
||||
final void Function(DateTime?) onChanged;
|
||||
|
||||
const DateTimeFormField(
|
||||
{Key? key,
|
||||
required this.date,
|
||||
this.minDate,
|
||||
this.maxDate,
|
||||
required this.controller,
|
||||
required this.label,
|
||||
required this.onChanged})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_DateTimeFormFieldState createState() =>
|
||||
_DateTimeFormFieldState();
|
||||
}
|
||||
|
||||
class _DateTimeFormFieldState extends State<DateTimeFormField> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextFormField(
|
||||
readOnly: true,
|
||||
controller: widget.controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: widget.label,
|
||||
),
|
||||
onTap: () async {
|
||||
final newTime = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: widget.date,
|
||||
firstDate: widget.minDate ?? DateTime(2000,1,1),
|
||||
lastDate: widget.maxDate ?? DateTime.now(),
|
||||
);
|
||||
widget.onChanged(newTime);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TimeOfDayFormField extends StatefulWidget {
|
||||
final TimeOfDay time;
|
||||
final TextEditingController controller;
|
||||
final String label;
|
||||
final void Function(TimeOfDay?) onChanged;
|
||||
|
||||
const StyledTimeOfDayFormField(
|
||||
const TimeOfDayFormField(
|
||||
{Key? key,
|
||||
required this.time,
|
||||
required this.controller,
|
||||
@ -95,11 +139,11 @@ class StyledTimeOfDayFormField extends StatefulWidget {
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_StyledTimeOfDayFormFieldState createState() =>
|
||||
_StyledTimeOfDayFormFieldState();
|
||||
_TimeOfDayFormFieldState createState() =>
|
||||
_TimeOfDayFormFieldState();
|
||||
}
|
||||
|
||||
class _StyledTimeOfDayFormFieldState extends State<StyledTimeOfDayFormField> {
|
||||
class _TimeOfDayFormFieldState extends State<TimeOfDayFormField> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextFormField(
|
||||
@ -119,14 +163,14 @@ class _StyledTimeOfDayFormFieldState extends State<StyledTimeOfDayFormField> {
|
||||
}
|
||||
}
|
||||
|
||||
class StyledDropdownButton<T> extends StatefulWidget {
|
||||
class LabeledDropdownButton<T> extends StatefulWidget {
|
||||
final String label;
|
||||
final T? selectedItem;
|
||||
final List<T> items;
|
||||
final Widget Function(T item) renderItem;
|
||||
final void Function(T? value) onChanged;
|
||||
|
||||
const StyledDropdownButton(
|
||||
const LabeledDropdownButton(
|
||||
{Key? key,
|
||||
this.selectedItem,
|
||||
required this.label,
|
||||
@ -136,10 +180,10 @@ class StyledDropdownButton<T> extends StatefulWidget {
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_StyledDropdownButtonState<T> createState() => _StyledDropdownButtonState();
|
||||
_LabeledDropdownButtonState<T> createState() => _LabeledDropdownButtonState();
|
||||
}
|
||||
|
||||
class _StyledDropdownButtonState<T> extends State<StyledDropdownButton<T>> {
|
||||
class _LabeledDropdownButtonState<T> extends State<LabeledDropdownButton<T>> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DropdownButtonFormField<T>(
|
||||
@ -158,65 +202,3 @@ class _StyledDropdownButtonState<T> extends State<StyledDropdownButton<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
class StyledFutureDropdownButton<T> extends StatefulWidget {
|
||||
final String label;
|
||||
final String? selectedItem;
|
||||
final Future<List<T>> items;
|
||||
final String? Function(T item) getItemValue;
|
||||
final Widget Function(T item) renderItem;
|
||||
final void Function(String? value) onChanged;
|
||||
|
||||
const StyledFutureDropdownButton(
|
||||
{Key? key,
|
||||
this.selectedItem,
|
||||
required this.label,
|
||||
required this.items,
|
||||
required this.getItemValue,
|
||||
required this.renderItem,
|
||||
required this.onChanged})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_StyledFutureDropdownButtonState<T> createState() =>
|
||||
_StyledFutureDropdownButtonState();
|
||||
}
|
||||
|
||||
class _StyledFutureDropdownButtonState<T>
|
||||
extends State<StyledFutureDropdownButton<T>> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<List<T>>(
|
||||
future: widget.items,
|
||||
builder: (context, snapshot) {
|
||||
return ViewWithProgressIndicator(
|
||||
snapshot: snapshot,
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
progressIndicatorSize: 44,
|
||||
child: snapshot.data == null || snapshot.data!.isEmpty
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(10.0),
|
||||
child: Text('No Meal Sources'),
|
||||
)
|
||||
],
|
||||
)
|
||||
: DropdownButtonFormField<String>(
|
||||
decoration: InputDecoration(
|
||||
labelText: widget.label,
|
||||
),
|
||||
value: widget.selectedItem,
|
||||
onChanged: widget.onChanged,
|
||||
items: snapshot.data!
|
||||
.map((item) => DropdownMenuItem<String>(
|
||||
value: widget.getItemValue(item),
|
||||
child: widget.renderItem(item),
|
||||
))
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
// import 'package:flutter/widgets.dart';
|
||||
|
||||
class ViewWithProgressIndicator extends StatefulWidget {
|
||||
final AsyncSnapshot snapshot;
|
||||
final Widget child;
|
||||
final double progressIndicatorSize;
|
||||
final EdgeInsets padding;
|
||||
|
||||
const ViewWithProgressIndicator(
|
||||
{Key? key,
|
||||
required this.snapshot,
|
||||
required this.child,
|
||||
this.progressIndicatorSize = 100,
|
||||
this.padding = const EdgeInsets.all(0)})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_ViewWithProgressIndicatorState createState() =>
|
||||
_ViewWithProgressIndicatorState();
|
||||
}
|
||||
|
||||
class _ViewWithProgressIndicatorState extends State<ViewWithProgressIndicator> {
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
switch (widget.snapshot.connectionState) {
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: widget.padding,
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: widget.progressIndicatorSize,
|
||||
height: widget.progressIndicatorSize,
|
||||
child: FutureBuilder(
|
||||
future: Future.delayed(const Duration(seconds: 1)),
|
||||
builder: (context, wait) {
|
||||
if (wait.connectionState != ConnectionState.waiting) {
|
||||
return const CircularProgressIndicator();
|
||||
}
|
||||
return Container();
|
||||
}
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
default:
|
||||
if (widget.snapshot.hasError) {
|
||||
return Center(
|
||||
child: Text(widget.snapshot.error.toString()),
|
||||
);
|
||||
}
|
||||
if (!widget.snapshot.hasData) {
|
||||
return const Center(
|
||||
child: Text("No data"),
|
||||
);
|
||||
} else {
|
||||
return widget.child;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';
|
||||
import 'package:diameter/screens/accuracy_list.dart';
|
||||
import 'package:diameter/config.dart';
|
||||
import 'package:diameter/screens/basal/basal_profiles_list.dart';
|
||||
import 'package:diameter/screens/basal/basal_profile_list.dart';
|
||||
import 'package:diameter/screens/bolus/bolus_profile_list.dart';
|
||||
import 'package:diameter/navigation.dart';
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:diameter/main.dart';
|
||||
import 'package:diameter/objectbox.g.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 3095978685310268382)
|
||||
class Accuracy {
|
||||
static final Box<Accuracy> box = objectBox.store.box<Accuracy>();
|
||||
|
||||
|
@ -2,7 +2,7 @@ import 'package:diameter/main.dart';
|
||||
import 'package:diameter/models/basal_profile.dart';
|
||||
import 'package:diameter/objectbox.g.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 1467758525778521891)
|
||||
class Basal {
|
||||
static final Box<Basal> box = objectBox.store.box<Basal>();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:diameter/main.dart';
|
||||
import 'package:diameter/objectbox.g.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 3613736032926903785)
|
||||
class BasalProfile {
|
||||
static final Box<BasalProfile> box = objectBox.store.box<BasalProfile>();
|
||||
|
||||
|
@ -2,7 +2,7 @@ import 'package:diameter/main.dart';
|
||||
import 'package:diameter/models/bolus_profile.dart';
|
||||
import 'package:diameter/objectbox.g.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 3417770529060202389)
|
||||
class Bolus {
|
||||
static final Box<Bolus> box = objectBox.store.box<Bolus>();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:diameter/main.dart';
|
||||
import 'package:diameter/objectbox.g.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 8812452529027052317)
|
||||
class BolusProfile {
|
||||
static final Box<BolusProfile> box = objectBox.store.box<BolusProfile>();
|
||||
|
||||
|
@ -2,9 +2,8 @@ import 'package:diameter/main.dart';
|
||||
import 'package:diameter/models/log_event.dart';
|
||||
import 'package:diameter/models/log_meal.dart';
|
||||
import 'package:diameter/objectbox.g.dart';
|
||||
import 'package:objectbox/objectbox.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 752131069307970560)
|
||||
class LogEntry {
|
||||
static final Box<LogEntry> box = objectBox.store.box<LogEntry>();
|
||||
|
||||
|
@ -3,7 +3,7 @@ import 'package:diameter/models/log_entry.dart';
|
||||
import 'package:diameter/models/log_event_type.dart';
|
||||
import 'package:diameter/objectbox.g.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 4303325892753185970)
|
||||
class LogEvent {
|
||||
static final Box<LogEvent> box = objectBox.store.box<LogEvent>();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:diameter/main.dart';
|
||||
import 'package:objectbox/objectbox.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 8362795406595606110)
|
||||
class LogEventType {
|
||||
static final Box<LogEventType> box = objectBox.store.box<LogEventType>();
|
||||
|
||||
|
@ -7,7 +7,7 @@ import 'package:diameter/models/meal_source.dart';
|
||||
import 'package:diameter/models/accuracy.dart';
|
||||
import 'package:objectbox/objectbox.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 411177866700467286)
|
||||
class LogMeal {
|
||||
static final Box<LogMeal> box = objectBox.store.box<LogMeal>();
|
||||
|
||||
|
@ -7,7 +7,7 @@ import 'package:objectbox/objectbox.dart';
|
||||
|
||||
enum PortionCarbsParameter { carbsRatio, portionSize, carbsPerPortion }
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 382130101578692012)
|
||||
class Meal {
|
||||
static final Box<Meal> box = objectBox.store.box<Meal>();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:diameter/main.dart';
|
||||
import 'package:objectbox/objectbox.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 3158200688796904913)
|
||||
class MealCategory {
|
||||
static final Box<MealCategory> box = objectBox.store.box<MealCategory>();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import 'package:diameter/main.dart';
|
||||
import 'package:objectbox/objectbox.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 2111511899235985637)
|
||||
class MealPortionType {
|
||||
static final Box<MealPortionType> box = objectBox.store.box<MealPortionType>();
|
||||
|
||||
|
@ -4,7 +4,7 @@ import 'package:diameter/models/meal_category.dart';
|
||||
import 'package:diameter/models/meal_portion_type.dart';
|
||||
import 'package:objectbox/objectbox.dart';
|
||||
|
||||
@Entity()
|
||||
@Entity(uid: 1283034494527412242)
|
||||
class MealSource {
|
||||
static final Box<MealSource> box = objectBox.store.box<MealSource>();
|
||||
|
||||
|
@ -2,7 +2,7 @@ import 'package:diameter/screens/accuracy_detail.dart';
|
||||
import 'package:diameter/screens/accuracy_list.dart';
|
||||
import 'package:diameter/screens/basal/basal_detail.dart';
|
||||
import 'package:diameter/screens/basal/basal_profile_detail.dart';
|
||||
import 'package:diameter/screens/basal/basal_profiles_list.dart';
|
||||
import 'package:diameter/screens/basal/basal_profile_list.dart';
|
||||
import 'package:diameter/screens/bolus/bolus_detail.dart';
|
||||
import 'package:diameter/screens/bolus/bolus_profile_detail.dart';
|
||||
import 'package:diameter/screens/bolus/bolus_profile_list.dart';
|
||||
|
@ -665,8 +665,8 @@ Future<Store> openStore(
|
||||
ModelDefinition getObjectBoxModel() {
|
||||
final model = ModelInfo(
|
||||
entities: _entities,
|
||||
lastEntityId: const IdUid(18, 1283034494527412242),
|
||||
lastIndexId: const IdUid(25, 1931330716440762729),
|
||||
lastEntityId: const IdUid(13, 1283034494527412242),
|
||||
lastIndexId: const IdUid(21, 1931330716440762729),
|
||||
lastRelationId: const IdUid(0, 0),
|
||||
lastSequenceId: const IdUid(0, 0),
|
||||
retiredEntityUids: const [],
|
||||
|
@ -108,7 +108,7 @@ class _AccuracyDetailScreenState extends State<AccuracyDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _accuracyForm,
|
||||
fields: [
|
||||
TextFormField(
|
||||
@ -123,7 +123,7 @@ class _AccuracyDetailScreenState extends State<AccuracyDetailScreen> {
|
||||
return null;
|
||||
},
|
||||
),
|
||||
StyledBooleanFormField(
|
||||
BooleanFormField(
|
||||
value: _forCarbsRatio,
|
||||
label: 'for carbs ratio',
|
||||
onChanged: (value) {
|
||||
@ -132,7 +132,7 @@ class _AccuracyDetailScreenState extends State<AccuracyDetailScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
StyledBooleanFormField(
|
||||
BooleanFormField(
|
||||
value: _forPortionSize,
|
||||
label: 'for portion size',
|
||||
onChanged: (value) {
|
||||
|
@ -105,6 +105,7 @@ class _AccuracyListScreenState extends State<AccuracyListScreen> {
|
||||
IconButton(
|
||||
icon: const Icon(Icons.reorder),
|
||||
onPressed: () {
|
||||
// ignore: todo
|
||||
// TODO: implement reordering
|
||||
},
|
||||
),
|
||||
|
@ -85,8 +85,6 @@ class _BasalDetailScreenState extends State<BasalDetailScreen> {
|
||||
String? error;
|
||||
List<Basal> basalRates = Basal.getAllForProfile(widget.basalProfileId);
|
||||
|
||||
// TODO use a query for the following checks instead?
|
||||
// check for duplicates
|
||||
if (basalRates
|
||||
.where((other) =>
|
||||
(widget.id != other.id) &&
|
||||
@ -187,7 +185,7 @@ class _BasalDetailScreenState extends State<BasalDetailScreen> {
|
||||
drawer: const Navigation(currentLocation: BasalDetailScreen.routeName),
|
||||
body: Column(
|
||||
children: [
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _basalForm,
|
||||
fields: [
|
||||
Row(
|
||||
@ -195,7 +193,7 @@ class _BasalDetailScreenState extends State<BasalDetailScreen> {
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 5),
|
||||
child: StyledTimeOfDayFormField(
|
||||
child: TimeOfDayFormField(
|
||||
label: 'Start Time',
|
||||
controller: _startTimeController,
|
||||
time: _startTime,
|
||||
@ -213,7 +211,7 @@ class _BasalDetailScreenState extends State<BasalDetailScreen> {
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 5),
|
||||
child: StyledTimeOfDayFormField(
|
||||
child: TimeOfDayFormField(
|
||||
label: 'End Time',
|
||||
controller: _endTimeController,
|
||||
time: _endTime,
|
||||
|
@ -72,7 +72,6 @@ class _BasalListScreenState extends State<BasalListScreen> {
|
||||
List<Basal> basalRates = widget.basalRates;
|
||||
Basal basal = basalRates[index];
|
||||
|
||||
// TODO: use queries for all this
|
||||
// check for gaps
|
||||
if (index == 0 &&
|
||||
(basal.startTime.hour != 0 || basal.startTime.minute != 0)) {
|
||||
|
@ -27,7 +27,6 @@ class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
|
||||
BasalProfile? _basalProfile;
|
||||
List<Basal> _basalRates = [];
|
||||
bool _isNew = true;
|
||||
bool _isSaving = false;
|
||||
|
||||
final GlobalKey<FormState> _basalProfileForm = GlobalKey<FormState>();
|
||||
|
||||
@ -35,6 +34,7 @@ class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
|
||||
late IconButton refreshButton;
|
||||
late IconButton closeButton;
|
||||
late DetailBottomRow detailBottomRow;
|
||||
late DetailBottomRow detailBottomRowWhileSaving;
|
||||
|
||||
FloatingActionButton? actionButton;
|
||||
List<Widget> appBarActions = [];
|
||||
@ -77,7 +77,12 @@ class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
|
||||
|
||||
detailBottomRow = DetailBottomRow(
|
||||
onCancel: handleCancelAction,
|
||||
onSave: _isSaving ? null : handleSaveAction,
|
||||
onSave: handleSaveAction,
|
||||
);
|
||||
|
||||
detailBottomRowWhileSaving = DetailBottomRow(
|
||||
onCancel: handleCancelAction,
|
||||
onSave: null,
|
||||
);
|
||||
|
||||
actionButton = null;
|
||||
@ -146,7 +151,7 @@ class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
|
||||
});
|
||||
} else if (!_active &&
|
||||
((_isNew && _activeCount == 0) ||
|
||||
(_activeCount == 1 && _basalProfile!.active))) {
|
||||
(!_isNew && _activeCount == 1 && _basalProfile!.active))) {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
@ -214,7 +219,7 @@ class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
|
||||
|
||||
void handleSaveAction() async {
|
||||
setState(() {
|
||||
_isSaving = true;
|
||||
bottomNav = detailBottomRowWhileSaving;
|
||||
});
|
||||
if (_basalProfileForm.currentState!.validate()) {
|
||||
await checkActiveProfiles();
|
||||
@ -227,7 +232,7 @@ class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
|
||||
Navigator.pop(context, '${_isNew ? 'New' : ''} Basal Profile saved');
|
||||
}
|
||||
setState(() {
|
||||
_isSaving = false;
|
||||
bottomNav = detailBottomRow;
|
||||
});
|
||||
}
|
||||
|
||||
@ -283,7 +288,7 @@ class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _basalProfileForm,
|
||||
fields: [
|
||||
TextFormField(
|
||||
@ -307,7 +312,7 @@ class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
|
||||
alignLabelWithHint: true,
|
||||
),
|
||||
),
|
||||
StyledBooleanFormField(
|
||||
BooleanFormField(
|
||||
value: _active,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
|
@ -93,9 +93,7 @@ class _BolusDetailScreenState extends State<BolusDetailScreen> {
|
||||
Future<String?> validateTimePeriod() async {
|
||||
String? error;
|
||||
List<Bolus> bolusRates = Bolus.getAllForProfile(widget.bolusProfileId);
|
||||
// BolusProfile.get(widget.bolusProfileId)?.bolusRates ?? [];
|
||||
|
||||
// TODO use a query for the following checks instead?
|
||||
// check for duplicates
|
||||
if (bolusRates
|
||||
.where((other) =>
|
||||
@ -238,7 +236,7 @@ class _BolusDetailScreenState extends State<BolusDetailScreen> {
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _bolusForm,
|
||||
fields: [
|
||||
Row(
|
||||
@ -246,7 +244,7 @@ class _BolusDetailScreenState extends State<BolusDetailScreen> {
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 5),
|
||||
child: StyledTimeOfDayFormField(
|
||||
child: TimeOfDayFormField(
|
||||
label: 'Start Time',
|
||||
controller: _startTimeController,
|
||||
time: _startTime,
|
||||
@ -264,7 +262,7 @@ class _BolusDetailScreenState extends State<BolusDetailScreen> {
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 5),
|
||||
child: StyledTimeOfDayFormField(
|
||||
child: TimeOfDayFormField(
|
||||
label: 'End Time',
|
||||
controller: _endTimeController,
|
||||
time: _endTime,
|
||||
|
@ -70,8 +70,6 @@ class _BolusListScreenState extends State<BolusListScreen> {
|
||||
List<Bolus> bolusRates = widget.bolusRates;
|
||||
Bolus bolus = bolusRates[index];
|
||||
|
||||
// TODO: use queries for all this
|
||||
// check for gaps
|
||||
if (index == 0 &&
|
||||
(bolus.startTime.toLocal().hour != 0 || bolus.startTime.minute != 0)) {
|
||||
return 'First Bolus of the day needs to start at 00:00';
|
||||
|
@ -26,7 +26,6 @@ class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
|
||||
BolusProfile? _bolusProfile;
|
||||
List<Bolus> _bolusRates = [];
|
||||
bool _isNew = true;
|
||||
bool _isSaving = false;
|
||||
|
||||
final GlobalKey<FormState> _bolusProfileForm = GlobalKey<FormState>();
|
||||
|
||||
@ -34,6 +33,7 @@ class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
|
||||
late IconButton refreshButton;
|
||||
late IconButton closeButton;
|
||||
late DetailBottomRow detailBottomRow;
|
||||
late DetailBottomRow detailBottomRowWhileSaving;
|
||||
|
||||
FloatingActionButton? actionButton;
|
||||
List<Widget> appBarActions = [];
|
||||
@ -73,10 +73,14 @@ class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
|
||||
icon: const Icon(Icons.close),
|
||||
);
|
||||
|
||||
// TODO: fix (saving button doesnt get disabled)
|
||||
detailBottomRow = DetailBottomRow(
|
||||
onCancel: handleCancelAction,
|
||||
onSave: _isSaving ? null : handleSaveAction,
|
||||
onSave: handleSaveAction,
|
||||
);
|
||||
|
||||
detailBottomRowWhileSaving = DetailBottomRow(
|
||||
onCancel: handleCancelAction,
|
||||
onSave: null,
|
||||
);
|
||||
|
||||
actionButton = null;
|
||||
@ -144,7 +148,7 @@ class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
|
||||
});
|
||||
} else if (!_active &&
|
||||
((_isNew && _activeCount == 0) ||
|
||||
(_activeCount == 1 && _bolusProfile!.active))) {
|
||||
(!_isNew && _activeCount == 1 && _bolusProfile!.active))) {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
@ -212,7 +216,7 @@ class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
|
||||
|
||||
void handleSaveAction() async {
|
||||
setState(() {
|
||||
_isSaving = true;
|
||||
bottomNav = detailBottomRowWhileSaving;
|
||||
});
|
||||
|
||||
if (_bolusProfileForm.currentState!.validate()) {
|
||||
@ -229,7 +233,7 @@ class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isSaving = false;
|
||||
bottomNav = detailBottomRow;
|
||||
});
|
||||
}
|
||||
|
||||
@ -286,7 +290,7 @@ class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _bolusProfileForm,
|
||||
fields: [
|
||||
TextFormField(
|
||||
@ -309,7 +313,7 @@ class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
|
||||
controller: _notesController,
|
||||
keyboardType: TextInputType.multiline,
|
||||
),
|
||||
StyledBooleanFormField(
|
||||
BooleanFormField(
|
||||
value: _active,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
@ -326,8 +330,10 @@ class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
|
||||
];
|
||||
|
||||
if (!_isNew) {
|
||||
tabs.add(
|
||||
BolusListScreen(bolusProfile: _bolusProfile!, bolusRates: _bolusRates, reload: reload));
|
||||
tabs.add(BolusListScreen(
|
||||
bolusProfile: _bolusProfile!,
|
||||
bolusRates: _bolusRates,
|
||||
reload: reload));
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
|
@ -165,7 +165,6 @@ class _BolusProfileListScreenState extends State<BolusProfileListScreen> {
|
||||
? Colors.green.shade100
|
||||
: null,
|
||||
onTap: () {
|
||||
// TODO: make pick active profile visually distinct
|
||||
pickActiveProfileMode
|
||||
? onPickActive(bolusProfile)
|
||||
: onEdit(bolusProfile);
|
||||
|
@ -96,7 +96,6 @@ class _ActiveLogEventListScreenState extends State<ActiveLogEventListScreen> {
|
||||
padding: const EdgeInsets.only(top: 10.0),
|
||||
child: Column(
|
||||
children: [
|
||||
// TODO: make action button instead of appbar
|
||||
AppBar(
|
||||
title: const Text('Active Events'),
|
||||
primary: false,
|
||||
|
@ -107,8 +107,8 @@ class _LogScreenState extends State<LogScreen> {
|
||||
title: Text(
|
||||
DateTimeUtils.displayTime(
|
||||
logEntry.time)),
|
||||
// TODO: add additional fields (event icons...)
|
||||
// TODO: display glucose in colors according to target settings
|
||||
// ignore: todo
|
||||
// TODO: add more data (event, glucose color...)
|
||||
subtitle: Text(logEntry
|
||||
.mgPerDl !=
|
||||
null
|
||||
@ -141,6 +141,7 @@ class _LogScreenState extends State<LogScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
// ignore: todo
|
||||
// TODO: add button for active events
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
|
@ -1,13 +1,16 @@
|
||||
import 'package:diameter/components/detail.dart';
|
||||
import 'package:diameter/components/dialogs.dart';
|
||||
import 'package:diameter/components/forms.dart';
|
||||
import 'package:diameter/config.dart';
|
||||
import 'package:diameter/models/log_entry.dart';
|
||||
import 'package:diameter/navigation.dart';
|
||||
import 'package:diameter/screens/log/log_entry_form.dart';
|
||||
import 'package:diameter/screens/log/log_event_detail.dart';
|
||||
import 'package:diameter/screens/log/log_event_list.dart';
|
||||
import 'package:diameter/screens/log/log_meal_detail.dart';
|
||||
import 'package:diameter/screens/log/log_meal_list.dart';
|
||||
import 'package:diameter/settings.dart';
|
||||
import 'package:diameter/utils/date_time_utils.dart';
|
||||
import 'package:diameter/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LogEntryScreen extends StatefulWidget {
|
||||
@ -27,6 +30,17 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||
|
||||
final GlobalKey<FormState> logEntryForm = GlobalKey<FormState>();
|
||||
|
||||
DateTime _time = DateTime.now();
|
||||
|
||||
final _timeController = TextEditingController(text: '');
|
||||
final _dateController = TextEditingController(text: '');
|
||||
final _mgPerDlController = TextEditingController(text: '');
|
||||
final _mmolPerLController = TextEditingController(text: '');
|
||||
final _bolusGlucoseController = TextEditingController(text: '');
|
||||
final _delayedBolusRateController = TextEditingController(text: '');
|
||||
final _delayedBolusDurationController = TextEditingController(text: '');
|
||||
final _notesController = TextEditingController(text: '');
|
||||
|
||||
late FloatingActionButton addMealButton;
|
||||
late FloatingActionButton addEventButton;
|
||||
late IconButton refreshButton;
|
||||
@ -37,39 +51,12 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||
List<Widget> appBarActions = [];
|
||||
DetailBottomRow? bottomNav;
|
||||
|
||||
final formDataControllers = <String, TextEditingController>{
|
||||
'time': TextEditingController(text: ''),
|
||||
'mgPerDl': TextEditingController(text: ''),
|
||||
'mmolPerL': TextEditingController(text: ''),
|
||||
'bolusGlucose': TextEditingController(text: ''),
|
||||
'delayedBolusRate': TextEditingController(text: ''),
|
||||
'delayedBolusDuration': TextEditingController(text: ''),
|
||||
'notes': TextEditingController(text: ''),
|
||||
};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
reload();
|
||||
|
||||
if (_logEntry != null) {
|
||||
formDataControllers['time']!.text = _logEntry!.time.toString();
|
||||
formDataControllers['mgPerDl']!.text =
|
||||
(_logEntry!.mgPerDl ?? '').toString();
|
||||
formDataControllers['mmolPerL']!.text =
|
||||
(_logEntry!.mmolPerL ?? '').toString();
|
||||
formDataControllers['bolusGlucose']!.text =
|
||||
(_logEntry!.bolusGlucose ?? '').toString();
|
||||
formDataControllers['delayedBolusRate']!.text =
|
||||
(_logEntry!.delayedBolusRate ?? '').toString();
|
||||
formDataControllers['delayedBolusDuration']!.text =
|
||||
(_logEntry!.delayedBolusDuration ?? '').toString();
|
||||
formDataControllers['notes']!.text = _logEntry!.notes ?? '';
|
||||
} else {
|
||||
formDataControllers['time']!.text = DateTime.now().toString();
|
||||
}
|
||||
|
||||
addMealButton = FloatingActionButton(
|
||||
onPressed: handleAddNewMeal,
|
||||
child: const Icon(Icons.add),
|
||||
@ -98,6 +85,20 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||
actionButton = null;
|
||||
appBarActions = [closeButton];
|
||||
bottomNav = detailBottomRow;
|
||||
|
||||
if (_logEntry != null) {
|
||||
_time = _logEntry!.time;
|
||||
_mgPerDlController.text = (_logEntry!.mgPerDl ?? '').toString();
|
||||
_mmolPerLController.text = (_logEntry!.mmolPerL ?? '').toString();
|
||||
_bolusGlucoseController.text = (_logEntry!.bolusGlucose ?? '').toString();
|
||||
_delayedBolusRateController.text =
|
||||
(_logEntry!.delayedBolusRate ?? '').toString();
|
||||
_delayedBolusDurationController.text =
|
||||
(_logEntry!.delayedBolusDuration ?? '').toString();
|
||||
_notesController.text = _logEntry!.notes ?? '';
|
||||
}
|
||||
|
||||
updateTime();
|
||||
}
|
||||
|
||||
void reload({String? message}) {
|
||||
@ -121,6 +122,95 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||
});
|
||||
}
|
||||
|
||||
void updateTime() {
|
||||
_timeController.text = DateTimeUtils.displayTime(_time);
|
||||
_dateController.text = DateTimeUtils.displayDate(_time);
|
||||
}
|
||||
|
||||
void convertBetweenMgPerDlAndMmolPerL({GlucoseMeasurement? calculateFrom}) {
|
||||
int? mgPerDl;
|
||||
double? mmolPerL;
|
||||
|
||||
if (calculateFrom != GlucoseMeasurement.mmolPerL &&
|
||||
_mgPerDlController.text != '') {
|
||||
mgPerDl = int.tryParse(_mgPerDlController.text);
|
||||
}
|
||||
if (calculateFrom != GlucoseMeasurement.mgPerDl &&
|
||||
_mmolPerLController.text != '') {
|
||||
mmolPerL = double.tryParse(_mmolPerLController.text);
|
||||
}
|
||||
|
||||
if (mgPerDl != null && mmolPerL == null) {
|
||||
setState(() {
|
||||
_mmolPerLController.text =
|
||||
Utils.convertMgPerDlToMmolPerL(mgPerDl!).toString();
|
||||
});
|
||||
}
|
||||
if (mmolPerL != null && mgPerDl == null) {
|
||||
setState(() {
|
||||
_mgPerDlController.text =
|
||||
Utils.convertMmolPerLToMgPerDl(mmolPerL!).toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void handleSaveAction() async {
|
||||
setState(() {
|
||||
_isSaving = true;
|
||||
});
|
||||
if (logEntryForm.currentState!.validate()) {
|
||||
LogEntry.put(LogEntry(
|
||||
id: widget.id,
|
||||
time: _time,
|
||||
mgPerDl: int.tryParse(_mgPerDlController.text),
|
||||
mmolPerL: double.tryParse(_mmolPerLController.text),
|
||||
bolusGlucose: double.tryParse(_bolusGlucoseController.text),
|
||||
delayedBolusDuration:
|
||||
int.tryParse(_delayedBolusDurationController.text),
|
||||
delayedBolusRate: double.tryParse(_delayedBolusRateController.text),
|
||||
notes: _notesController.text,
|
||||
));
|
||||
Navigator.pushReplacementNamed(context, '/log',
|
||||
arguments: '${_isNew ? 'New' : ''} Log Entry Saved');
|
||||
}
|
||||
setState(() {
|
||||
_isSaving = false;
|
||||
});
|
||||
}
|
||||
|
||||
void handleCancelAction() {
|
||||
if (showConfirmationDialogOnCancel &&
|
||||
((_isNew &&
|
||||
(int.tryParse(_mgPerDlController.text) != null ||
|
||||
double.tryParse(_mmolPerLController.text) != null ||
|
||||
double.tryParse(_bolusGlucoseController.text) != null ||
|
||||
int.tryParse(_delayedBolusDurationController.text) !=
|
||||
null ||
|
||||
double.tryParse(_delayedBolusRateController.text) != null ||
|
||||
_notesController.text != '')) ||
|
||||
(!_isNew &&
|
||||
(int.tryParse(_mgPerDlController.text) != _logEntry!.mgPerDl ||
|
||||
double.tryParse(_mmolPerLController.text) !=
|
||||
_logEntry!.mmolPerL ||
|
||||
double.tryParse(_bolusGlucoseController.text) !=
|
||||
_logEntry!.bolusGlucose ||
|
||||
int.tryParse(_delayedBolusDurationController.text) !=
|
||||
_logEntry!.delayedBolusDuration ||
|
||||
double.tryParse(_delayedBolusRateController.text) !=
|
||||
_logEntry!.delayedBolusRate ||
|
||||
_notesController.text != (_logEntry!.notes ?? ''))))) {
|
||||
Dialogs.showCancelConfirmationDialog(
|
||||
context: context,
|
||||
isNew: _isNew,
|
||||
onSave: handleSaveAction,
|
||||
onDiscard: (context) => Navigator.pushReplacementNamed(context, '/log'),
|
||||
);
|
||||
} else {
|
||||
Navigator.pushReplacementNamed(context, '/log',
|
||||
arguments: '${_isNew ? 'New' : ''} Log Entry Saved');
|
||||
}
|
||||
}
|
||||
|
||||
void handleAddNewMeal() async {
|
||||
Navigator.push(
|
||||
context,
|
||||
@ -143,73 +233,6 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||
).then((message) => reload(message: message));
|
||||
}
|
||||
|
||||
void handleSaveAction() async {
|
||||
setState(() {
|
||||
_isSaving = true;
|
||||
});
|
||||
if (logEntryForm.currentState!.validate()) {
|
||||
LogEntry.put(LogEntry(
|
||||
id: widget.id,
|
||||
time: DateTime.parse(formDataControllers['time']!.text),
|
||||
mgPerDl: int.tryParse(formDataControllers['mgPerDl']!.text),
|
||||
mmolPerL: double.tryParse(formDataControllers['mmolPerL']!.text),
|
||||
bolusGlucose:
|
||||
double.tryParse(formDataControllers['delayedBolusRate']!.text),
|
||||
delayedBolusDuration:
|
||||
int.tryParse(formDataControllers['delayedBolusDuration']!.text),
|
||||
delayedBolusRate:
|
||||
double.tryParse(formDataControllers['delayedBolusRate']!.text),
|
||||
notes: formDataControllers['notes']!.text,
|
||||
));
|
||||
Navigator.pushReplacementNamed(context, '/log',
|
||||
arguments: '${_isNew ? 'New' : ''} Log Entry Saved');
|
||||
}
|
||||
setState(() {
|
||||
_isSaving = false;
|
||||
});
|
||||
}
|
||||
|
||||
void handleCancelAction() {
|
||||
if (showConfirmationDialogOnCancel &&
|
||||
((_isNew &&
|
||||
(int.tryParse(formDataControllers['mgPerDl']?.text ?? '') !=
|
||||
null ||
|
||||
double.tryParse(formDataControllers['mmolPerL']?.text ?? '') !=
|
||||
null ||
|
||||
double.tryParse(formDataControllers['bolusGlucose']?.text ?? '') !=
|
||||
null ||
|
||||
int.tryParse(formDataControllers['delayedBolusDuration']?.text ?? '') !=
|
||||
null ||
|
||||
double.tryParse(formDataControllers['delayedBolusRate']?.text ?? '') !=
|
||||
null ||
|
||||
formDataControllers['notes']?.text != '')) ||
|
||||
(!_isNew &&
|
||||
(int.tryParse(formDataControllers['mgPerDl']?.text ?? '') !=
|
||||
_logEntry!.mgPerDl ||
|
||||
double.tryParse(formDataControllers['mmolPerL']?.text ?? '') !=
|
||||
_logEntry!.mmolPerL ||
|
||||
double.tryParse(formDataControllers['bolusGlucose']?.text ?? '') !=
|
||||
_logEntry!.bolusGlucose ||
|
||||
int.tryParse(
|
||||
formDataControllers['delayedBolusDuration']?.text ??
|
||||
'') !=
|
||||
_logEntry!.delayedBolusDuration ||
|
||||
double.tryParse(formDataControllers['delayedBolusRate']?.text ?? '') !=
|
||||
_logEntry!.delayedBolusRate ||
|
||||
formDataControllers['notes']?.text !=
|
||||
(_logEntry!.notes ?? ''))))) {
|
||||
Dialogs.showCancelConfirmationDialog(
|
||||
context: context,
|
||||
isNew: _isNew,
|
||||
onSave: handleSaveAction,
|
||||
onDiscard: (context) => Navigator.pushReplacementNamed(context, '/log'),
|
||||
);
|
||||
} else {
|
||||
Navigator.pushReplacementNamed(context, '/log',
|
||||
arguments: '${_isNew ? 'New' : ''} Log Entry Saved');
|
||||
}
|
||||
}
|
||||
|
||||
void renderTabButtons(index) {
|
||||
if (_logEntry != null) {
|
||||
setState(() {
|
||||
@ -243,8 +266,189 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||
renderTabButtons(tabController.index);
|
||||
});
|
||||
List<Widget> tabs = [
|
||||
LogEntryForm(
|
||||
formState: logEntryForm, controllers: formDataControllers),
|
||||
SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
FormWrapper(
|
||||
formState: logEntryForm,
|
||||
fields: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 5),
|
||||
child: DateTimeFormField(
|
||||
date: _time,
|
||||
label: 'Date',
|
||||
controller: _dateController,
|
||||
onChanged: (newTime) {
|
||||
if (newTime != null) {
|
||||
setState(() {
|
||||
_time = DateTime(
|
||||
newTime.year,
|
||||
newTime.month,
|
||||
newTime.day,
|
||||
_time.hour,
|
||||
_time.minute);
|
||||
});
|
||||
updateTime();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 5),
|
||||
child: TimeOfDayFormField(
|
||||
time: TimeOfDay.fromDateTime(_time),
|
||||
label: 'Time',
|
||||
controller: _timeController,
|
||||
onChanged: (newTime) {
|
||||
if (newTime != null) {
|
||||
setState(() {
|
||||
_time = DateTime(
|
||||
_time.year,
|
||||
_time.month,
|
||||
_time.day,
|
||||
newTime.hour,
|
||||
newTime.minute);
|
||||
});
|
||||
updateTime();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
glucoseMeasurement == GlucoseMeasurement.mgPerDl ||
|
||||
glucoseDisplayMode ==
|
||||
GlucoseDisplayMode.both ||
|
||||
glucoseDisplayMode ==
|
||||
GlucoseDisplayMode.bothForDetail
|
||||
? Expanded(
|
||||
child: TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'mg/dl',
|
||||
suffixText: 'mg/dl',
|
||||
),
|
||||
controller: _mgPerDlController,
|
||||
onChanged: (_) =>
|
||||
convertBetweenMgPerDlAndMmolPerL(
|
||||
calculateFrom:
|
||||
GlucoseMeasurement.mgPerDl),
|
||||
keyboardType:
|
||||
const TextInputType.numberWithOptions(),
|
||||
validator: (value) {
|
||||
if (value!.trim().isEmpty &&
|
||||
_mmolPerLController.text
|
||||
.trim()
|
||||
.isEmpty) {
|
||||
return 'How many mg/dl or mmol/l does the rate make up for?';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||
glucoseDisplayMode ==
|
||||
GlucoseDisplayMode.bothForDetail
|
||||
? IconButton(
|
||||
onPressed: () =>
|
||||
convertBetweenMgPerDlAndMmolPerL(
|
||||
calculateFrom:
|
||||
GlucoseMeasurement.mmolPerL),
|
||||
icon: const Icon(Icons.calculate),
|
||||
)
|
||||
: Container(),
|
||||
glucoseMeasurement == GlucoseMeasurement.mmolPerL ||
|
||||
glucoseDisplayMode ==
|
||||
GlucoseDisplayMode.both ||
|
||||
glucoseDisplayMode ==
|
||||
GlucoseDisplayMode.bothForDetail
|
||||
? Expanded(
|
||||
child: TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'mmol/l',
|
||||
suffixText: 'mmol/l',
|
||||
),
|
||||
controller: _mmolPerLController,
|
||||
onChanged: (_) =>
|
||||
convertBetweenMgPerDlAndMmolPerL(
|
||||
calculateFrom:
|
||||
GlucoseMeasurement.mmolPerL),
|
||||
keyboardType:
|
||||
const TextInputType.numberWithOptions(
|
||||
decimal: true),
|
||||
validator: (value) {
|
||||
if (value!.trim().isEmpty &&
|
||||
_mgPerDlController.text
|
||||
.trim()
|
||||
.isEmpty) {
|
||||
return 'How many mg/dl or mmol/l does rhe rate make up for?';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||
glucoseDisplayMode ==
|
||||
GlucoseDisplayMode.bothForDetail
|
||||
? IconButton(
|
||||
onPressed: () =>
|
||||
convertBetweenMgPerDlAndMmolPerL(
|
||||
calculateFrom:
|
||||
GlucoseMeasurement.mgPerDl),
|
||||
icon: const Icon(Icons.calculate),
|
||||
)
|
||||
: Container(),
|
||||
],
|
||||
),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Bolus Units',
|
||||
suffixText: 'U',
|
||||
),
|
||||
controller: _bolusGlucoseController,
|
||||
keyboardType: const TextInputType.numberWithOptions(
|
||||
decimal: true),
|
||||
),
|
||||
// ignore: todo
|
||||
// TODO: change field functionality according to time format
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Delayed Bolus Duration',
|
||||
suffixText: ' min',
|
||||
),
|
||||
controller: _delayedBolusDurationController,
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Delayed Bolus Units',
|
||||
),
|
||||
controller: _delayedBolusRateController,
|
||||
keyboardType: const TextInputType.numberWithOptions(
|
||||
decimal: true),
|
||||
),
|
||||
TextFormField(
|
||||
controller: _notesController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Notes',
|
||||
alignLabelWithHint: true,
|
||||
),
|
||||
keyboardType: TextInputType.multiline,
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
),
|
||||
];
|
||||
|
||||
if (!_isNew) {
|
||||
@ -272,8 +476,7 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||
),
|
||||
bottomNavigationBar: bottomNav,
|
||||
floatingActionButton: actionButton,
|
||||
floatingActionButtonLocation:
|
||||
FloatingActionButtonLocation.endFloat,
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
@ -1,185 +0,0 @@
|
||||
import 'package:diameter/components/forms.dart';
|
||||
import 'package:diameter/config.dart';
|
||||
import 'package:diameter/settings.dart';
|
||||
import 'package:diameter/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LogEntryForm extends StatefulWidget {
|
||||
final GlobalKey<FormState> formState;
|
||||
final Map<String, TextEditingController> controllers;
|
||||
|
||||
const LogEntryForm(
|
||||
{Key? key, required this.formState, required this.controllers})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_LogEntryFormState createState() => _LogEntryFormState();
|
||||
}
|
||||
|
||||
class _LogEntryFormState extends State<LogEntryForm> {
|
||||
void convertBetweenMgPerDlAndMmolPerL({GlucoseMeasurement? calculateFrom}) {
|
||||
int? mgPerDl;
|
||||
double? mmolPerL;
|
||||
final _mgPerDlController = widget.controllers['mgPerDl'];
|
||||
final _mmolPerLController = widget.controllers['mmolPerL'];
|
||||
|
||||
if (calculateFrom != GlucoseMeasurement.mmolPerL &&
|
||||
_mgPerDlController!.text != '') {
|
||||
mgPerDl = int.tryParse(_mgPerDlController.text);
|
||||
}
|
||||
if (calculateFrom != GlucoseMeasurement.mgPerDl &&
|
||||
_mmolPerLController!.text != '') {
|
||||
mmolPerL = double.tryParse(_mmolPerLController.text);
|
||||
}
|
||||
|
||||
if (mgPerDl != null && mmolPerL == null) {
|
||||
setState(() {
|
||||
_mmolPerLController!.text =
|
||||
Utils.convertMgPerDlToMmolPerL(mgPerDl!).toString();
|
||||
});
|
||||
}
|
||||
if (mmolPerL != null && mgPerDl == null) {
|
||||
setState(() {
|
||||
_mgPerDlController!.text =
|
||||
Utils.convertMmolPerLToMgPerDl(mmolPerL!).toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// final _timeController = widget.controllers['time'];
|
||||
final _mgPerDlController = widget.controllers['mgPerDl'];
|
||||
final _mmolPerLController = widget.controllers['mmolPerL'];
|
||||
final _bolusGlucoseController = widget.controllers['bolusGlucose'];
|
||||
final _delayedBolusRateController = widget.controllers['delayedBolusRate'];
|
||||
final _delayedBolusDurationController =
|
||||
widget.controllers['delayedBolusDuration'];
|
||||
final _notesController = widget.controllers['notes'];
|
||||
|
||||
return SingleChildScrollView(
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: <
|
||||
Widget>[
|
||||
StyledForm(
|
||||
formState: widget.formState,
|
||||
fields: [
|
||||
// TODO: insert time picker
|
||||
// Expanded(
|
||||
// child: StyledTimeOfDayFormField(
|
||||
// label: 'Time',
|
||||
// controller: _timeController,
|
||||
// onChanged: (newEndTime) {
|
||||
// if (newEndTime != null) {
|
||||
// setState(() {
|
||||
// _endTime = newEndTime;
|
||||
// });
|
||||
// updateEndTime();
|
||||
// }
|
||||
//),
|
||||
Row(
|
||||
children: [
|
||||
glucoseMeasurement == GlucoseMeasurement.mgPerDl ||
|
||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||
glucoseDisplayMode == GlucoseDisplayMode.bothForDetail
|
||||
? Expanded(
|
||||
child: TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'mg/dl',
|
||||
suffixText: 'mg/dl',
|
||||
),
|
||||
controller: _mgPerDlController,
|
||||
onChanged: (_) => convertBetweenMgPerDlAndMmolPerL(
|
||||
calculateFrom: GlucoseMeasurement.mgPerDl),
|
||||
keyboardType: const TextInputType.numberWithOptions(),
|
||||
validator: (value) {
|
||||
if (value!.trim().isEmpty &&
|
||||
_mmolPerLController!.text.trim().isEmpty) {
|
||||
return 'How many mg/dl or mmol/l does the rate make up for?';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||
glucoseDisplayMode == GlucoseDisplayMode.bothForDetail
|
||||
? IconButton(
|
||||
onPressed: () => convertBetweenMgPerDlAndMmolPerL(
|
||||
calculateFrom: GlucoseMeasurement.mmolPerL),
|
||||
icon: const Icon(Icons.calculate),
|
||||
)
|
||||
: Container(),
|
||||
glucoseMeasurement == GlucoseMeasurement.mmolPerL ||
|
||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||
glucoseDisplayMode == GlucoseDisplayMode.bothForDetail
|
||||
? Expanded(
|
||||
child: TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'mmol/l',
|
||||
suffixText: 'mmol/l',
|
||||
),
|
||||
controller: _mmolPerLController,
|
||||
onChanged: (_) => convertBetweenMgPerDlAndMmolPerL(
|
||||
calculateFrom: GlucoseMeasurement.mmolPerL),
|
||||
keyboardType: const TextInputType.numberWithOptions(
|
||||
decimal: true),
|
||||
validator: (value) {
|
||||
if (value!.trim().isEmpty &&
|
||||
_mgPerDlController!.text.trim().isEmpty) {
|
||||
return 'How many mg/dl or mmol/l does rhe rate make up for?';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
)
|
||||
: Container(),
|
||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||
glucoseDisplayMode == GlucoseDisplayMode.bothForDetail
|
||||
? IconButton(
|
||||
onPressed: () => convertBetweenMgPerDlAndMmolPerL(
|
||||
calculateFrom: GlucoseMeasurement.mgPerDl),
|
||||
icon: const Icon(Icons.calculate),
|
||||
)
|
||||
: Container(),
|
||||
],
|
||||
),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Bolus Units',
|
||||
suffixText: 'U',
|
||||
),
|
||||
controller: _bolusGlucoseController,
|
||||
keyboardType:
|
||||
const TextInputType.numberWithOptions(decimal: true),
|
||||
),
|
||||
// TODO: change field functionality according to time format
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Delayed Bolus Duration',
|
||||
suffixText: ' min',
|
||||
),
|
||||
controller: _delayedBolusDurationController,
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Delayed Bolus Units',
|
||||
),
|
||||
controller: _delayedBolusRateController,
|
||||
keyboardType:
|
||||
const TextInputType.numberWithOptions(decimal: true),
|
||||
),
|
||||
TextFormField(
|
||||
controller: _notesController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Notes',
|
||||
alignLabelWithHint: true,
|
||||
),
|
||||
keyboardType: TextInputType.multiline,
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
@ -114,10 +114,10 @@ class _LogEventDetailScreenState extends State<LogEventDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _logEventForm,
|
||||
fields: [
|
||||
StyledDropdownButton<LogEventType>(
|
||||
LabeledDropdownButton<LogEventType>(
|
||||
selectedItem: _eventType,
|
||||
label: 'Event Type',
|
||||
items: _logEventTypes,
|
||||
@ -128,26 +128,14 @@ class _LogEventDetailScreenState extends State<LogEventDetailScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
// StyledFutureDropdownButton<LogEventType>(
|
||||
// selectedItem: _eventType,
|
||||
// label: 'Event Type',
|
||||
// items: _logEventTypes,
|
||||
// getItemValue: (item) => item.objectId,
|
||||
// renderItem: (item) => Text(item.value),
|
||||
// onChanged: (value) {
|
||||
// setState(() {
|
||||
// _eventType = value;
|
||||
// });
|
||||
// },
|
||||
// ),
|
||||
StyledBooleanFormField(
|
||||
BooleanFormField(
|
||||
value: _hasEndTime,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_hasEndTime = value;
|
||||
});
|
||||
},
|
||||
label: 'active',
|
||||
label: 'has end time',
|
||||
),
|
||||
TextFormField(
|
||||
controller: _notesController,
|
||||
|
@ -68,7 +68,6 @@ class _LogEventListScreenState extends State<LogEventListScreen> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// TODO: add button for active events
|
||||
Expanded(
|
||||
child: (widget.logEntry.events.isNotEmpty || widget.logEntry.endedEvents.isNotEmpty)
|
||||
? ListView.builder(
|
||||
|
@ -45,22 +45,6 @@ class _LogEventTypeDetailScreenState extends State<LogEventTypeDetailScreen> {
|
||||
});
|
||||
if (_logEventTypeForm.currentState!.validate()) {
|
||||
bool isNew = widget.logEventType == null;
|
||||
// isNew
|
||||
// ? await LogEventType.save(
|
||||
// value: _valueController.text,
|
||||
// notes: _notesController.text,
|
||||
// defaultReminderDuration:
|
||||
// int.tryParse(_defaultReminderDurationController.text),
|
||||
// hasEndTime: _hasEndTime,
|
||||
// )
|
||||
// : await LogEventType.update(
|
||||
// widget.logEventType!.objectId!,
|
||||
// value: _valueController.text,
|
||||
// notes: _notesController.text,
|
||||
// defaultReminderDuration:
|
||||
// int.tryParse(_defaultReminderDurationController.text),
|
||||
// hasEndTime: _hasEndTime,
|
||||
// );
|
||||
LogEventType.put(LogEventType(
|
||||
id: widget.logEventType?.id ?? 0,
|
||||
value: _valueController.text,
|
||||
@ -115,7 +99,7 @@ class _LogEventTypeDetailScreenState extends State<LogEventTypeDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _logEventTypeForm,
|
||||
fields: [
|
||||
TextFormField(
|
||||
@ -131,7 +115,7 @@ class _LogEventTypeDetailScreenState extends State<LogEventTypeDetailScreen> {
|
||||
return null;
|
||||
},
|
||||
),
|
||||
StyledBooleanFormField(
|
||||
BooleanFormField(
|
||||
value: _hasEndTime,
|
||||
label: 'has end time',
|
||||
onChanged: (value) {
|
||||
|
@ -315,7 +315,7 @@ class _LogMealDetailScreenState extends State<LogMealDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _logMealForm,
|
||||
fields: [
|
||||
TextFormField(
|
||||
@ -330,7 +330,7 @@ class _LogMealDetailScreenState extends State<LogMealDetailScreen> {
|
||||
return null;
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<Meal>(
|
||||
LabeledDropdownButton<Meal>(
|
||||
selectedItem: _meal,
|
||||
label: 'Meal',
|
||||
items: _meals,
|
||||
@ -342,7 +342,7 @@ class _LogMealDetailScreenState extends State<LogMealDetailScreen> {
|
||||
}
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<MealSource>(
|
||||
LabeledDropdownButton<MealSource>(
|
||||
selectedItem: _mealSource,
|
||||
label: 'Meal Source',
|
||||
items: _mealSources,
|
||||
@ -354,7 +354,7 @@ class _LogMealDetailScreenState extends State<LogMealDetailScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<MealCategory>(
|
||||
LabeledDropdownButton<MealCategory>(
|
||||
selectedItem: _mealCategory,
|
||||
label: 'Meal Category',
|
||||
items: _mealCategories,
|
||||
@ -366,7 +366,7 @@ class _LogMealDetailScreenState extends State<LogMealDetailScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<MealPortionType>(
|
||||
LabeledDropdownButton<MealPortionType>(
|
||||
selectedItem: _mealPortionType,
|
||||
label: 'Meal Portion Type',
|
||||
items: _mealPortionTypes,
|
||||
@ -434,7 +434,7 @@ class _LogMealDetailScreenState extends State<LogMealDetailScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
StyledDropdownButton<Accuracy>(
|
||||
LabeledDropdownButton<Accuracy>(
|
||||
selectedItem: _portionSizeAccuracy,
|
||||
label: 'Portion Size Accuracy',
|
||||
items: _portionSizeAccuracies,
|
||||
@ -488,7 +488,7 @@ class _LogMealDetailScreenState extends State<LogMealDetailScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
StyledDropdownButton<Accuracy>(
|
||||
LabeledDropdownButton<Accuracy>(
|
||||
selectedItem: _carbsRatioAccuracy,
|
||||
label: 'Carbs Ratio Accuracy',
|
||||
items: _carbsRatioAccuracies,
|
||||
|
@ -78,7 +78,7 @@ class _MealCategoryDetailScreenState extends State<MealCategoryDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _mealCategoryForm,
|
||||
fields: [
|
||||
TextFormField(
|
||||
|
@ -266,7 +266,7 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _mealForm,
|
||||
fields: [
|
||||
TextFormField(
|
||||
@ -281,7 +281,7 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||
return null;
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<MealSource>(
|
||||
LabeledDropdownButton<MealSource>(
|
||||
selectedItem: _mealSource,
|
||||
label: 'Meal Source',
|
||||
items: _mealSources,
|
||||
@ -293,7 +293,7 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||
}
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<MealCategory>(
|
||||
LabeledDropdownButton<MealCategory>(
|
||||
selectedItem: _mealCategory,
|
||||
label: 'Meal Category',
|
||||
items: _mealCategories,
|
||||
@ -305,7 +305,7 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<MealPortionType>(
|
||||
LabeledDropdownButton<MealPortionType>(
|
||||
selectedItem: _mealPortionType,
|
||||
label: 'Meal Portion Type',
|
||||
items: _mealPortionTypes,
|
||||
@ -373,7 +373,7 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
StyledDropdownButton<Accuracy>(
|
||||
LabeledDropdownButton<Accuracy>(
|
||||
selectedItem: _portionSizeAccuracy,
|
||||
label: 'Portion Size Accuracy',
|
||||
items: _portionSizeAccuracies,
|
||||
@ -385,18 +385,6 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
// StyledFutureDropdownButton<Accuracy>(
|
||||
// selectedItem: _portionSizeAccuracy,
|
||||
// label: 'Portion Size Accuracy',
|
||||
// items: _portionSizeAccuracies,
|
||||
// getItemValue: (item) => item.objectId,
|
||||
// renderItem: (item) => Text(item.value),
|
||||
// onChanged: (value) {
|
||||
// setState(() {
|
||||
// _portionSizeAccuracy = value;
|
||||
// });
|
||||
// },
|
||||
// ),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
@ -427,7 +415,7 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||
),
|
||||
],
|
||||
),
|
||||
StyledDropdownButton<Accuracy>(
|
||||
LabeledDropdownButton<Accuracy>(
|
||||
selectedItem: _carbsRatioAccuracy,
|
||||
label: 'Carbs Ratio Accuracy',
|
||||
items: _carbsRatioAccuracies,
|
||||
@ -439,18 +427,7 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
// StyledFutureDropdownButton<Accuracy>(
|
||||
// selectedItem: _carbsRatioAccuracy,
|
||||
// label: 'Carbs Ratio Accuracy',
|
||||
// items: _carbsRatioAccuracies,
|
||||
// getItemValue: (item) => item.objectId,
|
||||
// renderItem: (item) => Text(item.value),
|
||||
// onChanged: (value) {
|
||||
// setState(() {
|
||||
// _carbsRatioAccuracy = value;
|
||||
// });
|
||||
// },
|
||||
// ),
|
||||
// ignore: todo
|
||||
// TODO: display according to time format
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
|
@ -89,7 +89,7 @@ class _MealPortionTypeDetailScreenState
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _mealPortionTypeForm,
|
||||
fields: [
|
||||
TextFormField(
|
||||
|
@ -145,7 +145,7 @@ class _MealSourceDetailScreenState extends State<MealSourceDetailScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _mealSourceForm,
|
||||
fields: [
|
||||
TextFormField(
|
||||
@ -160,7 +160,7 @@ class _MealSourceDetailScreenState extends State<MealSourceDetailScreen> {
|
||||
return null;
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<Accuracy>(
|
||||
LabeledDropdownButton<Accuracy>(
|
||||
selectedItem: _defaultCarbsRatioAccuracy,
|
||||
label: 'Default Carbs Ratio Accuracy',
|
||||
items: _carbsRatioAccuracies,
|
||||
@ -171,7 +171,7 @@ class _MealSourceDetailScreenState extends State<MealSourceDetailScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<Accuracy>(
|
||||
LabeledDropdownButton<Accuracy>(
|
||||
selectedItem: _defaultPortionSizeAccuracy,
|
||||
label: 'Default Portion Size Accuracy',
|
||||
items: _portionSizeAccuracies,
|
||||
@ -206,7 +206,7 @@ class _MealSourceDetailScreenState extends State<MealSourceDetailScreen> {
|
||||
// });
|
||||
// },
|
||||
// ),
|
||||
StyledDropdownButton<MealCategory>(
|
||||
LabeledDropdownButton<MealCategory>(
|
||||
selectedItem: _defaultMealCategory,
|
||||
label: 'Default Meal Category',
|
||||
items: _mealCategories,
|
||||
@ -218,7 +218,7 @@ class _MealSourceDetailScreenState extends State<MealSourceDetailScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<MealPortionType>(
|
||||
LabeledDropdownButton<MealPortionType>(
|
||||
selectedItem: _defaultMealPortionType,
|
||||
label: 'Default Meal Portion Type',
|
||||
items: _mealPortionTypes,
|
||||
|
@ -127,10 +127,10 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
StyledForm(
|
||||
FormWrapper(
|
||||
formState: _settingsForm,
|
||||
fields: [
|
||||
StyledDropdownButton<NutritionMeasurement>(
|
||||
LabeledDropdownButton<NutritionMeasurement>(
|
||||
selectedItem: nutritionMeasurement,
|
||||
label: 'Preferred Nutrition Measurement',
|
||||
items: NutritionMeasurement.values,
|
||||
@ -144,7 +144,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
}
|
||||
},
|
||||
),
|
||||
StyledDropdownButton<GlucoseMeasurement>(
|
||||
LabeledDropdownButton<GlucoseMeasurement>(
|
||||
selectedItem: glucoseMeasurement,
|
||||
label: 'Preferred Glucose Measurement',
|
||||
items: GlucoseMeasurement.values,
|
||||
@ -158,7 +158,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
}
|
||||
},
|
||||
),
|
||||
StyledBooleanFormField(
|
||||
BooleanFormField(
|
||||
value: glucoseDisplayMode == GlucoseDisplayMode.activeOnly,
|
||||
label: 'only display active glucose measurement',
|
||||
onChanged: (_) {
|
||||
@ -172,7 +172,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
StyledBooleanFormField(
|
||||
BooleanFormField(
|
||||
value: glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||
glucoseDisplayMode == GlucoseDisplayMode.bothForDetail,
|
||||
enabled: glucoseDisplayMode != GlucoseDisplayMode.activeOnly,
|
||||
@ -190,7 +190,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
StyledBooleanFormField(
|
||||
BooleanFormField(
|
||||
value: glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||
glucoseDisplayMode == GlucoseDisplayMode.bothForList,
|
||||
enabled: glucoseDisplayMode != GlucoseDisplayMode.activeOnly,
|
||||
@ -208,8 +208,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||
});
|
||||
},
|
||||
),
|
||||
// TODO: add fields for date and time formats
|
||||
// TODO: add fields for glucose target
|
||||
],
|
||||
),
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user