Editable search data collections

This commit is contained in:
2024-08-15 20:10:07 +08:00
parent 09e904f52f
commit 403639088f
12 changed files with 439 additions and 184 deletions

View File

@ -0,0 +1,152 @@
import 'package:dietary_guard/controllers/alert.dart';
import 'package:dietary_guard/models/alert_configuration.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class AlertSettingsScreen extends StatefulWidget {
const AlertSettingsScreen({super.key});
@override
State<AlertSettingsScreen> createState() => _AlertSettingsScreenState();
}
class _AlertSettingsScreenState extends State<AlertSettingsScreen> {
List<AlertConfiguration> _currentAlerts = List.empty(growable: true);
void _addAlert() {
setState(() {
_currentAlerts.add(AlertConfiguration(
nutrientId: 0,
maxValue: 0,
minValue: 0,
));
});
}
void _removeAlert(AlertConfiguration item) {
setState(() {
_currentAlerts.remove(item);
});
}
Future<void> _applySettings() async {
final AlertController alert = Get.find();
await alert.setAlertConfiguration(_currentAlerts);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('settingsApplied'.tr),
));
}
@override
void initState() {
final AlertController alert = Get.find();
_currentAlerts = List.from(alert.configuration, growable: true);
super.initState();
}
@override
Widget build(BuildContext context) {
return Material(
color: Theme.of(context).colorScheme.surface,
child: Scaffold(
appBar: AppBar(
title: Text('alertSettings'.tr),
),
body: ListView(
children: [
..._currentAlerts.map(
(x) => Card(
child: Column(
children: [
Row(
children: [
Expanded(
child: TextFormField(
initialValue: x.nutrientId.toString(),
decoration: InputDecoration(
border: const OutlineInputBorder(),
label: Text("alertNutrientId".tr),
isDense: true,
),
onTapOutside: (_) =>
FocusManager.instance.primaryFocus?.unfocus(),
onChanged: (value) {
x.nutrientId = int.tryParse(value) ?? 0;
},
),
),
const SizedBox(width: 6),
IconButton(
icon: const Icon(Icons.close),
onPressed: () {
_removeAlert(x);
},
),
],
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: TextFormField(
initialValue: x.maxValue.toString(),
decoration: InputDecoration(
border: const OutlineInputBorder(),
label: Text("alertMaxValue".tr),
isDense: true,
),
onTapOutside: (_) =>
FocusManager.instance.primaryFocus?.unfocus(),
onChanged: (value) {
x.maxValue = double.tryParse(value) ?? 0;
},
),
),
const SizedBox(width: 6),
Expanded(
child: TextFormField(
initialValue: x.minValue.toString(),
decoration: InputDecoration(
border: const OutlineInputBorder(),
label: Text("alertMinValue".tr),
isDense: true,
),
onTapOutside: (_) =>
FocusManager.instance.primaryFocus?.unfocus(),
onChanged: (value) {
x.minValue = double.tryParse(value) ?? 0;
},
),
),
],
),
],
).paddingAll(16),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton.icon(
icon: const Icon(Icons.save, size: 16),
label: Text('apply'.tr),
onPressed: () => _applySettings(),
),
ElevatedButton.icon(
style: const ButtonStyle(
foregroundColor: WidgetStatePropertyAll(Colors.teal),
),
icon: const Icon(Icons.add, size: 16),
label: Text('newAlert'.tr),
onPressed: () => _addAlert(),
),
],
).paddingSymmetric(vertical: 4),
],
).paddingSymmetric(horizontal: 12),
),
);
}
}

View File

