fix in auto save
This commit is contained in:
parent
9653ca7395
commit
a59f32db26
@ -214,6 +214,7 @@ const handleResubmit = async (submission) => {
|
||||
}
|
||||
};
|
||||
const handleEdit = async (submission) => {
|
||||
localStorage.removeItem('autoSaveData');
|
||||
if (submission.status.toLowerCase() === 'draft') {
|
||||
try {
|
||||
const submissionData = await fetchSubmissionDetail(submission.id);
|
||||
|
||||
@ -653,7 +653,7 @@ React.useEffect(() => {
|
||||
</Card>
|
||||
|
||||
<Card className="mt-10">
|
||||
<h3 className="text-sm font-semibold text-gray-900 mb-4">Productss</h3>
|
||||
<h3 className="text-sm font-semibold text-gray-900 mb-4">Products</h3>
|
||||
{loadingProducts ? (
|
||||
<div className="flex justify-center py-4">
|
||||
<div className="h-6 w-6 animate-spin rounded-full border-b-2 border-[#92722A]" />
|
||||
|
||||
@ -563,6 +563,26 @@ const ProductData = ({
|
||||
persistLocalDraft(latestDraftRef.current);
|
||||
}, [persistLocalDraft]);
|
||||
|
||||
// Function to synchronize draft products with current establishment products
|
||||
const synchronizeDraftWithEstablishmentProducts = React.useCallback((draftProducts, currentEstablishmentProducts) => {
|
||||
if (!Array.isArray(draftProducts) || !Array.isArray(currentEstablishmentProducts)) {
|
||||
return draftProducts;
|
||||
}
|
||||
|
||||
// Create a Set of valid product IDs from current establishment products
|
||||
const validProductIds = new Set(
|
||||
currentEstablishmentProducts.map(p => p.value || p.id || p.product_id || p.productId)
|
||||
);
|
||||
|
||||
// Filter draft products to only include those that are still valid
|
||||
const synchronizedProducts = draftProducts.filter(draftProduct => {
|
||||
const productId = draftProduct.product || draftProduct.productId || draftProduct.product_id;
|
||||
return productId && validProductIds.has(productId.toString());
|
||||
});
|
||||
|
||||
return synchronizedProducts;
|
||||
}, []);
|
||||
|
||||
const handleRemarksChange = (e) => {
|
||||
const value = e.target.value;
|
||||
setRemarks(value);
|
||||
@ -621,16 +641,81 @@ const ProductData = ({
|
||||
if (restoredDraftKeyRef.current === key && restoredDraftSignatureRef.current === parsedSignature) {
|
||||
return;
|
||||
}
|
||||
onProductsChange(parsed.products);
|
||||
if (Array.isArray(parsed.deletedProducts)) setDeletedProducts(parsed.deletedProducts);
|
||||
if (typeof parsed.remarks === 'string') setRemarks(parsed.remarks);
|
||||
restoredDraftKeyRef.current = key;
|
||||
restoredDraftSignatureRef.current = parsedSignature;
|
||||
|
||||
// Synchronize draft products with current establishment products
|
||||
const synchronizedProducts = synchronizeDraftWithEstablishmentProducts(parsed.products, productOptions);
|
||||
|
||||
// Only restore if we have valid products after synchronization
|
||||
if (synchronizedProducts.length > 0) {
|
||||
onProductsChange(synchronizedProducts);
|
||||
if (Array.isArray(parsed.deletedProducts)) setDeletedProducts(parsed.deletedProducts);
|
||||
if (typeof parsed.remarks === 'string') setRemarks(parsed.remarks);
|
||||
restoredDraftKeyRef.current = key;
|
||||
restoredDraftSignatureRef.current = JSON.stringify({
|
||||
products: synchronizedProducts,
|
||||
deletedProducts: Array.isArray(parsed.deletedProducts) ? parsed.deletedProducts : [],
|
||||
remarks: typeof parsed.remarks === 'string' ? parsed.remarks : '',
|
||||
});
|
||||
|
||||
// Update the localStorage with synchronized data to prevent future issues
|
||||
persistLocalDraft({
|
||||
products: synchronizedProducts,
|
||||
deletedProducts: Array.isArray(parsed.deletedProducts) ? parsed.deletedProducts : [],
|
||||
remarks: typeof parsed.remarks === 'string' ? parsed.remarks : '',
|
||||
});
|
||||
} else {
|
||||
// If no valid products remain, clear the draft and start fresh
|
||||
onProductsChange([{ id: Date.now() }]);
|
||||
// Clear the invalid draft from localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore parse errors
|
||||
}
|
||||
}, [getLocalDraftKey, onProductsChange, products]);
|
||||
}, [getLocalDraftKey, onProductsChange, products, synchronizeDraftWithEstablishmentProducts, productOptions]);
|
||||
|
||||
// Synchronize existing products when establishment products change
|
||||
React.useEffect(() => {
|
||||
if (productOptions.length === 0) return;
|
||||
|
||||
// Check if current products have any that are no longer valid
|
||||
const validProductIds = new Set(
|
||||
productOptions.map(p => p.value || p.id || p.product_id || p.productId)
|
||||
);
|
||||
|
||||
const hasInvalidProducts = products.some(product => {
|
||||
const productId = product.product || product.productId || product.product_id;
|
||||
return productId && !validProductIds.has(productId.toString());
|
||||
});
|
||||
|
||||
if (hasInvalidProducts) {
|
||||
// Filter out invalid products
|
||||
const validProducts = products.filter(product => {
|
||||
const productId = product.product || product.productId || product.product_id;
|
||||
return !productId || validProductIds.has(productId.toString());
|
||||
});
|
||||
|
||||
// Update products state
|
||||
onProductsChange(validProducts);
|
||||
|
||||
// Update the draft with filtered products
|
||||
persistLocalDraft({
|
||||
products: validProducts,
|
||||
deletedProducts,
|
||||
remarks,
|
||||
});
|
||||
|
||||
// Update the latest draft ref
|
||||
latestDraftRef.current = {
|
||||
products: validProducts,
|
||||
deletedProducts,
|
||||
remarks,
|
||||
};
|
||||
}
|
||||
}, [productOptions, products, onProductsChange, deletedProducts, remarks, persistLocalDraft]);
|
||||
|
||||
// Debounced autosave to localStorage whenever user changes anything
|
||||
React.useEffect(() => {
|
||||
@ -959,11 +1044,69 @@ const existingProduct = currentSubmission.products?.find(p =>
|
||||
other_variation_reason: product.otherVariationReason || '',
|
||||
zero_target_reason_master_id: product.zeroTargetReason === null ? null : (parseInt(product.zeroTargetReason) || 0),
|
||||
other_zero_target_reason: product.otherZeroTargetReason || '',
|
||||
remarks: product.remarks || remarks || '' // Use product.remarks if available, otherwise use the component's remarks state
|
||||
remarks: product.remarks || remarks || '', // Use product.remarks if available, otherwise use the component's remarks state
|
||||
is_active: true // Mark current products as active
|
||||
};
|
||||
});
|
||||
|
||||
// Add deleted products with is_active: false if we're in draft edit mode
|
||||
// Get all products from current submission to identify removed ones
|
||||
const currentSubmissionProducts = currentSubmission.products || [];
|
||||
const currentProductIds = new Set(
|
||||
products.map(p => p.product || p.productId || p.product_id)
|
||||
);
|
||||
|
||||
// Find products that are in current submission but not in current products (removed products)
|
||||
const removedProducts = currentSubmissionProducts.filter(submissionProduct => {
|
||||
const productId = submissionProduct.product_id || submissionProduct.product?.id;
|
||||
return productId && !currentProductIds.has(productId.toString());
|
||||
});
|
||||
|
||||
// Add removed products with is_active: false
|
||||
if (removedProducts.length > 0) {
|
||||
const removedFormattedProducts = removedProducts.map(product => {
|
||||
return {
|
||||
id: product.id || 0,
|
||||
product_id: product.product_id || product.product?.id || null,
|
||||
unit_id: product.unit_id?.toString() || '0',
|
||||
annual_installed_capacity: product.annual_installed_capacity || '0',
|
||||
previous_quantity_period_one: product.previous_quantity_period_one || '0',
|
||||
previous_quantity_period_two: product.previous_quantity_period_two || '0',
|
||||
previous_quantity_period_three: product.previous_quantity_period_three || '0',
|
||||
previous_cost_period_one: product.previous_cost_period_one || '0',
|
||||
previous_cost_period_two: product.previous_cost_period_two || '0',
|
||||
previous_cost_period_three: product.previous_cost_period_three || '0',
|
||||
current_quantity_period_one: product.current_quantity_period_one || '0',
|
||||
current_quantity_period_two: product.current_quantity_period_two || '0',
|
||||
current_quantity_period_three: product.current_quantity_period_three || '0',
|
||||
current_cost_period_one: product.current_cost_period_one || '0',
|
||||
current_cost_period_two: product.current_cost_period_two || '0',
|
||||
current_cost_period_three: product.current_cost_period_three || '0',
|
||||
forecast_quantity_period_one: product.forecast_quantity_period_one || '0',
|
||||
forecast_quantity_period_two: product.forecast_quantity_period_two || '0',
|
||||
forecast_quantity_period_three: product.forecast_quantity_period_three || '0',
|
||||
forecast_cost_period_one: product.forecast_cost_period_one || '0',
|
||||
forecast_cost_period_two: product.forecast_cost_period_two || '0',
|
||||
forecast_cost_period_three: product.forecast_cost_period_three || '0',
|
||||
previous_quantity: product.previous_quantity || '0',
|
||||
previous_cost: product.previous_cost || '0',
|
||||
current_quantity: product.current_quantity || '0',
|
||||
current_cost: product.current_cost || '0',
|
||||
forecast_quantity: product.forecast_quantity || '0',
|
||||
forecast_cost: product.forecast_cost || '0',
|
||||
variation_reason_master_id: product.variation_reason_master_id || null,
|
||||
other_variation_reason: product.other_variation_reason || '',
|
||||
zero_target_reason_master_id: product.zero_target_reason_master_id || null,
|
||||
other_zero_target_reason: product.other_zero_target_reason || '',
|
||||
remarks: product.remarks || '',
|
||||
is_active: false // Mark removed products as inactive
|
||||
};
|
||||
});
|
||||
|
||||
// Combine active and removed products
|
||||
formattedProducts.push(...removedFormattedProducts);
|
||||
}
|
||||
|
||||
// Also add deleted products from local state if we're in edit mode
|
||||
if (location.state?.isEdit && deletedProducts.length > 0) {
|
||||
const deletedFormattedProducts = deletedProducts.map(product => {
|
||||
const selectedProduct = productOptions.find(p => p.value === product.product);
|
||||
@ -1345,17 +1488,17 @@ useEffect(() => {
|
||||
const [lastAutoSave, setLastAutoSave] = React.useState(null);
|
||||
const autoSaveInterval = React.useRef(null);
|
||||
|
||||
// Auto-save every 2 minutes
|
||||
// Auto-save every 1 second
|
||||
React.useEffect(() => {
|
||||
// Clear any existing interval
|
||||
if (autoSaveInterval.current) {
|
||||
clearInterval(autoSaveInterval.current);
|
||||
}
|
||||
|
||||
// Set up new interval for auto-save every 2 minutes (120000 ms)
|
||||
// Set up new interval for auto-save every 1 second (1000 ms)
|
||||
autoSaveInterval.current = setInterval(() => {
|
||||
autoSaveDraft();
|
||||
}, 120000); // 2 minutes = 120000 ms
|
||||
}, 1000); // 1 second = 1000 ms
|
||||
|
||||
// Cleanup interval on unmount
|
||||
return () => {
|
||||
|
||||
@ -178,6 +178,7 @@ const showToast = (message, type = 'success') => {
|
||||
onClick={async (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
localStorage.removeItem('autoSaveData');
|
||||
try {
|
||||
const submissionData = await fetchSubmissionDetail(record.id);
|
||||
navigate('/survey', {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user