DietaryGuard/lib/screens/food/details.dart

169 lines
5.7 KiB
Dart
Raw Permalink Normal View History

2024-08-15 07:57:58 +00:00
import 'package:dietary_guard/controllers/alert.dart';
import 'package:dietary_guard/models/alert_configuration.dart';
2024-08-14 17:38:29 +00:00
import 'package:dietary_guard/models/food_data.dart';
2024-08-15 07:57:58 +00:00
import 'package:dietary_guard/widgets/alert_detect_result.dart';
2024-08-14 17:38:29 +00:00
import 'package:flutter/material.dart';
import 'package:get/get.dart';
2024-08-15 07:57:58 +00:00
class FoodDetailsScreen extends StatefulWidget {
2024-08-14 17:38:29 +00:00
final FoodData item;
const FoodDetailsScreen({super.key, required this.item});
2024-08-15 07:57:58 +00:00
@override
State<FoodDetailsScreen> createState() => _FoodDetailsScreenState();
}
class _FoodDetailsScreenState extends State<FoodDetailsScreen> {
final List<AlertDetectResult> _alertDetectResult = List.empty(growable: true);
@override
void initState() {
super.initState();
_detectAlert();
}
void _detectAlert() {
final AlertController alert = Get.find();
if (alert.configuration.isEmpty) return;
for (final item in alert.configuration) {
bool isUndetected = true;
bool isOutOfRange = false;
double? difference;
String name = 'undetected'.tr;
String? unitName;
2024-08-15 14:50:00 +00:00
FoodNutrient? current;
2024-08-15 07:57:58 +00:00
for (final nutrient in widget.item.foodNutrients) {
if (item.nutrientId != nutrient.nutrientId) continue;
name = nutrient.nutrientName;
unitName = unitNameValues.reverse[nutrient.unitName];
2024-08-15 07:57:58 +00:00
if (nutrient.value != null) {
2024-08-15 14:50:00 +00:00
current = nutrient;
final value = nutrient.value!;
2024-08-15 07:57:58 +00:00
if (value > item.maxValue) {
difference = value - item.maxValue;
isOutOfRange = true;
} else if (value < item.minValue) {
difference = value - item.minValue;
isOutOfRange = true;
}
isUndetected = false;
2024-08-15 07:57:58 +00:00
}
}
_alertDetectResult.add(AlertDetectResult(
config: item,
2024-08-15 14:50:00 +00:00
nutrient: current,
name: name,
unitName: unitName,
difference: difference,
isOutOfRange: isOutOfRange,
isUndetected: isUndetected,
));
2024-08-15 07:57:58 +00:00
}
}
Widget _buildShowAlertResultButton() {
return IconButton(
icon: const Icon(Icons.assignment),
onPressed: () {
showModalBottomSheet(
useRootNavigator: true,
isScrollControlled: true,
context: context,
builder: (context) => AlertDetectResultDialog(
result: _alertDetectResult,
),
);
},
);
}
2024-08-14 17:38:29 +00:00
@override
Widget build(BuildContext context) {
2024-08-15 03:53:01 +00:00
return Material(
color: Theme.of(context).colorScheme.surface,
child: Scaffold(
appBar: AppBar(
2024-08-15 07:57:58 +00:00
title: Text(widget.item.description),
2024-08-15 03:53:01 +00:00
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
2024-08-15 07:57:58 +00:00
if (_alertDetectResult.isEmpty)
MaterialBanner(
padding: const EdgeInsets.only(left: 24, right: 8),
content: Text('alertEmpty'.tr),
actions: const [SizedBox()],
dividerColor: Colors.transparent,
)
else if (_alertDetectResult.any((x) => x.isOutOfRange))
MaterialBanner(
leading: const Icon(Icons.close),
backgroundColor: Colors.red,
padding: const EdgeInsets.only(left: 24, right: 8),
content: Text('alertOutOfRange'.trParams({
'count': _alertDetectResult
.where((x) => x.isOutOfRange)
.length
.toString()
})),
actions: [_buildShowAlertResultButton()],
dividerColor: Colors.transparent,
)
else if (_alertDetectResult.any((x) => x.isUndetected))
MaterialBanner(
leading: const Icon(Icons.question_mark),
backgroundColor: Colors.grey,
padding: const EdgeInsets.only(left: 24, right: 8),
content: Text('alertUnclear'.trParams({
'count': _alertDetectResult
.where((x) => x.isUndetected)
.length
.toString()
})),
actions: [_buildShowAlertResultButton()],
dividerColor: Colors.transparent,
)
else
MaterialBanner(
leading: const Icon(Icons.check),
backgroundColor: Colors.green,
padding: const EdgeInsets.only(left: 24, right: 8),
content: Text('alertSafe'.tr),
actions: [_buildShowAlertResultButton()],
dividerColor: Colors.transparent,
),
const SizedBox(height: 16),
2024-08-15 03:53:01 +00:00
Text('nutrients'.tr).paddingOnly(left: 24, right: 24, bottom: 8),
Expanded(
child: ListView.builder(
2024-08-15 07:57:58 +00:00
itemCount: widget.item.foodNutrients.length,
2024-08-15 03:53:01 +00:00
itemBuilder: (context, idx) {
2024-08-15 07:57:58 +00:00
final entry = widget.item.foodNutrients[idx];
2024-08-15 03:53:01 +00:00
final unitName = unitNameValues.reverse[entry.unitName];
return ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
title: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(entry.nutrientName),
const SizedBox(width: 6),
Badge(label: Text('#${entry.nutrientId}'))
],
),
2024-08-15 07:57:58 +00:00
subtitle: Text(
'${entry.value?.toString() ?? '-'} $unitName',
),
2024-08-15 03:53:01 +00:00
);
},
),
)
],
2024-08-15 07:57:58 +00:00
),
2024-08-14 17:38:29 +00:00
),
);
}
}