LifeInfoRecordingPage.dart 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  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/ConfigProvider.dart';
  6. import 'package:flutter_habit/provider/DataProvider.dart';
  7. import 'package:flutter_habit/provider/UserProvider.dart';
  8. import 'package:flutter_habit/common/utils/ConvertUtils.dart';
  9. import 'package:flutter_habit/common/utils/VerificationUtils.dart';
  10. import 'package:flutter_habit/database/entity/FoodInfo.dart';
  11. import 'package:flutter_habit/database/entity/LifeInfo.dart';
  12. import 'package:flutter_habit/database/mapper/FoodInfoMapper.dart';
  13. import 'package:flutter_habit/database/mapper/LifeInfoMapper.dart';
  14. import 'package:flutter_habit/network/Repository.dart';
  15. import 'package:flutter_habit/view/record/sub/FoodRecordPage.dart';
  16. import 'package:provider/provider.dart';
  17. class LifeInfoRecordingPage extends StatelessWidget {
  18. @override
  19. Widget build(BuildContext context) {
  20. return MultiProvider(
  21. providers: [
  22. ChangeNotifierProvider<LifeInfoRecordingPageService>(
  23. create: (_) => LifeInfoRecordingPageService(context)),
  24. ChangeNotifierProvider<LifeInfoRecordingPageModel>(
  25. create: (_) => LifeInfoRecordingPageModel(context)),
  26. ],
  27. child: _LifeInfoRecordingPageView(),
  28. );
  29. }
  30. }
  31. // model
  32. class LifeInfoRecordingPageModel extends BaseModel {
  33. LifeInfoRecordingPageModel(BuildContext context) : super(context);
  34. int? currId;
  35. late bool isSignGetUp;
  36. late bool isSignBreakfast;
  37. late bool isSignMidRest;
  38. late bool isSignLunch;
  39. late bool isSignDinner;
  40. late bool isSignRest;
  41. @override
  42. void init(BuildContext context) {
  43. super.init(context);
  44. currId = null;
  45. isSignGetUp = true;
  46. isSignBreakfast = true;
  47. isSignMidRest = true;
  48. isSignLunch = true;
  49. isSignDinner = true;
  50. isSignRest = true;
  51. }
  52. @override
  53. Future<void> asyncInit(BuildContext context) async {
  54. DateTime now = DateTime.now();
  55. List<LifeInfo> list = (await LifeInfoMapper().selectWhere(
  56. "date >= ${ConvertUtils.dateOfDateTime(now).millisecondsSinceEpoch}"))!;
  57. if (list.isNotEmpty) {
  58. LifeInfo localLifeInfo = list[0];
  59. currId = list[0].getId();
  60. isSignGetUp = localLifeInfo.getGetUpTime() != null;
  61. isSignBreakfast = localLifeInfo.getBreakfastTime() != null;
  62. isSignMidRest = localLifeInfo.getMidRestTime() != null;
  63. isSignLunch = localLifeInfo.getLunchTime() != null;
  64. isSignDinner = localLifeInfo.getDinnerTime() != null;
  65. isSignRest = localLifeInfo.getRestTime() != null;
  66. } else {
  67. await LifeInfoMapper()
  68. .insert(LifeInfo().setDate(now.millisecondsSinceEpoch));
  69. list = (await LifeInfoMapper().selectWhere(
  70. "date >= ${ConvertUtils.dateOfDateTime(now).millisecondsSinceEpoch}"))!;
  71. currId = list[0].getId();
  72. isSignGetUp = false;
  73. isSignBreakfast = false;
  74. isSignMidRest = false;
  75. isSignLunch = false;
  76. isSignDinner = false;
  77. isSignRest = false;
  78. }
  79. refresh();
  80. }
  81. }
  82. // service
  83. class LifeInfoRecordingPageService extends BaseProvider {
  84. LifeInfoRecordingPageService(BuildContext context) : super(context);
  85. Future<void> signGetUp(BuildContext context) async {
  86. LifeInfoRecordingPageModel model =
  87. Provider.of<LifeInfoRecordingPageModel>(context, listen: false);
  88. ConfigProvider configProvider =
  89. Provider.of<ConfigProvider>(context, listen: false);
  90. // 记录
  91. await PopMenus.sliderConfirm(
  92. context: context,
  93. content: Text(I18N.of("滑动来打卡")),
  94. function: () async {
  95. LifeInfo lifeInfo = LifeInfo();
  96. lifeInfo.setId(model.currId);
  97. lifeInfo.setGetUpTime(DateTime.now().millisecondsSinceEpoch);
  98. model.isSignGetUp =
  99. await LifeInfoMapper().updateByFirstKeySelective(lifeInfo);
  100. // 时间验证
  101. if (!VerifyUtils.nowIsBetweenTime(
  102. configProvider.getUpTimeStart, configProvider.getUpTimeEnd)) {
  103. await PopMenus.attention(
  104. context: context, content: Text(I18N.of("非打卡时间打卡成功")));
  105. } else {
  106. // 增加金币
  107. UserProvider userProvider =
  108. Provider.of<UserProvider>(context, listen: false);
  109. if (userProvider.token != null) {
  110. int? increasedCoin = await Repository.getInstance()!
  111. .increaseCoin(context, userProvider.uid, userProvider.token);
  112. if (increasedCoin != null) {
  113. await PopMenus.coinAdd(
  114. context: context, addedCoins: increasedCoin);
  115. userProvider.coins += increasedCoin;
  116. userProvider.refresh();
  117. }
  118. }
  119. }
  120. model.refresh();
  121. await Provider.of<DataProvider>(context, listen: false)
  122. .loadLifeInfoData();
  123. },
  124. );
  125. }
  126. Future<void> signBreakfast(BuildContext context) async {
  127. LifeInfoRecordingPageModel model =
  128. Provider.of<LifeInfoRecordingPageModel>(context, listen: false);
  129. ConfigProvider configProvider =
  130. Provider.of<ConfigProvider>(context, listen: false);
  131. List? info = await Navigator.of(context)
  132. .push(MaterialPageRoute(builder: (_) => FoodRecordPage()));
  133. if (info != null) {
  134. LifeInfo lifeInfo = LifeInfo();
  135. lifeInfo.setId(model.currId);
  136. lifeInfo.setBreakfastId(info[0]);
  137. lifeInfo.setBreakfastQuantity(info[1]);
  138. lifeInfo.setBreakfastMoney(info[3]);
  139. lifeInfo.setBreakfastTime(DateTime.now().millisecondsSinceEpoch);
  140. model.isSignBreakfast =
  141. await LifeInfoMapper().updateByFirstKeySelective(lifeInfo);
  142. // 增加食用次数
  143. FoodInfo foodInfo = FoodInfo();
  144. foodInfo.setId(info[0]);
  145. foodInfo.setEatTimes(info[2] + 1);
  146. await FoodInfoMapper().updateByFirstKeySelective(foodInfo);
  147. // 时间验证
  148. if (!VerifyUtils.nowIsBetweenTime(
  149. configProvider.breakfastTimeStart, configProvider.breakfastTimeEnd)) {
  150. await PopMenus.attention(
  151. context: context, content: Text(I18N.of("非打卡时间打卡成功")));
  152. } else {
  153. // 增加金币
  154. UserProvider userProvider =
  155. Provider.of<UserProvider>(context, listen: false);
  156. if (userProvider.token != null) {
  157. int? increasedCoin = await Repository.getInstance()!
  158. .increaseCoin(context, userProvider.uid, userProvider.token);
  159. if (increasedCoin != null) {
  160. await PopMenus.coinAdd(context: context, addedCoins: increasedCoin);
  161. userProvider.coins += increasedCoin;
  162. userProvider.refresh();
  163. }
  164. }
  165. }
  166. model.refresh();
  167. await Provider.of<DataProvider>(context, listen: false)
  168. .loadLifeInfoData();
  169. }
  170. }
  171. Future<void> signLunch(BuildContext context) async {
  172. LifeInfoRecordingPageModel model =
  173. Provider.of<LifeInfoRecordingPageModel>(context, listen: false);
  174. ConfigProvider configProvider =
  175. Provider.of<ConfigProvider>(context, listen: false);
  176. List? info = await Navigator.of(context)
  177. .push(MaterialPageRoute(builder: (_) => FoodRecordPage()));
  178. if (info != null) {
  179. LifeInfo lifeInfo = LifeInfo();
  180. lifeInfo.setId(model.currId);
  181. lifeInfo.setLunchId(info[0]);
  182. lifeInfo.setLunchQuantity(info[1]);
  183. lifeInfo.setLunchMoney(info[3]);
  184. lifeInfo.setLunchTime(DateTime.now().millisecondsSinceEpoch);
  185. model.isSignLunch =
  186. await LifeInfoMapper().updateByFirstKeySelective(lifeInfo);
  187. // 增加食用次数
  188. FoodInfo foodInfo = FoodInfo();
  189. foodInfo.setId(info[0]);
  190. foodInfo.setEatTimes(info[2] + 1);
  191. await FoodInfoMapper().updateByFirstKeySelective(foodInfo);
  192. // 时间验证
  193. if (!VerifyUtils.nowIsBetweenTime(
  194. configProvider.lunchTimeStart, configProvider.lunchTimeEnd)) {
  195. await PopMenus.attention(
  196. context: context, content: Text(I18N.of("非打卡时间打卡成功")));
  197. } else {
  198. // 增加金币
  199. UserProvider userProvider =
  200. Provider.of<UserProvider>(context, listen: false);
  201. if (userProvider.token != null) {
  202. int? increasedCoin = await Repository.getInstance()!
  203. .increaseCoin(context, userProvider.uid, userProvider.token);
  204. if (increasedCoin != null) {
  205. await PopMenus.coinAdd(context: context, addedCoins: increasedCoin);
  206. userProvider.coins += increasedCoin;
  207. userProvider.refresh();
  208. }
  209. }
  210. }
  211. model.refresh();
  212. await Provider.of<DataProvider>(context, listen: false)
  213. .loadLifeInfoData();
  214. }
  215. }
  216. Future<void> signDinner(BuildContext context) async {
  217. LifeInfoRecordingPageModel model =
  218. Provider.of<LifeInfoRecordingPageModel>(context, listen: false);
  219. ConfigProvider configProvider =
  220. Provider.of<ConfigProvider>(context, listen: false);
  221. List? info = await Navigator.of(context)
  222. .push(MaterialPageRoute(builder: (_) => FoodRecordPage()));
  223. if (info != null) {
  224. LifeInfo lifeInfo = LifeInfo();
  225. lifeInfo.setId(model.currId);
  226. lifeInfo.setDinnerId(info[0]);
  227. lifeInfo.setDinnerQuantity(info[1]);
  228. lifeInfo.setDinnerMoney(info[3]);
  229. lifeInfo.setDinnerTime(DateTime.now().millisecondsSinceEpoch);
  230. model.isSignDinner =
  231. await LifeInfoMapper().updateByFirstKeySelective(lifeInfo);
  232. // 增加食用次数
  233. FoodInfo foodInfo = FoodInfo();
  234. foodInfo.setId(info[0]);
  235. foodInfo.setEatTimes(info[2] + 1);
  236. await FoodInfoMapper().updateByFirstKeySelective(foodInfo);
  237. // 时间验证
  238. if (!VerifyUtils.nowIsBetweenTime(
  239. configProvider.dinnerTimeStart, configProvider.dinnerTimeEnd)) {
  240. await PopMenus.attention(
  241. context: context, content: Text(I18N.of("非打卡时间打卡成功")));
  242. } else {
  243. // 增加金币
  244. UserProvider userProvider =
  245. Provider.of<UserProvider>(context, listen: false);
  246. if (userProvider.token != null) {
  247. int? increasedCoin = await Repository.getInstance()!
  248. .increaseCoin(context, userProvider.uid, userProvider.token);
  249. if (increasedCoin != null) {
  250. await PopMenus.coinAdd(context: context, addedCoins: increasedCoin);
  251. userProvider.coins += increasedCoin;
  252. userProvider.refresh();
  253. }
  254. }
  255. }
  256. model.refresh();
  257. await Provider.of<DataProvider>(context, listen: false)
  258. .loadLifeInfoData();
  259. }
  260. }
  261. Future<void> signRest(BuildContext context) async {
  262. LifeInfoRecordingPageModel model =
  263. Provider.of<LifeInfoRecordingPageModel>(context, listen: false);
  264. ConfigProvider configProvider =
  265. Provider.of<ConfigProvider>(context, listen: false);
  266. // 记录
  267. await PopMenus.sliderConfirm(
  268. context: context,
  269. content: Text(I18N.of("滑动来打卡")),
  270. function: () async {
  271. LifeInfo lifeInfo = LifeInfo();
  272. lifeInfo.setId(model.currId);
  273. lifeInfo.setRestTime(DateTime.now().millisecondsSinceEpoch);
  274. model.isSignRest =
  275. await LifeInfoMapper().updateByFirstKeySelective(lifeInfo);
  276. // 时间验证
  277. if (!VerifyUtils.nowIsBetweenTime(
  278. configProvider.restTimeStart, configProvider.restTimeEnd)) {
  279. await PopMenus.attention(
  280. context: context, content: Text(I18N.of("非打卡时间打卡成功")));
  281. } else {
  282. // 增加金币
  283. UserProvider userProvider =
  284. Provider.of<UserProvider>(context, listen: false);
  285. if (userProvider.token != null) {
  286. int? increasedCoin = await Repository.getInstance()!
  287. .increaseCoin(context, userProvider.uid, userProvider.token);
  288. if (increasedCoin != null) {
  289. await PopMenus.coinAdd(
  290. context: context, addedCoins: increasedCoin);
  291. userProvider.coins += increasedCoin;
  292. userProvider.refresh();
  293. }
  294. }
  295. }
  296. model.refresh();
  297. await Provider.of<DataProvider>(context, listen: false)
  298. .loadLifeInfoData();
  299. },
  300. );
  301. }
  302. Future<void> signMidRest(BuildContext context) async {
  303. LifeInfoRecordingPageModel model =
  304. Provider.of<LifeInfoRecordingPageModel>(context, listen: false);
  305. ConfigProvider configProvider =
  306. Provider.of<ConfigProvider>(context, listen: false);
  307. // 记录
  308. await PopMenus.sliderConfirm(
  309. context: context,
  310. content: Text(I18N.of("滑动来打卡")),
  311. function: () async {
  312. LifeInfo lifeInfo = LifeInfo();
  313. lifeInfo.setId(model.currId);
  314. lifeInfo.setMidRestTime(DateTime.now().millisecondsSinceEpoch);
  315. model.isSignMidRest =
  316. await LifeInfoMapper().updateByFirstKeySelective(lifeInfo);
  317. // 时间验证
  318. if (!VerifyUtils.nowIsBetweenTime(
  319. configProvider.midRestTimeStart, configProvider.midRestTimeEnd)) {
  320. await PopMenus.attention(
  321. context: context, content: Text(I18N.of("非打卡时间打卡成功")));
  322. } else {
  323. // 增加金币
  324. UserProvider userProvider =
  325. Provider.of<UserProvider>(context, listen: false);
  326. if (userProvider.token != null) {
  327. int? increasedCoin = await Repository.getInstance()!
  328. .increaseCoin(context, userProvider.uid, userProvider.token);
  329. if (increasedCoin != null) {
  330. await PopMenus.coinAdd(
  331. context: context, addedCoins: increasedCoin);
  332. userProvider.coins += increasedCoin;
  333. userProvider.refresh();
  334. }
  335. }
  336. }
  337. model.refresh();
  338. await Provider.of<DataProvider>(context, listen: false)
  339. .loadLifeInfoData();
  340. },
  341. );
  342. }
  343. }
  344. // view
  345. class _LifeInfoRecordingPageView extends StatelessWidget {
  346. @override
  347. Widget build(BuildContext context) {
  348. LifeInfoRecordingPageService service =
  349. Provider.of<LifeInfoRecordingPageService>(context, listen: false);
  350. LifeInfoRecordingPageModel model =
  351. Provider.of<LifeInfoRecordingPageModel>(context, listen: true);
  352. ConfigProvider configProvider =
  353. Provider.of<ConfigProvider>(context, listen: true);
  354. return Scaffold(
  355. appBar: AppBar(
  356. title: Text(I18N.of("日常生活记录")),
  357. ),
  358. body: Padding(
  359. padding: EdgeInsets.all(16),
  360. child: ListView(
  361. children: <Widget>[
  362. ListTile(
  363. leading: Icon(Icons.wb_sunny),
  364. title: Text(I18N.of("起床打卡")),
  365. subtitle: Text(
  366. "${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.getUpTimeStart)} - ${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.getUpTimeEnd!)}"),
  367. trailing: Icon(
  368. model.isSignGetUp ? Icons.check_circle : Icons.chevron_right,
  369. color: model.isSignGetUp
  370. ? Theme.of(context).colorScheme.secondary
  371. : null,
  372. ),
  373. onTap:
  374. model.isSignGetUp ? null : () => service.signGetUp(context),
  375. ),
  376. ListTile(
  377. leading: Icon(Icons.free_breakfast),
  378. title: Text(I18N.of("早饭打卡")),
  379. subtitle: Text(
  380. "${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.breakfastTimeStart)} - ${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.breakfastTimeEnd!)}"),
  381. trailing: Icon(
  382. model.isSignBreakfast
  383. ? Icons.check_circle
  384. : Icons.chevron_right,
  385. color: model.isSignBreakfast
  386. ? Theme.of(context).colorScheme.secondary
  387. : null,
  388. ),
  389. onTap: model.isSignBreakfast
  390. ? null
  391. : () => service.signBreakfast(context),
  392. ),
  393. ListTile(
  394. leading: Icon(Icons.local_dining),
  395. title: Text(I18N.of("午饭打卡")),
  396. subtitle: Text(
  397. "${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.lunchTimeStart)} - ${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.lunchTimeEnd!)}"),
  398. trailing: Icon(
  399. model.isSignLunch ? Icons.check_circle : Icons.chevron_right,
  400. color: model.isSignLunch
  401. ? Theme.of(context).colorScheme.secondary
  402. : null,
  403. ),
  404. onTap:
  405. model.isSignLunch ? null : () => service.signLunch(context),
  406. ),
  407. ListTile(
  408. leading: Icon(Icons.local_hotel),
  409. title: Text(I18N.of("午休打卡")),
  410. subtitle: Text(
  411. "${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.midRestTimeStart)} - ${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.midRestTimeEnd!)}"),
  412. trailing: Icon(
  413. model.isSignMidRest ? Icons.check_circle : Icons.chevron_right,
  414. color:
  415. model.isSignMidRest
  416. ? Theme.of(context).colorScheme.secondary
  417. : null,
  418. ),
  419. onTap: model.isSignMidRest
  420. ? null
  421. : () => service.signMidRest(context),
  422. ),
  423. ListTile(
  424. leading: Icon(Icons.restaurant),
  425. title: Text(I18N.of("晚饭打卡")),
  426. subtitle: Text(
  427. "${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.dinnerTimeStart)} - ${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.dinnerTimeEnd!)}"),
  428. trailing: Icon(
  429. model.isSignDinner ? Icons.check_circle : Icons.chevron_right,
  430. color:
  431. model.isSignDinner
  432. ? Theme.of(context).colorScheme.secondary
  433. : null,
  434. ),
  435. onTap:
  436. model.isSignDinner ? null : () => service.signDinner(context),
  437. ),
  438. ListTile(
  439. leading: Icon(Icons.brightness_4),
  440. title: Text(I18N.of("晚安打卡")),
  441. subtitle: Text(
  442. "${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.restTimeStart)} - ${ConvertUtils.timeFormMillisecondsSinceEpoch(configProvider.restTimeEnd!)}"),
  443. trailing: Icon(
  444. model.isSignRest ? Icons.check_circle : Icons.chevron_right,
  445. color: model.isSignRest
  446. ? Theme.of(context).colorScheme.secondary
  447. : null,
  448. ),
  449. onTap: model.isSignRest ? null : () => service.signRest(context),
  450. ),
  451. ],
  452. ),
  453. ),
  454. );
  455. }
  456. }