Files
digital-pilates/components/StepsCard.tsx

152 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useMemo } from 'react';
import {
StyleSheet,
Text,
View,
ViewStyle
} from 'react-native';
import { HourlyStepData } from '@/utils/health';
// 使用原生View来替代SVG避免导入问题
// import Svg, { Rect } from 'react-native-svg';
interface StepsCardProps {
stepCount: number | null;
stepGoal: number;
hourlySteps: HourlyStepData[];
style?: ViewStyle;
}
const StepsCard: React.FC<StepsCardProps> = ({
stepCount,
stepGoal,
hourlySteps,
style
}) => {
// 计算柱状图数据
const chartData = useMemo(() => {
if (!hourlySteps || hourlySteps.length === 0) {
return Array.from({ length: 24 }, (_, i) => ({ hour: i, steps: 0, height: 0 }));
}
// 找到最大步数用于计算高度比例
const maxSteps = Math.max(...hourlySteps.map(data => data.steps), 1);
const maxHeight = 20; // 柱状图最大高度(缩小一半)
return hourlySteps.map(data => ({
...data,
height: maxSteps > 0 ? (data.steps / maxSteps) * maxHeight : 0
}));
}, [hourlySteps]);
// 获取当前小时
const currentHour = new Date().getHours();
return (
<View style={[styles.container, style]}>
{/* 标题和步数显示 */}
<View style={styles.header}>
<Text style={styles.title}></Text>
</View>
{/* 柱状图 */}
<View style={styles.chartContainer}>
<View style={styles.chartWrapper}>
<View style={styles.chartArea}>
{chartData.map((data, index) => {
// 判断是否是当前小时或者有活动的小时
const isActive = data.steps > 0;
const isCurrent = index <= currentHour;
return (
<View
key={`bar-${index}`}
style={[
styles.chartBar,
{
height: data.height || 2, // 最小高度2px
backgroundColor: isCurrent && isActive ? '#FFC365' : '#FFEBCB',
}
]}
/>
);
})}
</View>
</View>
</View>
{/* 步数和目标显示 */}
<View style={styles.statsContainer}>
<Text style={styles.stepCount}>
{stepCount !== null ? stepCount.toLocaleString() : '——'}
</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-between',
borderRadius: 20,
padding: 16,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 4,
},
shadowOpacity: 0.08,
shadowRadius: 20,
elevation: 8,
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
title: {
fontSize: 16,
fontWeight: '700',
color: '#192126',
},
footprintIcons: {
flexDirection: 'row',
alignItems: 'center',
gap: 6,
},
chartContainer: {
flex: 1,
justifyContent: 'center',
},
chartWrapper: {
width: '100%',
alignItems: 'center',
},
chartArea: {
flexDirection: 'row',
alignItems: 'flex-end',
height: 20,
width: '100%',
maxWidth: 240,
justifyContent: 'space-between',
paddingHorizontal: 4,
},
chartBar: {
width: 4,
borderRadius: 1,
alignSelf: 'flex-end',
},
statsContainer: {
alignItems: 'flex-start',
marginTop: 6
},
stepCount: {
fontSize: 18,
fontWeight: '600',
color: '#192126',
},
});
export default StepsCard;