From 16b892b0e210691afcf14101b3484b106cc1417c Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 20 Jun 2025 18:14:45 +0300 Subject: [PATCH] feat(ItemsList): enhance addProperty function with error handling and logging --- src/components/ItemsList.tsx | 95 ++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 30 deletions(-) diff --git a/src/components/ItemsList.tsx b/src/components/ItemsList.tsx index 06e2c11..3ef91c1 100644 --- a/src/components/ItemsList.tsx +++ b/src/components/ItemsList.tsx @@ -306,9 +306,6 @@ export function ItemsList({ url }: ItemsListProps) { const addPropertyMutation = useMutation({ mutationFn: (property: string) => addPropertyToDb(url, property), - onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ['items', url] }); - } }); // Event handlers @@ -386,23 +383,31 @@ export function ItemsList({ url }: ItemsListProps) { // Modify the addProperty function to handle auto-population const addProperty = useCallback(async (property: string) => { + console.log('Adding property:', property); const normalizedProperty = property.replace('http://www.wikidata.org/prop/', ''); if (!normalizedProperty || selectedProperties[normalizedProperty]) { + console.log('Property already exists or invalid:', normalizedProperty); return; } - // Add to selected properties + console.log('Proceeding to add property:', normalizedProperty); + + // FIRST: Add to selected properties and custom properties (optimistic update) setSelectedProperties(prev => ({ ...prev, [normalizedProperty]: true })); setCustomProperties(prev => [...prev, normalizedProperty]); - // Fetch label if not exists + // SECOND: Fetch label if not exists if (!propertyLabels[normalizedProperty]) { - const labels = await fetchPropertyLabels([normalizedProperty]); - setPropertyLabels(prev => ({ ...prev, ...labels })); + try { + const labels = await fetchPropertyLabels([normalizedProperty]); + setPropertyLabels(prev => ({ ...prev, ...labels })); + } catch (error) { + console.error('Error fetching property labels:', error); + } } - // Add to all items with auto-population from propertyCache + // THIRD: Add to all items with auto-population from propertyCache setItems(prev => prev.map(item => { const existingValue = item.customProperties[normalizedProperty] || ''; let autoPopulatedValue = existingValue; @@ -410,6 +415,7 @@ export function ItemsList({ url }: ItemsListProps) { // If item has Wikidata ID and we have cached properties, use the cached value if (item.wikidataId && propertyCache[item.wikidataId] && propertyCache[item.wikidataId][normalizedProperty]) { autoPopulatedValue = propertyCache[item.wikidataId][normalizedProperty]; + console.log(`Auto-populating ${normalizedProperty} for ${item.wikidataId} with value:`, autoPopulatedValue); } return { @@ -421,32 +427,61 @@ export function ItemsList({ url }: ItemsListProps) { }; })); - // Save to database - addPropertyMutation.mutate(normalizedProperty); + // FOURTH: Save to database (but don't invalidate queries immediately) + try { + await addPropertyToDb(url, normalizedProperty); + console.log('Property successfully saved to database:', normalizedProperty); + } catch (error) { + console.error('Error saving property to database:', error); + // Revert optimistic updates on error + setSelectedProperties(prev => { + const newSelected = { ...prev }; + delete newSelected[normalizedProperty]; + return newSelected; + }); + setCustomProperties(prev => prev.filter(p => p !== normalizedProperty)); + setItems(prev => prev.map(item => ({ + ...item, + customProperties: Object.fromEntries( + Object.entries(item.customProperties).filter(([key]) => key !== normalizedProperty) + ) + }))); + return; + } - // Fetch Wikidata properties for items with wikidata_id that don't have cached data - items.forEach(async (item) => { - if (item.wikidataId && !propertyCache[item.wikidataId]) { - const properties = await fetchWikidataProperties(item.wikidataId); - setPropertyCache(prev => ({ ...prev, [item.wikidataId!]: properties })); - - // Update the item with the fetched property value - if (properties[normalizedProperty]) { - setItems(prevItems => prevItems.map(prevItem => - prevItem.wikidataId === item.wikidataId - ? { - ...prevItem, - customProperties: { - ...prevItem.customProperties, - [normalizedProperty]: properties[normalizedProperty] + // FIFTH: Fetch Wikidata properties for items with wikidata_id that don't have cached data + const itemsWithWikidataId = items.filter(item => item.wikidataId && !propertyCache[item.wikidataId]); + + for (const item of itemsWithWikidataId) { + if (item.wikidataId) { + try { + console.log('Fetching Wikidata properties for:', item.wikidataId); + const properties = await fetchWikidataProperties(item.wikidataId); + setPropertyCache(prev => ({ ...prev, [item.wikidataId!]: properties })); + + // Update the item with the fetched property value if it exists + if (properties[normalizedProperty]) { + console.log(`Updating ${item.wikidataId} with ${normalizedProperty}:`, properties[normalizedProperty]); + setItems(prevItems => prevItems.map(prevItem => + prevItem.wikidataId === item.wikidataId + ? { + ...prevItem, + customProperties: { + ...prevItem.customProperties, + [normalizedProperty]: properties[normalizedProperty] + } } - } - : prevItem - )); + : prevItem + )); + } + } catch (error) { + console.error(`Error fetching Wikidata properties for ${item.wikidataId}:`, error); } } - }); - }, [selectedProperties, propertyLabels, items, propertyCache, addPropertyMutation]); + } + + console.log('Property addition completed:', normalizedProperty); + }, [selectedProperties, propertyLabels, items, propertyCache, url]); const handleWikidataSelect = useCallback(async (suggestion: WikidataSuggestion, itemId: string) => { console.log('Wikidata selection for item:', itemId, suggestion);