diameter/lib/screens/bolus/bolus_profile_detail.dart

363 lines
11 KiB
Dart
Raw Normal View History

2021-10-22 23:08:09 +00:00
import 'package:diameter/components/detail.dart';
import 'package:diameter/components/dialogs.dart';
import 'package:diameter/config.dart';
import 'package:diameter/models/bolus.dart';
import 'package:diameter/navigation.dart';
import 'package:diameter/screens/bolus/bolus_detail.dart';
import 'package:flutter/material.dart';
import 'package:diameter/components/forms.dart';
import 'package:diameter/models/bolus_profile.dart';
import 'package:diameter/screens/bolus/bolus_list.dart';
class BolusProfileDetailScreen extends StatefulWidget {
static const String routeName = '/bolus-profile';
final BolusProfile? bolusProfile;
final bool active;
const BolusProfileDetailScreen(
{Key? key, this.active = false, this.bolusProfile})
: super(key: key);
@override
_BolusProfileDetailScreenState createState() =>
_BolusProfileDetailScreenState();
}
class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
final GlobalKey<FormState> _bolusProfileForm = GlobalKey<FormState>();
late FloatingActionButton addBolusButton;
late IconButton refreshButton;
late IconButton closeButton;
late DetailBottomRow detailBottomRow;
FloatingActionButton? actionButton;
List<Widget> appBarActions = [];
DetailBottomRow? bottomNav;
2021-10-22 23:08:09 +00:00
final _nameController = TextEditingController(text: '');
final _notesController = TextEditingController(text: '');
bool _active = false;
bool _isSaving = false;
2021-10-22 23:08:09 +00:00
@override
void initState() {
super.initState();
if (widget.bolusProfile != null) {
_nameController.text = widget.bolusProfile!.name;
_active = widget.bolusProfile!.active;
_notesController.text = widget.bolusProfile!.notes ?? '';
}
if (widget.active) {
_active = true;
}
addBolusButton = FloatingActionButton(
onPressed: handleAddNew,
2021-10-22 23:08:09 +00:00
child: const Icon(Icons.add),
);
refreshButton = IconButton(
icon: const Icon(Icons.refresh),
onPressed: refresh,
);
closeButton = IconButton(
onPressed: handleCancelAction,
icon: const Icon(Icons.close),
);
// TODO: fix (saving button doesnt get disabled)
detailBottomRow = DetailBottomRow(
onCancel: handleCancelAction,
onSave: _isSaving ? null : handleSaveAction,
);
2021-10-22 23:08:09 +00:00
actionButton = null;
appBarActions = [closeButton];
bottomNav = detailBottomRow;
2021-10-22 23:08:09 +00:00
}
void refresh({String? message}) {
setState(() {
if (widget.bolusProfile != null) {
widget.bolusProfile!.bolusRates =
Bolus.fetchAllForBolusProfile(widget.bolusProfile!);
}
});
setState(() {
if (message != null) {
var snackBar = SnackBar(
content: Text(message),
duration: const Duration(seconds: 2),
);
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(snackBar);
}
});
}
Future<void> checkActiveProfiles() async {
int _activeCount = await BolusProfile.getActiveCount();
bool isNew = widget.bolusProfile == null;
if (_active &&
(_activeCount > 1 ||
_activeCount == 1 && (isNew || !widget.bolusProfile!.active))) {
await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: const Text(
'There are already one or more active profiles. What would you like to do?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, 0),
child: const Text('IGNORE'),
),
TextButton(
onPressed: () => Navigator.pop(context, 1),
child:
Text('DEACTIVATE ${_nameController.text.toUpperCase()}'),
),
ElevatedButton(
onPressed: () => Navigator.pop(context, 2),
child: const Text('DEACTIVATE ALL OTHERS'),
)
],
);
}).then((value) async {
if (value == 1) {
setState(() {
_active = false;
});
} else if (value == 2) {
await BolusProfile.setAllInactive();
}
});
} else if (!_active &&
((isNew && _activeCount == 0) ||
(_activeCount == 1 && widget.bolusProfile!.active))) {
await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: const Text(
'There is currently no active profile. Would you like to set this one as active?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, 0),
child: const Text('IGNORE'),
),
TextButton(
onPressed: () => Navigator.pop(context, 1),
child: const Text('ACTIVATE THIS PROFILE'),
),
],
);
}).then((value) {
if (value == 1) {
setState(() {
_active = true;
});
}
});
}
}
void handleAddNew() async {
List<Bolus> bolusRates =
await Bolus.fetchAllForBolusProfile(widget.bolusProfile!);
TimeOfDay? suggestedStartTime;
TimeOfDay? suggestedEndTime;
bolusRates.asMap().forEach((index, bolus) {
if (suggestedStartTime == null && suggestedEndTime == null) {
if (index == 0 &&
(bolus.startTime.hour != 0 || bolus.startTime.minute != 0)) {
suggestedStartTime = const TimeOfDay(hour: 0, minute: 0);
suggestedEndTime = TimeOfDay.fromDateTime(bolus.startTime);
} else if ((index == bolusRates.length - 1) &&
(bolus.endTime.hour != 0 || bolus.endTime.minute != 0)) {
suggestedStartTime = TimeOfDay.fromDateTime(bolus.endTime);
suggestedEndTime = const TimeOfDay(hour: 0, minute: 0);
} else if (index != 0) {
var lastEndTime = bolusRates[index - 1].endTime;
if (bolus.startTime.isAfter(lastEndTime)) {
suggestedStartTime = TimeOfDay.fromDateTime(lastEndTime);
suggestedEndTime = TimeOfDay.fromDateTime(bolus.startTime);
}
}
}
});
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return BolusDetailScreen(
bolusProfile: widget.bolusProfile!,
suggestedStartTime: suggestedStartTime,
suggestedEndTime: suggestedEndTime,
);
},
),
).then((message) => refresh(message: message));
}
2021-10-22 23:08:09 +00:00
void handleSaveAction() async {
setState(() {
_isSaving = true;
});
2021-10-22 23:08:09 +00:00
if (_bolusProfileForm.currentState!.validate()) {
await checkActiveProfiles();
2021-10-22 23:08:09 +00:00
bool isNew = widget.bolusProfile == null;
isNew
? await BolusProfile.save(
name: _nameController.text,
active: _active,
notes: _notesController.text)
: await BolusProfile.update(
widget.bolusProfile!.objectId!,
name: _nameController.text,
active: _active,
notes: _notesController.text,
);
Navigator.pop(context, '${isNew ? 'New' : ''} Bolus Profile saved');
}
setState(() {
_isSaving = false;
});
2021-10-22 23:08:09 +00:00
}
void handleCancelAction() {
bool isNew = widget.bolusProfile == null;
if (showConfirmationDialogOnCancel &&
(isNew &&
(_active != widget.active ||
2021-10-22 23:08:09 +00:00
_nameController.text != '' ||
_notesController.text != '')) ||
(!isNew &&
(widget.bolusProfile!.active != _active ||
widget.bolusProfile!.name != _nameController.text ||
(widget.bolusProfile!.notes ?? '') != _notesController.text))) {
Dialogs.showCancelConfirmationDialog(
context: context,
isNew: isNew,
onSave: handleSaveAction,
);
} else {
Navigator.pop(context);
}
}
void renderTabButtons(index) {
if (widget.bolusProfile != null) {
setState(() {
switch (index) {
case 1:
actionButton = addBolusButton;
appBarActions = [refreshButton, closeButton];
bottomNav = null;
2021-10-22 23:08:09 +00:00
break;
default:
actionButton = null;
appBarActions = [closeButton];
bottomNav = detailBottomRow;
2021-10-22 23:08:09 +00:00
}
});
}
}
@override
Widget build(BuildContext context) {
bool isNew = widget.bolusProfile == null;
return DefaultTabController(
length: isNew ? 1 : 2,
2021-10-22 23:08:09 +00:00
child: Builder(builder: (BuildContext context) {
final TabController tabController = DefaultTabController.of(context)!;
tabController.addListener(() {
renderTabButtons(tabController.index);
});
List<Widget> tabs = [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
StyledForm(
formState: _bolusProfileForm,
fields: [
TextFormField(
controller: _nameController,
decoration: const InputDecoration(
labelText: 'Name',
),
validator: (value) {
if (value!.trim().isEmpty) {
return 'Empty title';
}
return null;
},
),
TextFormField(
decoration: const InputDecoration(
labelText: 'Notes',
alignLabelWithHint: true,
),
controller: _notesController,
keyboardType: TextInputType.multiline,
),
StyledBooleanFormField(
value: _active,
onChanged: (value) {
setState(() {
_active = value;
});
},
label: 'active',
),
],
),
],
),
),
];
if (!isNew) {
tabs.add(BolusListScreen(bolusProfile: widget.bolusProfile));
}
2021-10-22 23:08:09 +00:00
return Scaffold(
appBar: AppBar(
title:
Text(isNew ? 'New Bolus Profile' : widget.bolusProfile!.name),
bottom: isNew
? PreferredSize(child: Container(), preferredSize: Size.zero)
: const TabBar(
tabs: [
Tab(text: 'PROFILE'),
Tab(text: 'RATES'),
],
),
actions: appBarActions,
),
drawer: const Navigation(
currentLocation: BolusProfileDetailScreen.routeName),
body: TabBarView(
children: tabs,
2021-10-22 23:08:09 +00:00
),
bottomNavigationBar: bottomNav,
2021-10-22 23:08:09 +00:00
floatingActionButton: actionButton,
floatingActionButtonLocation:
FloatingActionButtonLocation.endFloat,
2021-10-22 23:08:09 +00:00
);
}),
);
}
}