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 && (
{/* 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,
},
});