SetGoal.tsx 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. import { View, Text, Image } from "@tarojs/components";
  2. import './ChooseScenario.scss'
  3. import { useRouter } from "@tarojs/taro";
  4. import { kIsIOS, 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. import { getLocalPush } from "@/features/trackTimeDuration/actions/TrackTimeActions";
  18. let OneSignal
  19. let NativeAppEventEmitter
  20. let Jto
  21. let uploadPermissions, checkNotification, PushNotification
  22. if (process.env.TARO_ENV == 'rn') {
  23. OneSignal = require('react-native-onesignal').OneSignal
  24. NativeAppEventEmitter = require('react-native').NativeAppEventEmitter
  25. Jto = require('react-native').NativeModules.NativeBridge;
  26. uploadPermissions = require('@/utils/native_permission_check').uploadPermissions;
  27. checkNotification = require('@/utils/native_permission_check').checkNotification;
  28. PushNotification = require('react-native-push-notification')
  29. }
  30. export default function SetGoal() {
  31. let router
  32. var navigation: any = null
  33. if (process.env.TARO_ENV === 'rn') {
  34. var useNavigation = require("@react-navigation/native").useNavigation
  35. navigation = useNavigation()
  36. const useRoute = require("@react-navigation/native").useRoute
  37. router = useRoute()
  38. }
  39. else {
  40. router = useRouter()
  41. }
  42. const isSelf = router.params.isSelf
  43. const target = useSelector((state: any) => state.target);
  44. const [fastDuration, setFastDuration] = useState<any>(0)
  45. const [sleepDuration, setSleepDuration] = useState<any>(0)
  46. const [fastTarget, setFastTarget] = useState(target.fast.schedule.fast)
  47. const [sleepTarget, setSleepTarget] = useState(target.sleep.schedule.sleep)
  48. const [showTimePicker, setShowTimePicker] = useState(false)
  49. const [isFast, setIsFast] = useState(true)
  50. const [isStart, setIsStart] = useState(true)
  51. const [authStatus, setAuthStatus] = useState('')
  52. const [btnDisable, setBtnDisable] = useState(false)
  53. const { t } = useTranslation()
  54. const dispatch = useDispatch();
  55. useEffect(() => {
  56. if (navigation) {
  57. navigation.setOptions({
  58. headerTitle: '',
  59. });
  60. }
  61. if (process.env.TARO_ENV == 'rn') {
  62. rnNotification()
  63. }
  64. }, [])
  65. useEffect(() => {
  66. getFastDuration()
  67. getSleepDuration()
  68. }, [target.fast, target.sleep])
  69. function rnNotification() {
  70. if (kIsIOS) {
  71. Jto.getNotificationAuthStatus()
  72. NativeAppEventEmitter.addListener('notificationResult', (data) => {
  73. setAuthStatus(data)
  74. global.notification = data
  75. uploadPermissions()
  76. })
  77. NativeAppEventEmitter.addListener('operateNotificationResult', (data) => {
  78. getLocalPush()
  79. global.notification = data
  80. navigation.popToTop()
  81. uploadPermissions()
  82. })
  83. }
  84. else {
  85. OneSignal.Notifications.canRequestPermission().then((status) => {
  86. if (status) {
  87. OneSignal.Notifications.getPermissionAsync().then((res) => {
  88. if (res) {
  89. global.notification = 'authorized'
  90. uploadPermissions()
  91. }
  92. else {
  93. global.notification = 'denied'
  94. uploadPermissions()
  95. }
  96. })
  97. }
  98. else {
  99. global.notification = 'not_determined'
  100. uploadPermissions()
  101. }
  102. })
  103. }
  104. }
  105. function getFastDuration() {
  106. var obj = target.fast.schedule.fast
  107. 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)
  108. if (duration <= 0) {
  109. duration += 24 * 60
  110. }
  111. var hours = Math.floor(duration / 60)
  112. var minutes = duration % 60
  113. var str = ''
  114. if (hours > 0) {
  115. str = hours + (global.language == 'en' ? ' hours' : '小时')// + minutes + ' minutes'
  116. }
  117. if (minutes > 0) {
  118. if (global.language == 'en') {
  119. str += ` ${minutes}` + (global.language == 'en' ? ' minutes' : '分钟')
  120. }
  121. else {
  122. str += `${minutes}` + '分钟'
  123. }
  124. }
  125. setFastDuration(str)
  126. }
  127. function getFastDurationMinutes() {
  128. var obj = target.fast.schedule.fast
  129. 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)
  130. if (duration <= 0) {
  131. duration += 24 * 60
  132. }
  133. return duration
  134. }
  135. function getSleepDuration() {
  136. var obj = target.sleep.schedule.sleep
  137. 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)
  138. if (duration <= 0) {
  139. duration += 24 * 60
  140. }
  141. var hours = Math.floor(duration / 60)
  142. var minutes = duration % 60
  143. var str = ''
  144. if (hours > 0) {
  145. str = hours + (global.language == 'en' ? ' hours' : '小时')// + minutes + ' minutes'
  146. }
  147. if (minutes > 0) {
  148. if (global.language == 'en') {
  149. str += ` ${minutes}` + (global.language == 'en' ? ' minutes' : '分钟')
  150. }
  151. else {
  152. str += `${minutes}` + '分钟'
  153. }
  154. }
  155. setSleepDuration(str)
  156. }
  157. function getSleepDurationMinutes() {
  158. var obj = target.sleep.schedule.sleep
  159. 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)
  160. if (duration <= 0) {
  161. duration += 24 * 60
  162. }
  163. return duration
  164. }
  165. function hidePicker() {
  166. setShowTimePicker(false)
  167. }
  168. function modalContent() {
  169. return <Modal
  170. testInfo={null}
  171. dismiss={() => {
  172. hidePicker()
  173. // setShowTimeoutPicker(false)
  174. }}
  175. confirm={() => { }}>
  176. {
  177. timePickerContent()
  178. }
  179. </Modal>
  180. }
  181. function pickerTitle() {
  182. if (isFast) {
  183. if (isStart) {
  184. return t('feature.track_time_duration.dial.picker_fast_schedule_start_time');
  185. }
  186. return t('feature.track_time_duration.dial.picker_fast_schedule_end_time');
  187. }
  188. else {
  189. if (isStart) {
  190. return t('feature.track_time_duration.dial.picker_sleep_schedule_start_time');
  191. }
  192. return t('feature.track_time_duration.dial.picker_sleep_schedule_end_time');
  193. }
  194. }
  195. function pickerConfirm(e) {
  196. hidePicker()
  197. if (isFast) {
  198. var fast = JSON.parse(JSON.stringify(target.fast))
  199. if (isStart) {
  200. fast.schedule.fast.start_time = e
  201. }
  202. else {
  203. fast.schedule.fast.end_time = e
  204. }
  205. dispatch(updateFast({ fast: fast }))
  206. setFastTarget(fast.schedule.fast)
  207. }
  208. else {
  209. var sleep = JSON.parse(JSON.stringify(target.sleep))
  210. if (isStart) {
  211. sleep.schedule.sleep.start_time = e
  212. }
  213. else {
  214. sleep.schedule.sleep.end_time = e
  215. }
  216. dispatch(updateSleep({ sleep: sleep }))
  217. setSleepTarget(sleep.schedule.sleep)
  218. }
  219. getFastDuration()
  220. getSleepDuration()
  221. }
  222. function timePickerContent() {
  223. var time = ''
  224. if (isFast) {
  225. if (isStart) {
  226. time = fastTarget.start_time
  227. }
  228. else {
  229. time = fastTarget.end_time
  230. }
  231. }
  232. else {
  233. if (isStart) {
  234. time = sleepTarget.start_time
  235. }
  236. else {
  237. time = sleepTarget.end_time
  238. }
  239. }
  240. return <TimePicker time={time}
  241. color={isFast ? ColorType.fast : ColorType.sleep}
  242. title={pickerTitle()}
  243. confirm={pickerConfirm}
  244. cancel={hidePicker} />
  245. }
  246. function confirm() {
  247. setBtnDisable(true)
  248. var params: any = {
  249. method: parseInt(router.params.isSelf + '') == 1 ? 'USER_SET' : 'SUGGEST',
  250. schedule: {
  251. fast: {
  252. start_time: fastTarget.start_time,
  253. end_time: fastTarget.end_time,
  254. duration: {
  255. input_value: getFastDurationMinutes()//target.fast.schedule.fast.duration.init_value,
  256. }
  257. },
  258. }
  259. }
  260. if (target.isMixed) {
  261. params.scenario = 'FAST_SLEEP'
  262. params.schedule.sleep = {
  263. start_time: sleepTarget.start_time,
  264. end_time: sleepTarget.end_time,
  265. duration: {
  266. input_value: getSleepDurationMinutes()
  267. },
  268. latency: parseInt(router.params.isSelf + '') == 1 ? null : {
  269. input_value: target.sleep.schedule.sleep.latency.init_value,
  270. },
  271. cycle: parseInt(router.params.isSelf + '') == 1 ? null : {
  272. num: {
  273. input_value: target.sleep.schedule.sleep.cycle.num.init_value,
  274. }
  275. }
  276. }
  277. }
  278. else {
  279. params.scenario = 'FAST'
  280. }
  281. if (router.params.upgrade) {
  282. params.trigger_event = router.params.trigger_event
  283. }
  284. else {
  285. params.trigger_event = router.params.trigger_event ? router.params.trigger_event : 'SET'
  286. }
  287. setPlan(params).then(res => {
  288. setBtnDisable(false)
  289. if (global.checkData) {
  290. global.checkData()
  291. }
  292. if (global.indexPageRefresh) {
  293. global.indexPageRefresh()
  294. }
  295. global.chooseMixed()
  296. if (process.env.TARO_ENV === 'rn') {
  297. popRNAlert()
  298. }
  299. else {
  300. popAlert()
  301. }
  302. // popAlert()
  303. }).catch(e => {
  304. setBtnDisable(false)
  305. })
  306. }
  307. function popAlert() {
  308. if (process.env.TARO_ENV === 'weapp') {
  309. Taro.navigateBack({ delta: 6 }).then(res => {
  310. })
  311. }
  312. else {
  313. navigation.popToTop()
  314. }
  315. if (target.isMixed) {
  316. setTimeout(() => {
  317. global.popMixScheduleAlert(fastTarget.start_time, sleepTarget.start_time)
  318. }, 800)
  319. }
  320. else {
  321. setTimeout(() => {
  322. global.popScheduleAlert({
  323. name: 'FAST'
  324. }, fastTarget.start_time)
  325. }, 800)
  326. }
  327. }
  328. function popRNAlert() {
  329. debugger
  330. if (target.isMixed) {
  331. popMixScheduleAlert(fastTarget.start_time, sleepTarget.start_time)
  332. }
  333. else {
  334. popScheduleAlert({
  335. name: 'FAST'
  336. }, fastTarget.start_time)
  337. }
  338. }
  339. function popScheduleAlert(scenario, startTime) {
  340. if (process.env.TARO_ENV === 'rn') {
  341. PushNotification.checkPermissions((res) => {
  342. //允许授权
  343. if ((kIsIOS && res.authorizationStatus == 2) || (!kIsIOS && res.alert)) {
  344. getLocalPush();
  345. navigation.popToTop()
  346. // showAlert({
  347. // title: t('feature.track_time_duration.reminders.schedule_title'),
  348. // content: scenario.name == 'FAST' ?
  349. // t('feature.track_time_duration.reminders.enable_schedule_fast_content', { time: startTime }) :
  350. // t('feature.track_time_duration.reminders.enable_schedule_sleep_content', { time: startTime }),
  351. // showCancel: false,
  352. // confirmText: t('feature.track_time_duration.reminders.ok'),
  353. // cancel: () => {
  354. // navigation.popToTop()
  355. // },
  356. // confirm: () => {
  357. // navigation.popToTop()
  358. // },
  359. // })
  360. }
  361. else {
  362. showAlert({
  363. title: t('feature.track_time_duration.reminders.schedule_title'),
  364. content: scenario.name == 'FAST' ?
  365. t('feature.track_time_duration.reminders.schedule_fast_content', { time: startTime }) :
  366. t('feature.track_time_duration.reminders.schedule_sleep_content', { time: startTime }),
  367. cancelText: t('feature.track_time_duration.reminders.later'),
  368. confirmText: t('feature.track_time_duration.reminders.open'),
  369. showCancel: true,
  370. cancel: () => {
  371. navigation.popToTop()
  372. },
  373. confirm: () => {
  374. if (authStatus != 'not_determined') {
  375. navigation.popToTop()
  376. }
  377. checkNotification()
  378. // Linking.openURL('app-settings:notifications')
  379. }
  380. })
  381. }
  382. })
  383. }
  384. }
  385. function popMixScheduleAlert(time1, time2) {
  386. console.log(time1, time2)
  387. if (process.env.TARO_ENV === 'rn') {
  388. // const JPush = require('jpush-react-native').default;
  389. const checkNotification = require('@/utils/native_permission_check').checkNotification;
  390. PushNotification.checkPermissions((res) => {
  391. //允许授权
  392. if ((kIsIOS && res.authorizationStatus == 2) || (!kIsIOS && res.alert)) {
  393. getLocalPush();
  394. navigation.popToTop()
  395. // showAlert({
  396. // title: t('feature.track_time_duration.reminders.schedule_title'),
  397. // content: t('feature.track_time_duration.reminders.enable_schedule_mix_content', { time1: time1, time2: time2 }),
  398. // showCancel: false,
  399. // confirmText: t('feature.track_time_duration.reminders.ok'),
  400. // cancel: () => {
  401. // navigation.popToTop()
  402. // },
  403. // confirm: () => {
  404. // navigation.popToTop()
  405. // },
  406. // })
  407. }
  408. else {
  409. showAlert({
  410. title: t('feature.track_time_duration.reminders.schedule_title'),
  411. content:
  412. t('feature.track_time_duration.reminders.schedule_mix_content'),
  413. cancelText: t('feature.track_time_duration.reminders.later'),
  414. confirmText: t('feature.track_time_duration.reminders.open'),
  415. showCancel: true,
  416. cancel: () => {
  417. navigation.popToTop()
  418. },
  419. confirm: () => {
  420. if (authStatus != 'not_determined') {
  421. navigation.popToTop()
  422. }
  423. checkNotification()
  424. // Linking.openURL('app-settings:notifications')
  425. }
  426. })
  427. }
  428. })
  429. }
  430. }
  431. function isNextDay(isFast: boolean, isStart: boolean) {
  432. var time = fastTarget.start_time.split(':')[0] * 60 + fastTarget.start_time.split(':')[1] * 1
  433. if (isFast) {
  434. var time2 = fastTarget.end_time.split(':')[0] * 60 + fastTarget.end_time.split(':')[1] * 1
  435. return time2 <= time
  436. }
  437. else {
  438. if (isStart) {
  439. time2 = sleepTarget.start_time.split(':')[0] * 60 + sleepTarget.start_time.split(':')[1] * 1
  440. return time2 <= time
  441. }
  442. else {
  443. time2 = sleepTarget.end_time.split(':')[0] * 60 + sleepTarget.end_time.split(':')[1] * 1
  444. return time2 <= time
  445. }
  446. }
  447. }
  448. return <View style={{ display: 'flex', flexDirection: 'column', flex: 1 }}>
  449. <Text className="target_title">{isSelf ? t('feature.set_goal.set_action_plan') : t('feature.set_goal.almost_done')}</Text>
  450. {
  451. !isSelf && <Text className="target_desc">{t('feature.set_goal.header')}</Text>
  452. }
  453. <View style={{ color: '#fff' }}>
  454. <View className="cell_bg" style={{ overflow: 'hidden' }}>
  455. <View className="cell_full" style={{
  456. // marginLeft: rpxToPx(46),
  457. // marginRight: rpxToPx(46),
  458. // paddingLeft: rpxToPx(40),
  459. // paddingRight: rpxToPx(40),
  460. margin: 0,
  461. // backgroundColor:'red'
  462. }} onClick={() => { }}>
  463. <Text className="cell_title">{t('feature.set_goal.fast')}</Text>
  464. <Text className="cell_value" style={{ color: ColorType.fast }}>{fastDuration}</Text>
  465. </View>
  466. {
  467. target.isMixed && <View className="cell_line" style={{ marginLeft: -rpxToPx(46), marginRight: -rpxToPx(46) }} />
  468. }
  469. {
  470. target.isMixed && <View className="cell_full" style={{
  471. marginLeft: 0,
  472. marginRight: 0,
  473. paddingLeft: 0,
  474. paddingRight: 0
  475. }} onClick={() => { }}>
  476. <Text className="cell_title">{t('feature.set_goal.sleep')}</Text>
  477. <Text className="cell_value" style={{ color: ColorType.sleep }}>{sleepDuration}</Text>
  478. </View>
  479. }
  480. </View>
  481. <View style={{ height: rpxToPx(20) }} />
  482. <View className="cell_bg" style={{ overflow: 'hidden' }}>
  483. <View className="cell_top" style={{
  484. marginLeft: 0,
  485. marginRight: 0,
  486. paddingLeft: 0,
  487. paddingRight: 0
  488. }} onClick={() => {
  489. setIsFast(true)
  490. setIsStart(true)
  491. setShowTimePicker(true)
  492. }}>
  493. <Text className="cell_title">{t('feature.set_goal.start_fasting')}</Text>
  494. <Text className="cell_value" style={{ color: ColorType.fast }}>{fastTarget.start_time}</Text>
  495. <Image className="cell_arrow" src={require('@/assets/images/arrow3.png')} />
  496. <View className="cell_line" style={{ height: 1 }} />
  497. </View>
  498. {
  499. target.isMixed && <View className="cell_line" style={{ marginLeft: -rpxToPx(46), marginRight: -rpxToPx(46) }} />
  500. }
  501. {
  502. target.isMixed && <View className="cell_top" style={{
  503. marginLeft: 0,
  504. marginRight: 0,
  505. paddingLeft: 0,
  506. paddingRight: 0
  507. }} onClick={() => {
  508. setIsFast(false)
  509. setIsStart(true)
  510. setShowTimePicker(true)
  511. }}>
  512. <Text className="cell_title">{t('feature.set_goal.go_to_bed')}</Text>
  513. <Text className="cell_value" style={{ color: ColorType.sleep }}>{isNextDay(false, true) ? t('feature.set_goal.next_day') : ' '}{sleepTarget.start_time}</Text>
  514. <Image className="cell_arrow" src={require('@/assets/images/arrow3.png')} />
  515. <View className="cell_line" style={{ height: 1 }} />
  516. </View>
  517. }
  518. {
  519. target.isMixed && <View className="cell_line" style={{ marginLeft: -rpxToPx(46), marginRight: -rpxToPx(46) }} />
  520. }
  521. {
  522. target.isMixed && <View className="cell_bottom" style={{
  523. marginLeft: 0,
  524. marginRight: 0,
  525. paddingLeft: 0,
  526. paddingRight: 0
  527. }} onClick={() => {
  528. setIsFast(false)
  529. setIsStart(false)
  530. setShowTimePicker(true)
  531. }}>
  532. <Text className="cell_title">{t('feature.set_goal.wake_up')}</Text>
  533. <Text className="cell_value" style={{ color: ColorType.sleep }}>{isNextDay(false, false) ? t('feature.set_goal.next_day') : ' '}{sleepTarget.end_time}</Text>
  534. <Image className="cell_arrow" src={require('@/assets/images/arrow3.png')} />
  535. </View>
  536. }
  537. <View className="cell_line" style={{ marginLeft: -rpxToPx(46), marginRight: -rpxToPx(46) }} />
  538. <View className="cell_bottom" style={{
  539. marginLeft: 0,
  540. marginRight: 0,
  541. paddingLeft: 0,
  542. paddingRight: 0
  543. }} onClick={() => {
  544. setIsFast(true)
  545. setIsStart(false)
  546. setShowTimePicker(true)
  547. }}>
  548. <Text className="cell_title">{t('feature.set_goal.end_fasting')}</Text>
  549. <Text className="cell_value" style={{ color: ColorType.fast }}>{isNextDay(true, false) ? t('feature.set_goal.next_day') : ' '}{fastTarget.end_time}</Text>
  550. <Image className="cell_arrow" src={require('@/assets/images/arrow3.png')} />
  551. </View>
  552. </View>
  553. {
  554. parseInt(router.params.isSelf + '') != 1 && <Text className="cell_footer">{t('feature.set_goal.footer')}</Text>
  555. }
  556. </View>
  557. <View style={{ flex: 1 }} />
  558. <Footer>
  559. <ChooseScenarioBtn
  560. disable={btnDisable}
  561. onClick={confirm}
  562. title={t('feature.set_goal.done')}
  563. background={ColorType.fast}
  564. />
  565. </Footer>
  566. {
  567. showTimePicker && modalContent()
  568. }
  569. {
  570. process.env.TARO_ENV == 'rn' && <View style={{ marginBottom: 40 }} />
  571. }
  572. </View>
  573. }