import { useAuthGuard } from '@/hooks/useAuthGuard';
import {
BMI_CATEGORIES,
canCalculateBMI,
getBMIResult,
type BMIResult
} from '@/utils/bmi';
import { Ionicons } from '@expo/vector-icons';
import React, { useState } from 'react';
import {
Modal,
Pressable,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import Toast from 'react-native-toast-message';
interface BMICardProps {
weight?: number;
height?: number;
style?: any;
}
export function BMICard({ weight, height, style }: BMICardProps) {
const { pushIfAuthedElseLogin } = useAuthGuard();
const [showInfoModal, setShowInfoModal] = useState(false);
const canCalculate = canCalculateBMI(weight, height);
let bmiResult: BMIResult | null = null;
if (canCalculate && weight && height) {
try {
bmiResult = getBMIResult(weight, height);
} catch (error) {
console.warn('BMI 计算错误:', error);
}
}
const handleGoToProfile = () => {
Toast.show({
text1: '请先登录',
type: 'info',
});
pushIfAuthedElseLogin('/profile/edit');
};
const handleShowInfoModal = () => {
setShowInfoModal(true);
};
const handleHideInfoModal = () => {
setShowInfoModal(false);
};
const renderContent = () => {
if (!canCalculate) {
// 缺少数据的情况
return (
BMI 指数
{!weight && !height ? '请完善身高和体重信息' :
!weight ? '请完善体重信息' : '请完善身高信息'}
前往完善
);
}
// 有完整数据的情况
return (
BMI 指数
{bmiResult?.value}
{bmiResult?.category.name}
{bmiResult?.description}
{bmiResult?.category.encouragement}
);
};
return (
<>
{renderContent()}
{/* BMI 信息弹窗 */}
e.stopPropagation()}>
BMI 指数说明
BMI(身体质量指数)是评估体重与身高关系的常用指标,计算公式为:体重(kg) ÷ 身高²(m)
BMI 分类标准
{BMI_CATEGORIES.map((category, index) => {
const colors = index === 0 ? { bg: '#FFF4E6', text: '#8B7355' } :
index === 1 ? { bg: '#E8F5E8', text: '#2D5016' } :
index === 2 ? { bg: '#FEF3C7', text: '#B45309' } :
{ bg: '#FEE2E2', text: '#B91C1C' };
return (
{category.name}
{category.range}
{category.advice}
);
})}
* BMI 仅供参考,不能完全反映身体健康状况。如有疑问,请咨询专业医生。
>
);
}
const styles = StyleSheet.create({
card: {
borderRadius: 22,
padding: 18,
marginBottom: 16,
overflow: 'hidden',
},
cardHeader: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 12,
},
titleRow: {
flexDirection: 'row',
alignItems: 'center',
},
iconSquare: {
width: 30,
height: 30,
borderRadius: 8,
backgroundColor: '#FFFFFF',
alignItems: 'center',
justifyContent: 'center',
marginRight: 10,
},
cardTitle: {
fontSize: 18,
fontWeight: '800',
color: '#192126',
},
infoButton: {
padding: 4,
},
// 缺少数据时的样式
incompleteContent: {
minHeight: 120,
backgroundColor: '#FFFFFF',
borderRadius: 22,
padding: 18,
margin: -18,
},
missingDataContainer: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#FEF3C7',
borderRadius: 12,
padding: 12,
marginBottom: 12,
},
missingDataText: {
fontSize: 14,
color: '#B45309',
fontWeight: '600',
marginLeft: 8,
flex: 1,
},
completeButton: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#F3F4F6',
borderRadius: 12,
paddingVertical: 12,
paddingHorizontal: 16,
},
completeButtonText: {
fontSize: 16,
fontWeight: '600',
color: '#6B7280',
marginRight: 4,
},
// 有完整数据时的样式
completeContent: {
minHeight: 120,
borderRadius: 22,
padding: 18,
margin: -18,
},
bmiValueContainer: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 8,
},
bmiValue: {
fontSize: 32,
fontWeight: '800',
marginRight: 12,
},
categoryBadge: {
paddingHorizontal: 12,
paddingVertical: 4,
borderRadius: 12,
},
categoryText: {
fontSize: 14,
fontWeight: '700',
},
bmiDescription: {
fontSize: 14,
fontWeight: '600',
marginBottom: 8,
},
encouragementText: {
fontSize: 13,
color: '#6B7280',
fontWeight: '500',
lineHeight: 18,
fontStyle: 'italic',
},
// 弹窗样式
modalBackdrop: {
flex: 1,
backgroundColor: 'rgba(0,0,0,0.6)',
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
modalContainer: {
width: '90%',
maxHeight: '85%',
backgroundColor: '#FFFFFF',
borderRadius: 24,
overflow: 'hidden',
elevation: 20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 8 },
shadowOpacity: 0.3,
shadowRadius: 20,
},
modalContent: {
maxHeight: '100%',
},
modalHeader: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
padding: 24,
borderBottomWidth: 1,
borderBottomColor: '#F3F4F6',
backgroundColor: '#FAFAFA',
},
modalTitle: {
fontSize: 22,
fontWeight: '800',
color: '#111827',
letterSpacing: -0.5,
},
closeButton: {
padding: 8,
borderRadius: 20,
backgroundColor: '#F3F4F6',
},
modalBody: {
paddingHorizontal: 24,
paddingVertical: 20,
},
modalDescription: {
fontSize: 16,
color: '#4B5563',
lineHeight: 26,
marginBottom: 28,
textAlign: 'center',
backgroundColor: '#F8FAFC',
padding: 16,
borderRadius: 12,
borderLeftWidth: 4,
borderLeftColor: '#3B82F6',
},
sectionTitle: {
fontSize: 20,
fontWeight: '800',
color: '#111827',
marginBottom: 16,
letterSpacing: -0.3,
},
categoryItem: {
borderRadius: 16,
padding: 20,
marginBottom: 16,
borderWidth: 1,
borderColor: 'rgba(0,0,0,0.05)',
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.05,
shadowRadius: 4,
elevation: 2,
},
categoryHeader: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 12,
},
categoryName: {
fontSize: 18,
fontWeight: '800',
letterSpacing: -0.2,
},
categoryRange: {
fontSize: 15,
fontWeight: '700',
backgroundColor: 'rgba(255,255,255,0.8)',
paddingHorizontal: 12,
paddingVertical: 4,
borderRadius: 20,
},
categoryAdvice: {
fontSize: 15,
color: '#374151',
lineHeight: 22,
fontWeight: '500',
},
disclaimer: {
fontSize: 13,
color: '#6B7280',
fontStyle: 'italic',
marginTop: 24,
textAlign: 'center',
backgroundColor: '#F9FAFB',
padding: 16,
borderRadius: 12,
lineHeight: 20,
},
});