Enhancement version2
This commit is contained in:
parent
5f37883a3b
commit
9e5088eb42
@ -1509,19 +1509,22 @@ useEffect(() => {
|
|||||||
|
|
||||||
// Auto-save functionality
|
// Auto-save functionality
|
||||||
const [lastAutoSave, setLastAutoSave] = React.useState(null);
|
const [lastAutoSave, setLastAutoSave] = React.useState(null);
|
||||||
|
const [isAutoSaving, setIsAutoSaving] = React.useState(false);
|
||||||
const autoSaveInterval = React.useRef(null);
|
const autoSaveInterval = React.useRef(null);
|
||||||
|
|
||||||
// Auto-save every 1 second
|
// Auto-save every 30 seconds
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
// Clear any existing interval
|
// Clear any existing interval
|
||||||
if (autoSaveInterval.current) {
|
if (autoSaveInterval.current) {
|
||||||
clearInterval(autoSaveInterval.current);
|
clearInterval(autoSaveInterval.current);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up new interval for auto-save every 1 second (1000 ms)
|
// Set up new interval for auto-save every 30 seconds (30000 ms)
|
||||||
autoSaveInterval.current = setInterval(() => {
|
autoSaveInterval.current = setInterval(() => {
|
||||||
|
if (!isAutoSaving) {
|
||||||
autoSaveDraft();
|
autoSaveDraft();
|
||||||
}, 1000); // 1 second = 1000 ms
|
}
|
||||||
|
}, 1000); // 2 seconds = 2000 ms
|
||||||
|
|
||||||
// Cleanup interval on unmount
|
// Cleanup interval on unmount
|
||||||
return () => {
|
return () => {
|
||||||
@ -1533,7 +1536,10 @@ useEffect(() => {
|
|||||||
|
|
||||||
// Auto-save function
|
// Auto-save function
|
||||||
const autoSaveDraft = async () => {
|
const autoSaveDraft = async () => {
|
||||||
|
if (isAutoSaving) return; // Prevent overlapping saves
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
setIsAutoSaving(true);
|
||||||
// Check if there's any data to save
|
// Check if there's any data to save
|
||||||
const hasAnyData = products.some(product =>
|
const hasAnyData = products.some(product =>
|
||||||
product.product ||
|
product.product ||
|
||||||
@ -1554,75 +1560,51 @@ useEffect(() => {
|
|||||||
return; // Don't auto-save if no data
|
return; // Don't auto-save if no data
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save to localStorage for persistence across page refreshes
|
// Get current quarter and year from session storage first, then quarterPeriods, then props
|
||||||
|
const currentQuarter = localStorage.getItem('currentQuarter') || quarterPeriods?.current_quarter || quarter || '';
|
||||||
|
const currentYear = localStorage.getItem('currentYear') || quarterPeriods?.current_year || year || '';
|
||||||
|
const establishmentId = localStorage.getItem('establishment_id');
|
||||||
|
|
||||||
|
// Debug logging
|
||||||
|
// console.log('Auto-save debug:', {
|
||||||
|
// quarterPeriods,
|
||||||
|
// currentQuarter,
|
||||||
|
// currentYear,
|
||||||
|
// establishmentId,
|
||||||
|
// hasProducts: products.length > 0
|
||||||
|
// });
|
||||||
|
|
||||||
|
// Validate required fields
|
||||||
|
if (!currentQuarter || !currentYear || !establishmentId) {
|
||||||
|
console.error('Auto-save failed: Missing required data', {
|
||||||
|
currentQuarter,
|
||||||
|
currentYear,
|
||||||
|
establishmentId
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save to localStorage for persistence across page refreshes (auto-save only)
|
||||||
const autoSaveData = {
|
const autoSaveData = {
|
||||||
establishment_id: localStorage.getItem('establishment_id'),
|
establishment_id: establishmentId,
|
||||||
quarter: surveyData.quarter,
|
quarter: currentQuarter,
|
||||||
year: surveyData.year,
|
year: currentYear,
|
||||||
products: products,
|
products: products,
|
||||||
timestamp: new Date().toISOString()
|
timestamp: new Date().toISOString()
|
||||||
};
|
};
|
||||||
localStorage.setItem('autoSaveData', JSON.stringify(autoSaveData));
|
localStorage.setItem('autoSaveData', JSON.stringify(autoSaveData));
|
||||||
|
|
||||||
// Prepare data for backend saving
|
|
||||||
const submissionData = {
|
|
||||||
establishment_id: localStorage.getItem('establishment_id'),
|
|
||||||
quarter: surveyData.quarter,
|
|
||||||
year: surveyData.year,
|
|
||||||
products: products.map(product => ({
|
|
||||||
product_id: product.product || null,
|
|
||||||
unit_id: product.unit || '0',
|
|
||||||
annual_installed_capacity: product.capacity || '0',
|
|
||||||
previous_quantity_period_one: product.octQuantity || '0',
|
|
||||||
previous_quantity_period_two: product.novQuantity || '0',
|
|
||||||
previous_quantity_period_three: product.decQuantity || '0',
|
|
||||||
previous_cost_period_one: product.octCost || '0',
|
|
||||||
previous_cost_period_two: product.novCost || '0',
|
|
||||||
previous_cost_period_three: product.decCost || '0',
|
|
||||||
current_quantity_period_one: product.janQuantity || '0',
|
|
||||||
current_quantity_period_two: product.febQuantity || '0',
|
|
||||||
current_quantity_period_three: product.marQuantity || '0',
|
|
||||||
current_cost_period_one: product.janCost || '0',
|
|
||||||
current_cost_period_two: product.febCost || '0',
|
|
||||||
current_cost_period_three: product.marCost || '0',
|
|
||||||
forecast_quantity_period_one: product.aprQuantity || '0',
|
|
||||||
forecast_quantity_period_two: product.mayQuantity || '0',
|
|
||||||
forecast_quantity_period_three: product.junQuantity || '0',
|
|
||||||
forecast_cost_period_one: product.aprCost || '0',
|
|
||||||
forecast_cost_period_two: product.mayCost || '0',
|
|
||||||
forecast_cost_period_three: product.junCost || '0',
|
|
||||||
variation_reason_master_id: product.variationReason === null ? null : (product.variationReason || '0'),
|
|
||||||
other_variation_reason: product.otherVariationReason || '0',
|
|
||||||
zero_target_reason_master_id: product.zeroTargetReason === null ? null : (product.zeroTargetReason || '0'),
|
|
||||||
other_zero_target_reason: product.otherZeroTargetReason || '0',
|
|
||||||
remarks: product.remarks || '',
|
|
||||||
is_active: true
|
|
||||||
}))
|
|
||||||
};
|
|
||||||
|
|
||||||
// Save to backend
|
|
||||||
await submitSurvey(submissionData);
|
|
||||||
|
|
||||||
// Update last auto-save timestamp
|
// Update last auto-save timestamp
|
||||||
setLastAutoSave(new Date());
|
setLastAutoSave(new Date());
|
||||||
|
|
||||||
// Show toast notification for auto-save
|
|
||||||
toast.success('Draft auto-saved successfully', {
|
|
||||||
position: "top-right",
|
|
||||||
autoClose: 2000,
|
|
||||||
hideProgressBar: false,
|
|
||||||
closeOnClick: true,
|
|
||||||
pauseOnHover: true,
|
|
||||||
draggable: true,
|
|
||||||
progress: undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Auto-save failed:', error);
|
console.error('Auto-save failed:', error);
|
||||||
toast.error('Auto-save failed. Please save manually.', {
|
toast.error('Auto-save failed. Please save manually.', {
|
||||||
position: "top-right",
|
position: "top-right",
|
||||||
autoClose: 3000,
|
autoClose: 3000,
|
||||||
});
|
});
|
||||||
|
} finally {
|
||||||
|
setIsAutoSaving(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1635,9 +1617,11 @@ useEffect(() => {
|
|||||||
|
|
||||||
// Check if auto-save data matches current establishment, quarter, and year
|
// Check if auto-save data matches current establishment, quarter, and year
|
||||||
const currentEstablishmentId = localStorage.getItem('establishment_id');
|
const currentEstablishmentId = localStorage.getItem('establishment_id');
|
||||||
|
const currentSessionQuarter = localStorage.getItem('currentQuarter') || '';
|
||||||
|
const currentSessionYear = localStorage.getItem('currentYear') || '';
|
||||||
const isSameContext = autoSaveData.establishment_id === currentEstablishmentId &&
|
const isSameContext = autoSaveData.establishment_id === currentEstablishmentId &&
|
||||||
autoSaveData.quarter === (quarter || '') &&
|
autoSaveData.quarter === currentSessionQuarter &&
|
||||||
autoSaveData.year === (year || '');
|
autoSaveData.year === currentSessionYear;
|
||||||
|
|
||||||
if (isSameContext && autoSaveData.products && autoSaveData.products.length > 0) {
|
if (isSameContext && autoSaveData.products && autoSaveData.products.length > 0) {
|
||||||
// Restore products from auto-save
|
// Restore products from auto-save
|
||||||
@ -1817,8 +1801,23 @@ useEffect(() => {
|
|||||||
hasFieldErrors = true;
|
hasFieldErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only quantity fields with asterisk (*) are mandatory (current and next quarter)
|
// Dynamic mandatory fields based on hide/show logic
|
||||||
const mandatoryQuantityFields = ['janQuantity', 'febQuantity', 'marQuantity', 'aprQuantity', 'mayQuantity', 'junQuantity'];
|
let mandatoryQuantityFields = [];
|
||||||
|
let mandatoryCostFields = [];
|
||||||
|
|
||||||
|
// Always require current quarter (Jan-Mar) unless hidden by Q1 2022/2025 logic
|
||||||
|
if (!shouldHidePreviousQuarter) {
|
||||||
|
mandatoryQuantityFields.push('janQuantity', 'febQuantity', 'marQuantity');
|
||||||
|
mandatoryCostFields.push('janCost', 'febCost', 'marCost');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add forecast quarter (Apr-Jun) unless forecast section is hidden
|
||||||
|
if (!shouldHideForecast) {
|
||||||
|
mandatoryQuantityFields.push('aprQuantity', 'mayQuantity', 'junQuantity');
|
||||||
|
mandatoryCostFields.push('aprCost', 'mayCost', 'junCost');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate mandatory quantity fields
|
||||||
mandatoryQuantityFields.forEach(field => {
|
mandatoryQuantityFields.forEach(field => {
|
||||||
if (!product[field] || product[field] === '' || parseFloat(product[field]) <= 0) {
|
if (!product[field] || product[field] === '' || parseFloat(product[field]) <= 0) {
|
||||||
errors[`${field}_${index}`] = 'Required';
|
errors[`${field}_${index}`] = 'Required';
|
||||||
@ -1827,8 +1826,7 @@ useEffect(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Only value fields with asterisk (*) are mandatory (current and next quarter)
|
// Validate mandatory cost fields
|
||||||
const mandatoryCostFields = ['janCost', 'febCost', 'marCost', 'aprCost', 'mayCost', 'junCost'];
|
|
||||||
mandatoryCostFields.forEach(field => {
|
mandatoryCostFields.forEach(field => {
|
||||||
if (!product[field] || product[field] === '' || parseFloat(product[field]) <= 0) {
|
if (!product[field] || product[field] === '' || parseFloat(product[field]) <= 0) {
|
||||||
errors[`${field}_${index}`] = 'Required';
|
errors[`${field}_${index}`] = 'Required';
|
||||||
|
|||||||
@ -2573,7 +2573,7 @@ const handleView = async (id) => {
|
|||||||
return 'ISIC code must contain only digits';
|
return 'ISIC code must contain only digits';
|
||||||
}
|
}
|
||||||
if (value.length < 10 || value.length > 32) {
|
if (value.length < 10 || value.length > 32) {
|
||||||
return 'Industry Code must be between 10 and 32 digits';
|
return 'Industry Code must be between 10 to 32 digits';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user