App.tsx refactor + even more unit tests
All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 8m28s

This commit is contained in:
2025-12-08 12:18:46 -08:00
parent e022a4a2cc
commit 0eda796fad
34 changed files with 1999 additions and 611 deletions

View File

@@ -0,0 +1,61 @@
// src/hooks/useWatchedItems.tsx
import { useState, useCallback } from 'react';
import { useAuth } from './useAuth';
import { useData } from './useData';
import * as apiClient from '../services/apiClient';
import type { MasterGroceryItem } from '../types';
import { logger } from '../services/logger';
/**
* 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.
*/
export const useWatchedItems = () => {
const { user } = useAuth();
// Get the watched items and the global setter from the DataContext.
const { watchedItems, setWatchedItems } = useData();
const [error, setError] = useState<string | null>(null);
const addWatchedItem = useCallback(async (itemName: string, category: string) => {
if (!user) return;
try {
setError(null);
const updatedOrNewItem: MasterGroceryItem = await (await apiClient.addWatchedItem(itemName, category)).json();
// 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;
});
} catch (e) {
const errorMessage = e instanceof Error ? e.message : String(e);
logger.error('Could not add watched item', { error: errorMessage });
setError(`Could not add watched item: ${errorMessage}`);
}
}, [user, setWatchedItems]);
const removeWatchedItem = useCallback(async (masterItemId: number) => {
if (!user) return;
try {
setError(null);
await apiClient.removeWatchedItem(masterItemId);
// Update the global state in the DataContext.
setWatchedItems(currentItems => currentItems.filter(item => item.master_grocery_item_id !== masterItemId));
} catch (e) {
const errorMessage = e instanceof Error ? e.message : String(e);
logger.error('Could not remove watched item', { error: errorMessage });
setError(`Could not remove watched item: ${errorMessage}`);
}
}, [user, setWatchedItems]);
return {
watchedItems,
addWatchedItem,
removeWatchedItem,
error,
};
};