diameter/lib/screens/basal/basal_profile_detail.dart

316 lines
9.7 KiB
Dart

import 'package:diameter/components/detail.dart';
import 'package:diameter/components/dialogs.dart';
import 'package:diameter/config.dart';
import 'package:diameter/models/basal.dart';
import 'package:diameter/navigation.dart';
import 'package:diameter/screens/basal/basal_detail.dart';
import 'package:flutter/material.dart';
import 'package:diameter/components/forms.dart';
import 'package:diameter/models/basal_profile.dart';
import 'package:diameter/screens/basal/basal_list.dart';
class BasalProfileDetailScreen extends StatefulWidget {
static const String routeName = '/basal-profile';
final BasalProfile? basalProfile;
final bool active;
const BasalProfileDetailScreen(
{Key? key, this.active = false, this.basalProfile})
: super(key: key);
@override
_BasalProfileDetailScreenState createState() =>
_BasalProfileDetailScreenState();
}
class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
final GlobalKey<FormState> _basalProfileForm = GlobalKey<FormState>();
late FloatingActionButton addBasalButton;
late IconButton refreshButton;
late IconButton closeButton;
final _nameController = TextEditingController(text: '');
final _notesController = TextEditingController(text: '');
bool _active = false;
@override
void initState() {
super.initState();
if (widget.basalProfile != null) {
_nameController.text = widget.basalProfile!.name;
_active = widget.basalProfile!.active;
_notesController.text = widget.basalProfile!.notes ?? '';
}
if (widget.active) {
_active = true;
}
addBasalButton = FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return BasalDetailScreen(basalProfile: widget.basalProfile!);
},
),
).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.basalProfile != null) {
widget.basalProfile!.basalRates =
Basal.fetchAllForBasalProfile(widget.basalProfile!);
}
});
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 BasalProfile.getActiveCount();
bool isNew = widget.basalProfile == null;
if (_active &&
(_activeCount > 1 ||
_activeCount == 1 && (isNew || !widget.basalProfile!.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 BasalProfile.setAllInactive();
}
});
} else if (!_active &&
((isNew && _activeCount == 0) ||
(_activeCount == 1 && widget.basalProfile!.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 handleSaveAction() async {
if (_basalProfileForm.currentState!.validate()) {
await checkActiveProfiles();
bool isNew = widget.basalProfile == null;
isNew
? await BasalProfile.save(
name: _nameController.text,
active: _active,
notes: _notesController.text)
: await BasalProfile.update(
widget.basalProfile!.objectId!,
name: _nameController.text,
active: _active,
notes: _notesController.text,
);
Navigator.pop(context, '${isNew ? 'New' : ''} Basal Profile saved');
}
}
void handleCancelAction() {
bool isNew = widget.basalProfile == null;
if (showConfirmationDialogOnCancel &&
(isNew &&
(_active ||
_nameController.text != '' ||
_notesController.text != '')) ||
(!isNew &&
(widget.basalProfile!.active != _active ||
widget.basalProfile!.name != _nameController.text ||
(widget.basalProfile!.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.basalProfile != null) {
setState(() {
switch (index) {
case 1:
actionButton = addBasalButton;
appBarActions = [refreshButton, closeButton];
break;
default:
actionButton = null;
appBarActions = [closeButton];
}
});
}
}
@override
Widget build(BuildContext context) {
bool isNew = widget.basalProfile == null;
return DefaultTabController(
length: isNew ? 1 : 2,
child: Builder(builder: (BuildContext context) {
final TabController tabController = DefaultTabController.of(context)!;
tabController.addListener(() {
if (tabController.indexIsChanging) {
renderTabButtons(tabController.index);
}
});
List<Widget> tabs = [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
StyledForm(
formState: _basalProfileForm,
fields: [
TextFormField(
controller: _nameController,
decoration: const InputDecoration(
labelText: 'Name',
),
validator: (value) {
if (value!.trim().isEmpty) {
return 'Empty title';
}
return null;
},
),
TextFormField(
keyboardType: TextInputType.multiline,
controller: _notesController,
decoration: const InputDecoration(
labelText: 'Notes',
suffixText: '',
alignLabelWithHint: true,
),
),
StyledBooleanFormField(
value: _active,
onChanged: (value) {
setState(() {
_active = value;
});
},
label: 'active',
),
],
),
],
),
),
];
if (!isNew) {
tabs.add(BasalListScreen(basalProfile: widget.basalProfile));
}
return Scaffold(
appBar: AppBar(
title:
Text(isNew ? 'New Basal Profile' : widget.basalProfile!.name),
bottom: isNew
? PreferredSize(child: Container(), preferredSize: Size.zero)
: const TabBar(
tabs: [
Tab(text: 'PROFILE'),
Tab(text: 'RATES'),
],
),
actions: appBarActions,
),
drawer: const Navigation(
currentLocation: BasalProfileDetailScreen.routeName),
body: TabBarView(children: tabs),
bottomNavigationBar: DetailBottomRow(
onCancel: handleCancelAction,
onSave: handleSaveAction,
),
floatingActionButton: actionButton,
floatingActionButtonLocation:
FloatingActionButtonLocation.centerDocked,
);
}),
);
}
}