✨ Support named alert config
This commit is contained in:
parent
22b863f2bf
commit
cfa61e1a8a
@ -1,15 +1,20 @@
|
||||
import 'package:dietary_guard/models/food_data.dart';
|
||||
|
||||
class AlertConfiguration {
|
||||
String name;
|
||||
int nutrientId;
|
||||
double maxValue;
|
||||
double minValue;
|
||||
|
||||
AlertConfiguration({
|
||||
required this.name,
|
||||
required this.nutrientId,
|
||||
required this.maxValue,
|
||||
required this.minValue,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'name': name,
|
||||
'nutrient_id': nutrientId,
|
||||
'min_value': minValue,
|
||||
'max_value': maxValue,
|
||||
@ -17,6 +22,7 @@ class AlertConfiguration {
|
||||
|
||||
factory AlertConfiguration.fromJson(Map<String, dynamic> json) =>
|
||||
AlertConfiguration(
|
||||
name: json['name'],
|
||||
nutrientId: json['nutrient_id'],
|
||||
minValue: json['min_value'],
|
||||
maxValue: json['max_value'],
|
||||
@ -25,18 +31,18 @@ class AlertConfiguration {
|
||||
|
||||
class AlertDetectResult {
|
||||
AlertConfiguration config;
|
||||
FoodNutrient? nutrient;
|
||||
String name;
|
||||
String? unitName;
|
||||
double? current;
|
||||
double? difference;
|
||||
bool isOutOfRange;
|
||||
bool isUndetected;
|
||||
|
||||
AlertDetectResult({
|
||||
required this.config,
|
||||
required this.nutrient,
|
||||
required this.name,
|
||||
required this.unitName,
|
||||
required this.current,
|
||||
required this.difference,
|
||||
required this.isOutOfRange,
|
||||
required this.isUndetected,
|
||||
|
@ -33,14 +33,14 @@ class _FoodDetailsScreenState extends State<FoodDetailsScreen> {
|
||||
double? difference;
|
||||
String name = 'undetected'.tr;
|
||||
String? unitName;
|
||||
double? current;
|
||||
FoodNutrient? current;
|
||||
for (final nutrient in widget.item.foodNutrients) {
|
||||
if (item.nutrientId != nutrient.nutrientId) continue;
|
||||
name = nutrient.nutrientName;
|
||||
unitName = unitNameValues.reverse[nutrient.unitName];
|
||||
if (nutrient.value != null) {
|
||||
current = nutrient;
|
||||
final value = nutrient.value!;
|
||||
current = value;
|
||||
if (value > item.maxValue) {
|
||||
difference = value - item.maxValue;
|
||||
isOutOfRange = true;
|
||||
@ -54,9 +54,9 @@ class _FoodDetailsScreenState extends State<FoodDetailsScreen> {
|
||||
|
||||
_alertDetectResult.add(AlertDetectResult(
|
||||
config: item,
|
||||
nutrient: current,
|
||||
name: name,
|
||||
unitName: unitName,
|
||||
current: current,
|
||||
difference: difference,
|
||||
isOutOfRange: isOutOfRange,
|
||||
isUndetected: isUndetected,
|
||||
|
@ -16,6 +16,7 @@ class _AlertSettingsScreenState extends State<AlertSettingsScreen> {
|
||||
void _addAlert() {
|
||||
setState(() {
|
||||
_currentAlerts.add(AlertConfiguration(
|
||||
name: 'Alert #${_currentAlerts.length}',
|
||||
nutrientId: 0,
|
||||
maxValue: 0,
|
||||
minValue: 0,
|
||||
@ -64,16 +65,16 @@ class _AlertSettingsScreenState extends State<AlertSettingsScreen> {
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
initialValue: x.nutrientId.toString(),
|
||||
initialValue: x.name,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
label: Text("alertNutrientId".tr),
|
||||
label: Text("alertName".tr),
|
||||
isDense: true,
|
||||
),
|
||||
onTapOutside: (_) =>
|
||||
FocusManager.instance.primaryFocus?.unfocus(),
|
||||
onChanged: (value) {
|
||||
x.nutrientId = int.tryParse(value) ?? 0;
|
||||
x.name = value;
|
||||
},
|
||||
),
|
||||
),
|
||||
@ -87,6 +88,20 @@ class _AlertSettingsScreenState extends State<AlertSettingsScreen> {
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
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(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
|
@ -17,6 +17,7 @@ const i18nEnglish = {
|
||||
'alertNutrientId': 'Nutrient ID',
|
||||
'alertMaxValue': 'Alert Max Value',
|
||||
'alertMinValue': 'Alert Min Value',
|
||||
'alertName': 'Alert Name',
|
||||
'alerts': 'Alerts',
|
||||
'alertOutOfRange':
|
||||
'@count alert rules triggered, click the button on the right for details',
|
||||
|
@ -17,6 +17,7 @@ const i18nSimplifiedChinese = {
|
||||
'alertNutrientId': '营养物质编号',
|
||||
'alertMaxValue': '告警上限',
|
||||
'alertMinValue': '告警下限',
|
||||
'alertName': '告警规则名',
|
||||
'alerts': '告警',
|
||||
'alertOutOfRange': '有 @count 项告警规则触发,点击右侧按钮了解详情',
|
||||
'alertUnclear': '有 @count 项告警规则并无数据支持,点击右侧按钮了解详情',
|
||||
|
@ -60,13 +60,13 @@ class AlertDetectResultDialog extends StatelessWidget {
|
||||
title: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(item.name),
|
||||
Text(item.config.name),
|
||||
const SizedBox(width: 6),
|
||||
Badge(label: Text('#${item.config.nutrientId}'))
|
||||
],
|
||||
),
|
||||
subtitle: Text(
|
||||
'${item.current ?? 'undetected'.tr} ${(item.difference ?? 0) > 0 ? '↑' : '↓'}${item.difference?.abs().toPrecision(2) ?? '-'} ${item.unitName ?? ''}',
|
||||
'${item.nutrient?.value ?? 'undetected'.tr} ${(item.difference ?? 0) > 0 ? '↑' : '↓'}${item.difference?.abs().toPrecision(2) ?? '-'} ${item.unitName ?? ''}',
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 1.0.0+1
|
||||
version: 1.0.0+2
|
||||
|
||||
environment:
|
||||
sdk: ^3.5.0
|
||||
|
Loading…
Reference in New Issue
Block a user