ExerciseInfoContext.dart 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_habit/common/BaseArchitectural.dart';
  3. import 'package:flutter_habit/common/I18N.dart';
  4. import 'package:flutter_habit/common/components/PopMenus.dart';
  5. import 'package:flutter_habit/provider/DataProvider.dart';
  6. import 'package:flutter_habit/provider/UserProvider.dart';
  7. import 'package:flutter_habit/common/utils/ConvertUtils.dart';
  8. import 'package:flutter_habit/database/entity/ExerciseInfo.dart';
  9. import 'package:flutter_habit/database/entity/ScheduledExercise.dart';
  10. import 'package:flutter_habit/database/entity/SportInfo.dart';
  11. import 'package:flutter_habit/database/mapper/ExerciseInfoMapper.dart';
  12. import 'package:flutter_habit/database/mapper/ScheduledExerciseMapper.dart';
  13. import 'package:flutter_habit/database/mapper/SportInfoMapper.dart';
  14. import 'package:flutter_habit/network/Repository.dart';
  15. import 'package:flutter_habit/view/context/widget/BaseCard.dart';
  16. import 'package:flutter_habit/view/context/widget/DateValueSingleLineChart.dart';
  17. import 'package:flutter_habit/view/record/sub/AddScheduledExercisePage.dart';
  18. import 'package:provider/provider.dart';
  19. class ExerciseInfoContext extends StatelessWidget {
  20. @override
  21. Widget build(BuildContext context) {
  22. return MultiProvider(
  23. providers: [
  24. ChangeNotifierProvider<ExerciseInfoContextService>(
  25. create: (_) => ExerciseInfoContextService(context)),
  26. ],
  27. child: _ExerciseInfoContextView(),
  28. );
  29. }
  30. }
  31. // service
  32. class ExerciseInfoContextService extends BaseProvider {
  33. ExerciseInfoContextService(BuildContext context) : super(context);
  34. Future<void> cancelScheduledExercise(BuildContext context,
  35. MapEntry<ScheduledExercise, SportInfo> mapEntry) async {
  36. await PopMenus.sliderConfirm(
  37. context: context,
  38. content: Text(I18N.of("滑动来删除该条数据")),
  39. function: () async {
  40. await ScheduledExerciseMapper().delete(mapEntry.key);
  41. SportInfo sportInfo = SportInfo();
  42. sportInfo.setId(mapEntry.value.getId());
  43. sportInfo.setSportTimes(mapEntry.value.getSportTimes()! - 1);
  44. await SportInfoMapper().updateByFirstKeySelective(sportInfo);
  45. await Provider.of<DataProvider>(context, listen: false)
  46. .loadExerciseInfoData();
  47. },
  48. );
  49. }
  50. Future<void> completeScheduledExercise(BuildContext context,
  51. MapEntry<ScheduledExercise, SportInfo> mapEntry) async {
  52. await PopMenus.sliderConfirm(
  53. context: context,
  54. content: Text(I18N.of("滑动来完成计划")),
  55. function: () async {
  56. DateTime now = DateTime.now();
  57. ExerciseInfo exerciseInfo = ExerciseInfo();
  58. exerciseInfo.setSportId(mapEntry.key.getSportId());
  59. exerciseInfo.setExerciseQuantity(mapEntry.key.getQuantity());
  60. exerciseInfo.setExerciseTime(now.millisecondsSinceEpoch);
  61. // 今日首次运动?
  62. List<ExerciseInfo> localExerciseInfo = (await ExerciseInfoMapper().selectWhere(
  63. "exerciseTime > ${ConvertUtils.dateOfDateTime(now).millisecondsSinceEpoch}"))!;
  64. if (localExerciseInfo.isEmpty){
  65. // 今日首次运动
  66. // 增加金币
  67. UserProvider userProvider =
  68. Provider.of<UserProvider>(context, listen: false);
  69. if (userProvider.token != null) {
  70. int? increasedCoin = await Repository.getInstance()!
  71. .increaseCoin(context, userProvider.uid, userProvider.token);
  72. if (increasedCoin != null) {
  73. await PopMenus.coinAdd(
  74. context: context, addedCoins: increasedCoin);
  75. userProvider.coins += increasedCoin;
  76. userProvider.refresh();
  77. }
  78. }
  79. }
  80. await ExerciseInfoMapper().insert(exerciseInfo);
  81. await ScheduledExerciseMapper().delete(mapEntry.key);
  82. await Provider.of<DataProvider>(context, listen: false)
  83. .loadExerciseInfoData();
  84. },
  85. );
  86. }
  87. void toAddScheduledExercisePage(BuildContext context) {
  88. Navigator.of(context)
  89. .push(MaterialPageRoute(builder: (_) => AddScheduledExercisePage()));
  90. }
  91. void changeSizeOfExerciseInfoChartCard(BuildContext context) {
  92. DataProvider dataProvider =
  93. Provider.of<DataProvider>(context, listen: false);
  94. switch (dataProvider.exerciseInfoChartSize) {
  95. case 7:
  96. dataProvider.exerciseInfoChartSize = 30;
  97. break;
  98. case 30:
  99. dataProvider.exerciseInfoChartSize = 90;
  100. break;
  101. case 90:
  102. dataProvider.exerciseInfoChartSize = 7;
  103. break;
  104. }
  105. dataProvider.notifyListeners();
  106. }
  107. }
  108. // view
  109. class _ExerciseInfoContextView extends StatelessWidget {
  110. @override
  111. Widget build(BuildContext context) {
  112. return ListView(
  113. children: <Widget>[
  114. overviewCard(context),
  115. exerciseInfoChartCard(context),
  116. Divider(),
  117. scheduledExerciseCards(context),
  118. addScheduledExercise(context),
  119. ],
  120. );
  121. }
  122. Widget overviewCard(BuildContext context) {
  123. DataProvider dataProvider =
  124. Provider.of<DataProvider>(context, listen: true);
  125. return BaseCard(
  126. title: Text(
  127. I18N.of("最近"),
  128. style: Theme.of(context).textTheme.titleLarge,
  129. ),
  130. subtitle: Text(I18N.of("概览")),
  131. child: Row(
  132. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  133. children: <Widget>[
  134. Container(),
  135. Icon(
  136. Icons.fitness_center,
  137. size: 100,
  138. color: Theme.of(context).colorScheme.secondary,
  139. ),
  140. Column(
  141. crossAxisAlignment: CrossAxisAlignment.start,
  142. children: <Widget>[
  143. Text(
  144. "${I18N.of("待完成计划数")}: ${dataProvider.scheduledExerciseCount}",
  145. ),
  146. Text(
  147. "${I18N.of("7日运动次数")}: ${dataProvider.sevenDayExerciseTimes}",
  148. ),
  149. Text(
  150. "${I18N.of("7日运动总消耗")}: ${dataProvider.sevenDayExerciseTotalKCal.toStringAsFixed(2)} kcal",
  151. ),
  152. ],
  153. ),
  154. Container(),
  155. ],
  156. ),
  157. );
  158. }
  159. Widget exerciseInfoChartCard(BuildContext context) {
  160. ExerciseInfoContextService service =
  161. Provider.of<ExerciseInfoContextService>(context, listen: false);
  162. DataProvider dataProvider =
  163. Provider.of<DataProvider>(context, listen: true);
  164. return BaseCard(
  165. title: Text(
  166. "${I18N.of("卡路里消耗")} (kcal)",
  167. style: Theme.of(context).textTheme.titleLarge,
  168. ),
  169. subtitle: Container(
  170. height: 25,
  171. child: TextButton(
  172. child: Text("< ${dataProvider.exerciseInfoChartSize} >"),
  173. onPressed: () => service.changeSizeOfExerciseInfoChartCard(context),
  174. ),
  175. ),
  176. child: DateValueSingleLineChart(
  177. size: dataProvider.exerciseInfoChartSize,
  178. sports: dataProvider.exerciseInfoFlSpots,
  179. ),
  180. );
  181. }
  182. Widget addScheduledExercise(BuildContext context) {
  183. ExerciseInfoContextService service =
  184. Provider.of<ExerciseInfoContextService>(context, listen: false);
  185. return Padding(
  186. padding: EdgeInsets.only(left: 5, right: 5, bottom: 5),
  187. child: ElevatedButton(
  188. style: ButtonStyle(
  189. backgroundColor: MaterialStateProperty.all(
  190. Theme.of(context).colorScheme.secondary),
  191. foregroundColor:
  192. MaterialStateProperty.all(Theme.of(context).cardColor)),
  193. child: Text(I18N.of("添加计划任务")),
  194. onPressed: () => service.toAddScheduledExercisePage(context),
  195. ),
  196. );
  197. }
  198. Widget scheduledExerciseCards(BuildContext context) {
  199. ExerciseInfoContextService service =
  200. Provider.of<ExerciseInfoContextService>(context, listen: false);
  201. DataProvider dataProvider =
  202. Provider.of<DataProvider>(context, listen: true);
  203. return Column(
  204. children: dataProvider.scheduledExerciseSportInfoList.map((i) {
  205. return BaseCard(
  206. title: Text(I18N.of("计划任务"),
  207. style: Theme.of(context).textTheme.titleLarge,
  208. ),
  209. child: Row(
  210. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  211. children: <Widget>[
  212. Container(),
  213. Icon(
  214. Icons.timer,
  215. size: 100,
  216. color: Theme.of(context).colorScheme.secondary,
  217. ),
  218. Container(),
  219. Column(
  220. crossAxisAlignment: CrossAxisAlignment.start,
  221. children: <Widget>[
  222. Text("${I18N.of("运动类型")}: ${i.value.getName()}"),
  223. Text(
  224. "${I18N.of("运动时长")}: ${ConvertUtils.fixedDouble(i.key.getQuantity()! * 60, 2)} min"),
  225. Text("${I18N.of("消耗")}: ${i.value.getHkCalorie()} h/kcal"),
  226. Text(
  227. "${I18N.of("预计消耗")}: ${ConvertUtils.fixedDouble(i.key.getQuantity()! * i.value.getHkCalorie()!, 2)} kcal"),
  228. Row(
  229. mainAxisAlignment: MainAxisAlignment.end,
  230. children: <Widget>[
  231. ElevatedButton(
  232. style: ButtonStyle(
  233. backgroundColor: MaterialStateProperty.all(
  234. Theme.of(context).colorScheme.secondary),
  235. foregroundColor: MaterialStateProperty.all(
  236. Theme.of(context).cardColor)),
  237. child: Text(I18N.of("取消")),
  238. onPressed: () =>
  239. service.cancelScheduledExercise(context, i),
  240. ),
  241. Container(
  242. width: 10,
  243. ),
  244. ElevatedButton(
  245. style: ButtonStyle(
  246. backgroundColor: MaterialStateProperty.all(
  247. Theme.of(context).colorScheme.secondary),
  248. foregroundColor: MaterialStateProperty.all(
  249. Theme.of(context).cardColor)),
  250. child: Text(I18N.of("完成")),
  251. onPressed: () =>
  252. service.completeScheduledExercise(context, i),
  253. ),
  254. ],
  255. ),
  256. ],
  257. ),
  258. Container(),
  259. ],
  260. ),
  261. );
  262. }).toList(),
  263. );
  264. }
  265. }