123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- import 'package:flutter/material.dart';
- import 'package:flutter_habit/common/I18N.dart';
- import 'package:flutter_habit/common/components/PopMenus.dart';
- import 'package:flutter_habit/database/entity/FoodInfo.dart';
- import 'package:flutter_habit/database/mapper/FoodInfoMapper.dart';
- class FoodRecordPage extends StatefulWidget {
- @override
- _FoodRecordPageState createState() => _FoodRecordPageState();
- }
- class _FoodRecordPageState extends State<FoodRecordPage> {
- List<FoodInfo>? foods;
- @override
- void initState() {
-
- super.initState();
- foods = [];
- loadData();
- }
- Future<void> loadData() async {
- foods = await FoodInfoMapper()
- .selectAll(orderBy: "eatTimes desc,name asc, gkCalorie asc");
- setState(() {});
- }
- Future<void> onSelected(FoodInfo foodInfo) async {
- TextEditingController intakeController = TextEditingController();
- TextEditingController moneyController = TextEditingController();
- List? res = await PopMenus.baseMenu<List>(
- context: context,
- title: Text(foodInfo.getName()!),
- children: <Widget>[
- Divider(),
- Text("${I18N.of("食用次数")}: ${foodInfo.getEatTimes()}"),
- Text("${I18N.of("食物热量")}: ${foodInfo.getHgkCalorie()} (100g/kcal)"),
- TextFormField(
- keyboardType: TextInputType.number,
- controller: intakeController,
- decoration: InputDecoration(
- icon: Icon(Icons.restaurant),
- labelText: "${I18N.of("进食量")} (g)",
- hintText: I18N.of("请输入进食量"),
- ),
- ),
- TextFormField(
- keyboardType: TextInputType.number,
- controller: moneyController,
- decoration: InputDecoration(
- icon: Icon(Icons.monetization_on),
- labelText: "${I18N.of("花费")}",
- hintText: I18N.of("请输入花费"),
- ),
- ),
- TextButton(
- child: Text(I18N.of("确定")),
- onPressed: () async {
- if (intakeController.text.trim().isNotEmpty &&
- double.tryParse(intakeController.text.trim()) != null &&
- double.tryParse(moneyController.text.trim()) != null) {
- Navigator.of(context).pop([
- foodInfo.getId(),
- double.parse(intakeController.text.trim()) / 100,
- foodInfo.getEatTimes(),
- double.parse(moneyController.text.trim()),
- ]);
- } else {
- await PopMenus.attention(
- context: context, content: Text(I18N.of("输入有误")));
- }
- },
- ),
- ],
- contentPadding: EdgeInsets.all(16),
- );
- if (res != null) {
- Navigator.of(context).pop(res);
- }
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- title: Text(I18N.of("选择食物")),
- actions: <Widget>[
- IconButton(
- icon: Icon(Icons.search),
- onPressed: () async {
- String? name = await showSearch<String?>(
- context: context,
- delegate: _FoodSearchDelegate(foods),
- );
- await loadData();
- List<FoodInfo> list =
- foods!.where((test) => test.getName() == name).toList();
- if (list.isNotEmpty) {
- await onSelected(list.last);
- }
- },
- ),
- ],
- ),
- body: Padding(
- padding: EdgeInsets.all(16),
- child: Column(
- children: <Widget>[
- ListTile(
- leading: Icon(Icons.restaurant),
- title: Text(I18N.of("添加食物")),
- trailing: Icon(Icons.add),
- onTap: () async {
- TextEditingController nameController =
- TextEditingController();
- TextEditingController gkCalorieController =
- TextEditingController();
- await PopMenus.baseMenu<String>(
- context: context,
- title: Text(I18N.of("添加食物")),
- children: <Widget>[
- TextFormField(
- controller: nameController,
- decoration: InputDecoration(
- icon: Icon(Icons.restaurant_menu),
- labelText: I18N.of("食物名称"),
- hintText: I18N.of("请输入食物名称"),
- ),
- ),
- TextFormField(
- keyboardType: TextInputType.number,
- controller: gkCalorieController,
- decoration: InputDecoration(
- icon: Icon(Icons.whatshot),
- labelText: "${I18N.of("食物热量")} (100g/kcal)",
- hintText: I18N.of("请输入食物热量"),
- ),
- ),
- TextButton(
- child: Text(I18N.of("确定")),
- onPressed: () async {
- if (nameController.text.trim().isNotEmpty &&
- gkCalorieController.text.trim().isNotEmpty &&
- double.tryParse(gkCalorieController.text.trim()) !=
- null) {
- FoodInfo foodInfo = FoodInfo();
- foodInfo.setName(nameController.text.trim());
- foodInfo.setHgkCalorie(
- double.parse(gkCalorieController.text.trim()));
- foodInfo.setEatTimes(0);
- bool isSuccess =
- await FoodInfoMapper().insert(foodInfo);
- if (isSuccess) {
- await loadData();
- Navigator.of(context).pop();
- } else {
- await PopMenus.attention(
- context: context,
- content: Text(I18N.of("该食物已存在")));
- }
- } else {
- await PopMenus.attention(
- context: context, content: Text(I18N.of("输入有误")));
- }
- },
- ),
- ],
- contentPadding: EdgeInsets.all(16),
- );
- },
- ),
- Divider(),
- Text(
- I18N.of("长按可删除食物"),
- style: Theme.of(context).textTheme.bodySmall,
- ),
- Expanded(
- child: ListView(
- children: foods!.map((i) {
- return ListTile(
- title: Text(i.getName()!),
- subtitle: Text(
- "${I18N.of("食物热量")}: ${i.getHgkCalorie()} (100g/kcal)"),
- trailing: Text("${I18N.of("食用次数")}: ${i.getEatTimes()}"),
- onTap: () {
- onSelected(i);
- },
- onLongPress: () async {
- await PopMenus.sliderConfirm(
- context: context,
- content: Text(I18N.of("滑动来删除该条数据")),
- function: () async {
- if (i.getEatTimes() == 0) {
- await FoodInfoMapper().delete(i);
- await loadData();
- await PopMenus.attention(
- context: context,
- content: Text(I18N.of("删除成功")));
- } else {
- await PopMenus.attention(
- context: context,
- content: Text(I18N.of("您不能删除吃过的食物")));
- }
- },
- );
- },
- );
- }).toList(),
- ),
- ),
- ],
- ),
- ),
- );
- }
- }
- class _FoodSearchDelegate extends SearchDelegate<String?> {
- List<FoodInfo>? foods;
- _FoodSearchDelegate(this.foods);
- @override
- Widget buildLeading(BuildContext context) {
-
- return IconButton(
- icon: Icon(Icons.arrow_back),
- onPressed: () {
- this.close(context, null);
- },
- );
- }
- @override
- List<Widget> buildActions(BuildContext context) {
-
- return [
- IconButton(
- icon: Icon(Icons.clear),
- onPressed: () {
- query = "";
- showSuggestions(context);
- },
- ),
- ];
- }
- @override
- Widget buildResults(BuildContext context) {
- return Padding(
- padding: EdgeInsets.all(16),
- child: ListView(
- children:
- foods!.where((test) => test.getName()!.contains(query)).map((i) {
- return ListTile(
- title: Text(i.getName()!),
- subtitle:
- Text("${I18N.of("食物热量")}: ${i.getHgkCalorie()} (100g/kcal)"),
- trailing: Text("${I18N.of("食用次数")}: ${i.getEatTimes()}"),
- onTap: () {
- this.close(context, i.getName());
- },
- onLongPress: () async {
- await PopMenus.sliderConfirm(
- context: context,
- content: Text(I18N.of("滑动来删除该条数据")),
- function: () async {
- if (i.getEatTimes() == 0) {
- await FoodInfoMapper().delete(i);
- await PopMenus.attention(
- context: context, content: Text(I18N.of("删除成功")));
- this.close(context, null);
- } else {
- await PopMenus.attention(
- context: context, content: Text(I18N.of("您不能删除吃过的食物")));
- }
- },
- );
- },
- );
- }).toList(),
- ),
- );
- }
- @override
- Widget buildSuggestions(BuildContext context) {
- return buildResults(context);
- }
- @override
- ThemeData appBarTheme(BuildContext context) {
- return Theme.of(context);
- }
- @override
-
- String get searchFieldLabel => I18N.of("搜索");
- }
|