Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 3x 3x 3x 3x | /**
* @file useItemSearchQuery.ts
* @module api/inventory/hooks
*
* @summary
* Hook to search items with supplier-scoped filtering and type-ahead.
* Applies client-side filtering due to backend limitation.
*
* @enterprise
* - Requires supplier selection first (prevents cross-supplier errors)
* - Minimum 2 characters to trigger search (reduces API load)
* - **Client-side supplier filtering** (backend doesn't filter properly)
* - Returns placeholder price/quantity (actual values fetched on selection)
* - 30-second cache improves UX during selection
*
* @backend_limitation
* The /api/inventory search endpoint doesn't properly filter by supplierId parameter,
* so this hook applies client-side filtering to ensure supplier isolation.
*/
import { useQuery } from '@tanstack/react-query';
import { searchItemsForSupplier } from '../../analytics/search';
import type { SupplierOption, ItemOption } from '../../analytics/types';
/**
* Hook to search items with supplier-scoped filtering and type-ahead search.
* Applies client-side supplier filtering due to backend limitation.
*
* @param selectedSupplier - Currently selected supplier (required for filtering)
* @param searchQuery - User's search query (minimum 2 characters to trigger search)
* @returns React Query result with filtered item options
*
* @enterprise
* - Requires supplier selection first (prevents cross-supplier errors)
* - Minimum 2 characters to trigger search (reduces API load)
* - **Client-side supplier filtering** (backend doesn't filter properly)
* - Returns placeholder price/quantity (actual values fetched on selection)
* - 30-second cache improves UX during selection
*
* @backend_limitation
* Backend /api/inventory endpoint ignores supplierId parameter, so we:
* 1. Fetch up to 500 items from backend
* 2. Apply client-side filtering: `item.supplierId === selectedSupplier.id`
* 3. Return only items belonging to selected supplier
*
* @remarks
* The returned `ItemOption` objects have placeholder values (0) for `onHand` and `price`.
* Fetch full details using `useItemDetailsQuery()` when user selects an item.
*
* @example
* ```typescript
* const { data: items, isLoading } = useItemSearchQuery(selectedSupplier, "widget");
*
* <Autocomplete
* options={items || []}
* loading={isLoading}
* getOptionLabel={(opt) => opt.name}
* />
* ```
*/
export function useItemSearchQuery(
selectedSupplier: SupplierOption | null,
searchQuery: string
) {
return useQuery({
queryKey: ['inventory', 'search', selectedSupplier?.id, searchQuery],
queryFn: async () => {
if (!selectedSupplier) return [];
// Fetch items from backend (may include cross-supplier results due to backend bug)
const items = await searchItemsForSupplier(
String(selectedSupplier.id),
searchQuery,
500 // Fetch more items since we'll filter client-side
);
// CRITICAL: Apply client-side supplier filtering (backend doesn't filter properly)
// This ensures only items belonging to the selected supplier are returned
const supplierIdStr = String(selectedSupplier.id);
const supplierFiltered = items.filter(
(item) => String(item.supplierId ?? '') === supplierIdStr
);
// Map to ItemOption with placeholder values (full details fetched on selection)
return supplierFiltered.map((item): ItemOption => ({
id: item.id,
name: item.name,
}));
},
enabled: !!selectedSupplier && searchQuery.length >= 2,
staleTime: 30_000, // 30 seconds cache
});
}
|