245 lines
7.6 KiB
Dart
245 lines
7.6 KiB
Dart
|
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';
|
||
|
import 'package:flutter/widgets.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;
|
||
|
|
||
|
final _nameController = TextEditingController(text: '');
|
||
|
final _notesController = TextEditingController(text: '');
|
||
|
bool _active = false;
|
||
|
|
||
|
@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: () {
|
||
|
Navigator.push(
|
||
|
context,
|
||
|
MaterialPageRoute(
|
||
|
builder: (context) {
|
||
|
return BolusDetailScreen(bolusProfile: widget.bolusProfile!);
|
||
|
},
|
||
|
),
|
||
|
).then((message) => refresh(message: message));
|
||
|
},
|
||
|
child: const Icon(Icons.add),
|
||
|
);
|
||
|
|
||
|
refreshButton = IconButton(
|
||
|
icon: const Icon(Icons.refresh),
|
||
|
onPressed: refresh,
|
||
|
);
|
||
|
|
||
|
closeButton = IconButton(
|
||
|
onPressed: handleCancelAction,
|
||
|
icon: const Icon(Icons.close),
|
||
|
);
|
||
|
|
||
|
actionButton = null;
|
||
|
appBarActions = [closeButton];
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
void handleSaveAction() async {
|
||
|
// TODO: if this would be the second active profile, prompt for deactivating that one
|
||
|
if (_bolusProfileForm.currentState!.validate()) {
|
||
|
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');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void handleCancelAction() {
|
||
|
bool isNew = widget.bolusProfile == null;
|
||
|
|
||
|
if (showConfirmationDialogOnCancel &&
|
||
|
(isNew &&
|
||
|
(_active ||
|
||
|
_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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FloatingActionButton? actionButton;
|
||
|
List<Widget> appBarActions = [];
|
||
|
|
||
|
void renderTabButtons(index) {
|
||
|
if (widget.bolusProfile != null) {
|
||
|
setState(() {
|
||
|
switch (index) {
|
||
|
case 1:
|
||
|
actionButton = addBolusButton;
|
||
|
appBarActions = [refreshButton, closeButton];
|
||
|
break;
|
||
|
default:
|
||
|
actionButton = null;
|
||
|
appBarActions = [closeButton];
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
bool isNew = widget.bolusProfile == null;
|
||
|
return DefaultTabController(
|
||
|
length: 2,
|
||
|
child: Builder(builder: (BuildContext context) {
|
||
|
final TabController tabController = DefaultTabController.of(context)!;
|
||
|
tabController.addListener(() {
|
||
|
if (tabController.indexIsChanging) {
|
||
|
renderTabButtons(tabController.index);
|
||
|
}
|
||
|
});
|
||
|
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: [
|
||
|
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',
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
BolusListScreen(bolusProfile: widget.bolusProfile),
|
||
|
],
|
||
|
),
|
||
|
bottomNavigationBar: DetailBottomRow(
|
||
|
onCancel: handleCancelAction,
|
||
|
onSave: handleSaveAction,
|
||
|
),
|
||
|
floatingActionButton: actionButton,
|
||
|
floatingActionButtonLocation:
|
||
|
FloatingActionButtonLocation.centerDocked,
|
||
|
);
|
||
|
}),
|
||
|
);
|
||
|
}
|
||
|
}
|