|
|
@@ -1,6 +1,6 @@
|
|
|
import { View, Text } from "@tarojs/components";
|
|
|
import './MainCard.scss'
|
|
|
-import { useEffect, useState } from "react";
|
|
|
+import { useEffect, useRef, useState } from "react";
|
|
|
import Modal from "@/components/layout/Modal.weapp";
|
|
|
import { rpxToPx } from "@/utils/tools";
|
|
|
import Rings, { RingCommon, BgRing, TargetRing, CurrentDot } from "@/features/trackTimeDuration/components/Rings";
|
|
|
@@ -9,16 +9,39 @@ import moment from 'moment-timezone'
|
|
|
import { MainColorType } from "@/context/themes/color";
|
|
|
import { fastWindow } from "@/services/trackTimeDuration";
|
|
|
import { useSelector } from "react-redux";
|
|
|
-
|
|
|
+import { jumpPage } from "../hooks/Common";
|
|
|
+import ConsolePicker from "./ConsolePicker";
|
|
|
+import { endFast, startFast } from "../actions/TrackTimeActions";
|
|
|
+import formatMilliseconds from "@/utils/format_time";
|
|
|
+
|
|
|
+let useNavigation;
|
|
|
+
|
|
|
+let Linking, PushNotification;
|
|
|
+let checkNotification;
|
|
|
+let min = 0
|
|
|
+let max = 0
|
|
|
+let defaultTimestamp = 0
|
|
|
+
|
|
|
+if (process.env.TARO_ENV == 'rn') {
|
|
|
+ useNavigation = require("@react-navigation/native").useNavigation
|
|
|
+ Linking = require('react-native').Linking;
|
|
|
+ // JPush = require('jpush-react-native').default;
|
|
|
+ PushNotification = require('react-native-push-notification')
|
|
|
+ checkNotification = require('@/utils/native_permission_check').checkNotification;
|
|
|
+}
|
|
|
export default function MainFastEatCard(props: { count: any }) {
|
|
|
- const [isFast, setIsFast] = useState(true)
|
|
|
const [isFastMode, setIsFastMode] = useState(true)
|
|
|
|
|
|
const [showModal, setShowModal] = useState(false)
|
|
|
+ const [showTimePicker, setShowTimePicker] = useState(false);
|
|
|
+ const limitPickerRef = useRef(null)
|
|
|
+ const [operateType, setOperateType] = useState('startFast')
|
|
|
+ const [btnDisable, setBtnDisable] = useState(false)
|
|
|
+ const [logEvent, setLogEvent] = useState('LOG_ONCE');
|
|
|
|
|
|
const [startScheduleTime, setStartScheduleTime] = useState('00:00')
|
|
|
const [endScheduleTime, setEndScheduleTime] = useState('00:00')
|
|
|
- const [eatData, setEatData] = useState(null)
|
|
|
+ const [eatData, setEatData] = useState<any>(null)
|
|
|
const [fastData, setFastData] = useState<any>(null)
|
|
|
const [startTime, setStartTime] = useState<any>(null)
|
|
|
const [endTime, setEndTime] = useState<any>(null)
|
|
|
@@ -28,6 +51,11 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
|
|
|
const user = useSelector((state: any) => state.user);
|
|
|
|
|
|
+ let navigation;
|
|
|
+ if (useNavigation) {
|
|
|
+ navigation = useNavigation()
|
|
|
+ }
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
fastWindow().then(res => {
|
|
|
setLoaded(true)
|
|
|
@@ -39,7 +67,7 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
setEndScheduleTime(fast_win.fast.schedule_end_time)
|
|
|
|
|
|
var now = new Date().getTime()
|
|
|
- if ((fast.status == 'ONGOING' || fast.target_start_time <= now && fast.target_end_time >= now) ||
|
|
|
+ if ((fast.status == 'WAIT_FOR_END' || fast.target_start_time <= now && fast.target_end_time >= now) ||
|
|
|
isCurrentTimeInRange(fast.schedule_start_time, fast.schedule_end_time)) {
|
|
|
setIsFastMode(true)
|
|
|
}
|
|
|
@@ -57,10 +85,21 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
}
|
|
|
}, [props.count])
|
|
|
|
|
|
+ function refresh() {
|
|
|
+ fastWindow().then(res => {
|
|
|
+ const { eat_win, fast_win } = res
|
|
|
+ const fast = fast_win.fast
|
|
|
+ setEatData(eat_win)
|
|
|
+ setFastData(fast_win)
|
|
|
+ setStartScheduleTime(fast_win.fast.schedule_start_time)
|
|
|
+ setEndScheduleTime(fast_win.fast.schedule_end_time)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
function update(fast) {
|
|
|
var now = new Date().getTime()
|
|
|
|
|
|
- if (fast.status == 'ONGOING') {
|
|
|
+ if (fast.status == 'WAIT_FOR_END') {
|
|
|
setStatus('process')
|
|
|
}
|
|
|
else if ((fast.target_start_time <= now && fast.target_end_time >= now) || isCurrentTimeInRange(fast.schedule_start_time, fast.schedule_end_time)) {
|
|
|
@@ -84,8 +123,7 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
color: '#EAE9E9'
|
|
|
}
|
|
|
|
|
|
- function targetRing() {
|
|
|
-
|
|
|
+ function scheduleRing() {
|
|
|
var starts: any = startScheduleTime.split(':')
|
|
|
var ends: any = endScheduleTime.split(':')
|
|
|
const startSeconds: any = parseInt(starts[0] + '') * 60 + parseInt(starts[1] + '')
|
|
|
@@ -105,26 +143,69 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ function targetRing() {
|
|
|
+ if (status != 'process') {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ var starts: any = startScheduleTime.split(':')
|
|
|
+ var ends: any = endScheduleTime.split(':')
|
|
|
+ const startSeconds: any = parseInt(starts[0] + '') * 60 + parseInt(starts[1] + '')
|
|
|
+ const endSeconds: any = parseInt(ends[0] + '') * 60 + parseInt(ends[1] + '')
|
|
|
+ const color = isFastMode ? '#9AE2FE' : '#FE810C66'
|
|
|
+ var startArc = isFastMode ? startSeconds / 1440 * 2 * Math.PI - Math.PI / 2 : endSeconds / 1440 * 2 * Math.PI - Math.PI / 2
|
|
|
+
|
|
|
+ const fastCount = endSeconds - startSeconds > 0 ? endSeconds - startSeconds : endSeconds - startSeconds + 1440
|
|
|
+ const eatCount = 1440 - fastCount
|
|
|
+
|
|
|
+ var durationArc = isFastMode ? fastCount / 1440 * 2 * Math.PI : eatCount / 1440 * 2 * Math.PI
|
|
|
+
|
|
|
+ if (isFastMode) {
|
|
|
+ var dt = new Date(fastData.fast.target_start_time)
|
|
|
+ var realSeconds = dt.getHours() * 3600 + dt.getMinutes() * 60 + dt.getSeconds()
|
|
|
+ startArc = realSeconds / (1440 * 60) * 2 * Math.PI - Math.PI / 2
|
|
|
+ durationArc = ((fastData.fast.target_end_time - fastData.fast.target_start_time) / 1000) / (1440 * 60) * 2 * Math.PI
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ color,
|
|
|
+ startArc,
|
|
|
+ durationArc,
|
|
|
+ radius: isFastMode ? 90 : null,
|
|
|
+ lineWidth: isFastMode ? 10 : null
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
function realRing() {
|
|
|
if (isFastMode) {
|
|
|
- if (isFast) {
|
|
|
+ if (status != 'upcoming') {
|
|
|
var starts: any = startTime ? startTime.split(':') : startScheduleTime.split(':')
|
|
|
const startSeconds = parseInt(starts[0] + '') * 3600 + parseInt(starts[1] + '') * 60
|
|
|
|
|
|
const color = MainColorType.fast
|
|
|
- const startArc = startSeconds / (1440 * 60) * 2 * Math.PI - Math.PI / 2
|
|
|
+ var startArc = startSeconds / (1440 * 60) * 2 * Math.PI - Math.PI / 2
|
|
|
var endSeconds = new Date().getHours() * 3600 + new Date().getMinutes() * 60 + new Date().getSeconds()
|
|
|
if (endTime) {
|
|
|
var ends: any = endTime.split(':')
|
|
|
endSeconds = parseInt(ends[0] + '') * 3600 + parseInt(ends[1] + '') * 60
|
|
|
}
|
|
|
const fastCount = endSeconds - startSeconds > 0 ? endSeconds - startSeconds : endSeconds - startSeconds + 1440 * 60
|
|
|
- const durationArc = fastCount / (1440 * 60) * 2 * Math.PI
|
|
|
+ var durationArc = fastCount / (1440 * 60) * 2 * Math.PI
|
|
|
+
|
|
|
+ if (status == 'process') {
|
|
|
+ var dt = new Date(fastData.fast.target_start_time)
|
|
|
+ var realSeconds = dt.getHours() * 3600 + dt.getMinutes() * 60 + dt.getSeconds()
|
|
|
+ startArc = realSeconds / (1440 * 60) * 2 * Math.PI - Math.PI / 2
|
|
|
+ durationArc = ((new Date().getTime() - fastData.fast.target_start_time) / 1000) / (1440 * 60) * 2 * Math.PI
|
|
|
+ }
|
|
|
|
|
|
return {
|
|
|
color,
|
|
|
startArc,
|
|
|
- durationArc
|
|
|
+ durationArc,
|
|
|
+ radius: status == 'process' ? 90 : null,
|
|
|
+ lineWidth: status == 'process' ? 15 : null
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -143,7 +224,9 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
return {
|
|
|
color,
|
|
|
startArc,
|
|
|
- durationArc
|
|
|
+ durationArc,
|
|
|
+ radius: 90,
|
|
|
+ lineWidth: 10
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -169,6 +252,46 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
return currentTime >= startTime && currentTime <= endTime;
|
|
|
}
|
|
|
|
|
|
+ function getTimeToDestination(timeStr, isPasted) {
|
|
|
+ // 获取当前时间
|
|
|
+ const now = new Date();
|
|
|
+ const currentHours = now.getHours();
|
|
|
+ const currentMinutes = now.getMinutes();
|
|
|
+ const currentSeconds = now.getSeconds();
|
|
|
+
|
|
|
+ // 解析目标时间
|
|
|
+ const [targetHours, targetMinutes] = timeStr.split(':').map(Number);
|
|
|
+
|
|
|
+ // 计算时间差
|
|
|
+ let hours = targetHours - currentHours;
|
|
|
+ let minutes = targetMinutes - currentMinutes;
|
|
|
+ let seconds = 60 - currentSeconds;
|
|
|
+
|
|
|
+ if (minutes < 0) {
|
|
|
+ minutes += 60;
|
|
|
+ hours--;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hours < 0) {
|
|
|
+ hours += 24;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (seconds === 60) {
|
|
|
+ seconds = 0;
|
|
|
+ minutes++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果是过去的时间,则返回剩余时间
|
|
|
+ if (isPasted) {
|
|
|
+ hours = 24 - hours;
|
|
|
+ minutes = 60 - minutes;
|
|
|
+ seconds = 60 - seconds;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 格式化输出
|
|
|
+ return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
|
|
+ }
|
|
|
+
|
|
|
function ring() {
|
|
|
var offset = 0
|
|
|
|
|
|
@@ -187,7 +310,7 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
whiteIcon: true
|
|
|
}
|
|
|
|
|
|
- return <Rings common={common} bgRing={bgRing} targetRing={targetRing()} realRing={realRing()} currentDot={currentDot} canvasId={'smal11l'} />
|
|
|
+ return <Rings common={common} bgRing={bgRing} scheduleRing={scheduleRing()} targetRing={targetRing()} realRing={realRing()} currentDot={currentDot} canvasId={'smal11l'} />
|
|
|
}
|
|
|
|
|
|
function formatTime(format: string, timestamp?: number) {
|
|
|
@@ -226,11 +349,9 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
milliSeconds = new Date().getTime() - fastData.fast.real_start_time
|
|
|
break;
|
|
|
case 'new':
|
|
|
- milliSeconds = new Date().getTime() - fastData.fast.target_start_time
|
|
|
- break;
|
|
|
+ return getTimeToDestination(fastData.fast.schedule_start_time, true)
|
|
|
case 'upcoming':
|
|
|
- milliSeconds = fastData.fast.target_start_time - new Date().getTime()
|
|
|
- break;
|
|
|
+ return getTimeToDestination(fastData.fast.schedule_start_time, false)
|
|
|
|
|
|
}
|
|
|
var seconds = Math.floor(milliSeconds / 1000)
|
|
|
@@ -240,11 +361,134 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;
|
|
|
}
|
|
|
|
|
|
+ function getEatTime() {
|
|
|
+
|
|
|
+ return getTimeToDestination(eatData.schedule_start_time, isCurrentTimeInRange(eatData.schedule_start_time, eatData.schedule_end_time))
|
|
|
+ }
|
|
|
+
|
|
|
+ function tapFastStart() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function tapFastEnd() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function tapStartLog() {
|
|
|
+ if (status == 'upcoming'){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!user.isLogin) {
|
|
|
+ jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defaultTimestamp = new Date().getTime()
|
|
|
+ min = defaultTimestamp - 1 * 24 * 3600 * 1000
|
|
|
+ max = defaultTimestamp
|
|
|
+
|
|
|
+ setOperateType('startFast')
|
|
|
+ setShowTimePicker(true)
|
|
|
+ }
|
|
|
+
|
|
|
+ function tapEndLog() {
|
|
|
+ if (status != 'process') {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defaultTimestamp = new Date().getTime()
|
|
|
+ // defaultTimestamp = e ? new Date().getTime() : logEventTimestamp
|
|
|
+ min = defaultTimestamp - 1 * 24 * 3600 * 1000
|
|
|
+ max = defaultTimestamp
|
|
|
+ setOperateType('endFast')
|
|
|
+ setShowTimePicker(true)
|
|
|
+ }
|
|
|
+
|
|
|
+ function modalContent() {
|
|
|
+ global.set_time = new Date().getTime()
|
|
|
+ return <Modal
|
|
|
+ testInfo={null}
|
|
|
+ dismiss={() => {
|
|
|
+ setShowTimePicker(false)
|
|
|
+ }}
|
|
|
+ confirm={() => { }}>
|
|
|
+ {
|
|
|
+ timePickerContent()
|
|
|
+ }
|
|
|
+ </Modal>
|
|
|
+ }
|
|
|
+
|
|
|
+ function timePickerContent() {
|
|
|
+ var title = operateType == 'endFast' ? '结束断食' : '开始断食'
|
|
|
+ var color = MainColorType.fast
|
|
|
+ var endTimestamp = 0
|
|
|
+ if (operateType == 'endFast') {
|
|
|
+ endTimestamp = fastData.fast.target_end_time
|
|
|
+ }
|
|
|
+
|
|
|
+ var duration = fastData.fast.target_duration
|
|
|
+
|
|
|
+ return <View className="modal_content">
|
|
|
+ <ConsolePicker ref={limitPickerRef}
|
|
|
+ themeColor={color}
|
|
|
+ title={title}
|
|
|
+ onCancel={() => {
|
|
|
+ setShowTimePicker(false)
|
|
|
+ }}
|
|
|
+ min={min}
|
|
|
+ max={max}
|
|
|
+ current={defaultTimestamp}
|
|
|
+ duration={duration}
|
|
|
+ endTimestamp={endTimestamp}
|
|
|
+ isFast={true}
|
|
|
+ isEnd={operateType == 'endFast'}
|
|
|
+ isTimeout={false}
|
|
|
+ isLoading={btnDisable}
|
|
|
+ onChange={(e) => {
|
|
|
+ pickerConfirm(e, null)
|
|
|
+ global.pauseIndexTimer = false
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ }
|
|
|
+
|
|
|
+ function pickerConfirm(t1: number, event: any) {
|
|
|
+ if (btnDisable) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ global.scenario = 'FAST'
|
|
|
+ setBtnDisable(true)
|
|
|
+
|
|
|
+ var date = new Date(t1)
|
|
|
+ var setDate = new Date(global.set_time);
|
|
|
+ date.setMilliseconds(setDate.getMilliseconds());
|
|
|
+ date.setSeconds(setDate.getSeconds());
|
|
|
+
|
|
|
+ t1 = date.getTime();
|
|
|
+
|
|
|
+ if (operateType == 'startFast') {
|
|
|
+ startFast(t1, fastData.fast.target_duration, event ? event : logEvent).then(res => {
|
|
|
+ setBtnDisable(false)
|
|
|
+ refresh()
|
|
|
+ setShowTimePicker(false)
|
|
|
+ }).catch(e => {
|
|
|
+ setBtnDisable(false)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ endFast(t1, event ? event : logEvent).then(res => {
|
|
|
+ setBtnDisable(false)
|
|
|
+ refresh()
|
|
|
+ setShowTimePicker(false)
|
|
|
+ }).catch(e => {
|
|
|
+ setBtnDisable(false)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (!loaded) {
|
|
|
return <View />
|
|
|
}
|
|
|
|
|
|
- return <View style={{ alignItems: 'center', display: 'flex', flexDirection: 'column' }}>
|
|
|
+ return <View style={{ alignItems: 'center', display: 'flex', flexDirection: 'column', width: rpxToPx(750), flexShrink: 0 }}>
|
|
|
|
|
|
<View style={{ width: rpxToPx(750), }} />
|
|
|
<View onClick={() => { setShowModal(true) }}>Fast Eat Night{props.count}</View>
|
|
|
@@ -257,34 +501,42 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
{
|
|
|
isFastMode && <Text>{getFastStatus()}</Text>
|
|
|
}
|
|
|
- <Text className="time1">{getFastTime()}</Text>
|
|
|
+ <Text className="time1">{isFastMode ? getFastTime() : getEatTime()}</Text>
|
|
|
<Text className="date1">{global.language == 'en' ? formatTime('dddd, MMM D') : formatTime('MMMD日 dddd')}</Text>
|
|
|
</View>
|
|
|
</View>
|
|
|
+ <View>{isFastMode?formatMilliseconds(fastData.fast.target_duration):formatMilliseconds(eatData.target_end_time-eatData.target_start_time)}</View>
|
|
|
{
|
|
|
isFastMode && <View>
|
|
|
<View className="log_row">
|
|
|
- <View className="schedule">
|
|
|
- <Text className="schedule_name">
|
|
|
- Fast starts:
|
|
|
- </Text>
|
|
|
- <Text className="schedule_time">
|
|
|
- {startScheduleTime}
|
|
|
- </Text>
|
|
|
- </View>
|
|
|
+ {
|
|
|
+ status == 'process' ? <View className="schedule_name">Fast starts</View> : <View className="schedule" onClick={tapFastStart}>
|
|
|
+ <Text className="schedule_name">
|
|
|
+ Fast starts:
|
|
|
+ </Text>
|
|
|
+ <Text className="schedule_time">
|
|
|
+ {startScheduleTime}
|
|
|
+ </Text>
|
|
|
+ </View>
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ status == 'process' ? <View className="schedule_time">{dayjs(fastData.fast.target_start_time).format('HH:mm')}</View> :
|
|
|
+ <View onClick={tapStartLog} className={status == 'new' ? "fast_log_btn" : "fast_log_btn fast_log_btn_disable"}>Log{status == 'new' && <View className="badge" />}</View>
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
- <View className="fast_log_btn">Log{status == 'new' && <View className="badge" />}</View>
|
|
|
</View>
|
|
|
<View className="log_row">
|
|
|
- <View className="schedule">
|
|
|
+ <View className="schedule" onClick={tapFastEnd}>
|
|
|
<Text className="schedule_name">
|
|
|
- Fast starts:
|
|
|
+ Fast ends:
|
|
|
</Text>
|
|
|
<Text className="schedule_time">
|
|
|
- {endScheduleTime}
|
|
|
+ {status == 'process' ?dayjs(fastData.fast.target_end_time).format('HH:mm'):endScheduleTime}
|
|
|
</Text>
|
|
|
</View>
|
|
|
- <View className="fast_log_btn">Log</View>
|
|
|
+ <View onClick={tapEndLog} className={status == 'process' ? "fast_log_btn" : "fast_log_btn fast_log_btn_disable"}>Log</View>
|
|
|
</View>
|
|
|
</View>
|
|
|
}
|
|
|
@@ -297,5 +549,8 @@ export default function MainFastEatCard(props: { count: any }) {
|
|
|
<View style={{ width: 100, height: 100, backgroundColor: 'red' }}>{props.count}</View>
|
|
|
</Modal>
|
|
|
}
|
|
|
+ {
|
|
|
+ showTimePicker && modalContent()
|
|
|
+ }
|
|
|
</View>
|
|
|
}
|