import { ThemedText } from '@/components/ThemedText'; import { useThemeColor } from '@/hooks/useThemeColor'; import { DietRecord } from '@/services/dietRecords'; import { Ionicons } from '@expo/vector-icons'; import dayjs from 'dayjs'; import React, { useMemo, useState, useRef } from 'react'; import { Image, StyleSheet, TouchableOpacity, View } from 'react-native'; import Popover from 'react-native-popover-view'; export type NutritionRecordCardProps = { record: DietRecord; onPress?: () => void; onDelete?: () => void; showTimeline?: boolean; isFirst?: boolean; isLast?: boolean; }; const MEAL_TYPE_LABELS = { breakfast: '早餐', lunch: '午餐', dinner: '晚餐', snack: '加餐', other: '其他', } as const; const MEAL_TYPE_ICONS = { breakfast: 'sunny-outline', lunch: 'partly-sunny-outline', dinner: 'moon-outline', snack: 'cafe-outline', other: 'restaurant-outline', } as const; const MEAL_TYPE_COLORS = { breakfast: '#FFB366', lunch: '#4ECDC4', dinner: '#5D5FEF', snack: '#FF6B6B', other: '#9AA3AE', } as const; export function NutritionRecordCard({ record, onPress, onDelete, showTimeline = false, isFirst = false, isLast = false }: NutritionRecordCardProps) { const surfaceColor = useThemeColor({}, 'surface'); const textColor = useThemeColor({}, 'text'); const textSecondaryColor = useThemeColor({}, 'textSecondary'); const primaryColor = useThemeColor({}, 'primary'); // Popover 状态管理 const [showPopover, setShowPopover] = useState(false); const popoverRef = useRef(null); // 营养数据统计 const nutritionStats = useMemo(() => { return [ { label: '热量', value: record.estimatedCalories ? `${Math.round(record.estimatedCalories)} 千卡` : '-', icon: 'flame-outline' as const, color: '#FF6B6B' }, { label: '蛋白质', value: record.proteinGrams ? `${record.proteinGrams.toFixed(1)} g` : '-', icon: 'fitness-outline' as const, color: '#4ECDC4' }, { label: '碳水', value: record.carbohydrateGrams ? `${record.carbohydrateGrams.toFixed(1)} g` : '-', icon: 'leaf-outline' as const, color: '#45B7D1' }, { label: '脂肪', value: record.fatGrams ? `${record.fatGrams.toFixed(1)} g` : '-', icon: 'water-outline' as const, color: '#FFA07A' }, ]; }, [record]); const mealTypeColor = MEAL_TYPE_COLORS[record.mealType]; const mealTypeIcon = MEAL_TYPE_ICONS[record.mealType]; const mealTypeLabel = MEAL_TYPE_LABELS[record.mealType]; return ( {/* 时间轴 */} {showTimeline && ( {record.createdAt ? dayjs(record.createdAt).format('HH:mm') : '--:--'} {!isLast && ( )} )} {/* 卡片内容 */} {/* 主要内容区域 */} {!showTimeline && ( {record.mealTime ? dayjs(record.mealTime).format('HH:mm') : '时间未设置'} )} { setShowPopover(true) console.log('showPopover', showPopover) }} > {/* 食物名称和分量 */} {/* 左侧:食物图片 */} {record.imageUrl ? ( ) : ( )} {record.foodName} {(record.weightGrams || record.portionDescription) && ( {record.portionDescription || `${record.weightGrams}g`} )} {mealTypeLabel} {/* 营养信息 - 紧凑标签布局 */} {nutritionStats.map((stat, index) => ( {stat.label} {stat.value} ))} {/* 备注信息 */} {record.notes && ( {record.notes} )} {/* Popover for more options */} setShowPopover(false)} popoverStyle={styles.popoverContainer} backgroundStyle={styles.popoverBackground} > { setShowPopover(false); onDelete?.(); }} > 删除记录 ); } const styles = StyleSheet.create({ timelineContainer: { flexDirection: 'row', marginBottom: 12, }, timelineColumn: { width: 52, alignItems: 'center', paddingTop: 6, }, timeContainer: { marginBottom: 6, }, timeText: { fontSize: 11, fontWeight: '600', textAlign: 'center', }, timelineNode: { alignItems: 'center', flex: 1, }, timelineDot: { width: 20, height: 20, borderRadius: 10, justifyContent: 'center', alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.08, shadowRadius: 3, elevation: 1, }, timelineLine: { width: 1.5, flex: 1, marginTop: 6, opacity: 0.25, }, card: { flex: 1, borderRadius: 16, padding: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.06, shadowRadius: 8, elevation: 2, }, cardWithTimeline: { marginLeft: 6, }, mainContent: { flexDirection: 'row', }, foodImageContainer: { width: 28, height: 28, borderRadius: 16, marginRight: 8, overflow: 'hidden', }, foodImage: { width: '100%', height: '100%', }, foodImagePlaceholder: { backgroundColor: '#F8F9FA', justifyContent: 'center', alignItems: 'center', }, foodInfoContainer: { flex: 1, }, headerRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 8, position: 'absolute', top: 0, right: 0, zIndex: 1, }, mealTypeContainer: { flex: 1, }, mealTypeBadge: { paddingHorizontal: 4, borderRadius: 8, marginLeft: 4, }, mealTypeText: { fontSize: 8, fontWeight: '600', }, mealTime: { fontSize: 11, fontWeight: '500', }, moreButton: { padding: 4, marginLeft: 8, zIndex: 1, }, foodNameSection: { marginBottom: 12, flexDirection: 'row', gap: 4, alignItems: 'center', }, foodName: { fontSize: 18, fontWeight: '700', lineHeight: 24, marginBottom: 2, }, portionInfo: { fontSize: 12, fontWeight: '500', }, nutritionContainer: { flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-between', }, nutritionTag: { flexDirection: 'row', alignItems: 'center', backgroundColor: 'rgba(248, 249, 250, 0.8)', borderRadius: 8, paddingHorizontal: 8, paddingVertical: 2, marginBottom: 4, width: '48%', overflow: 'hidden', }, nutritionText: { fontSize: 9, fontWeight: '500', marginLeft: 4, marginRight: 2, flexShrink: 0, }, nutritionValue: { fontSize: 10, fontWeight: '700', flexShrink: 1, textAlign: 'right', flex: 1, }, notesSection: { marginTop: 8, paddingTop: 12, borderTopWidth: 1, borderTopColor: 'rgba(0,0,0,0.06)', }, notesText: { fontSize: 13, fontWeight: '500', lineHeight: 18, fontStyle: 'italic', }, popoverContainer: { borderRadius: 12, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 8, elevation: 5, }, popoverBackground: { backgroundColor: 'rgba(0, 0, 0, 0.3)', }, popoverContent: { minWidth: 140, paddingVertical: 8, }, popoverItem: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 12, gap: 12, }, popoverText: { fontSize: 16, fontWeight: '500', }, });