Compare commits
3 Commits
22b863f2bf
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 58578c734e | |||
| 76f2c0ad58 | |||
| cfa61e1a8a |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 900 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 7.3 KiB |
BIN
assets/icon.png
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 356 B After Width: | Height: | Size: 521 B |
|
Before Width: | Height: | Size: 723 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 791 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 723 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 930 B After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 6.1 KiB |
@@ -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,
|
||||
|
||||
@@ -26,7 +26,7 @@ class _QueryScreenState extends State<QueryScreen> {
|
||||
setState(() => _isLoading = true);
|
||||
|
||||
final FoodDataController data = Get.find();
|
||||
if (data.getApiKey() == null) {
|
||||
if (data.getApiKey() == null || data.getApiKey()!.isEmpty) {
|
||||
setState(() => _hasApiKey = false);
|
||||
return;
|
||||
}
|
||||
@@ -44,7 +44,11 @@ class _QueryScreenState extends State<QueryScreen> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
final FoodDataController data = Get.find();
|
||||
data.initialize(context);
|
||||
data.initialize(context).then((_) {
|
||||
setState(() {
|
||||
_hasApiKey = data.getApiKey() != null && data.getApiKey()!.isNotEmpty;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -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',
|
||||
@@ -48,5 +49,5 @@ const i18nEnglish = {
|
||||
'searchHint': 'Type keywords below to search',
|
||||
'searchNoKeyHint':
|
||||
'No API key, please first set up the API key in "Settings" > "Data Source"',
|
||||
'searchResultHint': '@count records matched (up to the first 100)',
|
||||
'searchResultHint': '@count records matched (showing 100)',
|
||||
};
|
||||
|
||||
@@ -17,6 +17,7 @@ const i18nSimplifiedChinese = {
|
||||
'alertNutrientId': '营养物质编号',
|
||||
'alertMaxValue': '告警上限',
|
||||
'alertMinValue': '告警下限',
|
||||
'alertName': '告警规则名',
|
||||
'alerts': '告警',
|
||||
'alertOutOfRange': '有 @count 项告警规则触发,点击右侧按钮了解详情',
|
||||
'alertUnclear': '有 @count 项告警规则并无数据支持,点击右侧按钮了解详情',
|
||||
@@ -41,5 +42,5 @@ const i18nSimplifiedChinese = {
|
||||
'loading': '加载中',
|
||||
'searchHint': '在下方键入关键词来搜索',
|
||||
'searchNoKeyHint': '无 API 令牌,请先在「设置」>「数据源」设置 API 密钥',
|
||||
'searchResultHint': '共命中 @count 条记录(截取前 100 条)',
|
||||
'searchResultHint': '共命中 @count 条记录(显示前 100 条)',
|
||||
};
|
||||
|
||||
@@ -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 ?? ''}',
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 293 B After Width: | Height: | Size: 385 B |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 590 B After Width: | Height: | Size: 823 B |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -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
|
||||
|
||||
BIN
web/favicon.png
|
Before Width: | Height: | Size: 293 B After Width: | Height: | Size: 385 B |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 10 KiB |