177 lines
4.2 KiB
TypeScript
177 lines
4.2 KiB
TypeScript
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
|
|
import {
|
|
addCustomFood,
|
|
addToFavorites,
|
|
clearError,
|
|
clearSearchResults,
|
|
fetchFoodLibrary,
|
|
getFoodById,
|
|
removeFoodFromCategory,
|
|
removeFromFavorites,
|
|
searchFoods,
|
|
selectCommonFoods,
|
|
selectFavoritesFoods,
|
|
selectFoodById,
|
|
selectFoodCategories,
|
|
selectFoodCategoryById,
|
|
selectFoodLibrary,
|
|
selectFoodLibraryError,
|
|
selectFoodLibraryLoading,
|
|
selectSearchLoading,
|
|
selectSearchResults,
|
|
} from '@/store/foodLibrarySlice';
|
|
import type { FoodItem } from '@/types/food';
|
|
import { useCallback, useEffect } from 'react';
|
|
|
|
/**
|
|
* 食物库自定义 Hook
|
|
* 提供食物库相关的状态和操作方法
|
|
*/
|
|
export const useFoodLibrary = () => {
|
|
const dispatch = useAppDispatch();
|
|
|
|
// 选择器
|
|
const foodLibrary = useAppSelector(selectFoodLibrary);
|
|
const categories = useAppSelector(selectFoodCategories);
|
|
const loading = useAppSelector(selectFoodLibraryLoading);
|
|
const error = useAppSelector(selectFoodLibraryError);
|
|
const searchResults = useAppSelector(selectSearchResults);
|
|
const searchLoading = useAppSelector(selectSearchLoading);
|
|
|
|
// 操作方法
|
|
const loadFoodLibrary = useCallback(() => {
|
|
dispatch(fetchFoodLibrary());
|
|
}, [dispatch]);
|
|
|
|
const searchFoodItems = useCallback((keyword: string) => {
|
|
if (keyword.trim()) {
|
|
dispatch(searchFoods(keyword));
|
|
} else {
|
|
dispatch(clearSearchResults());
|
|
}
|
|
}, [dispatch]);
|
|
|
|
const getFoodDetails = useCallback((id: number) => {
|
|
dispatch(getFoodById(id));
|
|
}, [dispatch]);
|
|
|
|
const clearErrors = useCallback(() => {
|
|
dispatch(clearError());
|
|
}, [dispatch]);
|
|
|
|
const clearSearch = useCallback(() => {
|
|
dispatch(clearSearchResults());
|
|
}, [dispatch]);
|
|
|
|
const addFoodToCategory = useCallback((categoryId: string, food: FoodItem) => {
|
|
dispatch(addCustomFood({ categoryId, food }));
|
|
}, [dispatch]);
|
|
|
|
const removeFoodFromCat = useCallback((categoryId: string, foodId: string) => {
|
|
dispatch(removeFoodFromCategory({ categoryId, foodId }));
|
|
}, [dispatch]);
|
|
|
|
const addFoodToFavorites = useCallback((food: FoodItem) => {
|
|
dispatch(addToFavorites(food));
|
|
}, [dispatch]);
|
|
|
|
const removeFoodFromFavorites = useCallback((foodId: string) => {
|
|
dispatch(removeFromFavorites(foodId));
|
|
}, [dispatch]);
|
|
|
|
// 自动加载数据
|
|
useEffect(() => {
|
|
if (categories.length === 0 && !loading && !error) {
|
|
loadFoodLibrary();
|
|
}
|
|
}, [categories.length, loading, error, loadFoodLibrary]);
|
|
|
|
return {
|
|
// 状态
|
|
foodLibrary,
|
|
categories,
|
|
loading,
|
|
error,
|
|
searchResults,
|
|
searchLoading,
|
|
|
|
// 操作方法
|
|
loadFoodLibrary,
|
|
searchFoodItems,
|
|
getFoodDetails,
|
|
clearErrors,
|
|
clearSearch,
|
|
addFoodToCategory,
|
|
removeFoodFromCat,
|
|
addFoodToFavorites,
|
|
removeFoodFromFavorites,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* 获取特定分类的食物
|
|
*/
|
|
export const useFoodCategory = (categoryId: string) => {
|
|
const category = useAppSelector(selectFoodCategoryById(categoryId));
|
|
return category;
|
|
};
|
|
|
|
/**
|
|
* 获取特定食物详情
|
|
*/
|
|
export const useFoodItem = (foodId: string) => {
|
|
const food = useAppSelector(selectFoodById(foodId));
|
|
return food;
|
|
};
|
|
|
|
/**
|
|
* 获取收藏的食物
|
|
*/
|
|
export const useFavoritesFoods = () => {
|
|
const favorites = useAppSelector(selectFavoritesFoods);
|
|
return favorites;
|
|
};
|
|
|
|
/**
|
|
* 获取常见食物
|
|
*/
|
|
export const useCommonFoods = () => {
|
|
const commonFoods = useAppSelector(selectCommonFoods);
|
|
return commonFoods;
|
|
};
|
|
|
|
/**
|
|
* 食物搜索 Hook
|
|
* 提供搜索相关的状态和方法
|
|
*/
|
|
export const useFoodSearch = () => {
|
|
const dispatch = useAppDispatch();
|
|
const searchResults = useAppSelector(selectSearchResults);
|
|
const searchLoading = useAppSelector(selectSearchLoading);
|
|
const error = useAppSelector(selectFoodLibraryError);
|
|
|
|
const search = useCallback((keyword: string) => {
|
|
if (keyword.trim()) {
|
|
dispatch(searchFoods(keyword));
|
|
} else {
|
|
dispatch(clearSearchResults());
|
|
}
|
|
}, [dispatch]);
|
|
|
|
const clearResults = useCallback(() => {
|
|
dispatch(clearSearchResults());
|
|
}, [dispatch]);
|
|
|
|
const clearErrors = useCallback(() => {
|
|
dispatch(clearError());
|
|
}, [dispatch]);
|
|
|
|
return {
|
|
searchResults,
|
|
searchLoading,
|
|
error,
|
|
search,
|
|
clearResults,
|
|
clearErrors,
|
|
};
|
|
}; |