StreakItem.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. import { View, Text, ScrollView } from '@tarojs/components'
  2. import './Streaks.scss'
  3. import { rpxToPx } from '@/utils/tools'
  4. import { ColorType } from '@/context/themes/color'
  5. import { useTranslation } from 'react-i18next'
  6. import { jumpPage } from '../hooks/Common'
  7. import { useEffect, useState } from 'react'
  8. import { TimeFormatter } from '@/utils/time_format'
  9. import showAlert from '@/components/basic/Alert'
  10. let useNavigation;
  11. let LinearGradient;
  12. if (process.env.TARO_ENV == 'rn') {
  13. useNavigation = require("@react-navigation/native").useNavigation
  14. LinearGradient = require('react-native-linear-gradient').default
  15. }
  16. export default function StreakItem(props: { isFast: boolean, data: any }) {
  17. const { t } = useTranslation()
  18. const [left, setLeft] = useState(500)
  19. const [points, setPoints] = useState([false, false, false, false, false, false, false])
  20. let navigation;
  21. if (useNavigation) {
  22. navigation = useNavigation()
  23. }
  24. useEffect(() => {
  25. if (props.data.current.num_days > 6) {
  26. var array = Array.from({ length: props.data.current.num_days }, () => true)
  27. array.push(false)
  28. setPoints(array)
  29. }
  30. else {
  31. let newPoints = [false, false, false, false, false, false, false]
  32. for (let i = 0; i < props.data.current.num_days; i++) {
  33. newPoints[i] = true
  34. }
  35. setPoints(newPoints)
  36. }
  37. setTimeout(() => {
  38. setLeft((prevCounter) => prevCounter + 1)
  39. }, 300)
  40. }, [props.data])
  41. function goDetail() {
  42. jumpPage(`/pages/clock/StreakDetail?isFast=${props.isFast ? 1 : 0}&data=${JSON.stringify(props.data)}`,
  43. 'StreakDetail',
  44. navigation,
  45. {
  46. isFast: props.isFast ? 1 : 0,
  47. data: JSON.stringify(props.data)
  48. })
  49. // jumpPage('/pages/clock/StreakDetail?isFast='+props.isFast+'&data=' + JSON.stringify(props.data), 'StreakDetail', navigation)
  50. }
  51. function day(num) {
  52. if (global.language == 'en') {
  53. return num == 1 ? 'day' : 'days'
  54. }
  55. return '天'
  56. }
  57. function nextStatus() {
  58. const { status } = props.data.current
  59. if (status == 'EXPIRED') {
  60. return t('feature.track_time_duration.streaks.last_reset')
  61. }
  62. else {
  63. return t('feature.track_time_duration.streaks.next_reset')
  64. }
  65. }
  66. function getTime() {
  67. const { status } = props.data.current
  68. var ts: any = null;
  69. switch (status) {
  70. case 'EXPIRED':
  71. ts = props.data.current.prev_reset_ts
  72. break;
  73. case 'ACTIVE':
  74. ts = props.data.current.reset_ts
  75. break;
  76. case 'NOT_DETERMINED':
  77. case 'HEADS_UP':
  78. return t('feature.track_time_duration.streaks.not_determined');
  79. }
  80. var date = new Date(ts)
  81. var time = TimeFormatter.padZero(date.getHours()) + ':' + TimeFormatter.padZero(date.getMinutes())
  82. if (TimeFormatter.dateDescription(ts, true) == 'Today') {
  83. return 'Tonight ' + time
  84. }
  85. if (TimeFormatter.dateDescription(ts, true) == '今天') {
  86. return '今晚 ' + time
  87. }
  88. return TimeFormatter.dateDescription(ts, true) + ' ' + time
  89. }
  90. function tapDetail() {
  91. showAlert({
  92. title: t('feature.track_time_duration.streaks.alert_title'),
  93. content: t('feature.track_time_duration.streaks.alert_content'),
  94. showCancel: false,
  95. confirmText: t('feature.track_time_duration.streaks.alert_confirm')
  96. })
  97. }
  98. function dayUnit(num) {
  99. if (global.language == 'en') {
  100. return num == 1 ? 'day' : 'days'
  101. }
  102. return '天'
  103. }
  104. return <View className='streaks_item' onClick={goDetail}>
  105. <View className='streaks_item_header'>
  106. <Text className='streak_item_type'>{props.isFast ? t('feature.track_time_duration.streaks.faststreak') : t('feature.track_time_duration.streaks.sleepstreak')}</Text>
  107. {/* <IconShare2 width={rpxToPx(32)} color={props.isFast ? ColorType.fast : ColorType.sleep} /> */}
  108. </View>
  109. <View style={{
  110. flexDirection: 'row',
  111. display: 'flex',
  112. marginTop: rpxToPx(6),
  113. alignItems: 'flex-end'
  114. }}>
  115. <Text className='streak_index'
  116. style={{ color: props.data.current.num_days == 0 ? '#ffffff99' : props.isFast ? ColorType.fast : ColorType.sleep }}
  117. >{props.data.current.num_days}</Text>
  118. <Text className='streak_index_day'
  119. style={{
  120. color: props.data.current.num_days == 0 ? '#ffffff99' : props.isFast ? ColorType.fast : ColorType.sleep,
  121. fontSize: global.language == 'en' ? rpxToPx(40) : rpxToPx(32)
  122. }}>
  123. {dayUnit(props.data.current.num_days)}
  124. </Text>
  125. </View>
  126. {
  127. props.data.current.num_days < 7 ? <View className='streak_item_point_bg'>
  128. {
  129. points.map((item, index) => {
  130. return <View className='streak_item_point' key={index}
  131. style={{
  132. backgroundColor: item ? props.isFast ? ColorType.fast : ColorType.sleep : 'rgba(216, 216, 216, 0.1)',
  133. width: rpxToPx(28),
  134. height: rpxToPx(28),
  135. borderRadius: rpxToPx(14),
  136. }}></View>
  137. })
  138. }
  139. </View> :
  140. <ScrollView scrollX className='scroll_point_bg'
  141. style={{ width: rpxToPx(270), height: rpxToPx(28) }}
  142. showScrollbar={false}
  143. enableFlex enhanced
  144. scrollLeft={left}
  145. showsHorizontalScrollIndicator={false}>
  146. <View style={{ flexDirection: 'row', display: 'flex', marginTop: 0 }}>
  147. {
  148. points.map((item, index) => {
  149. return <View className='streak_item_point' key={index}
  150. style={{
  151. backgroundColor: item ? props.isFast ? ColorType.fast : ColorType.sleep : 'rgba(216, 216, 216, 0.1)',
  152. marginRight: item ? rpxToPx(8) : 0,
  153. width: rpxToPx(28),
  154. height: rpxToPx(28),
  155. borderRadius: rpxToPx(14),
  156. }}></View>
  157. })
  158. }
  159. </View>
  160. </ScrollView>
  161. }
  162. <View className='streak_next'>
  163. {
  164. process.env.TARO_ENV == 'weapp' ? <View className='streak_line_left' /> :
  165. <LinearGradient style={{
  166. flex: 1,
  167. height: 1,
  168. marginRight: rpxToPx(20)
  169. }} colors={['#2f2f2f00', '#2f2f2fff']}
  170. start={{ x: 0, y: 0 }}
  171. end={{ x: 1, y: 0 }} />
  172. }
  173. <Text className='streak_next_text'>{nextStatus()}</Text>
  174. {
  175. process.env.TARO_ENV == 'weapp' ?<View className='streak_line_right' />:
  176. <LinearGradient style={{
  177. flex: 1,
  178. height: 1,
  179. marginLeft: rpxToPx(20)
  180. }} colors={['#2f2f2fff', '#2f2f2f00']}
  181. start={{ x: 0, y: 0 }}
  182. end={{ x: 1, y: 0 }} />
  183. }
  184. </View>
  185. <Text className='streak_status'>{getTime()}</Text>
  186. <View className='streak_bottom'>
  187. {
  188. props.data.current.status == 'ACTIVE' && <View className='streak_bottom_info' style={{ backgroundColor: 'red' }}>
  189. <Text className='streak_bottom_info_text'>{TimeFormatter.countdown(props.data.current.reset_ts)}</Text>
  190. </View>
  191. }
  192. {
  193. props.data.current.status == 'HEADS_UP' && <View className='streak_bottom_info' style={{ backgroundColor: ColorType.sleep }} onClick={(e) => {
  194. if (process.env.TARO_ENV == 'weapp')
  195. e.stopPropagation()
  196. tapDetail()
  197. }}>
  198. <Text className='streak_bottom_info_text'>{t('feature.track_time_duration.streaks.heads_up')}</Text>
  199. </View>
  200. }
  201. </View>
  202. {/* <View style={{ flexDirection: 'row', height: rpxToPx(36), overflow: 'hidden',alignItems:'flex-end' }}>
  203. <Text className='streak_item_note'>{t('feature.track_time_duration.streaks.current')}</Text>
  204. {
  205. props.data.current.num_days == 0 ? <Text className='streak_item_value' style={{ color: '#fff', opacity: 0.4,marginBottom:-2 }}>{props.data.current.num_days}</Text> :
  206. <Text className='streak_item_value' style={{ color: props.isFast ? ColorType.fast : ColorType.sleep,marginBottom:-2 }}>{props.data.current.num_days}</Text>
  207. }
  208. {
  209. props.data.current.num_days == 0 ? <Text className='streak_item_note' style={{ color: '#fff', opacity: 0.4, fontWeight: 'bold' }}>{day(props.data.current.num_days)}</Text> :
  210. <Text className='streak_item_note' style={{ color: props.isFast ? ColorType.fast : ColorType.sleep, opacity: 1, fontWeight: 'bold' }}>{day(props.data.current.num_days)}</Text>
  211. }
  212. </View> */}
  213. {/* <View style={{ marginTop: rpxToPx(16), flexDirection: 'row', height: rpxToPx(36), overflow: 'hidden',alignItems:'flex-end' }}>
  214. <Text className='streak_item_note'>{t('feature.track_time_duration.streaks.longest')}</Text>
  215. <Text className='streak_item_value' style={{ color: '#fff', opacity: 0.4,marginBottom:-2 }}>{props.data.longest.num_days}</Text>
  216. <Text className='streak_item_note' style={{ fontWeight: 'bold' }}>{day(props.data.longest.num_days)}</Text>
  217. </View> */}
  218. </View>
  219. }