import { ThemedText } from '@/components/ThemedText'; import { useI18n } from '@/hooks/useI18n'; import { useThemeColor } from '@/hooks/useThemeColor'; import { DietRecord } from '@/services/dietRecords'; import { Ionicons } from '@expo/vector-icons'; import dayjs from 'dayjs'; import { Image } from 'expo-image'; import React, { useMemo, useRef, useState } from 'react'; import { Alert, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { RectButton, Swipeable } from 'react-native-gesture-handler'; export type NutritionRecordCardProps = { record: DietRecord; onPress?: () => void; onDelete?: () => void; }; 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: '#FF6B35', lunch: '#4CAF50', dinner: '#2196F3', snack: '#FF7A85', other: '#9AA3AE', } as const; export function NutritionRecordCard({ record, onPress, onDelete }: NutritionRecordCardProps) { const { t } = useI18n(); const textColor = useThemeColor({}, 'text'); const textSecondaryColor = useThemeColor({}, 'textSecondary'); // 左滑删除相关 const swipeableRef = useRef(null); const [isSwiping, setIsSwiping] = useState(false); // 营养数据统计 const nutritionStats = useMemo(() => { return [ { label: t('nutritionRecords.nutrients.protein'), value: record.proteinGrams ? `${Math.round(record.proteinGrams)}` : '-', unit: t('nutritionRecords.nutrients.unit'), color: '#64748B' }, { label: t('nutritionRecords.nutrients.fat'), value: record.fatGrams ? `${Math.round(record.fatGrams)}` : '-', unit: t('nutritionRecords.nutrients.unit'), color: '#64748B' }, { label: t('nutritionRecords.nutrients.carbs'), value: record.carbohydrateGrams ? `${Math.round(record.carbohydrateGrams)}` : '-', unit: t('nutritionRecords.nutrients.unit'), color: '#64748B' }, ]; }, [record, t]); const mealTypeColor = MEAL_TYPE_COLORS[record.mealType]; const mealTypeLabel = t(`nutritionRecords.mealTypes.${record.mealType}`); // 处理点击事件,只有在非滑动状态下才触发 const handlePress = () => { if (!isSwiping && onPress) { onPress(); } }; const handleSwipeableWillOpen = () => setIsSwiping(true); const handleSwipeableClose = () => setTimeout(() => setIsSwiping(false), 100); const handleDelete = () => { Alert.alert( t('nutritionRecords.delete.title'), t('nutritionRecords.delete.message'), [ { text: t('nutritionRecords.delete.cancel'), style: 'cancel' }, { text: t('nutritionRecords.delete.confirm'), style: 'destructive', onPress: () => { onDelete?.(); swipeableRef.current?.close(); }, }, ] ); }; const renderRightActions = () => { return ( ); }; return ( {/* 左侧:时间线和图标 */} {/* 中间:主要信息 */} {record.foodName} {mealTypeLabel} {record.mealTime ? dayjs(record.mealTime).format('HH:mm') : '--:--'} {record.portionDescription && ( <> · {record.portionDescription} )} {/* 营养微缩信息 */} {nutritionStats.map((stat, index) => ( {stat.value}{stat.unit} {stat.label} ))} {/* 右侧:热量 */} {record.estimatedCalories ? Math.round(record.estimatedCalories) : '-'} {t('nutritionRecords.nutrients.caloriesUnit')} {/* 如果有图片,显示图片缩略图 */} {record.imageUrl && ( )} ); } const styles = StyleSheet.create({ container: { marginBottom: 12, marginHorizontal: 24, shadowColor: 'rgba(30, 41, 59, 0.05)', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.1, shadowRadius: 12, elevation: 2, }, card: { backgroundColor: '#FFFFFF', borderRadius: 24, padding: 16, }, mainContent: { flexDirection: 'row', }, leftSection: { marginRight: 12, alignItems: 'center', }, mealIconContainer: { width: 40, height: 40, borderRadius: 14, backgroundColor: '#F8FAFC', alignItems: 'center', justifyContent: 'center', }, mealIcon: { width: 20, height: 20, opacity: 0.8, }, centerSection: { flex: 1, marginRight: 12, }, titleRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 4, gap: 8, }, foodName: { fontSize: 16, fontWeight: '700', color: '#1E293B', fontFamily: 'AliBold', flexShrink: 1, }, mealTag: { paddingHorizontal: 6, paddingVertical: 2, borderRadius: 6, }, mealTagText: { fontSize: 10, fontWeight: '600', fontFamily: 'AliBold', }, metaRow: { flexDirection: 'row', alignItems: 'center', marginBottom: 10, }, timeText: { fontSize: 12, color: '#94A3B8', marginLeft: 4, fontFamily: 'AliRegular', }, dotSeparator: { marginHorizontal: 4, color: '#CBD5E1', }, portionText: { fontSize: 12, color: '#64748B', fontFamily: 'AliRegular', flex: 1, }, nutritionRow: { flexDirection: 'row', gap: 12, }, nutritionItem: { flexDirection: 'row', alignItems: 'baseline', gap: 2, }, nutritionValue: { fontSize: 13, fontWeight: '600', color: '#475569', fontFamily: 'AliBold', }, nutritionUnit: { fontSize: 10, fontWeight: '500', color: '#94A3B8', marginLeft: 1, }, nutritionLabel: { fontSize: 10, color: '#94A3B8', marginLeft: 2, fontFamily: 'AliRegular', }, rightSection: { alignItems: 'flex-end', justifyContent: 'flex-start', paddingTop: 2, }, caloriesValue: { fontSize: 18, fontWeight: '800', color: '#1E293B', fontFamily: 'AliBold', lineHeight: 22, }, caloriesUnit: { fontSize: 10, color: '#94A3B8', fontWeight: '500', fontFamily: 'AliRegular', }, imageSection: { marginTop: 12, height: 120, width: '100%', borderRadius: 16, overflow: 'hidden', backgroundColor: '#F1F5F9', }, foodImage: { width: '100%', height: '100%', }, deleteButton: { backgroundColor: '#FF6B6B', justifyContent: 'center', alignItems: 'center', width: 70, height: '100%', borderRadius: 24, marginLeft: 12, }, });