@ -0,0 +1,188 @@
import 'package:dietary_guard/controllers/food_data.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class DataSourceSettingsScreen extends StatefulWidget {
const DataSourceSettingsScreen({super.key});
@override
State<DataSourceSettingsScreen> createState() =>
_DataSourceSettingsScreenState();
}
class _DataSourceSettingsScreenState extends State<DataSourceSettingsScreen> {
final TextEditingController _fdcApiKeyController = TextEditingController();
final List<(String, String, String)> _dataCollectionList = [
(
"Foundation",
"dataCollectionFoundation".tr,
"dataCollectionFoundationDescription".tr,
),
(
"Branded",
"dataCollectionBranded".tr,
"dataCollectionBrandedDescription".tr,
),
(
"Survey (FNDDS)",
"dataCollectionSurvey".tr,
"dataCollectionSurveyDescription".tr,
),
(
"SR Legacy",
"dataCollectionLegacy".tr,
"dataCollectionLegacyDescription".tr,
),
];
List<String> _enabledDataCollections = List.empty(growable: true);
Future<void> _applySettings() async {
final FoodDataController data = Get.find();
await data.setApiKey(_fdcApiKeyController.text);
await data.setDataCollections(_enabledDataCollections);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('settingsApplied'.tr),
));
}
@override
void initState() {
final FoodDataController data = Get.find();
_fdcApiKeyController.text = data.getApiKey() ?? '';
_enabledDataCollections = List.from(
data.getDataCollections() ?? List.empty(),
growable: true,
);
super.initState();
}
Color get _unFocusColor =>
Theme.of(context).colorScheme.onSurface.withOpacity(0.75);
@override
Widget build(BuildContext context) {
return Material(
color: Theme.of(context).colorScheme.surface,
child: Scaffold(
appBar: AppBar(
title: Text('dataSourceSettings'.tr),
),
body: ListView(
children: [
const SizedBox(height: 8),
DropdownButtonFormField2<String>(
isExpanded: true,
decoration: const InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
),
hint: Text(
'dataCollectionSelection'.tr,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).hintColor,
),
),
items: _dataCollectionList.map((item) {
return DropdownMenuItem(
value: item.$1,
enabled: false,
child: StatefulBuilder(
builder: (context, menuSetState) {
final isSelected =
_enabledDataCollections.contains(item.$1);
return InkWell(
onTap: () {
isSelected
? _enabledDataCollections.remove(item.$1)
: _enabledDataCollections.add(item.$1);
setState(() {});
menuSetState(() {});
},
child: ListTile(
contentPadding:
const EdgeInsets.symmetric(horizontal: 16.0),
leading: isSelected
? const Icon(Icons.check_box_outlined)
: const Icon(Icons.check_box_outline_blank),
title: Text(item.$2),
subtitle: Text(item.$3),
),
);
},
),
);
}).toList(),
value: _enabledDataCollections.isEmpty
? null
: _enabledDataCollections.last,
onChanged: (value) {},
selectedItemBuilder: (context) {
return _dataCollectionList.map(
(item) {
return Text(
_enabledDataCollections.join(', '),
style: const TextStyle(
fontSize: 14,
overflow: TextOverflow.ellipsis,
),
maxLines: 1,
);
},
).toList();
},
buttonStyleData: const ButtonStyleData(height: 20),
menuItemStyleData: const MenuItemStyleData(
height: 80,
padding: EdgeInsets.zero,
),
),
const SizedBox(height: 16),
TextField(
controller: _fdcApiKeyController,
obscureText: true,
decoration: InputDecoration(
border: const OutlineInputBorder(),
label: Text("fdcApiKey".tr),
isDense: true,
),
onTapOutside: (_) =>
FocusManager.instance.primaryFocus?.unfocus(),
),
Text(
'fdcApiKeyHint'.tr,
style: TextStyle(color: _unFocusColor),
).paddingOnly(
left: 8,
right: 8,
top: 8,
),
const Divider(height: 1, thickness: 0.3).paddingSymmetric(
vertical: 8,
),
Text(
'fdcApiCredit'.tr,
style: TextStyle(color: _unFocusColor),
).paddingSymmetric(horizontal: 8),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton.icon(
icon: const Icon(Icons.save, size: 16),
label: Text('apply'.tr),
onPressed: () => _applySettings(),
),
],
).paddingSymmetric(vertical: 12),
],
).paddingSymmetric(horizontal: 24),
),
);
}
}