feat: 优化内容

This commit is contained in:
richarjiang
2025-08-29 16:01:13 +08:00
parent 93db9e2928
commit e9b593a07e
5 changed files with 889 additions and 101 deletions

View File

@@ -1,7 +1,10 @@
import { CreateCustomFoodModal, type CustomFoodData } from '@/components/model/food/CreateCustomFoodModal';
import { FoodDetailModal } from '@/components/model/food/FoodDetailModal';
import { HeaderBar } from '@/components/ui/HeaderBar';
import { DEFAULT_IMAGE_FOOD } from '@/constants/Image';
import { useFoodLibrary, useFoodSearch } from '@/hooks/useFoodLibrary';
import type { FoodItem, MealType, SelectedFoodItem } from '@/types/food';
import { addDietRecord, type CreateDietRecordDto } from '@/services/dietRecords';
import type { FoodItem, MealType, SelectedFoodItem } from '@/types/food';
import { Ionicons } from '@expo/vector-icons';
import { Image } from 'expo-image';
import { useLocalSearchParams, useRouter } from 'expo-router';
@@ -9,9 +12,7 @@ import React, { useEffect, useMemo, useState } from 'react';
import {
ActivityIndicator,
Modal,
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
TextInput,
@@ -47,6 +48,7 @@ export default function FoodLibraryScreen() {
const [showMealSelector, setShowMealSelector] = useState(false);
const [currentMealType, setCurrentMealType] = useState<MealType>(mealType);
const [isRecording, setIsRecording] = useState(false);
const [showCreateCustomFood, setShowCreateCustomFood] = useState(false);
// 获取当前选中的分类
const selectedCategory = categories.find(cat => cat.id === selectedCategoryId);
@@ -59,8 +61,6 @@ export default function FoodLibraryScreen() {
}
if (selectedCategory) {
console.log('selectedCategory', selectedCategory);
return selectedCategory.foods
}
@@ -132,9 +132,9 @@ export default function FoodLibraryScreen() {
// 处理饮食记录
const handleRecordDiet = async () => {
if (selectedFoodItems.length === 0) return;
setIsRecording(true);
try {
// 逐个记录选中的食物
for (const item of selectedFoodItems) {
@@ -155,10 +155,10 @@ export default function FoodLibraryScreen() {
mealTime: new Date().toISOString(),
imageUrl: item.food.imageUrl,
};
await addDietRecord(dietRecordData);
}
// 记录成功后清空选择列表并返回
setSelectedFoodItems([]);
router.back();
@@ -176,6 +176,45 @@ export default function FoodLibraryScreen() {
setShowMealSelector(false);
};
// 处理创建自定义食物
const handleCreateCustomFood = () => {
setShowCreateCustomFood(true);
};
// 处理保存自定义食物
const handleSaveCustomFood = (customFoodData: CustomFoodData) => {
// 创建一个临时的FoodItem对象
const customFoodItem: FoodItem = {
id: `custom_${Date.now()}`,
name: customFoodData.name,
calories: customFoodData.calories,
unit: customFoodData.unit,
description: `自定义食物 - ${customFoodData.name}`,
imageUrl: customFoodData.imageUrl,
protein: customFoodData.protein,
fat: customFoodData.fat,
carbohydrate: customFoodData.carbohydrate,
};
// 直接添加到选择列表中
const newSelectedItem: SelectedFoodItem = {
id: `custom_${Date.now()}`,
food: customFoodItem,
amount: customFoodData.defaultAmount,
unit: customFoodData.unit,
calories: Math.round((customFoodData.calories * customFoodData.defaultAmount) / 100)
};
setSelectedFoodItems(prev => [...prev, newSelectedItem]);
console.log('保存自定义食物:', customFoodData);
};
// 关闭自定义食物弹窗
const handleCloseCreateCustomFood = () => {
setShowCreateCustomFood(false);
};
// 餐次选择选项
const mealOptions = [
{ key: 'breakfast' as const, label: '早餐', color: '#FF6B35' },
@@ -185,19 +224,19 @@ export default function FoodLibraryScreen() {
];
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="dark-content" backgroundColor="#F8F9FA" />
<View style={styles.container}>
{/* 头部 */}
<View style={styles.header}>
<TouchableOpacity onPress={() => router.back()} style={styles.backButton}>
<Ionicons name="chevron-back" size={24} color="#333" />
</TouchableOpacity>
<Text style={styles.headerTitle}></Text>
<TouchableOpacity style={styles.customButton}>
<Text style={styles.customButtonText}></Text>
</TouchableOpacity>
</View>
<HeaderBar
title="食物库"
onBack={() => router.back()}
transparent={false}
variant="elevated"
right={
<TouchableOpacity style={styles.customButton} onPress={handleCreateCustomFood}>
<Text style={styles.customButtonText}></Text>
</TouchableOpacity>
}
/>
{/* 搜索框 */}
<View style={styles.searchContainer}>
@@ -275,11 +314,11 @@ export default function FoodLibraryScreen() {
{filteredFoods.map((food) => (
<View key={food.id} style={styles.foodItem}>
<View style={styles.foodInfo}>
{food.imageUrl ? <Image
<Image
style={styles.foodImage}
source={{ uri: food.imageUrl }}
source={{ uri: food.imageUrl || DEFAULT_IMAGE_FOOD }}
cachePolicy={'memory-disk'}
/> : <Text style={styles.foodEmoji}>{food.emoji || '🍽️'}</Text>}
/>
<View style={styles.foodDetails}>
<Text style={styles.foodName}>{food.name}</Text>
<Text style={styles.foodCalories}>
@@ -436,7 +475,14 @@ export default function FoodLibraryScreen() {
onClose={handleCloseFoodDetail}
onSave={handleSaveFood}
/>
</SafeAreaView>
{/* 创建自定义食物弹窗 */}
<CreateCustomFoodModal
visible={showCreateCustomFood}
onClose={handleCloseCreateCustomFood}
onSave={handleSaveCustomFood}
/>
</View>
);
}
@@ -445,24 +491,6 @@ const styles = StyleSheet.create({
flex: 1,
backgroundColor: '#F8F9FA',
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 16,
paddingVertical: 12,
backgroundColor: '#F8F9FA',
borderBottomWidth: 1,
borderBottomColor: '#E5E5E5',
},
backButton: {
padding: 4,
},
headerTitle: {
fontSize: 18,
fontWeight: '600',
color: '#333',
},
customButton: {
paddingHorizontal: 8,
paddingVertical: 4,