import { Colors } from '@/constants/Colors'; import { ROUTES } from '@/constants/Routes'; import { useAppDispatch, useAppSelector } from '@/hooks/redux'; import { useAuthGuard } from '@/hooks/useAuthGuard'; import { useColorScheme } from '@/hooks/useColorScheme'; import { fetchWeightHistory } from '@/store/userSlice'; import { BMI_CATEGORIES } from '@/utils/bmi'; import { Ionicons } from '@expo/vector-icons'; import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect'; import { Image } from 'expo-image'; import { LinearGradient } from 'expo-linear-gradient'; import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Dimensions, Modal, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import Svg, { Circle, Path } from 'react-native-svg'; const { width: screenWidth } = Dimensions.get('window'); const CARD_WIDTH = screenWidth - 40; // Subtract left and right margins const CHART_WIDTH = CARD_WIDTH - 36; // Subtract card padding const CHART_HEIGHT = 60; const PADDING = 10; export function WeightHistoryCard() { const { t } = useTranslation(); const dispatch = useAppDispatch(); const userProfile = useAppSelector((s) => s.user.profile); const weightHistory = useAppSelector((s) => s.user.weightHistory); const [showBMIModal, setShowBMIModal] = useState(false); const isLgAvaliable = isLiquidGlassAvailable(); const { pushIfAuthedElseLogin, isLoggedIn } = useAuthGuard(); const colorScheme = useColorScheme(); const themeColors = Colors[colorScheme ?? 'light']; const hasWeight = userProfile?.weight && parseFloat(userProfile.weight) > 0; useEffect(() => { if (isLoggedIn) { loadWeightHistory(); } }, [userProfile?.weight, isLoggedIn]); const loadWeightHistory = async () => { try { await dispatch(fetchWeightHistory() as any).unwrap(); } catch (error) { console.error('Failed to load weight history:', error); } }; const navigateToCoach = () => { pushIfAuthedElseLogin(ROUTES.WEIGHT_RECORDS); }; const handleHideBMIModal = () => { setShowBMIModal(false); }; const navigateToWeightRecords = () => { pushIfAuthedElseLogin(ROUTES.WEIGHT_RECORDS); }; // Process weight history data const sortedHistory = [...weightHistory] .sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()) .slice(-7); // Show only the last 7 records // return ( // // // {t('statistics.components.weight.title')} // // // // No weight records yet, click the button below to start recording // // { // e.stopPropagation(); // navigateToCoach(); // }} // activeOpacity={0.8} // > // // {t('statistics.components.weight.addButton')} // // // // ); // } // Generate chart data const weights = sortedHistory.map(item => parseFloat(item.weight)); const minWeight = Math.min(...weights); const maxWeight = Math.max(...weights); const weightRange = maxWeight - minWeight || 1; const points = sortedHistory.map((item, index) => { const x = PADDING + (index / Math.max(sortedHistory.length - 1, 1)) * (CHART_WIDTH - 2 * PADDING); const normalizedWeight = (parseFloat(item.weight) - minWeight) / weightRange; // Reduce top margin, compress whitespace const y = PADDING + 8 + (1 - normalizedWeight) * (CHART_HEIGHT - 2 * PADDING - 16); return { x, y, weight: item.weight, date: item.createdAt }; }); // Generate path const pathData = points.map((point, index) => { if (index === 0) return `M ${point.x} ${point.y}`; return `L ${point.x} ${point.y}`; }).join(' '); // If there's only one data point, display as a horizontal line const singlePointPath = points.length === 1 ? `M ${PADDING} ${points[0].y} L ${CHART_WIDTH - PADDING} ${points[0].y}` : pathData; return ( {t('statistics.components.weight.title')} {isLgAvaliable ? ( { e.stopPropagation(); navigateToCoach(); }} activeOpacity={0.8} > ) : ( { e.stopPropagation(); navigateToCoach(); }} activeOpacity={0.8} > )} {/* Default chart display */} {sortedHistory.length > 0 && ( {/* Background grid lines */} {/* More abstract line - reduce line width and display details */} {/* Simplified data points - smaller and more refined */} {points.map((point, index) => { const isLastPoint = index === points.length - 1; return ( ); })} {/* Concise chart information */} {userProfile.weight}kg {sortedHistory.length}{t('statistics.components.weight.days')} {minWeight.toFixed(1)}-{maxWeight.toFixed(1)}kg )} {/* BMI information modal */} {/* Title */} {t('statistics.components.weight.bmiModal.title')} {/* Introduction section */} {t('statistics.components.weight.bmiModal.description')} {t('statistics.components.weight.bmiModal.formula')} {/* BMI classification standards */} {t('statistics.components.weight.bmiModal.classificationTitle')} {BMI_CATEGORIES.map((category, index) => { const colors = [ { bg: '#FEF3C7', text: '#B45309', border: '#F59E0B' }, // Underweight { bg: '#E8F5E8', text: Colors.light.accentGreen, border: Colors.light.accentGreen }, // Normal { bg: '#FEF3C7', text: '#B45309', border: '#F59E0B' }, // Overweight { bg: '#FEE2E2', text: '#B91C1C', border: '#EF4444' } // Obese ][index]; return ( {category.name} {category.range} {category.advice} ); })} {/* Health tips */} {t('statistics.components.weight.bmiModal.healthTipsTitle')} {t('statistics.components.weight.bmiModal.tips.nutrition')} {t('statistics.components.weight.bmiModal.tips.exercise')} {t('statistics.components.weight.bmiModal.tips.sleep')} {t('statistics.components.weight.bmiModal.tips.monitoring')} {/* Disclaimer */} {t('statistics.components.weight.bmiModal.disclaimer')} {/* Bottom continue button */} {t('statistics.components.weight.bmiModal.continueButton')} ); } const styles = StyleSheet.create({ card: { backgroundColor: '#FFFFFF', borderRadius: 22, padding: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 8, elevation: 3, marginTop: 16 }, cardHeader: { flexDirection: 'row', alignItems: 'center', }, iconSquare: { width: 14, height: 14, borderRadius: 8, alignItems: 'center', justifyContent: 'center', marginRight: 4, }, cardTitle: { fontSize: 14, color: '#192126', flex: 1, fontWeight: '600' }, headerButtons: { flexDirection: 'row', alignItems: 'center', gap: 8, }, chartToggleButton: { width: 28, height: 28, borderRadius: 14, alignItems: 'center', justifyContent: 'center', }, addButton: { width: 28, height: 28, borderRadius: 14, alignItems: 'center', justifyContent: 'center', }, addButtonGlass: { width: 28, height: 28, borderRadius: 14, alignItems: 'center', justifyContent: 'center', backgroundColor: 'rgba(147, 112, 219, 0.3)', }, emptyContent: { alignItems: 'center', }, emptyTitle: { fontSize: 16, fontWeight: '700', color: '#192126', marginBottom: 6, }, emptyDescription: { fontSize: 14, color: '#687076', textAlign: 'center', marginBottom: 16, lineHeight: 20, }, recordButton: { flexDirection: 'row', alignItems: 'center', backgroundColor: Colors.light.accentGreen, paddingHorizontal: 16, paddingVertical: 10, borderRadius: 20, gap: 6, }, recordButtonText: { color: '#192126', fontSize: 14, fontWeight: '700', }, chartContainer: { width: '100%', alignItems: 'center', marginTop: 12, }, chartInfo: { flexDirection: 'row', justifyContent: 'space-around', width: '100%', }, infoItem: { alignItems: 'center', }, infoLabel: { fontSize: 11, color: '#687076', fontWeight: '500', }, infoValue: { fontSize: 14, fontWeight: '700', color: '#192126', }, // BMI modal styles bmiModalContainer: { flex: 1, }, bmiModalContent: { flex: 1, padding: 20, }, bmiModalTitle: { fontSize: 28, fontWeight: '800', color: '#111827', textAlign: 'center', marginBottom: 24, letterSpacing: -0.5, }, bmiModalIntroSection: { marginBottom: 32, }, bmiModalDescription: { fontSize: 16, color: '#374151', lineHeight: 24, textAlign: 'center', marginBottom: 16, }, bmiModalFormulaContainer: { backgroundColor: '#F3F4F6', borderRadius: 12, padding: 16, alignItems: 'center', }, bmiModalFormulaText: { fontSize: 14, fontWeight: '600', color: '#374151', }, bmiModalSectionTitle: { fontSize: 20, fontWeight: '700', color: '#111827', marginBottom: 16, letterSpacing: -0.5, }, bmiModalStatsCard: { marginBottom: 32, }, bmiModalStatItem: { borderRadius: 12, padding: 16, marginBottom: 12, borderWidth: 1, }, bmiModalStatHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8, }, bmiModalStatTitle: { fontSize: 16, fontWeight: '700', }, bmiModalStatRange: { fontSize: 14, fontWeight: '600', }, bmiModalStatAdvice: { fontSize: 14, lineHeight: 20, }, bmiModalHealthTips: { marginBottom: 32, }, bmiModalTipsItem: { flexDirection: 'row', alignItems: 'center', marginBottom: 16, paddingHorizontal: 16, paddingVertical: 12, backgroundColor: '#F8FAFC', borderRadius: 12, }, bmiModalTipsText: { fontSize: 14, color: '#374151', marginLeft: 12, flex: 1, lineHeight: 20, }, bmiModalDisclaimer: { flexDirection: 'row', alignItems: 'flex-start', backgroundColor: '#FEF3C7', borderRadius: 12, padding: 16, marginBottom: 20, }, bmiModalDisclaimerText: { fontSize: 13, color: '#B45309', marginLeft: 8, flex: 1, lineHeight: 18, }, bmiModalBottomContainer: { padding: 20, paddingBottom: 34, }, bmiModalContinueButton: { marginBottom: 8, }, bmiModalButtonBackground: { backgroundColor: '#192126', borderRadius: 16, paddingVertical: 16, alignItems: 'center', }, bmiModalButtonText: { fontSize: 16, fontWeight: '700', color: '#FFFFFF', }, bmiModalHomeIndicator: { height: 5, backgroundColor: '#D1D5DB', borderRadius: 3, alignSelf: 'center', width: 36, }, });