Files
digital-pilates/hooks/useFoodLibrary.ts
2025-08-29 09:41:05 +08:00

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,
};
};