feat(challenges): 支持即将开始与已结束挑战的禁用态及睡眠挑战自动进度上报
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
|
||||
import { ChallengeType } from '@/services/challengesApi';
|
||||
import { reportChallengeProgress, selectChallengeList } from '@/store/challengesSlice';
|
||||
import { logger } from '@/utils/logger';
|
||||
import { fetchCompleteSleepData, formatSleepTime } from '@/utils/sleepHealthKit';
|
||||
import dayjs from 'dayjs';
|
||||
import { Image } from 'expo-image';
|
||||
import { router } from 'expo-router';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||
|
||||
|
||||
@@ -15,8 +19,15 @@ const SleepCard: React.FC<SleepCardProps> = ({
|
||||
selectedDate,
|
||||
style,
|
||||
}) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const challenges = useAppSelector(selectChallengeList);
|
||||
const [sleepDuration, setSleepDuration] = useState<number | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const joinedSleepChallenges = useMemo(
|
||||
() => challenges.filter((challenge) => challenge.type === ChallengeType.SLEEP && challenge.isJoined),
|
||||
[challenges]
|
||||
);
|
||||
const lastReportedRef = useRef<{ date: string; value: number | null } | null>(null);
|
||||
|
||||
// 获取睡眠数据
|
||||
useEffect(() => {
|
||||
@@ -38,6 +49,41 @@ const SleepCard: React.FC<SleepCardProps> = ({
|
||||
loadSleepData();
|
||||
}, [selectedDate]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedDate || !sleepDuration || !joinedSleepChallenges.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果当前日期不是今天,不上报
|
||||
if (!dayjs(selectedDate).isSame(dayjs(), 'day')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dateKey = dayjs(selectedDate).format('YYYY-MM-DD');
|
||||
const lastReport = lastReportedRef.current;
|
||||
|
||||
if (lastReport && lastReport.date === dateKey && lastReport.value === sleepDuration) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reportProgress = async () => {
|
||||
const sleepChallenge = joinedSleepChallenges.find((c) => c.type === ChallengeType.SLEEP);
|
||||
if (!sleepChallenge) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await dispatch(reportChallengeProgress({ id: sleepChallenge.id, value: sleepDuration })).unwrap();
|
||||
} catch (error) {
|
||||
logger.warn('SleepCard: 挑战进度上报失败', { error, challengeId: sleepChallenge.id });
|
||||
}
|
||||
|
||||
lastReportedRef.current = { date: dateKey, value: sleepDuration };
|
||||
};
|
||||
|
||||
reportProgress();
|
||||
}, [dispatch, joinedSleepChallenges, selectedDate, sleepDuration]);
|
||||
|
||||
const CardContent = (
|
||||
<View style={[styles.container, style]}>
|
||||
<View style={styles.cardHeaderRow}>
|
||||
@@ -88,4 +134,4 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
export default SleepCard;
|
||||
export default SleepCard;
|
||||
|
||||
Reference in New Issue
Block a user