fast_sleep_console.tsx 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. import { View, Text, Image } from "@tarojs/components";
  2. import './fast_sleep_console.scss'
  3. import { rpxToPx } from "@/utils/tools";
  4. import NewButton, { NewButtonType } from "../base/new_button";
  5. import { getThemeColor } from "@/features/health/hooks/health_hooks";
  6. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  7. import dayjs from "dayjs";
  8. import { MainColorType } from "@/context/themes/color";
  9. import showAlert from "@/components/basic/Alert";
  10. import { IconArrow, IconCellArrow, IconNotification, IconNotificationOff } from "@/components/basic/Icons";
  11. import { useSelector } from "react-redux";
  12. import { delRecord } from "@/services/health";
  13. import { TimeFormatter } from "@/utils/time_format";
  14. import showActionSheet from "@/components/basic/ActionSheet";
  15. import { useTranslation } from "react-i18next";
  16. import ConsoleCell from "./console_cell";
  17. export default function FastSleepConsole(props: { step: number, data: any, del: any }) {
  18. const health = useSelector((state: any) => state.health);
  19. let navigation, showActionSheetWithOptions;
  20. const { t } = useTranslation()
  21. function tapLogBtn(index: number) {
  22. const { fast, sleep, status } = props.data
  23. var single = 0;
  24. var is_start = 0;
  25. var window = 'FAST'
  26. switch (index) {
  27. case 0:
  28. {
  29. single = 1;
  30. is_start = 1;
  31. }
  32. break;
  33. case 1:
  34. {
  35. if (status == 'OG1') {
  36. single = 1;
  37. is_start = 1;
  38. window = 'SLEEP'
  39. }
  40. else {
  41. single = 0;
  42. }
  43. }
  44. break;
  45. case 2:
  46. {
  47. if (status == 'OG2') {
  48. single = 1;
  49. is_start = 0;
  50. window = 'SLEEP'
  51. }
  52. else {
  53. single = 0;
  54. }
  55. }
  56. break;
  57. case 3:
  58. {
  59. if (status == 'OG3') {
  60. single = 1;
  61. is_start = 0;
  62. window = 'FAST'
  63. }
  64. else {
  65. single = 0;
  66. }
  67. }
  68. break;
  69. }
  70. jumpPage(`/_health/pages/log_time?is_fast_with_sleep=1&index=${index}&initCheck=${health.fast_with_sleep.status == 'OG2_MISALIGNED' ? 1 : 0}&single=${index == 0 ? 1 : 0}&is_start=${is_start}&window=${window}`)
  71. /*
  72. const isSingle = router.params.single == '1'
  73. const isFast = router.params.window == 'FAST'
  74. const isStart = router.params.is_start == '1'
  75. */
  76. }
  77. function goDetail(index) {
  78. if (index == 0 && props.data.fast.status == 'OG') {
  79. const { event_id, schedule_id } = props.data.fast.timeline[0]
  80. jumpPage(`/_health/pages/timeline_detail?event_id=${event_id}&schedule_id=${schedule_id}`)
  81. }
  82. else if (index == 1 && (props.data.sleep.status == 'OG' || props.data.status == 'OG3')) {
  83. const { event_id, schedule_id } = props.data.sleep.timeline[0]
  84. jumpPage(`/_health/pages/timeline_detail?event_id=${event_id}&schedule_id=${schedule_id}`)
  85. }
  86. }
  87. function itemDisableStatus(index){
  88. if (index == 0 && props.data.fast.status == 'OG') {
  89. return false
  90. }
  91. else if (index == 1 && (props.data.sleep.status == 'OG' || props.data.status == 'OG3')) {
  92. return false
  93. }
  94. return true
  95. }
  96. function delConfirm() {
  97. const { fast, sleep } = props.data
  98. let array: any = []
  99. if (fast.window_id) {
  100. array.push(fast.window_id)
  101. }
  102. if (sleep.window_id) {
  103. array.push(sleep.window_id)
  104. }
  105. showAlert({
  106. title: 'del',
  107. content: '确认删除此记录?',
  108. showCancel: true,
  109. confirm: () => {
  110. delRecord(array[0], { ids: array }).then(res => {
  111. global.refreshWindow()
  112. props.del()
  113. })
  114. }
  115. })
  116. }
  117. function getIconColor(index: number, finish: boolean) {
  118. var color = MainColorType.g03
  119. if (index == 1 || index == 2) {
  120. color = MainColorType.sleep
  121. }
  122. else {
  123. color = MainColorType.fast
  124. }
  125. if (finish) {
  126. color = MainColorType.g03
  127. }
  128. return color;
  129. }
  130. function processIcon(item, finish, isError) {
  131. if (isError) {
  132. return <Image style={{ width: rpxToPx(20), height: rpxToPx(20) }} src={require('@assets/_health/tip_error.png')} />
  133. }
  134. if (finish) {
  135. return <Image style={{ width: rpxToPx(20), height: rpxToPx(20) }} src={require('@assets/_health/checked.png')} />
  136. }
  137. if (item.timeline.reminder) {
  138. return <IconNotification color="#fff" width={rpxToPx(20)} />
  139. }
  140. return <IconNotificationOff color="#fff" width={rpxToPx(20)} />
  141. }
  142. function actionList() {
  143. var list: any = []
  144. if (!health.finish_setup) {
  145. list.push(t('health.finish_setup'))
  146. }
  147. if (props.data.status != 'WFS') {
  148. list.push(t('health.delete_current_record'))
  149. }
  150. if (health.finish_setup) {
  151. list.push(t('health.edit_schedule'))
  152. }
  153. return list
  154. }
  155. function showAction() {
  156. showActionSheet({
  157. showActionSheetWithOptions: showActionSheetWithOptions,
  158. title: t('health.more_actions'),
  159. itemList: actionList(),
  160. success: (res) => {
  161. tapActionSheet(res)
  162. }
  163. });
  164. }
  165. function tapActionSheet(index) {
  166. var title = actionList()[index]
  167. switch (title) {
  168. case t('health.finish_setup'):
  169. jumpPage('/_health/pages/guide_begin')
  170. break;
  171. case t('health.delete_current_record'):
  172. delConfirm()
  173. break;
  174. case t('health.edit_schedule'):
  175. jumpPage('/_health/pages/schedules?mode=FAST,EAT')
  176. break
  177. }
  178. }
  179. function timelineItem(item: any, index: number, count: number) {
  180. const { fast, sleep, status } = props.data
  181. var showBtn = true;
  182. var time = ''
  183. var hasDescription = item.moment && item.moment.description
  184. var finish = false;
  185. switch (index) {
  186. case 0:
  187. {
  188. if (status == 'OG2_NO1' || status == 'WFS') {
  189. showBtn = true
  190. }
  191. else {
  192. showBtn = false;
  193. finish = true;
  194. }
  195. time = TimeFormatter.dayjsFormat(fast.target.start_timestamp)//dayjs(fast.target.start_timestamp).format('MM-DD HH:mm')
  196. }
  197. break;
  198. case 1:
  199. {
  200. if (status == 'WFS' || status == 'OG1') {
  201. showBtn = true
  202. }
  203. else {
  204. showBtn = false
  205. finish = true;
  206. }
  207. if (status == 'OG3') {
  208. time = TimeFormatter.dayjsFormat(sleep.real.start_timestamp)//dayjs(sleep.real.start_timestamp).format('MM-DD HH:mm')
  209. }
  210. else {
  211. time = TimeFormatter.dayjsFormat(sleep.target.start_timestamp)//dayjs(sleep.target.start_timestamp).format('MM-DD HH:mm')
  212. }
  213. }
  214. break;
  215. case 2:
  216. {
  217. if (status == 'OG3') {
  218. showBtn = false
  219. finish = true;
  220. time = TimeFormatter.dayjsFormat(sleep.real.end_timestamp)//dayjs(sleep.real.end_timestamp).format('MM-DD HH:mm')
  221. }
  222. else {
  223. showBtn = true
  224. time = TimeFormatter.dayjsFormat(sleep.target.end_timestamp)//dayjs(sleep.target.end_timestamp).format('MM-DD HH:mm')
  225. }
  226. }
  227. break;
  228. case 3:
  229. {
  230. showBtn = true
  231. time = TimeFormatter.dayjsFormat(fast.target.end_timestamp)//dayjs(fast.target.end_timestamp).format('MM-DD HH:mm')
  232. }
  233. break;
  234. }
  235. var isError = false;
  236. if (health.fast_with_sleep.status == 'OG2_MISALIGNED' && (index == 0 || index == 1)) {
  237. isError = true;
  238. }
  239. function rightView() {
  240. if (isError) {
  241. return <View style={{
  242. borderColor: MainColorType.error,
  243. borderWidth: rpxToPx(2),
  244. borderRadius: rpxToPx(76 / 4),
  245. borderStyle: 'solid'
  246. }}>
  247. <NewButton
  248. type={NewButtonType.gray}
  249. title='Correct'
  250. fontSize={rpxToPx(34)}
  251. width={rpxToPx(128)}
  252. height={rpxToPx(72)}
  253. onClick={() => {
  254. jumpPage(`/_health/pages/log_time?is_fast_with_sleep=1&index=${1}&single=0&initCheck=1&initIndex=${index}`)
  255. }}
  256. />
  257. </View>
  258. }
  259. else {
  260. if (item.action == 'POST_MOMENT' && item.timeline.real)
  261. return <IconArrow color={MainColorType.g03} width={rpxToPx(34)} />
  262. if (item.moment && item.moment.media && item.moment.media.length > 0)
  263. return <Image
  264. src={item.moment.media[0].url}
  265. mode="aspectFill"
  266. className="console_item_img" />
  267. if (showBtn)
  268. return <NewButton
  269. color={getThemeColor(item.mode)}
  270. type={NewButtonType.alpha}
  271. title={'Log'}
  272. width={rpxToPx(128)}
  273. height={rpxToPx(72)}
  274. bold={true}
  275. onClick={() => {
  276. tapLogBtn(index)
  277. }} />
  278. }
  279. }
  280. return <ConsoleCell
  281. status={<View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
  282. <View style={{
  283. flexShrink: 0,
  284. width: rpxToPx(26),
  285. height: rpxToPx(26),
  286. borderRadius: rpxToPx(13),
  287. marginRight: rpxToPx(8),
  288. display: 'flex',
  289. alignItems: 'center',
  290. justifyContent: 'center',
  291. backgroundColor: isError ? MainColorType.error : getIconColor(index, finish)
  292. }}>
  293. {
  294. processIcon(item, finish, isError)
  295. }
  296. </View>
  297. <Text className="timeline_time" style={{ color: isError ? MainColorType.error : MainColorType.g01 }}>{time}</Text>
  298. </View>}
  299. title={(item.moment && item.moment.title) ? item.moment.title : item.title}
  300. description={hasDescription ? item.moment.description : null}
  301. disable={itemDisableStatus(index)}
  302. onClick={() => {
  303. goDetail(index)
  304. }}
  305. right={rightView()}
  306. showLine={true}
  307. fullLine={count - 1 == index}
  308. />
  309. return <View key={index}
  310. className="timeline_item"
  311. onClick={() => {
  312. goDetail(index)
  313. }}>
  314. <View className="timeline_left">
  315. <View style={{
  316. height: hasDescription ? rpxToPx(28) : rpxToPx(36), flexShrink: 0
  317. }} />
  318. <View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
  319. <View style={{
  320. flexShrink: 0,
  321. width: rpxToPx(26),
  322. height: rpxToPx(26),
  323. borderRadius: rpxToPx(13),
  324. marginRight: rpxToPx(8),
  325. display: 'flex',
  326. alignItems: 'center',
  327. justifyContent: 'center',
  328. backgroundColor: isError ? MainColorType.error : getIconColor(index, finish)
  329. }}>
  330. {
  331. processIcon(item, finish, isError)
  332. }
  333. </View>
  334. <Text className="timeline_time" style={{ color: isError ? MainColorType.error : MainColorType.g01 }}>{time}</Text>
  335. </View>
  336. <Text className="timeline_title"
  337. onClick={() => { }}>{(item.moment && item.moment.title) ? item.moment.title : item.title}</Text>
  338. {
  339. hasDescription && <Text className="timeline_desc">{item.moment.description}</Text>
  340. }
  341. <View style={{
  342. height: hasDescription ? rpxToPx(28) : rpxToPx(54), flexShrink: 0,
  343. }} />
  344. </View>
  345. <View style={{ flex: 1 }} />
  346. {
  347. !isError && item.moment && item.moment.media && item.moment.media.length > 0 && <Image
  348. src={item.moment.media[0].url}
  349. mode="aspectFill"
  350. className="console_item_img" />
  351. }
  352. {
  353. !isError && showBtn && <NewButton
  354. color={getThemeColor(item.mode)}
  355. type={NewButtonType.alpha}
  356. title={'Log'}
  357. width={rpxToPx(128)}
  358. height={rpxToPx(72)}
  359. bold={true}
  360. onClick={() => {
  361. tapLogBtn(index)
  362. }} />
  363. }
  364. {
  365. isError && <View style={{
  366. borderColor: MainColorType.error,
  367. borderWidth: rpxToPx(2),
  368. borderRadius: rpxToPx(76 / 4),
  369. borderStyle: 'solid'
  370. }}>
  371. <NewButton
  372. type={NewButtonType.gray}
  373. title='Correct'
  374. fontSize={rpxToPx(34)}
  375. width={rpxToPx(128)}
  376. height={rpxToPx(72)}
  377. onClick={() => {
  378. jumpPage(`/_health/pages/log_time?is_fast_with_sleep=1&index=${1}&single=0&initCheck=1&initIndex=${index}`)
  379. }}
  380. />
  381. </View>
  382. }
  383. {
  384. !isError && item.action == 'POST_MOMENT' && item.timeline.real && <IconArrow color={MainColorType.g03} width={rpxToPx(34)} />
  385. }
  386. <View className="seperate_line" style={{ left: count - 1 == index ? -rpxToPx(52) : rpxToPx(52) }} />
  387. </View>
  388. }
  389. return <View style={{ backgroundColor: '#fff' }}>
  390. {
  391. health.fast_with_sleep.status == 'OG2_MISALIGNED' && <View className="error_bg" >
  392. <View className="error_icon_bg">
  393. <Image src={require('@assets/_health/tip_error.png')} style={{ width: rpxToPx(26), height: rpxToPx(26) }} />
  394. </View>
  395. <Text className="h24" style={{ lineHeight: rpxToPx(36) + 'px' }}>Logged times are not in their proper order</Text>
  396. </View>
  397. }
  398. {
  399. props.step != 2 && props.step != 3 && timelineItem({
  400. title: 'Start Fast',
  401. mode: 'FAST',
  402. is_start: true,
  403. action: props.data.fast.timeline[0].action,
  404. moment: props.data.fast.timeline[0].moment,
  405. timeline: props.data.fast.timeline[0]
  406. }, 0, 4)
  407. }
  408. {
  409. props.step != 3 && timelineItem({
  410. title: 'Go to bed',
  411. mode: 'SLEEP',
  412. is_start: true,
  413. action: props.data.fast.timeline[0].action,
  414. moment: props.data.sleep.timeline[0].moment,
  415. timeline: props.data.sleep.timeline[0]
  416. }, 1, 4)
  417. }
  418. {
  419. props.step != 1 && timelineItem({
  420. title: 'Wake up',
  421. mode: 'SLEEP',
  422. is_start: false,
  423. moment: props.data.sleep.timeline[1].moment,
  424. timeline: props.data.sleep.timeline[1]
  425. }, 2, 4)
  426. }
  427. {
  428. props.step != 1 && props.step != 2 && timelineItem({
  429. title: 'End Fast',
  430. mode: 'FAST',
  431. is_start: false,
  432. moment: props.data.fast.timeline[1].moment,
  433. timeline: props.data.fast.timeline[1]
  434. }, 3, 4)
  435. }
  436. {
  437. <View className="main_console_footer">
  438. <NewButton
  439. btnStyle={{
  440. position: 'absolute',
  441. top: rpxToPx(42),
  442. right: rpxToPx(40)
  443. }}
  444. type={NewButtonType.more}
  445. onClick={showAction}
  446. />
  447. </View>
  448. }
  449. </View>
  450. }