feat: 添加食物编辑功能,支持修改食物名称、重量和卡路里

This commit is contained in:
richarjiang
2025-09-04 17:46:48 +08:00
parent a4a0e07227
commit 6c21c4b448

View File

@@ -15,9 +15,11 @@ import {
BackHandler,
Image,
Modal,
Pressable,
ScrollView,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View
} from 'react-native';
@@ -84,6 +86,8 @@ export default function FoodAnalysisResultScreen() {
const [isRecording, setIsRecording] = useState(false);
const [showImagePreview, setShowImagePreview] = useState(false);
const [animationTrigger, setAnimationTrigger] = useState(0);
const [editingFood, setEditingFood] = useState<string | null>(null);
const [editFormData, setEditFormData] = useState({ name: '', amount: '', calories: '' });
const { imageUri, recognitionId, hideRecordBar } = params;
// 判断是否隐藏记录栏(默认显示)
@@ -199,6 +203,39 @@ export default function FoodAnalysisResultScreen() {
setFoodItems(prev => prev.filter(item => item.id !== itemId));
};
// 打开编辑弹窗
const handleEditFood = (item: typeof mockFoodItems[0]) => {
setEditFormData({
name: item.name,
amount: item.amount.toString(),
calories: item.calories.toString(),
});
setEditingFood(item.id);
};
// 保存编辑
const handleSaveEdit = () => {
if (!editingFood) return;
const amount = parseFloat(editFormData.amount) || 0;
const calories = parseFloat(editFormData.calories) || 0;
setFoodItems(prev => prev.map(item =>
item.id === editingFood
? { ...item, name: editFormData.name, amount, calories }
: item
));
setEditingFood(null);
setEditFormData({ name: '', amount: '', calories: '' });
};
// 关闭编辑弹窗
const handleCloseEdit = () => {
setEditingFood(null);
setEditFormData({ name: '', amount: '', calories: '' });
};
// 获取随机食物emoji
function getRandomFoodEmoji(): string {
const foodEmojis = ['🍎', '🍌', '🍞', '🥛', '🥗', '🍗', '🍖', '🥕', '🥦', '🥬', '🍅', '🥒', '🍇', '🥝', '🍓'];
@@ -367,7 +404,10 @@ export default function FoodAnalysisResultScreen() {
<View style={styles.foodIntakeCalories}>
<Text style={styles.foodIntakeCaloriesValue}>{item.calories}</Text>
{shouldHideRecordBar ? null : <TouchableOpacity style={styles.editButton}>
{shouldHideRecordBar ? null : <TouchableOpacity
style={styles.editButton}
onPress={() => handleEditFood(item)}
>
<Ionicons name="create-outline" size={16} color="#666" />
</TouchableOpacity>}
{shouldHideRecordBar ? null : <TouchableOpacity
@@ -508,10 +548,109 @@ export default function FoodAnalysisResultScreen() {
</View>
)}
/>
{/* 编辑食物弹窗 */}
<FoodEditModal
visible={!!editingFood}
formData={editFormData}
onFormDataChange={setEditFormData}
onClose={handleCloseEdit}
onSave={handleSaveEdit}
/>
</View>
);
}
// 编辑食物弹窗组件
function FoodEditModal({
visible,
formData,
onFormDataChange,
onClose,
onSave
}: {
visible: boolean;
formData: { name: string; amount: string; calories: string };
onFormDataChange: (data: { name: string; amount: string; calories: string }) => void;
onClose: () => void;
onSave: () => void;
}) {
const handleFieldChange = (field: string, value: string) => {
onFormDataChange({ ...formData, [field]: value });
};
return (
<Modal
visible={visible}
transparent
animationType="fade"
onRequestClose={onClose}
>
<Pressable style={styles.modalBackdrop} onPress={onClose} />
<View style={styles.editModalSheet}>
<View style={styles.modalHandle} />
<Text style={styles.modalTitle}></Text>
{/* 食物名称 */}
<View style={styles.editFieldContainer}>
<Text style={styles.editFieldLabel}></Text>
<TextInput
style={styles.editInput}
placeholder="输入食物名称"
placeholderTextColor="#999"
value={formData.name}
onChangeText={(value) => handleFieldChange('name', value)}
autoFocus
/>
</View>
{/* 重量/数量 */}
<View style={styles.editFieldContainer}>
<Text style={styles.editFieldLabel}> ()</Text>
<TextInput
style={styles.editInput}
placeholder="输入重量"
placeholderTextColor="#999"
value={formData.amount}
onChangeText={(value) => handleFieldChange('amount', value)}
keyboardType="numeric"
/>
</View>
{/* 卡路里 */}
<View style={styles.editFieldContainer}>
<Text style={styles.editFieldLabel}> ()</Text>
<TextInput
style={styles.editInput}
placeholder="输入卡路里"
placeholderTextColor="#999"
value={formData.calories}
onChangeText={(value) => handleFieldChange('calories', value)}
keyboardType="numeric"
/>
</View>
{/* 按钮区域 */}
<View style={styles.modalButtons}>
<TouchableOpacity
onPress={onClose}
style={styles.modalCancelBtn}
>
<Text style={styles.modalCancelText}></Text>
</TouchableOpacity>
<TouchableOpacity
onPress={onSave}
style={[styles.modalSaveBtn, { backgroundColor: Colors.light.primary }]}
>
<Text style={[styles.modalSaveText, { color: Colors.light.onPrimary }]}></Text>
</TouchableOpacity>
</View>
</View>
</Modal>
);
}
// 营养圆环组件
function NutritionRing({
label,
@@ -1039,4 +1178,84 @@ const styles = StyleSheet.create({
fontSize: 16,
fontWeight: '500',
},
modalBackdrop: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(0,0,0,0.4)',
},
// 编辑弹窗样式
editModalSheet: {
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
backgroundColor: '#FFFFFF',
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
paddingHorizontal: 20,
paddingBottom: 40,
paddingTop: 20,
},
modalHandle: {
width: 36,
height: 4,
backgroundColor: '#E0E0E0',
borderRadius: 2,
alignSelf: 'center',
marginBottom: 20,
},
modalTitle: {
fontSize: 20,
fontWeight: '600',
color: '#333333',
marginBottom: 24,
textAlign: 'center',
},
editFieldContainer: {
marginBottom: 20,
},
editFieldLabel: {
fontSize: 16,
fontWeight: '500',
color: '#333333',
marginBottom: 8,
},
editInput: {
height: 50,
borderWidth: 1,
borderColor: '#E0E0E0',
borderRadius: 12,
paddingHorizontal: 16,
fontSize: 16,
backgroundColor: '#FFFFFF',
color: '#333333',
},
modalButtons: {
flexDirection: 'row',
gap: 12,
marginTop: 8,
},
modalCancelBtn: {
flex: 1,
height: 50,
backgroundColor: '#F0F0F0',
borderRadius: 12,
alignItems: 'center',
justifyContent: 'center',
},
modalCancelText: {
fontSize: 16,
fontWeight: '600',
color: '#666666',
},
modalSaveBtn: {
flex: 1,
height: 50,
borderRadius: 12,
alignItems: 'center',
justifyContent: 'center',
},
modalSaveText: {
fontSize: 16,
fontWeight: '600',
},
});