SetGoal.tsx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. import { View, Text, Image } from "@tarojs/components";
  2. import './ChooseScenario.scss'
  3. import { useRouter } from "@tarojs/taro";
  4. import { rpxToPx } from "@/utils/tools";
  5. import { ColorType } from "@/context/themes/color";
  6. import Footer from "@/components/layout/Footer";
  7. import { ChooseScenarioBtn, SetScheduleBtn } from "@/features/common/SpecBtns";
  8. import { useDispatch, useSelector } from "react-redux";
  9. import { useEffect, useState } from "react";
  10. import Modal from "@/components/layout/Modal.weapp";
  11. import TimePicker from "@/features/common/TimePicker";
  12. import { useTranslation } from "react-i18next";
  13. import { updateFast, updateSleep } from "@/store/set_target";
  14. import { setPlan } from "@/services/trackTimeDuration";
  15. import showAlert from "@/components/basic/Alert";
  16. import Taro from "@tarojs/taro";
  17. export default function SetGoal() {
  18. let router
  19. var navigation: any = null
  20. if (process.env.TARO_ENV === 'rn') {
  21. var useNavigation = require("@react-navigation/native").useNavigation
  22. navigation = useNavigation()
  23. const useRoute = require("@react-navigation/native").useRoute
  24. router = useRoute()
  25. }
  26. else {
  27. router = useRouter()
  28. }
  29. const isSelf = router.params.isSelf
  30. const target = useSelector((state: any) => state.target);
  31. const [fastDuration, setFastDuration] = useState<any>(0)
  32. const [sleepDuration, setSleepDuration] = useState<any>(0)
  33. const [fastTarget, setFastTarget] = useState(target.fast.schedule.fast)
  34. const [sleepTarget, setSleepTarget] = useState(target.sleep.schedule.sleep)
  35. const [showTimePicker, setShowTimePicker] = useState(false)
  36. const [isFast, setIsFast] = useState(true)
  37. const [isStart, setIsStart] = useState(true)
  38. const { t } = useTranslation()
  39. const dispatch = useDispatch();
  40. useEffect(() => {
  41. getFastDuration()
  42. getSleepDuration()
  43. }, [target.fast, target.sleep])
  44. function getFastDuration() {
  45. var obj = target.fast.schedule.fast
  46. var duration = obj.end_time.split(':')[0] * 60 + obj.end_time.split(':')[1] * 1 - (obj.start_time.split(':')[0] * 60 + obj.start_time.split(':')[1] * 1)
  47. if (duration <= 0) {
  48. duration += 24 * 60
  49. }
  50. var hours = Math.floor(duration / 60)
  51. var minutes = duration % 60
  52. var str = hours + ' hours ' + minutes + ' minutes'
  53. setFastDuration(str)
  54. }
  55. function getFastDurationMinutes(){
  56. var obj = target.fast.schedule.fast
  57. var duration = obj.end_time.split(':')[0] * 60 + obj.end_time.split(':')[1] * 1 - (obj.start_time.split(':')[0] * 60 + obj.start_time.split(':')[1] * 1)
  58. if (duration <= 0) {
  59. duration += 24 * 60
  60. }
  61. return duration
  62. }
  63. function getSleepDuration() {
  64. var obj = target.sleep.schedule.sleep
  65. var duration = obj.end_time.split(':')[0] * 60 + obj.end_time.split(':')[1] * 1 - (obj.start_time.split(':')[0] * 60 + obj.start_time.split(':')[1] * 1)
  66. if (duration <= 0) {
  67. duration += 24 * 60
  68. }
  69. var hours = Math.floor(duration / 60)
  70. var minutes = duration % 60
  71. var str = hours + ' hours ' + minutes + ' minutes'
  72. setSleepDuration(str)
  73. }
  74. function getSleepDurationMinutes(){
  75. var obj = target.sleep.schedule.sleep
  76. var duration = obj.end_time.split(':')[0] * 60 + obj.end_time.split(':')[1] * 1 - (obj.start_time.split(':')[0] * 60 + obj.start_time.split(':')[1] * 1)
  77. if (duration <= 0) {
  78. duration += 24 * 60
  79. }
  80. return duration
  81. }
  82. function hidePicker() {
  83. setShowTimePicker(false)
  84. }
  85. function modalContent() {
  86. return <Modal
  87. testInfo={null}
  88. dismiss={() => {
  89. hidePicker()
  90. // setShowTimeoutPicker(false)
  91. }}
  92. confirm={() => { }}>
  93. {
  94. timePickerContent()
  95. }
  96. </Modal>
  97. }
  98. function pickerTitle() {
  99. if (isFast) {
  100. if (isStart) {
  101. return t('feature.track_time_duration.dial.picker_fast_schedule_start_time');
  102. }
  103. return t('feature.track_time_duration.dial.picker_fast_schedule_end_time');
  104. }
  105. else {
  106. if (isStart) {
  107. return t('feature.track_time_duration.dial.picker_sleep_schedule_start_time');
  108. }
  109. return t('feature.track_time_duration.dial.picker_sleep_schedule_end_time');
  110. }
  111. }
  112. function pickerConfirm(e) {
  113. hidePicker()
  114. if (isFast) {
  115. var fast = JSON.parse(JSON.stringify(target.fast))
  116. if (isStart) {
  117. fast.schedule.fast.start_time = e
  118. }
  119. else {
  120. fast.schedule.fast.end_time = e
  121. }
  122. dispatch(updateFast({ fast: fast }))
  123. setFastTarget(fast.schedule.fast)
  124. }
  125. else {
  126. var sleep = JSON.parse(JSON.stringify(target.sleep))
  127. if (isStart) {
  128. sleep.schedule.sleep.start_time = e
  129. }
  130. else {
  131. sleep.schedule.sleep.end_time = e
  132. }
  133. dispatch(updateSleep({ sleep: sleep }))
  134. setSleepTarget(sleep.schedule.sleep)
  135. }
  136. getFastDuration()
  137. getSleepDuration()
  138. }
  139. function timePickerContent() {
  140. var time = ''
  141. if (isFast) {
  142. if (isStart) {
  143. time = fastTarget.start_time
  144. }
  145. else {
  146. time = fastTarget.end_time
  147. }
  148. }
  149. else {
  150. if (isStart) {
  151. time = sleepTarget.start_time
  152. }
  153. else {
  154. time = sleepTarget.end_time
  155. }
  156. }
  157. return <TimePicker time={time}
  158. color={isFast ? ColorType.fast : ColorType.sleep}
  159. title={pickerTitle()}
  160. confirm={pickerConfirm}
  161. cancel={hidePicker} />
  162. }
  163. function confirm() {
  164. var params: any = {
  165. method: parseInt(router.params.isSelf + '') == 1 ? 'USER_SET' : 'SUGGEST',
  166. schedule: {
  167. fast: {
  168. start_time: fastTarget.start_time,
  169. end_time: fastTarget.end_time,
  170. duration: {
  171. input_value: getFastDurationMinutes()//target.fast.schedule.fast.duration.init_value,
  172. }
  173. },
  174. }
  175. }
  176. if (target.isMixed) {
  177. params.scenario = 'FAST_SLEEP'
  178. params.schedule.sleep = {
  179. start_time: sleepTarget.start_time,
  180. end_time: sleepTarget.end_time,
  181. duration:{
  182. input_value:getSleepDurationMinutes()
  183. },
  184. latency: {
  185. input_value: target.sleep.schedule.sleep.latency.init_value,
  186. },
  187. cycle: {
  188. num: {
  189. input_value: target.sleep.schedule.sleep.cycle.num.init_value,
  190. }
  191. }
  192. }
  193. }
  194. else {
  195. params.scenario = 'FAST'
  196. }
  197. if (router.params.upgrade) {
  198. params.trigger_event = router.params.trigger_event
  199. }
  200. else {
  201. params.trigger_event = router.params.trigger_event ? router.params.trigger_event : 'SET'
  202. }
  203. setPlan(params).then(res => {
  204. if (global.checkData) {
  205. global.checkData()
  206. }
  207. if (global.indexPageRefresh) {
  208. global.indexPageRefresh()
  209. }
  210. // popMixScheduleAlert(scenario.schedule.fast.start_time, startTime)
  211. if (process.env.TARO_ENV === 'rn') {
  212. popRNAlert()
  213. }
  214. else {
  215. popAlert()
  216. }
  217. }).catch(e => {
  218. })
  219. }
  220. function popAlert() {
  221. global.chooseMixed()
  222. Taro.navigateBack({ delta: 6 }).then(res => {
  223. })
  224. if (target.isMixed) {
  225. setTimeout(() => {
  226. global.popMixScheduleAlert(fastTarget.start_time, sleepTarget.start_time)
  227. }, 800)
  228. }
  229. else {
  230. setTimeout(() => {
  231. global.popScheduleAlert({
  232. name: 'FAST'
  233. }, fastTarget.start_time)
  234. }, 800)
  235. }
  236. }
  237. function popRNAlert() {
  238. // if (target.isMixed) {
  239. // }
  240. // else {
  241. // const JPush = require('jpush-react-native').default;
  242. // JPush.isNotificationEnabled((res) => {
  243. // if (res) {
  244. // showAlert({
  245. // title: t('feature.track_time_duration.reminders.schedule_title'),
  246. // content:
  247. // t('feature.track_time_duration.reminders.enable_schedule_fast_content', { time: fastTarget.start_time }),
  248. // showCancel: false,
  249. // confirmText: t('feature.track_time_duration.reminders.ok'),
  250. // cancel: () => {
  251. // navigation.popToTop()
  252. // },
  253. // confirm: () => {
  254. // navigation.popToTop()
  255. // },
  256. // })
  257. // }
  258. // else {
  259. // showAlert({
  260. // title: t('feature.track_time_duration.reminders.schedule_title'),
  261. // content:
  262. // t('feature.track_time_duration.reminders.schedule_fast_content', { time: fastTarget.start_time }),
  263. // cancelText: t('feature.track_time_duration.reminders.later'),
  264. // confirmText: t('feature.track_time_duration.reminders.open'),
  265. // showCancel: true,
  266. // cancel: () => {
  267. // navigation.popToTop()
  268. // },
  269. // confirm: () => {
  270. // // if (authStatus != 'not_determined') {
  271. // // navigation.popToTop()
  272. // // }
  273. // // checkNotification()
  274. // // Linking.openURL('app-settings:notifications')
  275. // }
  276. // })
  277. // }
  278. // })
  279. // }
  280. }
  281. function isNextDay(isFast: boolean, isStart: boolean) {
  282. var time = fastTarget.start_time.split(':')[0] * 60 + fastTarget.start_time.split(':')[1] * 1
  283. if (isFast) {
  284. var time2 = fastTarget.end_time.split(':')[0] * 60 + fastTarget.end_time.split(':')[1] * 1
  285. return time2 <= time
  286. }
  287. else {
  288. if (isStart) {
  289. time2 = sleepTarget.start_time.split(':')[0] * 60 + sleepTarget.start_time.split(':')[1] * 1
  290. return time2 <= time
  291. }
  292. else {
  293. time2 = sleepTarget.end_time.split(':')[0] * 60 + sleepTarget.end_time.split(':')[1] * 1
  294. return time2 <= time
  295. }
  296. }
  297. }
  298. return <View style={{ display: 'flex', flexDirection: 'column',flex:1 }}>
  299. <Text className="target_title">{isSelf ? t('feature.set_goal.set_action_plan') : t('feature.set_goal.almost_done')}</Text>
  300. {
  301. !isSelf && <Text className="target_desc">{t('feature.set_goal.header')}</Text>
  302. }
  303. <View style={{ color: '#fff' }}>
  304. <View className="cell_bg" style={{ padding: 0 }}>
  305. <View className="cell_full" style={{
  306. marginLeft: rpxToPx(46),
  307. marginRight: rpxToPx(46),
  308. paddingLeft: rpxToPx(40),
  309. paddingRight: rpxToPx(40),
  310. margin: 0
  311. }} onClick={() => { }}>
  312. <Text className="cell_title">Fasting</Text>
  313. <Text className="cell_value" style={{ color: ColorType.fast }}>{fastDuration}</Text>
  314. </View>
  315. {
  316. target.isMixed && <View className="cell_full" style={{
  317. marginLeft: rpxToPx(46),
  318. marginRight: rpxToPx(46),
  319. paddingLeft: rpxToPx(40),
  320. paddingRight: rpxToPx(40),
  321. margin: 0
  322. }} onClick={() => { }}>
  323. <Text className="cell_title">Sleep</Text>
  324. <Text className="cell_value" style={{ color: ColorType.sleep }}>{sleepDuration}</Text>
  325. </View>
  326. }
  327. </View>
  328. <View style={{ height: rpxToPx(20) }} />
  329. <View className="cell_bg" style={{ padding: 0 }}>
  330. <View className="cell_top" style={{ margin: 0 }} onClick={() => {
  331. setIsFast(true)
  332. setIsStart(true)
  333. setShowTimePicker(true)
  334. }}>
  335. <Text className="cell_title">Start fasting</Text>
  336. <Text className="cell_value" style={{ color: ColorType.fast }}>{fastTarget.start_time}</Text>
  337. <Image className="cell_arrow" src={require('@/assets/images/arrow3.png')} />
  338. <View className="cell_line" style={{ height: 1 }} />
  339. </View>
  340. {
  341. target.isMixed && <View className="cell_top" style={{ margin: 0 }} onClick={() => {
  342. setIsFast(false)
  343. setIsStart(true)
  344. setShowTimePicker(true)
  345. }}>
  346. <Text className="cell_title">Go to bed</Text>
  347. <Text className="cell_value" style={{ color: ColorType.sleep }}>{isNextDay(false, true) ? '次日 ' : ' '}{sleepTarget.start_time}</Text>
  348. <Image className="cell_arrow" src={require('@/assets/images/arrow3.png')} />
  349. <View className="cell_line" style={{ height: 1 }} />
  350. </View>
  351. }
  352. {
  353. target.isMixed && <View className="cell_bottom" style={{ margin: 0 }} onClick={() => {
  354. setIsFast(false)
  355. setIsStart(false)
  356. setShowTimePicker(true)
  357. }}>
  358. <Text className="cell_title">Wake up</Text>
  359. <Text className="cell_value" style={{ color: ColorType.sleep }}>{isNextDay(false, false) ? '次日 ' : ' '}{sleepTarget.end_time}</Text>
  360. <Image className="cell_arrow" src={require('@/assets/images/arrow3.png')} />
  361. </View>
  362. }
  363. <View className="cell_bottom" style={{ margin: 0 }} onClick={() => {
  364. setIsFast(true)
  365. setIsStart(false)
  366. setShowTimePicker(true)
  367. }}>
  368. <Text className="cell_title">End fasting</Text>
  369. <Text className="cell_value" style={{ color: ColorType.fast }}>{isNextDay(true, false) ? '次日 ' : ' '}{fastTarget.end_time}</Text>
  370. <Image className="cell_arrow" src={require('@/assets/images/arrow3.png')} />
  371. </View>
  372. </View>
  373. <Text className="cell_footer">{t('feature.set_goal.footer')}</Text>
  374. </View>
  375. <View style={{ flex: 1 }} />
  376. <Footer>
  377. <ChooseScenarioBtn
  378. onClick={confirm}
  379. title={'Done'}
  380. background={ColorType.fast}
  381. />
  382. </Footer>
  383. {
  384. showTimePicker && modalContent()
  385. }
  386. {
  387. process.env.TARO_ENV == 'rn' && <View style={{ marginBottom: 40 }} />
  388. }
  389. </View>
  390. }