long_fast.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. import { View, Text, Image } from "@tarojs/components";
  2. import NewHeader, { NewHeaderType } from "../components/new_header";
  3. import Card from "../components/card";
  4. import './long_fast.scss'
  5. import '@features/health/MainConsole.scss'
  6. import { MainColorType } from "@/context/themes/color";
  7. import { rpxToPx } from "@/utils/tools";
  8. import NewButton, { NewButtonType } from "../base/new_button";
  9. import { getScenario, getThemeColor } from "@/features/health/hooks/health_hooks";
  10. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  11. import MainHistory from "@/features/health/MainHistory";
  12. import { useSelector } from "react-redux";
  13. import showAlert from "@/components/basic/Alert";
  14. import { clockTimes, delRecord, updateFast } from "@/services/health";
  15. import { useEffect, useState } from "react";
  16. import { TimeFormatter } from "@/utils/time_format";
  17. import dayjs from "dayjs";
  18. import showActionSheet from "@/components/basic/ActionSheet";
  19. import NewModal from "../base/new_modal";
  20. import NewDurationPicker, { DurationPickerType } from "../base/new_durationpicker";
  21. import Taro from "@tarojs/taro";
  22. import { useTranslation } from "react-i18next";
  23. import NewTimePicker from "../base/new_timepicker";
  24. let useActionSheet;
  25. if (process.env.TARO_ENV == 'rn') {
  26. useActionSheet = require('@expo/react-native-action-sheet').useActionSheet
  27. }
  28. export default function LongFast() {
  29. const health = useSelector((state: any) => state.health);
  30. const long_fast = health.long_fast
  31. const [count, setCount] = useState(1)
  32. const [editDuration, setEditDuration] = useState(false)
  33. const [showPicker, setShowPicker] = useState(false)
  34. const [duration, setDuration] = useState(0)
  35. const [time, setTime] = useState(dayjs().format('HH:mm'))
  36. const { t } = useTranslation()
  37. let showActionSheetWithOptions;
  38. if (process.env.TARO_ENV == 'rn') {
  39. showActionSheetWithOptions = useActionSheet()
  40. }
  41. useEffect(() => {
  42. var timer = setInterval(() => {
  43. setCount(count => count + 1)
  44. }, 1000)
  45. setDuration(health.long_fast.extra.long_fast_goal / 60)
  46. return () => {
  47. clearInterval(timer)
  48. }
  49. }, [])
  50. function tapStart() {
  51. const fast = getScenario(health.windows, 'FAST')
  52. if (fast.status == 'OG') {
  53. showAlert({
  54. title: '断食进行中',
  55. content: '当前有一个正在进行的间歇性断食记录,要转换为长断食吗?',
  56. showCancel: true,
  57. cancelText: '取消',
  58. confirmText: '转换',
  59. confirm: () => {
  60. //
  61. updateFast({ fast_type: 'LF' }).then(res => {
  62. global.refreshWindow()
  63. })
  64. }
  65. })
  66. }
  67. else {
  68. jumpPage('./long_fast_setting')
  69. }
  70. }
  71. function tapLog() {
  72. var item = long_fast.timeline[0]
  73. const { event_id, schedule_id } = item
  74. jumpPage(`/_health/pages/timeline_detail?event_id=${event_id}&schedule_id=${schedule_id}`)
  75. // jumpPage(`/_health/pages/add_moment?moment=${JSON.stringify(item)}&title=${item.title}&schedule_id=${item.schedule_id}&event_id=${item.event_id}`)
  76. }
  77. function tapEnd() {
  78. // save()
  79. setShowPicker(true)
  80. }
  81. function tapMore() {
  82. var listItems = ['编辑目标', t('health.delete_current_record')]
  83. if (long_fast.status == 'OG') {
  84. listItems.push('结束断食')
  85. // listItems.push(t('health.edit_fast_goal'))
  86. }
  87. showActionSheet({
  88. title: t('health.more_actions'),
  89. showActionSheetWithOptions: showActionSheetWithOptions,
  90. itemList: listItems,
  91. success: (res) => {
  92. switch (res) {
  93. case 0:
  94. setEditDuration(true)
  95. break
  96. case 1:
  97. showAlert({
  98. title: '确定要放弃本次断食吗?',
  99. content: '放弃后断食不会本记录',
  100. showCancel: true,
  101. cancelText: '取消',
  102. confirmText: '确定',
  103. confirm: () => {
  104. del()
  105. }
  106. })
  107. break;
  108. case 2:
  109. tapEnd()
  110. break;
  111. }
  112. }
  113. })
  114. }
  115. function del() {
  116. delRecord(health.long_fast.window_id).then(res => {
  117. global.refreshWindow()
  118. })
  119. }
  120. function save(warn_code = null) {
  121. var date = new Date()
  122. date.setHours(parseInt(time.substring(0, 2)))
  123. date.setMinutes(parseInt(time.substring(3, 5)))
  124. var params: any = {
  125. check_items: [{
  126. schedule_id: long_fast.timeline[1].schedule_id,
  127. date: dayjs(date.getTime()).format('YYYYMMDD'),
  128. timestamp: date.getTime(),
  129. extra: {
  130. set_time: global.set_time ? global.set_time : new Date().getTime(),
  131. confirm_time: new Date().getTime()
  132. }
  133. }]
  134. }
  135. if (warn_code) {
  136. params.save_confirm = warn_code
  137. }
  138. clockTimes(params).then(res => {
  139. if ((res as any).warn_code == 'SAVE_AS_IF') {
  140. showAlert({
  141. title: 'Saving as Intermittent Fasting',
  142. content: 'Fasting that lasts fewer than 24 hours will be saved as Intermittent Fasting.',
  143. showCancel: true,
  144. cancelText: '取消',
  145. confirmText: '保存',
  146. cancel: () => {
  147. },
  148. confirm: () => {
  149. save((res as any).warn_code)
  150. }
  151. })
  152. return
  153. }
  154. global.refreshWindow()
  155. global.refreshHistory()
  156. jumpPage('/_health/pages/post_result?data=' + JSON.stringify(res))
  157. }).catch(e => {
  158. })
  159. }
  160. function timeText() {
  161. if (long_fast.status == 'OG') {
  162. return TimeFormatter.countdown(long_fast.real.start_timestamp)
  163. }
  164. return '00:00:00'
  165. }
  166. function goal() {
  167. var hours = long_fast.extra.long_fast_goal / 60
  168. return hours + '小时'
  169. // var days = Math.floor(hours / 24)
  170. // var left = hours % 24
  171. // var str = ''
  172. // if (days > 0) {
  173. // str = days + '天'
  174. // }
  175. // if (left > 0) {
  176. // str += left + '小时'
  177. // }
  178. // return str
  179. }
  180. function moment() {
  181. if (long_fast.timeline[0].moment) {
  182. const moment = long_fast.timeline[0].moment
  183. return <View style={{
  184. marginTop: rpxToPx(22), display: 'flex',
  185. flexDirection: 'row', alignItems: 'center',
  186. justifyContent: 'center',
  187. }}>
  188. {
  189. moment.media && moment.media.length > 0 && <Image
  190. src={moment.media[0].url}
  191. mode="aspectFill"
  192. style={{ width: rpxToPx(28), height: rpxToPx(28), borderRadius: rpxToPx(4) }} />
  193. }
  194. <Text className="h20" style={{ marginLeft: rpxToPx(12), color: MainColorType.g02 }}>{moment.description} · {TimeFormatter.dateDescription(moment.time.timestamp, true)}</Text>
  195. {/* <Text className="h20" style={{ marginLeft: rpxToPx(12), color: MainColorType.g02 }}></Text> */}
  196. </View>
  197. }
  198. return <View />
  199. }
  200. return <View className="page_container">
  201. <NewHeader type={NewHeaderType.left_subtitle}
  202. title="Long Fast "
  203. subtitle="Prolonged Fasting beyond 24 hours"
  204. />
  205. <Card>
  206. <View className="long_fast_card" >
  207. <View style={{ height: rpxToPx(96) }} />
  208. <View className="h50 bold" style={{ color: MainColorType.fast }}>{timeText()}</View>
  209. <View className="h24" style={{ color: MainColorType.g02, marginTop: rpxToPx(12) }}>Goal {goal()}</View>
  210. <View style={{ height: rpxToPx(44) }} />
  211. {
  212. long_fast.status == 'WFS' ? <NewButton
  213. type={NewButtonType.fill}
  214. width={rpxToPx(538)}
  215. height={rpxToPx(96)}
  216. color={getThemeColor('FAST')}
  217. title="Start fast"
  218. onClick={() => {
  219. tapStart()
  220. //
  221. }}
  222. /> :
  223. <NewButton
  224. type={NewButtonType.alpha}
  225. width={rpxToPx(538)}
  226. height={rpxToPx(96)}
  227. color={getThemeColor('FAST')}
  228. title="How are you feeling?"
  229. onClick={() => {
  230. tapLog()
  231. }}
  232. />
  233. }
  234. {
  235. moment()
  236. }
  237. </View>
  238. </Card>
  239. {/* {
  240. long_fast.status == 'OG' && <View style={{ position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
  241. <NewButton
  242. type={NewButtonType.link}
  243. height={rpxToPx(96)}
  244. title='End fast'
  245. onClick={() => {
  246. tapEnd()
  247. }}
  248. />
  249. </View>
  250. }
  251. {
  252. long_fast.status == 'OG' && <Text onClick={tapMore}>More</Text>
  253. } */}
  254. <View className="long_fast_footer" style={{ backgroundColor: 'transparent', marginBottom: -rpxToPx(35) }}>
  255. <View style={{ width: rpxToPx(316), height: rpxToPx(128), display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
  256. {
  257. long_fast.status == 'OG' ? <NewButton
  258. type={NewButtonType.link}
  259. title={'End longfast'}
  260. onClick={tapEnd}
  261. >
  262. </NewButton> : <NewButton
  263. type={NewButtonType.link}
  264. title={'See Guidelines'}
  265. onClick={() => { }}
  266. >
  267. </NewButton>
  268. }
  269. </View>
  270. {
  271. long_fast.status == 'OG' && <NewButton
  272. btnStyle={{
  273. position: 'absolute',
  274. top: rpxToPx(42),
  275. right: rpxToPx(26)
  276. }}
  277. type={NewButtonType.more}
  278. onClick={tapMore}
  279. />
  280. }
  281. </View>
  282. <MainHistory type='FAST' fast_type="LF" />
  283. {
  284. editDuration && <NewModal
  285. title='长断食时长'
  286. dismiss={() => {
  287. setEditDuration(false)
  288. }}
  289. confirm={() => {
  290. updateFast({ fast_type: 'LF', long_fast_goal: duration * 60 }).then(res => {
  291. setEditDuration(false)
  292. global.refreshWindow()
  293. })
  294. }}
  295. themeColor={getThemeColor(health.mode)}>
  296. <View style={{ flexDirection: 'column', display: 'flex', alignItems: 'center', marginBottom: 20 }}>
  297. <NewDurationPicker type={DurationPickerType.long}
  298. color={MainColorType.fast}
  299. value={duration}
  300. onChange={e => setDuration(e)} />
  301. </View>
  302. </NewModal>
  303. }
  304. {
  305. showPicker && <NewModal
  306. title='结束长断食'
  307. dismiss={() => {
  308. setShowPicker(false)
  309. }}
  310. confirm={() => {
  311. save()
  312. }}
  313. themeColor={getThemeColor(health.mode)}>
  314. <View style={{ flexDirection: 'column', display: 'flex', alignItems: 'center', marginBottom: 20 }}>
  315. <NewTimePicker
  316. color={MainColorType.fast}
  317. time={dayjs().format('HH:mm')}
  318. onChange={e => setTime(e)} />
  319. </View>
  320. </NewModal>
  321. }
  322. </View>
  323. }