RecordFastSleep.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. import Box from "@/components/layout/Box";
  2. import Header from "@/components/layout/Header";
  3. import Modal from "@/components/layout/Modal";
  4. import RecordItem from "@/features/common/RecordItem";
  5. import { delRecord } from "@/services/trackTimeDuration";
  6. import { ModalType } from "@/utils/types";
  7. import { View, Text, Image } from "@tarojs/components";
  8. import Taro from "@tarojs/taro";
  9. import { useEffect, useState } from "react";
  10. import TimelineFastSleep from "./TimelineFastSleep";
  11. import { TimeFormatter } from "@/utils/time_format";
  12. import './RecordFastSleep.scss'
  13. import { getBgRing, getCommon, getDot, getReal, getTarget } from "../hooks/RingData";
  14. import Rings from "./Rings";
  15. import Segment from "@/components/navigation/Segment";
  16. import Stage from "./Stage";
  17. import CenterContentTitleModal from "@/features/common/CenterContentTitleModal";
  18. import { useTranslation } from "react-i18next";
  19. import { ColorType } from "@/context/themes/color";
  20. import TimelineStage from "./TimelineStage";
  21. import { jumpPage } from "../hooks/Common";
  22. // import { sqrt } from 'mathjs'
  23. let AppState;
  24. if (process.env.TARO_ENV == 'rn') {
  25. AppState = require("react-native").AppState
  26. }
  27. export default function RecordFastSleep(props: { data: any, type: string, delSuccess?: Function }) {
  28. const [showDetailModal, setShowDetailModal] = useState(false)
  29. const [segmentIndex, setSegmentIndex] = useState(0)
  30. const [diffTimeZone, setDiffTimeZone] = useState(false)
  31. const [multiTimeZone, setMultiTimeZone] = useState(false)
  32. const { t } = useTranslation()
  33. const canvasId = props.data.id
  34. const record = props.data;
  35. const handleAppStateChange = (nextAppState) => {
  36. checkTimezone()
  37. };
  38. useEffect(() => {
  39. checkTimezone()
  40. if (process.env.TARO_ENV == 'rn') {
  41. AppState.addEventListener('change', handleAppStateChange);
  42. }
  43. // console.log(sqrt(-4).toString())
  44. }, [props.data])
  45. function checkTimezone() {
  46. var split = new Date().toString().split(' ');
  47. var currentTZ = split[split.length - 2];
  48. var isDiff = false;
  49. var isMulti = false;
  50. var tempTZ = '';
  51. if (props.data.fast) {
  52. if (props.data.fast.real_start_time_zone) {
  53. tempTZ = props.data.fast.real_start_time_zone
  54. if (props.data.fast.real_start_time_zone != currentTZ) {
  55. isDiff = true
  56. }
  57. }
  58. if (props.data.fast.real_end_time_zone) {
  59. if (tempTZ != props.data.fast.real_end_time_zone) {
  60. isMulti = true
  61. }
  62. if (props.data.fast.real_end_time_zone != currentTZ) {
  63. isDiff = true
  64. }
  65. }
  66. }
  67. if (props.data.sleep) {
  68. if (props.data.sleep.real_start_time_zone) {
  69. if (tempTZ == '') {
  70. tempTZ = props.data.sleep.real_start_time_zone
  71. }
  72. else if (tempTZ != props.data.sleep.real_start_time_zone) {
  73. isMulti = true
  74. }
  75. if (props.data.sleep.real_start_time_zone != currentTZ) {
  76. isDiff = true
  77. }
  78. }
  79. if (props.data.sleep.real_end_time_zone) {
  80. if (tempTZ != props.data.sleep.real_end_time_zone) {
  81. isMulti = true
  82. }
  83. if (props.data.sleep.real_end_time_zone != currentTZ) {
  84. isDiff = true
  85. }
  86. }
  87. }
  88. setDiffTimeZone(isDiff)
  89. setMultiTimeZone(isMulti)
  90. }
  91. function del() {
  92. var id = props.data.id
  93. delRecord(id
  94. ).then(res => {
  95. global.refreshTime()
  96. Taro.showToast({
  97. title: t('page.records_history.del_success')
  98. })
  99. props.delSuccess && props.delSuccess(props.data)
  100. // Taro.navigateBack()
  101. })
  102. }
  103. function subTitle(timestamp) {
  104. if (multiTimeZone) {
  105. return t('feature.common.multi_timezones')
  106. }
  107. if (diffTimeZone) {
  108. return t('feature.common.different_timezone')
  109. }
  110. return TimeFormatter.getDateAndWeek(timestamp)
  111. }
  112. function schedules() {
  113. var timestamp = props.data.first_real_check_time
  114. return <View style={{ display: 'flex', flexDirection: 'column' }}>
  115. <TimelineStage data={props.data} title={t('feature.track_time_duration.record_fast_sleep.pop_title')}
  116. subTitle={subTitle(timestamp)} first_real_check_time={timestamp} />
  117. </View>
  118. }
  119. function showDetail(e) {
  120. if (props.type == 'latest') {
  121. setSegmentIndex(0)
  122. global.segmentIndex = 0
  123. setShowDetailModal(true)
  124. return;
  125. }
  126. setShowDetailModal(true)
  127. // var node = (<Modal children={schedules()}
  128. // modalType={ModalType.center}
  129. // dismiss={() => {
  130. // global.showModal(false, null)
  131. // }}
  132. // confirm={() => { }} />);
  133. // global.showModal(true, node);
  134. }
  135. function getDuration(obj) {
  136. if (!obj) {
  137. }
  138. if (obj.status == 'NOT_STARTED' || obj.status == 'NOT_COMPLETED') {
  139. return ''
  140. }
  141. var start = obj.real_start_time
  142. var end = obj.real_end_time
  143. if (!end) {
  144. end = (new Date()).getTime()
  145. }
  146. return TimeFormatter.durationFormate(start, end)
  147. // return TimeFormatter.calculateTimeDifference(start, end)
  148. }
  149. function durationArc(start_time: number, end_time: number) {
  150. var duration = (end_time - start_time) / 1000;
  151. return duration / (24 * 3600) * 2 * Math.PI;
  152. }
  153. function bigRing() {
  154. var common = getCommon(null, true)
  155. common.radius = 42;
  156. common.lineWidth = 9;
  157. var bgRing = getBgRing()
  158. if (props.type == 'record' || props.type == 'latest') {
  159. var realRing = getReal(record, true, true)
  160. if (props.data.status == 'ONGOING3') {
  161. realRing.color = 'rgba(0,0,0,0)'
  162. // bgRing.color = 'rgba(0,0,0,0)'
  163. }
  164. return <Rings common={common} bgRing={bgRing} canvasId={canvasId} realRing={realRing} />
  165. }
  166. else {
  167. var currentDot1 = getDot(record, true)
  168. var targetBigRing1 = getTarget(record, true)
  169. if (record.status == 'ONGOING') {
  170. var realRing1 = getReal(record, true, false)
  171. return <Rings common={common} bgRing={bgRing} currentDot={currentDot1} realRing={realRing1} targetRing={targetBigRing1} canvasId={canvasId} />
  172. }
  173. if (record.status == 'WAIT_FOR_START') {
  174. return <Rings common={common} bgRing={bgRing} currentDot={currentDot1} canvasId={canvasId} />
  175. }
  176. var realRing1 = getReal(record, true, false)
  177. return <Rings common={common} bgRing={bgRing} realRing={realRing1} currentDot={currentDot1} targetRing={targetBigRing1} canvasId={canvasId} />
  178. }
  179. }
  180. function smallRing() {
  181. if (record.scenario == 'FAST_SLEEP') {
  182. var common = getCommon(null, false)
  183. common.radius = 28;
  184. common.lineWidth = 9;
  185. var bgRing = getBgRing()
  186. var realRing = getReal(record, false, false)
  187. if (props.type == 'record' || props.type == 'latest') {
  188. if (record.sleep.status == 'WAIT_FOR_END') {
  189. realRing.durationArc = durationArc(record.sleep.target_start_time, (new Date()).getTime())
  190. return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
  191. }
  192. else if (record.sleep.status == 'NOT_COMPLETED') {
  193. realRing.durationArc = 0.01
  194. return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
  195. }
  196. else if (record.sleep.status == 'COMPLETED') {
  197. realRing = getReal(record, false, true)
  198. return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} realRing={realRing} />
  199. }
  200. return <Rings common={common} bgRing={bgRing} canvasId={canvasId + 'small'} />
  201. }
  202. else {
  203. var currentDot = getDot(record, false)
  204. var targetRing = getTarget(record, false)
  205. if (record.status == 'ONGOING2') {
  206. var realRing = getReal(record, false, false)
  207. return <Rings common={common} bgRing={bgRing} realRing={realRing} currentDot={currentDot} targetRing={targetRing} canvasId={canvasId + 'small'} />
  208. }
  209. if (record.status == 'ONGOING3') {
  210. currentDot.color = 'rgba(0, 255, 255, 0.5)'
  211. }
  212. return <Rings common={common} bgRing={bgRing} currentDot={currentDot} canvasId={canvasId + 'small'} />
  213. }
  214. }
  215. return null
  216. }
  217. function rings() {
  218. return <View style={{ position: 'relative', zIndex: 1 }}>
  219. {
  220. bigRing()
  221. }
  222. <View style={{ display: 'flex', position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, alignItems: 'center', justifyContent: 'center' }}>
  223. {
  224. smallRing()
  225. }
  226. </View>
  227. </View>
  228. }
  229. function recordTime() {
  230. var timestamp = props.data.first_real_check_time
  231. if (props.data.first_time_zone) {
  232. timestamp = TimeFormatter.transferTimestamp(timestamp, props.data.first_time_zone)
  233. }
  234. return TimeFormatter.dateDescription(timestamp, true)
  235. }
  236. function getArrowText() {
  237. if (multiTimeZone) {
  238. return t('feature.common.multi_timezones')
  239. }
  240. if (diffTimeZone) {
  241. return t('feature.common.different_timezone')
  242. }
  243. return recordTime()
  244. }
  245. function recordDetail() {
  246. var fastDuration = ''
  247. var sleepDuration = ''
  248. var showFast = false;
  249. var showSleep = false;
  250. if (record.scenario == 'FAST_SLEEP') {
  251. fastDuration = getDuration(record.fast)
  252. sleepDuration = getDuration(record.sleep)
  253. if (record.status == 'ONGOING3') {
  254. fastDuration = t('feature.common.wait_for_end')
  255. }
  256. if (record.sleep.status == "NOT_STARTED") {
  257. sleepDuration = t('feature.common.not_started')
  258. }
  259. else if (record.sleep.status == 'NOT_COMPLETED') {
  260. sleepDuration = t('feature.common.not_completed')
  261. }
  262. showFast = true
  263. showSleep = true
  264. }
  265. else if (record.scenario == 'FAST') {
  266. fastDuration = getDuration(record.fast)
  267. showFast = true
  268. }
  269. else {
  270. sleepDuration = getDuration(record.sleep)
  271. showSleep = true
  272. }
  273. return <View className="fast_sleep_item">
  274. {
  275. rings()
  276. }
  277. <View className="duration_bg">
  278. {
  279. showFast && <Text className="duration_title">{t('feature.track_time_duration.record_fast_sleep.item.fast')}</Text>
  280. }
  281. {
  282. showFast && <Text className="duration_value" style={{ color: global.fastColor ? global.fastColor : ColorType.fast }}>{fastDuration}</Text>
  283. }
  284. {
  285. showSleep && <Text className="duration_title">{t('feature.track_time_duration.record_fast_sleep.item.sleep')}</Text>
  286. }
  287. {
  288. showSleep && <Text className="duration_value" style={{ color: global.sleepColor ? global.sleepColor : ColorType.sleep }}>{sleepDuration}</Text>
  289. }
  290. </View>
  291. {/* <Image className="arrow1" src={require('@/assets/images/arrow.png')} /> */}
  292. <View className="record_arrow_bg" style={{ backgroundColor: global.isDebug ? 'red' : 'transparent' }}>
  293. <View style={{ flex: 1 }} />
  294. <Text className='recordTime'>{getArrowText()}</Text>
  295. <Image className="arrow2" src={require('@/assets/images/arrow3.png')} />
  296. </View>
  297. </View>
  298. }
  299. return <View>
  300. <View className="time_operate_item">
  301. <RecordItem canDel={record.status == 'COMPLETED'} delete={del}
  302. onClick={showDetail}
  303. >{recordDetail()}
  304. </RecordItem>
  305. {
  306. showDetailModal && <Modal children={schedules()}
  307. modalType={ModalType.center}
  308. dismiss={() => setShowDetailModal(false)}
  309. confirm={() => { }} />
  310. }
  311. </View>
  312. </View>
  313. }