added resumit flow and changes in quaterly surveys
This commit is contained in:
parent
63c7fb461d
commit
a24a4064e7
@ -159,12 +159,60 @@ export const SubmissionHistory = ({ history = [], loading = false, error = '' })
|
|||||||
const pageSize = 10;
|
const pageSize = 10;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleViewDetails = (submission) => {
|
const handleViewDetails = (submission) => {
|
||||||
navigate('/overview', { state: { selectedSubmission: 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) => {
|
const handleEdit = async (submission) => {
|
||||||
if (submission.status.toLowerCase() === 'draft') {
|
if (submission.status.toLowerCase() === 'draft') {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -52,7 +52,7 @@ const ProductDetails = ({
|
|||||||
bgColor: 'bg-red-50',
|
bgColor: 'bg-red-50',
|
||||||
textColor: 'text-red-600',
|
textColor: 'text-red-600',
|
||||||
iconColor: 'text-red-500',
|
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',
|
icon: '/assets/images/Vector-rejected.svg',
|
||||||
iconAlt: 'Rejected',
|
iconAlt: 'Rejected',
|
||||||
iconClassName: 'mr-2 h-5 w-5 flex-shrink-0'
|
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"
|
className="ml-auto px-3 py-1 bg-[#FEF2F2] text-[#7C2320] text-sm font-medium rounded hover:bg-[#FEF2F2] transition-colors"
|
||||||
>
|
>
|
||||||
Resubmit
|
{/* Resubmit */}
|
||||||
<img src="/assets/images/arrow-right-bold 1.svg" alt="" className="w-4 h-4 ml-1 inline-block" />
|
{/* <img src="/assets/images/arrow-right-bold 1.svg" alt="" className="w-4 h-4 ml-1 inline-block" /> */}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -338,41 +338,40 @@ const EstablishmentInfo = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Store establishment data in localStorage during resubmission
|
// Store establishment data in localStorage during resubmission
|
||||||
React.useEffect(() => {
|
// Store establishment data in localStorage during resubmission
|
||||||
// Check if this is a resubmission
|
React.useEffect(() => {
|
||||||
const isResubmit = location.state?.fromResubmit;
|
const isResubmit = location.state?.fromResubmit;
|
||||||
|
|
||||||
if (isResubmit && data) {
|
if (isResubmit) {
|
||||||
try {
|
try {
|
||||||
// Get existing resubmission data if it exists
|
const resubmissionData = JSON.parse(localStorage.getItem('resubmissionData') || '{}');
|
||||||
const existingData = JSON.parse(localStorage.getItem('resubmissionData') || '{}');
|
const establishmentData = resubmissionData.establishment || {};
|
||||||
// Update with establishment data
|
|
||||||
const updatedData = {
|
// Update the form with the resubmission data
|
||||||
...existingData,
|
onChange({
|
||||||
establishment: {
|
...data,
|
||||||
id: data.establishmentId,
|
establishmentId: establishmentData.id,
|
||||||
name: data.establishmentName,
|
establishmentName: establishmentData.factory_name,
|
||||||
permanent_factory_code: data.permanentFactoryCode,
|
permanentFactoryCode: establishmentData.permanent_factory_code,
|
||||||
industry_code: data.industryCode,
|
industryCode: establishmentData.industry_code,
|
||||||
license_number: data.licenseNumber,
|
licenseNumber: establishmentData.license_number,
|
||||||
isic_code: data.isicCode,
|
isicCode: establishmentData.isic_code,
|
||||||
emirate: data.emirate,
|
emirate: establishmentData.establishment_emirate_id,
|
||||||
establishment_contact_email: data.establishment_contact_email,
|
establishment_contact_email: establishmentData.establishment_contact_email,
|
||||||
employeeInfo: data.employeeInfo || {}
|
employeeInfo: {
|
||||||
},
|
emiratiMale: establishmentData.emirati_male || '',
|
||||||
// Ensure quarter and year are included
|
nonEmiratiMale: establishmentData.non_emirati_male || '',
|
||||||
quarter: data.quarter || surveyData.quarter,
|
emiratiFemale: establishmentData.emirati_female || '',
|
||||||
year: data.year || surveyData.year
|
nonEmiratiFemale: establishmentData.non_emirati_female || '',
|
||||||
};
|
totalEmployees: establishmentData.total_employees || '',
|
||||||
|
totalEmirati: establishmentData.total_emirati || ''
|
||||||
|
}
|
||||||
// Save back to localStorage
|
});
|
||||||
localStorage.setItem('resubmissionData', JSON.stringify(updatedData));
|
} catch (error) {
|
||||||
} catch (error) {
|
console.error('Error processing resubmission data:', error);
|
||||||
console.error('Error updating resubmission data with establishment info:', error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [data, location.state?.fromResubmit, surveyData.quarter, surveyData.year]);
|
}
|
||||||
|
}, [location.state]);
|
||||||
|
|
||||||
const info = React.useMemo(
|
const info = React.useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
|||||||
@ -97,6 +97,8 @@ const SearchableSelect = ({
|
|||||||
const [searchTerm, setSearchTerm] = React.useState('');
|
const [searchTerm, setSearchTerm] = React.useState('');
|
||||||
const selectRef = React.useRef(null);
|
const selectRef = React.useRef(null);
|
||||||
const inputRef = 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
|
// Close dropdown when clicking outside
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -494,6 +496,116 @@ const ProductData = ({
|
|||||||
fetchQuarterPeriods();
|
fetchQuarterPeriods();
|
||||||
}, [quarter, year]);
|
}, [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 () => {
|
const handleSaveDraft = async () => {
|
||||||
try {
|
try {
|
||||||
setIsSavingDraft(true);
|
setIsSavingDraft(true);
|
||||||
@ -882,22 +994,43 @@ useEffect(() => {
|
|||||||
|
|
||||||
const formattedProducts = productsList.map(product => {
|
const formattedProducts = productsList.map(product => {
|
||||||
// Handle nested properties with dot notation
|
// Handle nested properties with dot notation
|
||||||
const productName = product['product.product_name'] || product.product_name || '';
|
const productName = product['product.product_name'] || product.product_name || product.product?.product_name || '';
|
||||||
const hsCode = product['product.hs_code'] || product.hs_code || '';
|
const hsCode = product['product.hs_code'] || product.hs_code || product.product?.hs_code || '';
|
||||||
const unitName = product['product.unit.uom'] || '';
|
const unitName = product['product.unit.uom'] || product.unit?.uom || '';
|
||||||
|
const productId = product.product_id || product.product?.id || product.id;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
value: product.id.toString(),
|
value: productId.toString(),
|
||||||
label: hsCode ? `${hsCode} - ${productName}` : productName,
|
label: hsCode ? `${hsCode} - ${productName}` : productName,
|
||||||
originalData: product,
|
originalData: product,
|
||||||
hsCode: hsCode,
|
hsCode: hsCode,
|
||||||
name: productName,
|
name: productName,
|
||||||
productId: product.product_id, // Use product_id instead of id
|
productId: productId,
|
||||||
product_id: product.product_id, // Add product_id directly to the object
|
product_id: productId,
|
||||||
unit: unitName
|
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) {
|
} catch (error) {
|
||||||
console.error('Error fetching products:', error);
|
console.error('Error fetching products:', error);
|
||||||
setProductsError('Failed to load products. Please try again.');
|
setProductsError('Failed to load products. Please try again.');
|
||||||
@ -915,7 +1048,7 @@ useEffect(() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetchEstablishmentProducts();
|
fetchEstablishmentProducts();
|
||||||
}, []);
|
}, [location.state?.isResubmit]); // Add isResubmit to dependency array
|
||||||
// Moved inside the component
|
// Moved inside the component
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const maxId = products.reduce((max, item) => (item && typeof item.id === 'number' ? Math.max(max, item.id) : max), 0);
|
const maxId = products.reduce((max, item) => (item && typeof item.id === 'number' ? Math.max(max, item.id) : max), 0);
|
||||||
|
|||||||
@ -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"
|
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%)' }}
|
style={{ filter: 'invert(36%) sepia(49%) saturate(680%) hue-rotate(1deg) brightness(89%) contrast(91%)' }}
|
||||||
title="Resubmit"
|
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
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user