diff --git a/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx b/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx index 5cca6aa..dc04eef 100644 --- a/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx +++ b/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx @@ -1509,19 +1509,22 @@ useEffect(() => { // Auto-save functionality const [lastAutoSave, setLastAutoSave] = React.useState(null); + const [isAutoSaving, setIsAutoSaving] = React.useState(false); const autoSaveInterval = React.useRef(null); - // Auto-save every 1 second + // Auto-save every 30 seconds React.useEffect(() => { // Clear any existing interval if (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(() => { - autoSaveDraft(); - }, 1000); // 1 second = 1000 ms + if (!isAutoSaving) { + autoSaveDraft(); + } + }, 1000); // 2 seconds = 2000 ms // Cleanup interval on unmount return () => { @@ -1533,7 +1536,10 @@ useEffect(() => { // Auto-save function const autoSaveDraft = async () => { + if (isAutoSaving) return; // Prevent overlapping saves + try { + setIsAutoSaving(true); // Check if there's any data to save const hasAnyData = products.some(product => product.product || @@ -1554,68 +1560,42 @@ useEffect(() => { 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 = { - establishment_id: localStorage.getItem('establishment_id'), - quarter: surveyData.quarter, - year: surveyData.year, + establishment_id: establishmentId, + quarter: currentQuarter, + year: currentYear, products: products, timestamp: new Date().toISOString() }; 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 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) { console.error('Auto-save failed:', error); @@ -1623,6 +1603,8 @@ useEffect(() => { position: "top-right", autoClose: 3000, }); + } finally { + setIsAutoSaving(false); } }; @@ -1635,9 +1617,11 @@ useEffect(() => { // Check if auto-save data matches current establishment, quarter, and year const currentEstablishmentId = localStorage.getItem('establishment_id'); + const currentSessionQuarter = localStorage.getItem('currentQuarter') || ''; + const currentSessionYear = localStorage.getItem('currentYear') || ''; const isSameContext = autoSaveData.establishment_id === currentEstablishmentId && - autoSaveData.quarter === (quarter || '') && - autoSaveData.year === (year || ''); + autoSaveData.quarter === currentSessionQuarter && + autoSaveData.year === currentSessionYear; if (isSameContext && autoSaveData.products && autoSaveData.products.length > 0) { // Restore products from auto-save @@ -1817,8 +1801,23 @@ useEffect(() => { hasFieldErrors = true; } - // Only quantity fields with asterisk (*) are mandatory (current and next quarter) - const mandatoryQuantityFields = ['janQuantity', 'febQuantity', 'marQuantity', 'aprQuantity', 'mayQuantity', 'junQuantity']; + // Dynamic mandatory fields based on hide/show logic + 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 => { if (!product[field] || product[field] === '' || parseFloat(product[field]) <= 0) { errors[`${field}_${index}`] = 'Required'; @@ -1827,8 +1826,7 @@ useEffect(() => { } }); - // Only value fields with asterisk (*) are mandatory (current and next quarter) - const mandatoryCostFields = ['janCost', 'febCost', 'marCost', 'aprCost', 'mayCost', 'junCost']; + // Validate mandatory cost fields mandatoryCostFields.forEach(field => { if (!product[field] || product[field] === '' || parseFloat(product[field]) <= 0) { errors[`${field}_${index}`] = 'Required'; diff --git a/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx b/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx index 69d58ca..693a83f 100644 --- a/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx +++ b/ipi-survey-platform/src/pages/Admin/configuration/CompanyProfile.jsx @@ -2573,7 +2573,7 @@ const handleView = async (id) => { return 'ISIC code must contain only digits'; } 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'; } }