diff --git a/app/nutrition/records.tsx b/app/nutrition/records.tsx index 498f82b..19b51cb 100644 --- a/app/nutrition/records.tsx +++ b/app/nutrition/records.tsx @@ -216,9 +216,6 @@ export default function NutritionRecordsScreen() { const renderRecord = ({ item, index }: { item: DietRecord; index: number }) => ( handleDeleteRecord(item.id)} /> ); diff --git a/components/NutritionRecordCard.tsx b/components/NutritionRecordCard.tsx index fd4c523..0bd674e 100644 --- a/components/NutritionRecordCard.tsx +++ b/components/NutritionRecordCard.tsx @@ -3,17 +3,15 @@ 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 React, { useMemo, useRef, useState } from 'react'; +import { Alert, Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; +import { Swipeable } from 'react-native-gesture-handler'; 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 = { @@ -33,20 +31,17 @@ const MEAL_TYPE_ICONS = { } as const; const MEAL_TYPE_COLORS = { - breakfast: '#FFB366', - lunch: '#4ECDC4', - dinner: '#5D5FEF', - snack: '#FF6B6B', + breakfast: '#FF6B35', + lunch: '#4CAF50', + dinner: '#2196F3', + snack: '#FF7A85', other: '#9AA3AE', } as const; export function NutritionRecordCard({ record, onPress, - onDelete, - showTimeline = false, - isFirst = false, - isLast = false + onDelete }: NutritionRecordCardProps) { const surfaceColor = useThemeColor({}, 'surface'); const textColor = useThemeColor({}, 'text'); @@ -57,32 +52,29 @@ export function NutritionRecordCard({ const [showPopover, setShowPopover] = useState(false); const popoverRef = useRef(null); + // 左滑删除相关 + const swipeableRef = useRef(null); + // 营养数据统计 const nutritionStats = useMemo(() => { return [ { - label: '热量', - value: record.estimatedCalories ? `${Math.round(record.estimatedCalories)} 千卡` : '-', - icon: 'flame-outline' as const, + label: '蛋白质', + value: record.proteinGrams ? `${record.proteinGrams.toFixed(1)}g` : '-', + icon: '🥩', color: '#FF6B6B' }, { - label: '蛋白质', - value: record.proteinGrams ? `${record.proteinGrams.toFixed(1)} g` : '-', - icon: 'fitness-outline' as const, - color: '#4ECDC4' + label: '脂肪', + value: record.fatGrams ? `${record.fatGrams.toFixed(1)}g` : '-', + icon: '🥑', + color: '#FFB366' }, { 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' + value: record.carbohydrateGrams ? `${record.carbohydrateGrams.toFixed(1)}g` : '-', + icon: '🍞', + color: '#4ECDC4' }, ]; }, [record]); @@ -91,111 +83,123 @@ export function NutritionRecordCard({ 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 && ( - - )} - - - )} + // 处理删除操作 + const handleDelete = () => { + Alert.alert( + '确认删除', + `确定要删除这条营养记录吗?此操作无法撤销。`, + [ + { + text: '取消', + style: 'cancel', + }, + { + text: '删除', + style: 'destructive', + onPress: () => { + onDelete?.(); + swipeableRef.current?.close(); + }, + }, + ] + ); + }; - {/* 卡片内容 */} - { + return ( + - {/* 主要内容区域 */} - - - - + + 删除 + + ); + }; - {!showTimeline && ( - - {record.mealTime ? dayjs(record.mealTime).format('HH:mm') : '时间未设置'} - - )} - - { - setShowPopover(true) - console.log('showPopover', showPopover) - }} - > - - + return ( + + + + {/* 主要内容区域 - 水平布局 */} + + {/* 左侧:食物图片 */} + + {record.imageUrl ? ( + + ) : ( + + )} - {/* 食物名称和分量 */} - - {/* 左侧:食物图片 */} - - {record.imageUrl ? ( - - ) : ( - - )} - - + {/* 中间:食物信息 */} + + {/* 食物名称 */} {record.foodName} - {(record.weightGrams || record.portionDescription) && ( - - {record.portionDescription || `${record.weightGrams}g`} + + {/* 时间 */} + + {record.mealTime ? dayjs(record.mealTime).format('HH:mm') : '--:--'} + + + {/* 营养信息 - 水平排列 */} + + {nutritionStats.map((stat, index) => ( + + {stat.icon} + + {stat.value} + + + ))} + + + + {/* 右侧:热量和餐次标签 */} + + {/* 热量显示 */} + + + + {record.estimatedCalories ? `${Math.round(record.estimatedCalories)} kcal` : '- kcal'} - )} - - + + + {/* 餐次标签 */} + + {mealTypeLabel} - - {/* 营养信息 - 紧凑标签布局 */} - - {nutritionStats.map((stat, index) => ( - - - - {stat.label} - - - {stat.value} - - - ))} + {/* 更多操作按钮 */} + setShowPopover(true)} + > + + - - {/* 备注信息 */} - {record.notes && ( - - - {record.notes} - - - )} - - + + {/* Popover for more options */}