Files
flyer-crawler.projectium.com/src/hooks/useWatchedItems.tsx
Torben Sorensen 43ca7f9df2
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Has been cancelled
Refactor context and provider structure for improved organization and maintainability
- Removed individual context files for Auth, Flyers, MasterItems, Modal, UserData, and their respective hooks.
- Introduced centralized provider files for each context, encapsulating logic and state management.
- Updated imports across the application to reflect the new structure, ensuring all hooks and contexts are correctly referenced.
- Enhanced the AppProviders component to streamline the wrapping of all context providers in the application.
- Improved type definitions and context management for better type safety and clarity.
2025-12-14 21:00:58 -08:00

64 lines
2.4 KiB
TypeScript

// src/hooks/useWatchedItems.tsx
import { useMemo, useCallback } from 'react';
import { useAuth } from '../hooks/useAuth';
import { useApi } from './useApi';
import { useUserData } from '../hooks/useUserData';
import * as apiClient from '../services/apiClient';
import type { MasterGroceryItem } from '../types';
/**
* A custom hook to manage all state and logic related to a user's watched items.
* It encapsulates API calls and state updates for adding and removing items.
*/
const useWatchedItemsHook = () => {
const { user } = useAuth();
// Get the watched items and the global setter from the DataContext.
const { watchedItems, setWatchedItems } = useUserData();
// API hooks for watched item operations
const { execute: addWatchedItemApi, error: addError } = useApi<MasterGroceryItem, [string, string]>(
(itemName, category) => apiClient.addWatchedItem(itemName, category)
);
const { execute: removeWatchedItemApi, error: removeError } = useApi<null, [number]>(
(masterItemId) => apiClient.removeWatchedItem(masterItemId)
);
// Consolidate errors into a single displayable error message.
const error = useMemo(() => (addError || removeError ? (addError?.message || removeError?.message) : null), [addError, removeError]);
const addWatchedItem = useCallback(async (itemName: string, category: string) => {
if (!user) return;
const updatedOrNewItem = await addWatchedItemApi(itemName, category);
if (updatedOrNewItem) {
// Update the global state in the DataContext.
setWatchedItems(currentItems => {
const itemExists = currentItems.some(item => item.master_grocery_item_id === updatedOrNewItem.master_grocery_item_id);
if (!itemExists) {
return [...currentItems, updatedOrNewItem].sort((a, b) => a.name.localeCompare(b.name));
}
return currentItems;
});
}
}, [user, setWatchedItems, addWatchedItemApi]);
const removeWatchedItem = useCallback(async (masterItemId: number) => {
if (!user) return;
const result = await removeWatchedItemApi(masterItemId);
if (result === null) {
// Update the global state in the DataContext.
setWatchedItems(currentItems => currentItems.filter(item => item.master_grocery_item_id !== masterItemId));
}
}, [user, setWatchedItems, removeWatchedItemApi]);
return {
watchedItems,
addWatchedItem,
removeWatchedItem,
error,
};
};
export { useWatchedItemsHook as useWatchedItems };