Fix AI prompts not refreshing in the frontend after save, some AI tweaks

This commit is contained in:
2025-10-14 11:44:59 -04:00
parent f0e2023803
commit 0ceef144d7
3 changed files with 95 additions and 53 deletions

View File

@@ -1025,61 +1025,88 @@ router.post("/validate", async (req, res) => {
Object.keys(aiResponse) Object.keys(aiResponse)
); );
// Create a detailed comparison between original and corrected data // Merge AI changes back into original products
// AI now only returns changed products and changed fields
const mergedProducts = products.map((original, index) => ({ ...original }));
const changeDetails = []; const changeDetails = [];
// Compare original and corrected data if (aiResponse.correctedData && Array.isArray(aiResponse.correctedData)) {
if (aiResponse.correctedData) { console.log("📊 Processing AI changes - received", aiResponse.correctedData.length, "products with changes");
console.log("📊 Changes summary:");
// Debug: Log the first product's fields // Process each changed product from AI
if (products.length > 0) { aiResponse.correctedData.forEach((changedProduct) => {
console.log("🔍 First product fields:", Object.keys(products[0])); // Find the matching original product using stable identifiers in priority order
// Priority: upc > supplier_no > notions_no
// These fields should not change during validation
const identifiers = ['upc', 'supplier_no', 'notions_no'];
let matchedIndex = -1;
let matchedBy = null;
for (const identifier of identifiers) {
if (changedProduct[identifier] !== undefined && changedProduct[identifier] !== null && changedProduct[identifier] !== '') {
matchedIndex = products.findIndex(
(p) => p[identifier] !== undefined &&
p[identifier] !== null &&
p[identifier] !== '' &&
String(p[identifier]).trim() === String(changedProduct[identifier]).trim()
);
if (matchedIndex !== -1) {
matchedBy = identifier;
console.log(`✓ Matched product by ${identifier}:`, changedProduct[identifier]);
break;
}
}
} }
products.forEach((original, index) => { // If no identifier match found, log an error with details
const corrected = aiResponse.correctedData[index]; if (matchedIndex === -1) {
if (corrected) { console.error("❌ Could not match changed product to original. Product identifiers:", {
upc: changedProduct.upc,
supplier_no: changedProduct.supplier_no,
notions_no: changedProduct.notions_no
});
return;
}
const original = products[matchedIndex];
const productChanges = { const productChanges = {
productIndex: index, productIndex: matchedIndex,
title: original.name || original.title || `Product ${index + 1}`, title: original.name || original.title || `Product ${matchedIndex + 1}`,
changes: [] changes: []
}; };
const changes = Object.keys(corrected).filter( // Apply each changed field to the merged product
(key) => Object.keys(changedProduct).forEach((key) => {
JSON.stringify(original[key]) !== // Check if the value actually changed
JSON.stringify(corrected[key]) if (JSON.stringify(original[key]) !== JSON.stringify(changedProduct[key])) {
); console.log(`\nProduct ${matchedIndex + 1} - Field ${key}:`);
console.log(` - Original: ${JSON.stringify(original[key])}`);
console.log(` - Corrected: ${JSON.stringify(changedProduct[key])}`);
if (changes.length > 0) { // Apply the change to merged product
console.log(`\nProduct ${index + 1} changes:`); mergedProducts[matchedIndex][key] = changedProduct[key];
changes.forEach((key) => {
console.log(` ${key}:`);
console.log(
` - Original: ${JSON.stringify(original[key])}`
);
console.log(
` - Corrected: ${JSON.stringify(corrected[key])}`
);
// Add to our detailed changes array // Track the change
productChanges.changes.push({ productChanges.changes.push({
field: key, field: key,
original: original[key], original: original[key],
corrected: corrected[key] corrected: changedProduct[key]
}); });
}
}); });
// Only add products that have changes // Only add to changeDetails if there were actual changes
if (productChanges.changes.length > 0) { if (productChanges.changes.length > 0) {
changeDetails.push(productChanges); changeDetails.push(productChanges);
} }
}
}
}); });
console.log(`📊 Applied changes to ${changeDetails.length} products`);
} }
// Replace aiResponse.correctedData with the fully merged product array
aiResponse.correctedData = mergedProducts;
// Record performance metrics after successful validation // Record performance metrics after successful validation
const endTime = new Date(); const endTime = new Date();
let performanceMetrics = { let performanceMetrics = {

View File

@@ -186,7 +186,7 @@ export const ImageUploadStep = ({
} finally { } finally {
setIsSubmitting(false); setIsSubmitting(false);
} }
}, [data, file, onSubmit, productImages]); }, [data, file, onSubmit, productImages, targetEnvironment, useTestDataSource]);
return ( return (
<div className="flex flex-col h-[calc(100vh-9.5rem)] overflow-hidden"> <div className="flex flex-col h-[calc(100vh-9.5rem)] overflow-hidden">

View File

@@ -134,8 +134,12 @@ export function PromptManagement() {
return response.json(); return response.json();
}, },
onSuccess: () => { onSuccess: (newPrompt) => {
queryClient.invalidateQueries({ queryKey: ["ai-prompts"] }); // Optimistically update the cache with the new prompt
queryClient.setQueryData<AiPrompt[]>(["ai-prompts"], (old) => {
if (!old) return [newPrompt];
return [...old, newPrompt];
});
toast.success("Prompt created successfully"); toast.success("Prompt created successfully");
resetForm(); resetForm();
}, },
@@ -163,8 +167,14 @@ export function PromptManagement() {
return response.json(); return response.json();
}, },
onSuccess: () => { onSuccess: (updatedPrompt) => {
queryClient.invalidateQueries({ queryKey: ["ai-prompts"] }); // Optimistically update the cache with the returned data
queryClient.setQueryData<AiPrompt[]>(["ai-prompts"], (old) => {
if (!old) return [updatedPrompt];
return old.map((prompt) =>
prompt.id === updatedPrompt.id ? updatedPrompt : prompt
);
});
toast.success("Prompt updated successfully"); toast.success("Prompt updated successfully");
resetForm(); resetForm();
}, },
@@ -181,9 +191,14 @@ export function PromptManagement() {
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete prompt"); throw new Error("Failed to delete prompt");
} }
return id;
}, },
onSuccess: () => { onSuccess: (deletedId) => {
queryClient.invalidateQueries({ queryKey: ["ai-prompts"] }); // Optimistically update the cache by removing the deleted prompt
queryClient.setQueryData<AiPrompt[]>(["ai-prompts"], (old) => {
if (!old) return [];
return old.filter((prompt) => prompt.id !== deletedId);
});
toast.success("Prompt deleted successfully"); toast.success("Prompt deleted successfully");
}, },
onError: (error) => { onError: (error) => {