feat(ItemsList): add item content validation and improve row management logic

This commit is contained in:
ryan 2025-07-09 15:38:28 +03:00
parent f616d73826
commit c31b195b5e

View file

@ -210,6 +210,13 @@ async function fetchWikidataSuggestions(query: string): Promise<WikidataSuggesti
} }
} }
// Helper function to check if an item has content
function itemHasContent(item: Item): boolean {
return item.name.trim() !== '' ||
item.description.trim() !== '' ||
Object.values(item.customProperties).some(prop => prop.trim() !== '');
}
export function ItemsList({ url }: ItemsListProps) { export function ItemsList({ url }: ItemsListProps) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
@ -248,9 +255,24 @@ export function ItemsList({ url }: ItemsListProps) {
customProperties: {} customProperties: {}
}; };
setItems([emptyItem]); setItems([emptyItem]);
} else {
// Check if we need to add an empty row at the end
const lastItem = loadedItems[loadedItems.length - 1];
const needsEmptyRow = itemHasContent(lastItem);
if (needsEmptyRow) {
const emptyItem: Item = {
id: uuidv4(),
name: '',
description: '',
wikidataId: undefined,
customProperties: {}
};
setItems([...loadedItems, emptyItem]);
} else { } else {
setItems(loadedItems); setItems(loadedItems);
} }
}
// Set selected properties // Set selected properties
const selectedPropsMap: Record<string, boolean> = {}; const selectedPropsMap: Record<string, boolean> = {};
@ -283,8 +305,10 @@ export function ItemsList({ url }: ItemsListProps) {
// Mutations // Mutations
const saveItemMutation = useMutation({ const saveItemMutation = useMutation({
mutationFn: (item: Item) => saveItemToDb(url, item), mutationFn: (item: Item) => saveItemToDb(url, item),
onSuccess: () => { // REMOVED: onSuccess invalidation that was causing the issue
queryClient.invalidateQueries({ queryKey: ['items', url] }); onError: (error) => {
console.error('Failed to save item:', error);
// You could add a toast notification here
} }
}); });
@ -312,6 +336,9 @@ export function ItemsList({ url }: ItemsListProps) {
const newItems = [...prevItems]; const newItems = [...prevItems];
const item = { ...newItems[index] }; const item = { ...newItems[index] };
// Store the previous state of the item to check if it was empty before
const wasEmpty = !itemHasContent(item);
if (field === 'name') { if (field === 'name') {
item.name = value; item.name = value;
// Fetch Wikidata suggestions only if value is not empty // Fetch Wikidata suggestions only if value is not empty
@ -344,36 +371,22 @@ export function ItemsList({ url }: ItemsListProps) {
newItems[index] = item; newItems[index] = item;
// Check if the item now has content after the update
const nowHasContent = itemHasContent(item);
// Only save if the item has some content // Only save if the item has some content
const hasContent = item.name.trim() || if (nowHasContent) {
item.description.trim() ||
Object.values(item.customProperties).some(prop => prop.trim());
if (hasContent) {
// Auto-save with error handling // Auto-save with error handling
saveItemMutation.mutate(item, { saveItemMutation.mutate(item);
onError: (error) => {
console.error('Failed to save item:', error);
// You could add a toast notification here
},
onSuccess: () => {
// After successful save, reload items to get any synchronized properties
// This ensures that if another item with the same name exists,
// its properties are updated in the UI
queryClient.invalidateQueries({ queryKey: ['items', url] });
}
});
} }
// Add new row if editing last row and value is not empty // Add new row logic: only add if we're editing the last item AND
// Only add if the last item doesn't already have content and we're not already at the end // the item transitioned from empty to having content
if (index === newItems.length - 1 && value.trim()) { const isLastItem = index === newItems.length - 1;
const lastItem = newItems[newItems.length - 1]; const transitionedToContent = wasEmpty && nowHasContent;
const lastItemHasContent = lastItem.name.trim() ||
lastItem.description.trim() ||
Object.values(lastItem.customProperties).some(prop => prop.trim());
if (lastItemHasContent) { if (isLastItem && transitionedToContent) {
// Add a new empty row
const newItem: Item = { const newItem: Item = {
id: uuidv4(), id: uuidv4(),
name: '', name: '',
@ -382,15 +395,12 @@ export function ItemsList({ url }: ItemsListProps) {
customProperties: {} customProperties: {}
}; };
newItems.push(newItem); newItems.push(newItem);
console.log('Added new empty row after item got content');
// Don't auto-save empty items immediately
// They will be saved when user starts typing
}
} }
return newItems; return newItems;
}); });
}, [saveItemMutation, queryClient, url]); }, [saveItemMutation]);
const removeItem = useCallback((index: number) => { const removeItem = useCallback((index: number) => {
const itemId = items[index].id; const itemId = items[index].id;
@ -527,7 +537,7 @@ export function ItemsList({ url }: ItemsListProps) {
} }
console.log('Property addition completed:', normalizedProperty); console.log('Property addition completed:', normalizedProperty);
}, [selectedProperties, propertyLabels, items, propertyCache, url]); }, [customProperties, propertyLabels, items, propertyCache, url]);
const handleWikidataSelect = useCallback(async (suggestion: WikidataSuggestion, itemId: string) => { const handleWikidataSelect = useCallback(async (suggestion: WikidataSuggestion, itemId: string) => {
console.log('Wikidata selection for item:', itemId, suggestion); console.log('Wikidata selection for item:', itemId, suggestion);