Files
digital-pilates/components/BasalMetabolismCard.tsx
richarjiang fb85a5f30c refactor(health): remove basalEnergyBurned from global state and move to local component
Remove basalEnergyBurned from global health data structure and refactor BasalMetabolismCard to fetch its own data locally. This decouples the component from global state and improves data locality.

- Remove basalEnergyBurned from HealthData interface and health utilities
- Update BasalMetabolismCard to use selectedDate prop and fetch data locally
- Simplify statistics screen by removing unused basalMetabolism variable
- Update nutrition radar card to use activeCalories only for burned calories calculation
2025-09-19 17:01:45 +08:00

172 lines
4.2 KiB
TypeScript

import { fetchHealthDataForDate } from '@/utils/health';
import { Image } from 'expo-image';
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
interface BasalMetabolismCardProps {
selectedDate?: Date;
style?: any;
}
export function BasalMetabolismCard({ selectedDate, style }: BasalMetabolismCardProps) {
const [basalMetabolism, setBasalMetabolism] = useState<number | null>(null);
const [loading, setLoading] = useState(false);
// 获取基础代谢数据
useEffect(() => {
const loadBasalMetabolismData = async () => {
if (!selectedDate) return;
try {
setLoading(true);
const data = await fetchHealthDataForDate(selectedDate);
setBasalMetabolism(data?.basalEnergyBurned || null);
} catch (error) {
console.error('BasalMetabolismCard: 获取基础代谢数据失败:', error);
setBasalMetabolism(null);
} finally {
setLoading(false);
}
};
loadBasalMetabolismData();
}, [selectedDate]);
// 获取基础代谢状态描述
const getMetabolismStatus = () => {
if (basalMetabolism === null || basalMetabolism === 0) {
return { text: '未知', color: '#9AA3AE' };
}
// 基于常见的基础代谢范围来判断状态
if (basalMetabolism >= 1800) {
return { text: '高代谢', color: '#10B981' };
} else if (basalMetabolism >= 1400) {
return { text: '正常', color: '#3B82F6' };
} else if (basalMetabolism >= 1000) {
return { text: '偏低', color: '#F59E0B' };
} else {
return { text: '较低', color: '#EF4444' };
}
};
const status = getMetabolismStatus();
return (
<View style={[styles.container, style]}>
{/* 头部区域 */}
<View style={styles.header}>
<View style={styles.leftSection}>
<Image
source={require('@/assets/images/icons/icon-fire.png')}
style={styles.titleIcon}
/>
<Text style={styles.title}></Text>
</View>
<View style={[styles.statusBadge, { backgroundColor: status.color + '20' }]}>
<Text style={[styles.statusText, { color: status.color }]}>{status.text}</Text>
</View>
</View>
{/* 数值显示区域 */}
<View style={styles.valueSection}>
<Text style={styles.value}>
{loading ? '加载中...' : (basalMetabolism != null && basalMetabolism > 0 ? Math.round(basalMetabolism).toString() : '--')}
</Text>
<Text style={styles.unit}>/</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#FFFFFF',
borderRadius: 20,
padding: 16,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 4,
},
shadowOpacity: 0.08,
shadowRadius: 12,
elevation: 4,
position: 'relative',
overflow: 'hidden',
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 16,
zIndex: 1,
},
leftSection: {
flexDirection: 'row',
alignItems: 'center',
},
iconContainer: {
width: 32,
height: 32,
borderRadius: 10,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
marginRight: 8,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 1,
},
fireIcon: {
width: 14,
height: 18,
backgroundColor: '#EF4444',
borderTopLeftRadius: 7,
borderTopRightRadius: 7,
borderBottomLeftRadius: 2,
borderBottomRightRadius: 2,
},
title: {
fontSize: 14,
color: '#0F172A',
fontWeight: '600',
},
titleIcon: {
width: 16,
height: 16,
marginRight: 4,
},
statusBadge: {
paddingHorizontal: 8,
paddingVertical: 4,
borderRadius: 12,
},
statusText: {
fontSize: 11,
fontWeight: '600',
},
valueSection: {
flexDirection: 'row',
alignItems: 'center',
zIndex: 1,
},
value: {
fontSize: 16,
fontWeight: '600',
color: '#0F172A',
lineHeight: 28,
},
unit: {
fontSize: 12,
color: '#64748B',
marginLeft: 6,
},
});