diff --git a/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx b/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx
index 2e1af63..006cf52 100644
--- a/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx
+++ b/ipi-survey-platform/src/components/dashboard/SubmissionHistory.jsx
@@ -159,12 +159,60 @@ export const SubmissionHistory = ({ history = [], loading = false, error = '' })
const pageSize = 10;
const navigate = useNavigate();
-
-
const handleViewDetails = (submission) => {
navigate('/overview', { state: { selectedSubmission: submission } });
};
+const handleResubmit = async (submission) => {
+ try {
+ const response = await fetchSubmissionDetail(submission.id);
+ const submissionData = response.data;
+
+ // Structure the data in the format expected by the component
+ const formattedData = {
+ ...submissionData,
+ establishment: {
+ ...submissionData.establishment,
+ establishment_contact_email: submissionData.establishment.establishment_contact_email,
+ emirate: submissionData.establishment.establishment_emirate_id,
+ establishment_emirate_id: submissionData.establishment.establishment_emirate_id
+ },
+ employeeInfo: {
+ emiratiMale: submissionData.establishment.emirati_male,
+ emiratiFemale: submissionData.establishment.emirati_female,
+ nonEmiratiMale: submissionData.establishment.non_emirati_male,
+ nonEmiratiFemale: submissionData.establishment.non_emirati_female,
+ totalEmirati: submissionData.establishment.total_emirati,
+ totalEmployees: submissionData.establishment.total_employees
+ },
+ products: submissionData.products || [],
+ quarterWindow: submissionData.quarter_window || {}
+ };
+
+ // Save the complete data to localStorage
+ localStorage.setItem('resubmissionData', JSON.stringify(formattedData));
+
+ // Save products separately
+ if (submissionData.products && submissionData.products.length > 0) {
+ localStorage.setItem('submissionProducts', JSON.stringify(submissionData.products));
+ }
+
+ // Set resubmission flags
+ localStorage.setItem('isResubmission', 'true');
+
+ // Navigate to survey with resubmission state
+ navigate('/survey', {
+ state: {
+ submission: formattedData,
+ isResubmit: true,
+ fromResubmit: true
+ }
+ });
+ } catch (error) {
+ console.error('Error fetching submission details:', error);
+ showToast('Failed to load submission for resubmission', 'error');
+ }
+};
const handleEdit = async (submission) => {
if (submission.status.toLowerCase() === 'draft') {
try {
diff --git a/ipi-survey-platform/src/components/overview/ProductDetails.jsx b/ipi-survey-platform/src/components/overview/ProductDetails.jsx
index 1f0bcde..cb11604 100644
--- a/ipi-survey-platform/src/components/overview/ProductDetails.jsx
+++ b/ipi-survey-platform/src/components/overview/ProductDetails.jsx
@@ -52,7 +52,7 @@ const ProductDetails = ({
bgColor: 'bg-red-50',
textColor: 'text-red-600',
iconColor: 'text-red-500',
- message: 'Your survey has been rejected. Please review and resubmit.',
+ message: 'Your survey has been rejected.',
icon: '/assets/images/Vector-rejected.svg',
iconAlt: 'Rejected',
iconClassName: 'mr-2 h-5 w-5 flex-shrink-0'
@@ -357,8 +357,8 @@ const ProductDetails = ({
}}
className="ml-auto px-3 py-1 bg-[#FEF2F2] text-[#7C2320] text-sm font-medium rounded hover:bg-[#FEF2F2] transition-colors"
>
- Resubmit
-
+ {/* Resubmit */}
+ {/*
*/}
)}
diff --git a/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx b/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx
index 007975d..879b008 100644
--- a/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx
+++ b/ipi-survey-platform/src/components/survey/EstablishmentInfo/EstablishmentInfo.jsx
@@ -338,41 +338,40 @@ const EstablishmentInfo = ({
};
// Store establishment data in localStorage during resubmission
- React.useEffect(() => {
- // Check if this is a resubmission
- const isResubmit = location.state?.fromResubmit;
-
- if (isResubmit && data) {
- try {
- // Get existing resubmission data if it exists
- const existingData = JSON.parse(localStorage.getItem('resubmissionData') || '{}');
- // Update with establishment data
- const updatedData = {
- ...existingData,
- establishment: {
- id: data.establishmentId,
- name: data.establishmentName,
- permanent_factory_code: data.permanentFactoryCode,
- industry_code: data.industryCode,
- license_number: data.licenseNumber,
- isic_code: data.isicCode,
- emirate: data.emirate,
- establishment_contact_email: data.establishment_contact_email,
- employeeInfo: data.employeeInfo || {}
- },
- // Ensure quarter and year are included
- quarter: data.quarter || surveyData.quarter,
- year: data.year || surveyData.year
- };
-
-
- // Save back to localStorage
- localStorage.setItem('resubmissionData', JSON.stringify(updatedData));
- } catch (error) {
- console.error('Error updating resubmission data with establishment info:', error);
- }
+// Store establishment data in localStorage during resubmission
+React.useEffect(() => {
+ const isResubmit = location.state?.fromResubmit;
+
+ if (isResubmit) {
+ try {
+ const resubmissionData = JSON.parse(localStorage.getItem('resubmissionData') || '{}');
+ const establishmentData = resubmissionData.establishment || {};
+
+ // Update the form with the resubmission data
+ onChange({
+ ...data,
+ establishmentId: establishmentData.id,
+ establishmentName: establishmentData.factory_name,
+ permanentFactoryCode: establishmentData.permanent_factory_code,
+ industryCode: establishmentData.industry_code,
+ licenseNumber: establishmentData.license_number,
+ isicCode: establishmentData.isic_code,
+ emirate: establishmentData.establishment_emirate_id,
+ establishment_contact_email: establishmentData.establishment_contact_email,
+ employeeInfo: {
+ emiratiMale: establishmentData.emirati_male || '',
+ nonEmiratiMale: establishmentData.non_emirati_male || '',
+ emiratiFemale: establishmentData.emirati_female || '',
+ nonEmiratiFemale: establishmentData.non_emirati_female || '',
+ totalEmployees: establishmentData.total_employees || '',
+ totalEmirati: establishmentData.total_emirati || ''
+ }
+ });
+ } catch (error) {
+ console.error('Error processing resubmission data:', error);
}
- }, [data, location.state?.fromResubmit, surveyData.quarter, surveyData.year]);
+ }
+}, [location.state]);
const info = React.useMemo(
() => ({
diff --git a/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx b/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx
index 8880382..5db3ef8 100644
--- a/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx
+++ b/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx
@@ -97,6 +97,8 @@ const SearchableSelect = ({
const [searchTerm, setSearchTerm] = React.useState('');
const selectRef = React.useRef(null);
const inputRef = React.useRef(null);
+ const [savedQuarter, setSavedQuarter] = React.useState(null);
+ const [savedYear, setSavedYear] = React.useState(null);
// Close dropdown when clicking outside
React.useEffect(() => {
@@ -494,6 +496,116 @@ const ProductData = ({
fetchQuarterPeriods();
}, [quarter, year]);
+ // Load resubmission data when component mounts
+useEffect(() => {
+ const loadResubmissionData = async () => {
+ try {
+ // Check for resubmission data in localStorage and location state
+ const resubmissionData = localStorage.getItem('resubmissionData') ||
+ (location.state?.submission && JSON.stringify(location.state.submission));
+
+ if (resubmissionData) {
+ const parsedData = JSON.parse(resubmissionData);
+
+ if (parsedData.products && Array.isArray(parsedData.products) && parsedData.products.length > 0) {
+ console.log('Loading resubmission products:', parsedData.products);
+
+ // Wait for product options to be loaded
+ if (productOptions.length === 0) {
+ await new Promise(resolve => {
+ const checkProducts = setInterval(() => {
+ if (productOptions.length > 0) {
+ clearInterval(checkProducts);
+ resolve();
+ }
+ }, 100);
+ });
+ }
+
+ // Map the products to match the expected format
+ const mappedProducts = await Promise.all(parsedData.products.map(async (product, index) => {
+ // Find the matching product in productOptions
+ const matchedProduct = productOptions.find(
+ p => p.value === product.product_id?.toString() ||
+ p.productId === product.product_id ||
+ p.originalData?.id === product.product_id
+ );
+
+ return {
+ id: product.id || `resubmit-${index}-${Date.now()}`,
+ product: matchedProduct?.value || product.product_id?.toString() || '',
+ productId: product.product_id,
+ productName: matchedProduct?.name || product.product?.product_name || product.product_name || '',
+ unit: product.unit_id?.toString() || product.unit?.id?.toString() || '',
+ unitName: product.unit?.uom || product.unit_name || '',
+ capacity: product.annual_installed_capacity?.toString() || '0',
+
+ // Previous Quarter (Q4) - October, November, December
+ octQuantity: product.previous_quantity_period_one?.toString() || '0',
+ novQuantity: product.previous_quantity_period_two?.toString() || '0',
+ decQuantity: product.previous_quantity_period_three?.toString() || '0',
+ octCost: product.previous_cost_period_one?.toString() || '0',
+ novCost: product.previous_cost_period_two?.toString() || '0',
+ decCost: product.previous_cost_period_three?.toString() || '0',
+
+ // Current Quarter (Q1) - January, February, March
+ janQuantity: product.current_quantity_period_one?.toString() || '0',
+ febQuantity: product.current_quantity_period_two?.toString() || '0',
+ marQuantity: product.current_quantity_period_three?.toString() || '0',
+ janCost: product.current_cost_period_one?.toString() || '0',
+ febCost: product.current_cost_period_two?.toString() || '0',
+ marCost: product.current_cost_period_three?.toString() || '0',
+
+ // Forecast Quarter (Q2) - April, May, June
+ aprQuantity: product.forecast_quantity_period_one?.toString() || '0',
+ mayQuantity: product.forecast_quantity_period_two?.toString() || '0',
+ junQuantity: product.forecast_quantity_period_three?.toString() || '0',
+ aprCost: product.forecast_cost_period_one?.toString() || '0',
+ mayCost: product.forecast_cost_period_two?.toString() || '0',
+ junCost: product.forecast_cost_period_three?.toString() || '0',
+
+ // Variation reasons
+ variationReason: product.variation_reason_master_id?.toString() || '',
+ otherVariationReason: product.other_variation_reason || '',
+ zeroTargetReason: product.zero_target_reason_master_id?.toString() || '',
+ otherZeroTargetReason: product.other_zero_target_reason || '',
+ remarks: product.remarks || '',
+
+ // Additional fields for better tracking
+ isResubmitted: true,
+ originalData: product
+ };
+ }));
+
+ console.log('Mapped products for resubmission:', mappedProducts);
+
+ // Update the products state with the mapped products
+ if (mappedProducts.length > 0) {
+ onProductsChange(mappedProducts);
+
+ // Set selected product IDs for tracking
+ setSelectedProductIds(mappedProducts
+ .map(p => p.productId || p.product)
+ .filter(Boolean)
+ );
+
+ // Set initial tab to show the first product
+ setActiveTab('current');
+ }
+ }
+ }
+ } catch (error) {
+ console.error('Error loading resubmission data:', error);
+ }
+ };
+
+ // Only load resubmission data if we're in resubmit mode and don't have products yet
+ const isResubmit = location.state?.isResubmit || false;
+ if (isResubmit && (!products || products.length === 0)) {
+ loadResubmissionData();
+ }
+}, [onProductsChange, products, productOptions, location.state]);
+
const handleSaveDraft = async () => {
try {
setIsSavingDraft(true);
@@ -882,22 +994,43 @@ useEffect(() => {
const formattedProducts = productsList.map(product => {
// Handle nested properties with dot notation
- const productName = product['product.product_name'] || product.product_name || '';
- const hsCode = product['product.hs_code'] || product.hs_code || '';
- const unitName = product['product.unit.uom'] || '';
+ const productName = product['product.product_name'] || product.product_name || product.product?.product_name || '';
+ const hsCode = product['product.hs_code'] || product.hs_code || product.product?.hs_code || '';
+ const unitName = product['product.unit.uom'] || product.unit?.uom || '';
+ const productId = product.product_id || product.product?.id || product.id;
return {
- value: product.id.toString(),
+ value: productId.toString(),
label: hsCode ? `${hsCode} - ${productName}` : productName,
originalData: product,
hsCode: hsCode,
name: productName,
- productId: product.product_id, // Use product_id instead of id
- product_id: product.product_id, // Add product_id directly to the object
+ productId: productId,
+ product_id: productId,
unit: unitName
};
});
- setProductOptions(formattedProducts);
+
+ setProductOptions(prevOptions => {
+ // Only update if there are new products to avoid unnecessary re-renders
+ if (JSON.stringify(prevOptions) !== JSON.stringify(formattedProducts)) {
+ return formattedProducts;
+ }
+ return prevOptions;
+ });
+
+ // If we're in resubmit mode and have products in localStorage, trigger the resubmission load
+ const isResubmit = location.state?.isResubmit || false;
+ const resubmissionData = localStorage.getItem('resubmissionData');
+
+ if (isResubmit && resubmissionData) {
+ const parsedData = JSON.parse(resubmissionData);
+ if (parsedData.products && parsedData.products.length > 0) {
+ // Force a re-render to trigger the resubmission data load
+ onProductsChange([]);
+ }
+ }
+
} catch (error) {
console.error('Error fetching products:', error);
setProductsError('Failed to load products. Please try again.');
@@ -915,7 +1048,7 @@ useEffect(() => {
};
fetchEstablishmentProducts();
- }, []);
+ }, [location.state?.isResubmit]); // Add isResubmit to dependency array
// Moved inside the component
React.useEffect(() => {
const maxId = products.reduce((max, item) => (item && typeof item.id === 'number' ? Math.max(max, item.id) : max), 0);
diff --git a/ipi-survey-platform/src/pages/Overview/Overview.jsx b/ipi-survey-platform/src/pages/Overview/Overview.jsx
index 3536fa4..85f05d9 100644
--- a/ipi-survey-platform/src/pages/Overview/Overview.jsx
+++ b/ipi-survey-platform/src/pages/Overview/Overview.jsx
@@ -226,6 +226,57 @@ const showToast = (message, type = 'success') => {
className="w-5 h-5 text-[#92722A] opacity-60 hover:opacity-100 transition-opacity cursor-pointer"
style={{ filter: 'invert(36%) sepia(49%) saturate(680%) hue-rotate(1deg) brightness(89%) contrast(91%)' }}
title="Resubmit"
+ onClick={async (e) => {
+ e.stopPropagation();
+ try {
+ const response = await fetchSubmissionDetail(record.id);
+ const submissionData = response.data;
+
+ // Structure the data in the format expected by the component
+ const formattedData = {
+ ...submissionData,
+ establishment: {
+ ...submissionData.establishment,
+ establishment_contact_email: submissionData.establishment.establishment_contact_email,
+ emirate: submissionData.establishment.establishment_emirate_id,
+ establishment_emirate_id: submissionData.establishment.establishment_emirate_id
+ },
+ employeeInfo: {
+ emiratiMale: submissionData.establishment.emirati_male,
+ emiratiFemale: submissionData.establishment.emirati_female,
+ nonEmiratiMale: submissionData.establishment.non_emirati_male,
+ nonEmiratiFemale: submissionData.establishment.non_emirati_female,
+ totalEmirati: submissionData.establishment.total_emirati,
+ totalEmployees: submissionData.establishment.total_employees
+ },
+ products: submissionData.products || [],
+ quarterWindow: submissionData.quarter_window || {}
+ };
+
+ // Save the complete data to localStorage
+ localStorage.setItem('resubmissionData', JSON.stringify(formattedData));
+
+ // Save products separately
+ if (submissionData.products && submissionData.products.length > 0) {
+ localStorage.setItem('submissionProducts', JSON.stringify(submissionData.products));
+ }
+
+ // Set resubmission flags
+ localStorage.setItem('isResubmission', 'true');
+
+ // Navigate to survey with resubmission state
+ navigate('/survey', {
+ state: {
+ submission: formattedData,
+ isResubmit: true,
+ fromResubmit: true
+ }
+ });
+ } catch (error) {
+ console.error('Error preparing resubmission:', error);
+ // Optionally show error to user
+ }
+ }}
/>
)}