feat: 更新健康数据管理功能及相关组件
- 新增 healthSlice,用于管理健康数据的 Redux 状态 - 在 Statistics 组件中整合健康数据获取逻辑,优化数据展示 - 更新 NutritionRadarCard 组件,调整卡路里计算区域,提升用户体验 - 移除不必要的状态管理,简化组件逻辑 - 优化代码结构,提升可读性和维护性
This commit is contained in:
126
store/healthSlice.ts
Normal file
126
store/healthSlice.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import { AppDispatch, RootState } from './index';
|
||||
|
||||
// 健康数据类型定义
|
||||
export interface FitnessRingsData {
|
||||
activeCalories: number;
|
||||
activeCaloriesGoal: number;
|
||||
exerciseMinutes: number;
|
||||
exerciseMinutesGoal: number;
|
||||
standHours: number;
|
||||
standHoursGoal: number;
|
||||
}
|
||||
|
||||
export interface HealthData {
|
||||
steps: number | null;
|
||||
activeCalories: number | null;
|
||||
basalEnergyBurned: number | null;
|
||||
sleepDuration: number | null;
|
||||
hrv: number | null;
|
||||
oxygenSaturation: number | null;
|
||||
heartRate: number | null;
|
||||
activeEnergyBurned: number;
|
||||
activeCaloriesGoal: number;
|
||||
exerciseMinutes: number;
|
||||
exerciseMinutesGoal: number;
|
||||
standHours: number;
|
||||
standHoursGoal: number;
|
||||
}
|
||||
|
||||
export interface HealthState {
|
||||
// 按日期存储的历史数据
|
||||
dataByDate: Record<string, HealthData>;
|
||||
|
||||
// 加载状态
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
|
||||
// 最后更新时间
|
||||
lastUpdateTime: string | null;
|
||||
}
|
||||
|
||||
// 初始状态
|
||||
const initialState: HealthState = {
|
||||
dataByDate: {},
|
||||
loading: false,
|
||||
error: null,
|
||||
lastUpdateTime: null,
|
||||
};
|
||||
|
||||
const healthSlice = createSlice({
|
||||
name: 'health',
|
||||
initialState,
|
||||
reducers: {
|
||||
// 设置加载状态
|
||||
setLoading: (state, action: PayloadAction<boolean>) => {
|
||||
state.loading = action.payload;
|
||||
},
|
||||
|
||||
// 设置错误信息
|
||||
setError: (state, action: PayloadAction<string | null>) => {
|
||||
state.error = action.payload;
|
||||
},
|
||||
|
||||
// 设置完整的健康数据
|
||||
setHealthData: (state, action: PayloadAction<{
|
||||
date: string;
|
||||
data: HealthData;
|
||||
}>) => {
|
||||
const { date, data } = action.payload;
|
||||
|
||||
// 存储到历史数据
|
||||
state.dataByDate[date] = data;
|
||||
|
||||
state.lastUpdateTime = new Date().toISOString();
|
||||
},
|
||||
|
||||
// 清除特定日期的数据
|
||||
clearHealthDataForDate: (state, action: PayloadAction<string>) => {
|
||||
const date = action.payload;
|
||||
delete state.dataByDate[date];
|
||||
|
||||
},
|
||||
|
||||
// 清除所有健康数据
|
||||
clearAllHealthData: (state) => {
|
||||
state.dataByDate = {};
|
||||
state.error = null;
|
||||
state.lastUpdateTime = null;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators
|
||||
export const {
|
||||
setLoading,
|
||||
setError,
|
||||
setHealthData,
|
||||
clearHealthDataForDate,
|
||||
clearAllHealthData,
|
||||
} = healthSlice.actions;
|
||||
|
||||
// Thunk action to fetch and set health data for a specific date
|
||||
export const fetchHealthDataForDate = (date: Date) => {
|
||||
return async (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
try {
|
||||
dispatch(setLoading(true));
|
||||
dispatch(setError(null));
|
||||
|
||||
// 这里可以添加实际的 API 调用逻辑
|
||||
// 目前我们假设数据已经通过其他方式获取
|
||||
|
||||
dispatch(setLoading(false));
|
||||
} catch (error) {
|
||||
dispatch(setError(error instanceof Error ? error.message : '获取健康数据失败'));
|
||||
dispatch(setLoading(false));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Selectors
|
||||
export const selectHealthDataByDate = (date: string) => (state: RootState) => state.health.dataByDate[date];
|
||||
export const selectHealthLoading = (state: RootState) => state.health.loading;
|
||||
export const selectHealthError = (state: RootState) => state.health.error;
|
||||
export const selectLastUpdateTime = (state: RootState) => state.health.lastUpdateTime;
|
||||
|
||||
export default healthSlice.reducer;
|
||||
Reference in New Issue
Block a user