Files
digital-pilates/components/StressAnalysisModal.tsx
richarjiang d76ba48424 feat(ui): 统一应用主题色为天空蓝并优化渐变背景
将应用主色调从 '#BBF246' 更改为 '#87CEEB'(天空蓝),并更新所有相关组件和页面中的颜色引用。同时为多个页面添加统一的渐变背景,提升视觉效果和用户体验。新增压力分析模态框组件,并优化压力计组件的交互与显示逻辑。更新应用图标和启动图资源。
2025-08-20 09:38:25 +08:00

267 lines
7.1 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
import { LinearGradient } from 'expo-linear-gradient';
import React from 'react';
import {
Modal,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
interface StressAnalysisModalProps {
visible: boolean;
onClose: () => void;
hrvValue: number;
updateTime: Date;
}
export function StressAnalysisModal({ visible, onClose, hrvValue, updateTime }: StressAnalysisModalProps) {
const colorScheme = useColorScheme();
const colors = Colors[colorScheme ?? 'light'];
// 模拟30天HRV数据
const hrvData = {
goodEvents: { percentage: 26, count: 53, range: '>80毫秒' },
energetic: { percentage: 47, count: 97, range: '43-80毫秒' },
stressed: { percentage: 27, count: 56, range: '<43毫秒' },
};
return (
<Modal
visible={visible}
animationType="slide"
presentationStyle="pageSheet"
onRequestClose={onClose}
>
<LinearGradient
colors={[colors.backgroundGradientStart, colors.backgroundGradientEnd]}
style={styles.modalContainer}
start={{ x: 0, y: 0 }}
end={{ x: 0, y: 1 }}
>
<ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
{/* 标题 */}
<Text style={styles.title}></Text>
{/* 最近30天HRV情况 */}
<Text style={styles.sectionTitle}>30HRV情况</Text>
{/* 彩色横条图 */}
<View style={styles.chartContainer}>
<View style={styles.colorBar}>
<LinearGradient
colors={['#10B981', '#3B82F6', '#F59E0B']}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={styles.gradientBar}
/>
</View>
<View style={styles.legend}>
<View style={styles.legendItem}>
<View style={[styles.legendDot, { backgroundColor: '#10B981' }]} />
<Text style={styles.legendText}></Text>
</View>
<View style={styles.legendItem}>
<View style={[styles.legendDot, { backgroundColor: '#3B82F6' }]} />
<Text style={styles.legendText}></Text>
</View>
<View style={styles.legendItem}>
<View style={[styles.legendDot, { backgroundColor: '#F59E0B' }]} />
<Text style={styles.legendText}></Text>
</View>
</View>
</View>
{/* 数据统计卡片 */}
<View style={styles.statsCard}>
{/* 好事发生 & 活力满满 */}
<View style={styles.statsRow}>
<View style={styles.statItem}>
<Text style={[styles.statTitle, { color: '#10B981' }]}></Text>
<Text style={styles.statPercentage}>{hrvData.goodEvents.percentage}%</Text>
<View style={styles.statDetails}>
<Text style={styles.statRange}> {hrvData.goodEvents.range}</Text>
</View>
<Text style={styles.statCount}>{hrvData.goodEvents.count}</Text>
</View>
<View style={styles.statItem}>
<Text style={[styles.statTitle, { color: '#3B82F6' }]}></Text>
<Text style={styles.statPercentage}>{hrvData.energetic.percentage}%</Text>
<View style={styles.statDetails}>
<Text style={styles.statRange}> {hrvData.energetic.range}</Text>
</View>
<Text style={styles.statCount}>{hrvData.energetic.count}</Text>
</View>
</View>
{/* 鸭梨山大 */}
<View style={styles.statItem}>
<Text style={[styles.statTitle, { color: '#F59E0B' }]}></Text>
<Text style={styles.statPercentage}>{hrvData.stressed.percentage}%</Text>
<View style={styles.statDetails}>
<Text style={styles.statRange}> {hrvData.stressed.range}</Text>
</View>
<Text style={styles.statCount}>{hrvData.stressed.count}</Text>
</View>
</View>
</ScrollView>
{/* 底部继续按钮 */}
<View style={styles.bottomContainer}>
<TouchableOpacity style={styles.continueButton} onPress={onClose}>
<View style={styles.buttonBackground}>
<Text style={styles.buttonText}></Text>
</View>
</TouchableOpacity>
<View style={styles.homeIndicator} />
</View>
</LinearGradient>
</Modal>
);
}
const styles = StyleSheet.create({
modalContainer: {
flex: 1,
},
content: {
flex: 1,
paddingHorizontal: 20,
},
title: {
fontSize: 24,
fontWeight: '800',
color: '#111827',
textAlign: 'center',
marginTop: 20,
marginBottom: 32,
},
sectionTitle: {
fontSize: 22,
fontWeight: '800',
color: '#111827',
marginBottom: 20,
},
chartContainer: {
marginBottom: 32,
},
colorBar: {
height: 16,
borderRadius: 8,
overflow: 'hidden',
marginBottom: 16,
},
gradientBar: {
flex: 1,
},
legend: {
flexDirection: 'row',
justifyContent: 'space-around',
},
legendItem: {
flexDirection: 'row',
alignItems: 'center',
},
legendDot: {
width: 12,
height: 12,
borderRadius: 6,
marginRight: 6,
},
legendText: {
fontSize: 14,
fontWeight: '600',
color: '#374151',
},
statsCard: {
backgroundColor: '#FFFFFF',
borderRadius: 16,
padding: 20,
marginBottom: 32,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.05,
shadowRadius: 8,
elevation: 2,
},
statsRow: {
flexDirection: 'row',
gap: 20,
marginBottom: 24,
},
statItem: {
flex: 1,
},
statTitle: {
fontSize: 16,
fontWeight: '700',
marginBottom: 8,
},
statPercentage: {
fontSize: 36,
fontWeight: '800',
color: '#111827',
marginBottom: 4,
},
statDetails: {
marginBottom: 4,
},
statRange: {
fontSize: 14,
fontWeight: '600',
color: '#DC2626',
backgroundColor: '#FEE2E2',
paddingHorizontal: 8,
paddingVertical: 3,
borderRadius: 10,
alignSelf: 'flex-start',
},
statCount: {
fontSize: 16,
fontWeight: '600',
color: '#6B7280',
},
bottomContainer: {
paddingHorizontal: 20,
paddingBottom: 34,
},
continueButton: {
borderRadius: 25,
overflow: 'hidden',
marginBottom: 8,
},
buttonGradient: {
paddingVertical: 18,
alignItems: 'center',
justifyContent: 'center',
},
buttonBackground: {
backgroundColor: Colors.light.accentGreen, // 应用主色调
paddingVertical: 18,
alignItems: 'center',
justifyContent: 'center',
},
buttonText: {
fontSize: 18,
fontWeight: '700',
color: '#192126', // 主色调上的文字颜色
},
homeIndicator: {
width: 134,
height: 5,
backgroundColor: '#000',
borderRadius: 3,
alignSelf: 'center',
},
});