FCSC Bug fixed
This commit is contained in:
parent
8186987cb0
commit
8b1b09d8ba
@ -84,17 +84,29 @@ export const SurveyStatus = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleStartSurvey = (survey) => {
|
const handleStartSurvey = (survey) => {
|
||||||
// Store the survey data in localStorage
|
// Prepare survey data with all required fields
|
||||||
localStorage.setItem('currentSurvey', JSON.stringify({
|
const surveyData = {
|
||||||
quarter: survey.quarter,
|
quarter: survey.quarter,
|
||||||
year: survey.year,
|
year: survey.year,
|
||||||
startDate: survey.startDate,
|
startDate: survey.startDate,
|
||||||
endDate: survey.endDate,
|
endDate: survey.endDate,
|
||||||
title: survey.title
|
title: survey.title,
|
||||||
}));
|
// Include establishment data if available
|
||||||
|
establishment: survey.establishment || null
|
||||||
|
};
|
||||||
|
|
||||||
// Navigate to the survey page
|
// Store the survey data in localStorage
|
||||||
navigate('/survey');
|
localStorage.setItem('currentSurvey', JSON.stringify(surveyData));
|
||||||
|
|
||||||
|
// Navigate to the survey page with survey data in state
|
||||||
|
navigate('/survey', {
|
||||||
|
state: {
|
||||||
|
survey: surveyData,
|
||||||
|
isResubmit: survey.status === 'Submitted', // Mark as resubmit if status is 'Submitted'
|
||||||
|
// Include establishment data in the location state
|
||||||
|
establishment: survey.establishment || null
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const nextDeadline = dashboardData?.next_deadline;
|
const nextDeadline = dashboardData?.next_deadline;
|
||||||
|
|||||||
@ -160,21 +160,21 @@ const EstablishmentInfo = ({
|
|||||||
() => ({
|
() => ({
|
||||||
quarter: surveyData.quarter || '',
|
quarter: surveyData.quarter || '',
|
||||||
year: surveyData.year || '',
|
year: surveyData.year || '',
|
||||||
establishmentName: '',
|
establishmentName: data.establishmentName || '',
|
||||||
permanentFactoryCode: '',
|
permanentFactoryCode: data.permanentFactoryCode || '',
|
||||||
industryCode: '',
|
industryCode: data.industryCode || '',
|
||||||
licenseNumber: '',
|
licenseNumber: data.licenseNumber || '',
|
||||||
isicCode: '',
|
isicCode: data.isicCode || '',
|
||||||
emirate: '',
|
emirate: data.emirate || '',
|
||||||
establishment_contact_email: data?.establishment_contact_email || '',
|
establishment_contact_email: data.establishment_contact_email || '',
|
||||||
employeeInfo: {
|
employeeInfo: {
|
||||||
...defaultEmployeeInfo,
|
...defaultEmployeeInfo,
|
||||||
...(data.employeeInfo || {}),
|
...(data.employeeInfo || {}),
|
||||||
},
|
},
|
||||||
...data,
|
...data,
|
||||||
}),
|
}),
|
||||||
[data]
|
[data, surveyData.quarter, surveyData.year]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleFieldChange = (field) => (event) => {
|
const handleFieldChange = (field) => (event) => {
|
||||||
onChange({
|
onChange({
|
||||||
|
|||||||
@ -314,22 +314,23 @@ const ProductData = ({
|
|||||||
const [unitsError, setUnitsError] = React.useState('');
|
const [unitsError, setUnitsError] = React.useState('');
|
||||||
const [activeTab, setActiveTab] = React.useState('current');
|
const [activeTab, setActiveTab] = React.useState('current');
|
||||||
const [isInitialLoad, setIsInitialLoad] = React.useState(true);
|
const [isInitialLoad, setIsInitialLoad] = React.useState(true);
|
||||||
|
const [quarterPeriods, setQuarterPeriods] = React.useState(null);
|
||||||
|
const [isLoadingPeriods, setIsLoadingPeriods] = React.useState(false);
|
||||||
|
const [showOtherVariationReason, setShowOtherVariationReason] = React.useState({});
|
||||||
|
const [showOtherZeroTargetReason, setShowOtherZeroTargetReason] = React.useState({});
|
||||||
|
const [formErrors, setFormErrors] = React.useState({});
|
||||||
const [remarks, setRemarks] = React.useState(() => {
|
const [remarks, setRemarks] = React.useState(() => {
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
const savedRemarks = localStorage.getItem('surveyRemarks');
|
return localStorage.getItem('surveyRemarks') || '';
|
||||||
return savedRemarks || '';
|
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
const [formErrors, setFormErrors] = React.useState({});
|
|
||||||
const [quarterPeriods, setQuarterPeriods] = useState(null);
|
|
||||||
const [isLoadingPeriods, setIsLoadingPeriods] = useState(false);
|
|
||||||
|
|
||||||
const handleRemarksChange = (e) => {
|
const handleRemarksChange = (e) => {
|
||||||
const newRemarks = e.target.value;
|
const value = e.target.value;
|
||||||
setRemarks(newRemarks);
|
setRemarks(value);
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
localStorage.setItem('surveyRemarks', newRemarks);
|
localStorage.setItem('surveyRemarks', value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -362,12 +363,13 @@ const ProductData = ({
|
|||||||
setReasonsError('');
|
setReasonsError('');
|
||||||
try {
|
try {
|
||||||
const reasons = await fetchVariationReasons({ signal: variationController.signal });
|
const reasons = await fetchVariationReasons({ signal: variationController.signal });
|
||||||
setVariationReasons(reasons);
|
console.log('Loaded variation reasons:', reasons);
|
||||||
|
setVariationReasons(reasons || []);
|
||||||
setReasonsError('');
|
setReasonsError('');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch variation reasons:', error);
|
||||||
if (error.name !== 'AbortError') {
|
if (error.name !== 'AbortError') {
|
||||||
// console.error('Failed to fetch variation reasons', error);
|
setReasonsError('Failed to load variation reasons.');
|
||||||
// setReasonsError('Failed to load variation reasons.');
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setIsLoadingReasons(false);
|
setIsLoadingReasons(false);
|
||||||
@ -464,12 +466,12 @@ const ProductData = ({
|
|||||||
const formattedProducts = response.data.establishment_products.map(item => {
|
const formattedProducts = response.data.establishment_products.map(item => {
|
||||||
const product = item.product || {};
|
const product = item.product || {};
|
||||||
return {
|
return {
|
||||||
value: product.hs_code || '',
|
value: item.product_id, // Use product_id as the value
|
||||||
label: product.product_name ?
|
label: product.product_name ?
|
||||||
`${product.product_name} (${product.hs_code || 'N/A'})` :
|
`${product.product_name} (${product.hs_code || 'N/A'})` :
|
||||||
'Unknown Product',
|
'Unknown Product',
|
||||||
productId: item.product_id, // Include the actual product ID
|
originalData: product, // Store the full product data
|
||||||
productData: product // Include the full product data
|
hsCode: product.hs_code // Store HS code separately for display
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -674,86 +676,96 @@ const location = useLocation();
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const handleProductSelect = async (productId, establishmentId, id) => {
|
|
||||||
// if (!productId || !establishmentId) return;
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// const forecastData = await fetchPreviousForecastData(productId, establishmentId);
|
|
||||||
// console.log('Forecast data received:', forecastData);
|
|
||||||
|
|
||||||
// if (!forecastData) {
|
|
||||||
// console.warn('No forecast data received for product:', productId);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Check if the response has a data property (nested response) or is the data itself
|
|
||||||
// const data = forecastData.data || forecastData;
|
|
||||||
|
|
||||||
// const updatedProducts = products.map(product => {
|
|
||||||
// if (product.id === id) {
|
|
||||||
// return {
|
|
||||||
// ...product,
|
|
||||||
// octQuantity: data.previous_quantity_period_one || '',
|
|
||||||
// novQuantity: data.previous_quantity_period_two || '',
|
|
||||||
// decQuantity: data.previous_quantity_period_three || '',
|
|
||||||
// octCost: data.previous_cost_period_one || '',
|
|
||||||
// novCost: data.previous_cost_period_two || '',
|
|
||||||
// decCost: data.previous_cost_period_three || '',
|
|
||||||
// capacity: data.annual_installed_capacity || ''
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// return product;
|
|
||||||
// });
|
|
||||||
|
|
||||||
// onProductsChange(updatedProducts);
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error('Error in handleProductSelect:', error);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
const updateProductField = (id, field, value, options = null) => {
|
const updateProductField = (id, field, value, options = null) => {
|
||||||
const updatedProducts = products.map(product => {
|
const updatedProducts = products.map(product => {
|
||||||
if (product.id === id) {
|
if (product.id === id) {
|
||||||
// Clear error for the field being updated
|
// Check if 'Others' is selected for variation reason
|
||||||
|
if (field === 'variationReason' || field === 'otherVariationReason') {
|
||||||
|
if (field === 'variationReason') {
|
||||||
|
const selectedReason = options?.find(r => r.value === value || r.id === value);
|
||||||
|
// Check both name and label for 'other' to be more flexible
|
||||||
|
const isOtherSelected = selectedReason && (
|
||||||
|
(selectedReason.name && selectedReason.name.toLowerCase().includes('other')) ||
|
||||||
|
(selectedReason.label && selectedReason.label.toLowerCase().includes('other'))
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Selected reason:', selectedReason, 'Is other:', isOtherSelected);
|
||||||
|
|
||||||
|
// Update the showOtherVariationReason state for this product
|
||||||
|
setShowOtherVariationReason(prev => ({
|
||||||
|
...prev,
|
||||||
|
[id]: isOtherSelected
|
||||||
|
}));
|
||||||
|
|
||||||
|
// If not 'Others', clear any existing other reason
|
||||||
|
if (!isOtherSelected) {
|
||||||
|
return {
|
||||||
|
...product,
|
||||||
|
variationReason: value,
|
||||||
|
variationReasonName: selectedReason?.label || selectedReason?.name || '',
|
||||||
|
otherVariationReason: '',
|
||||||
|
[field]: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...product,
|
||||||
|
variationReason: value,
|
||||||
|
variationReasonName: selectedReason?.label || selectedReason?.name || '',
|
||||||
|
[field]: value
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Handle otherVariationReason update
|
||||||
|
return {
|
||||||
|
...product,
|
||||||
|
[field]: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...product,
|
||||||
|
variationReason: value,
|
||||||
|
variationReasonName: selectedReason?.label || selectedReason?.name || '',
|
||||||
|
[field]: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle product selection
|
||||||
if (field === 'product') {
|
if (field === 'product') {
|
||||||
const selectedProduct = options?.find(opt => opt.value === value);
|
const selectedProduct = options?.find(opt => opt.value === value);
|
||||||
const updatedProduct = {
|
const updatedProduct = {
|
||||||
...product,
|
...product,
|
||||||
product: selectedProduct?.value || value,
|
product: selectedProduct?.value || value,
|
||||||
productName: selectedProduct?.label || '',
|
productName: selectedProduct?.label || '',
|
||||||
productId: selectedProduct?.value || ''
|
hsCode: selectedProduct?.hsCode || '',
|
||||||
|
productData: selectedProduct?.originalData || null
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fetch previous forecast data when product is selected
|
// Fetch previous forecast data when product is selected
|
||||||
if (selectedProduct?.value) {
|
if (selectedProduct?.value) {
|
||||||
// Try to get establishmentId from sessionStorage first, then fallback to localStorage
|
const establishmentId = sessionStorage.getItem('establishment_id') ||
|
||||||
let establishmentId = sessionStorage.getItem('establishment_id') ||
|
|
||||||
localStorage.getItem('establishmentId') ||
|
localStorage.getItem('establishmentId') ||
|
||||||
localStorage.getItem('establishment_id');
|
localStorage.getItem('establishment_id');
|
||||||
|
|
||||||
|
|
||||||
if (establishmentId && quarter && year) {
|
if (establishmentId && quarter && year) {
|
||||||
// Get the actual product ID from the selected product object
|
// Use the product_id directly as the value
|
||||||
const selectedProductId = selectedProduct.originalData?.id || selectedProduct.value;
|
const productId = selectedProduct.value;
|
||||||
|
|
||||||
console.log('Fetching forecast data for:', {
|
console.log('Fetching forecast data for:', {
|
||||||
productId: selectedProductId,
|
productId,
|
||||||
establishmentId,
|
establishmentId,
|
||||||
quarter,
|
quarter,
|
||||||
year,
|
year,
|
||||||
storageSource: sessionStorage.getItem('establishment_id') ? 'sessionStorage' : 'localStorage'
|
storageSource: sessionStorage.getItem('establishment_id') ? 'sessionStorage' : 'localStorage'
|
||||||
});
|
});
|
||||||
handleProductSelect(selectedProductId, establishmentId, id);
|
|
||||||
|
// Call handleProductSelect with the product ID
|
||||||
|
handleProductSelect(productId, establishmentId, id);
|
||||||
} else {
|
} else {
|
||||||
console.warn('Missing required parameters for forecast data fetch:', {
|
console.warn('Missing required parameters for forecast data fetch:', {
|
||||||
hasEstablishmentId: !!establishmentId,
|
hasEstablishmentId: !!establishmentId,
|
||||||
establishmentIdValue: establishmentId, // Log the actual value for debugging
|
|
||||||
hasQuarter: !!quarter,
|
hasQuarter: !!quarter,
|
||||||
hasYear: !!year,
|
hasYear: !!year
|
||||||
availableStorage: {
|
|
||||||
sessionStorage: sessionStorage.getItem('establishment_id') ? 'exists' : 'not found',
|
|
||||||
localStorage: localStorage.getItem('establishmentId') ? 'exists' : 'not found',
|
|
||||||
localStorageAlt: localStorage.getItem('establishment_id') ? 'exists' : 'not found'
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -773,6 +785,29 @@ const location = useLocation();
|
|||||||
// When variation reason is selected, store both ID and name
|
// When variation reason is selected, store both ID and name
|
||||||
if (field === 'variationReason') {
|
if (field === 'variationReason') {
|
||||||
const selectedReason = options.find(r => r.value === value || r.id === value);
|
const selectedReason = options.find(r => r.value === value || r.id === value);
|
||||||
|
// Check both name and label for 'other' to be more flexible
|
||||||
|
const isOtherSelected = selectedReason && (
|
||||||
|
(selectedReason.name && selectedReason.name.toLowerCase().includes('other')) ||
|
||||||
|
(selectedReason.label && selectedReason.label.toLowerCase().includes('other'))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update the showOtherVariationReason state for this product
|
||||||
|
setShowOtherVariationReason(prev => ({
|
||||||
|
...prev,
|
||||||
|
[id]: isOtherSelected
|
||||||
|
}));
|
||||||
|
|
||||||
|
// If not 'Others', clear any existing other reason
|
||||||
|
if (!isOtherSelected) {
|
||||||
|
return {
|
||||||
|
...product,
|
||||||
|
variationReason: value,
|
||||||
|
variationReasonName: selectedReason?.label || selectedReason?.name || '',
|
||||||
|
otherVariationReason: '',
|
||||||
|
[field]: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...product,
|
...product,
|
||||||
variationReason: value,
|
variationReason: value,
|
||||||
@ -781,9 +816,34 @@ const location = useLocation();
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// When zero target reason is selected, store both ID and name
|
// Handle zero target reason selection
|
||||||
if (field === 'zeroTargetReason') {
|
if (field === 'zeroTargetReason') {
|
||||||
const selectedReason = options.find(r => r.value === value || r.id === value);
|
const selectedReason = options?.find(r => r.value === value || r.id === value);
|
||||||
|
// Check both name and label for 'other' to be more flexible
|
||||||
|
const isOtherSelected = selectedReason && (
|
||||||
|
(selectedReason.name && selectedReason.name.toLowerCase().includes('other')) ||
|
||||||
|
(selectedReason.label && selectedReason.label.toLowerCase().includes('other'))
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('Selected zero target reason:', selectedReason, 'Is other:', isOtherSelected);
|
||||||
|
|
||||||
|
// Update the showOtherZeroTargetReason state for this product
|
||||||
|
setShowOtherZeroTargetReason(prev => ({
|
||||||
|
...prev,
|
||||||
|
[id]: isOtherSelected
|
||||||
|
}));
|
||||||
|
|
||||||
|
// If not 'Others', clear any existing other reason
|
||||||
|
if (!isOtherSelected) {
|
||||||
|
return {
|
||||||
|
...product,
|
||||||
|
zeroTargetReason: value,
|
||||||
|
zeroTargetReasonName: selectedReason?.label || selectedReason?.name || '',
|
||||||
|
otherZeroTargetReason: '',
|
||||||
|
[field]: value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...product,
|
...product,
|
||||||
zeroTargetReason: value,
|
zeroTargetReason: value,
|
||||||
@ -809,10 +869,9 @@ const location = useLocation();
|
|||||||
}
|
}
|
||||||
|
|
||||||
onProductsChange(updatedProducts);
|
onProductsChange(updatedProducts);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleProductSelect = async (productId, establishmentId, id) => {
|
||||||
const handleProductSelect = async (productId, establishmentId, id) => {
|
|
||||||
if (!productId || !establishmentId) {
|
if (!productId || !establishmentId) {
|
||||||
console.warn('Missing required parameters in handleProductSelect:', {
|
console.warn('Missing required parameters in handleProductSelect:', {
|
||||||
hasProductId: !!productId,
|
hasProductId: !!productId,
|
||||||
@ -834,7 +893,7 @@ const location = useLocation();
|
|||||||
|
|
||||||
const updatedProducts = products.map(product => {
|
const updatedProducts = products.map(product => {
|
||||||
if (product.id === id) {
|
if (product.id === id) {
|
||||||
const updatedProduct = {
|
return {
|
||||||
...product,
|
...product,
|
||||||
octQuantity: data.previous_quantity_period_one || '',
|
octQuantity: data.previous_quantity_period_one || '',
|
||||||
novQuantity: data.previous_quantity_period_two || '',
|
novQuantity: data.previous_quantity_period_two || '',
|
||||||
@ -844,15 +903,12 @@ const location = useLocation();
|
|||||||
decCost: data.previous_cost_period_three || '',
|
decCost: data.previous_cost_period_three || '',
|
||||||
capacity: data.annual_installed_capacity || ''
|
capacity: data.annual_installed_capacity || ''
|
||||||
};
|
};
|
||||||
console.log('Updated product data:', updatedProduct);
|
|
||||||
return updatedProduct;
|
|
||||||
}
|
}
|
||||||
return product;
|
return product;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Updating products with new data');
|
console.log('Updating products with new data');
|
||||||
onProductsChange(updatedProducts);
|
onProductsChange(updatedProducts);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error in handleProductSelect:', {
|
console.error('Error in handleProductSelect:', {
|
||||||
message: error.message,
|
message: error.message,
|
||||||
@ -860,7 +916,7 @@ const location = useLocation();
|
|||||||
stack: error.stack
|
stack: error.stack
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const canAddMoreProducts = products.length < MAX_PRODUCTS;
|
const canAddMoreProducts = products.length < MAX_PRODUCTS;
|
||||||
|
|
||||||
const isLoading = loading || isLoadingReasons || isLoadingZeroReasons || isLoadingProducts || isLoadingUnits;
|
const isLoading = loading || isLoadingReasons || isLoadingZeroReasons || isLoadingProducts || isLoadingUnits;
|
||||||
@ -1323,6 +1379,18 @@ const location = useLocation();
|
|||||||
value={p.variationReason || ''}
|
value={p.variationReason || ''}
|
||||||
onChange={(e) => updateProductField(p.id, 'variationReason', e.target.value, variationReasons)}
|
onChange={(e) => updateProductField(p.id, 'variationReason', e.target.value, variationReasons)}
|
||||||
/>
|
/>
|
||||||
|
{(showOtherVariationReason[p.id] || (p.variationReason && (p.variationReason.toString().toLowerCase().includes('other') || (variationReasons.find(r => r.value === p.variationReason)?.name?.toLowerCase().includes('other') || variationReasons.find(r => r.value === p.variationReason)?.label?.toLowerCase().includes('other'))))) && (
|
||||||
|
<div className="mt-3 p-3 bg-gray-50 rounded-md border border-gray-200">
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-2">Please specify the reason</label>
|
||||||
|
<Input
|
||||||
|
className="w-full"
|
||||||
|
placeholder="Enter your reason here..."
|
||||||
|
value={p.otherVariationReason || ''}
|
||||||
|
onChange={(e) => updateProductField(p.id, 'otherVariationReason', e.target.value)}
|
||||||
|
/>
|
||||||
|
<p className="mt-1 text-xs text-gray-500">Please provide details about the variation reason</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{reasonsError && variationReasons.length === 0 && (
|
{reasonsError && variationReasons.length === 0 && (
|
||||||
<p className="mt-1 text-xs text-red-600">{reasonsError}</p>
|
<p className="mt-1 text-xs text-red-600">{reasonsError}</p>
|
||||||
)}
|
)}
|
||||||
@ -1458,6 +1526,18 @@ const location = useLocation();
|
|||||||
value={p.zeroTargetReason || ''}
|
value={p.zeroTargetReason || ''}
|
||||||
onChange={(e) => updateProductField(p.id, 'zeroTargetReason', e.target.value, zeroTargetReasons)}
|
onChange={(e) => updateProductField(p.id, 'zeroTargetReason', e.target.value, zeroTargetReasons)}
|
||||||
/>
|
/>
|
||||||
|
{(showOtherZeroTargetReason[p.id] || (p.zeroTargetReason && (p.zeroTargetReason.toString().toLowerCase().includes('other') || (zeroTargetReasons.find(r => r.value === p.zeroTargetReason)?.name?.toLowerCase().includes('other') || zeroTargetReasons.find(r => r.value === p.zeroTargetReason)?.label?.toLowerCase().includes('other'))))) && (
|
||||||
|
<div className="mt-3 p-3 bg-gray-50 rounded-md border border-gray-200">
|
||||||
|
<label className="block text-sm font-medium text-gray-700 mb-2">Please specify the reason</label>
|
||||||
|
<Input
|
||||||
|
className="w-full"
|
||||||
|
placeholder="Enter your reason here..."
|
||||||
|
value={p.otherZeroTargetReason || ''}
|
||||||
|
onChange={(e) => updateProductField(p.id, 'otherZeroTargetReason', e.target.value)}
|
||||||
|
/>
|
||||||
|
<p className="mt-1 text-xs text-gray-500">Please provide details about the zero target reason</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{zeroReasonsError && zeroTargetReasons.length === 0 && (
|
{zeroReasonsError && zeroTargetReasons.length === 0 && (
|
||||||
<p className="mt-1 text-xs text-red-600">{zeroReasonsError}</p>
|
<p className="mt-1 text-xs text-red-600">{zeroReasonsError}</p>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -222,9 +222,11 @@ const buildProductRows = (products = [], options = {}) => {
|
|||||||
q4_nov_cost: formatNumber(product.novCost) || '—',
|
q4_nov_cost: formatNumber(product.novCost) || '—',
|
||||||
q4_dec_cost: formatNumber(product.decCost) || '—',
|
q4_dec_cost: formatNumber(product.decCost) || '—',
|
||||||
|
|
||||||
// Reasons and remarks - use display names
|
// Reasons and remarks - use display names and include other reasons
|
||||||
variationReason: variationReasonName,
|
variationReason: variationReasonName,
|
||||||
|
otherVariationReason: product.otherVariationReason || '',
|
||||||
zeroTargetReason: zeroTargetReasonName,
|
zeroTargetReason: zeroTargetReasonName,
|
||||||
|
otherZeroTargetReason: product.otherZeroTargetReason || '',
|
||||||
remarks: product.remarks || '',
|
remarks: product.remarks || '',
|
||||||
|
|
||||||
// Keep the raw product data for debugging
|
// Keep the raw product data for debugging
|
||||||
@ -243,6 +245,80 @@ const buildProductRows = (products = [], options = {}) => {
|
|||||||
return rows.filter(Boolean);
|
return rows.filter(Boolean);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const formatSubmissionData = (establishment, products, remarks = '') => {
|
||||||
|
if (!establishment) {
|
||||||
|
throw new Error('Establishment data is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get employee info with proper fallbacks
|
||||||
|
const employeeInfo = establishment.employeeInfo || {};
|
||||||
|
const emiratiMale = parseInt(employeeInfo.emiratiMale) || 0;
|
||||||
|
const emiratiFemale = parseInt(employeeInfo.emiratiFemale) || 0;
|
||||||
|
const nonEmiratiMale = parseInt(employeeInfo.nonEmiratiMale) || 0;
|
||||||
|
const nonEmiratiFemale = parseInt(employeeInfo.nonEmiratiFemale) || 0;
|
||||||
|
const totalEmirati = emiratiMale + emiratiFemale;
|
||||||
|
const totalEmployees = totalEmirati + nonEmiratiMale + nonEmiratiFemale;
|
||||||
|
|
||||||
|
// Format products data
|
||||||
|
const formattedProducts = products.map(product => ({
|
||||||
|
product_id: parseInt(product.productId) || 0,
|
||||||
|
unit_id: parseInt(product.unit) || 0,
|
||||||
|
annual_installed_capacity: product.capacity?.toString() || '',
|
||||||
|
|
||||||
|
// Previous quarter (Oct-Dec)
|
||||||
|
previous_quantity_period_one: product.octQuantity?.toString() || '0',
|
||||||
|
previous_quantity_period_two: product.novQuantity?.toString() || '0',
|
||||||
|
previous_quantity_period_three: product.decQuantity?.toString() || '0',
|
||||||
|
previous_cost_period_one: product.octCost?.toString() || '0',
|
||||||
|
previous_cost_period_two: product.novCost?.toString() || '0',
|
||||||
|
previous_cost_period_three: product.decCost?.toString() || '0',
|
||||||
|
|
||||||
|
// Current quarter (Jan-Mar)
|
||||||
|
current_quantity_period_one: product.janQuantity?.toString() || '0',
|
||||||
|
current_quantity_period_two: product.febQuantity?.toString() || '0',
|
||||||
|
current_quantity_period_three: product.marQuantity?.toString() || '0',
|
||||||
|
current_cost_period_one: product.janCost?.toString() || '0',
|
||||||
|
current_cost_period_two: product.febCost?.toString() || '0',
|
||||||
|
current_cost_period_three: product.marCost?.toString() || '0',
|
||||||
|
|
||||||
|
// Next quarter forecast (Apr-Jun)
|
||||||
|
forecast_quantity_period_one: product.aprQuantity?.toString() || '0',
|
||||||
|
forecast_quantity_period_two: product.mayQuantity?.toString() || '0',
|
||||||
|
forecast_quantity_period_three: product.junQuantity?.toString() || '0',
|
||||||
|
forecast_cost_period_one: product.aprCost?.toString() || '0',
|
||||||
|
forecast_cost_period_two: product.mayCost?.toString() || '0',
|
||||||
|
forecast_cost_period_three: product.junCost?.toString() || '0',
|
||||||
|
|
||||||
|
// Totals (calculated on backend if needed)
|
||||||
|
previous_quantity: '',
|
||||||
|
previous_cost: '',
|
||||||
|
current_quantity: '',
|
||||||
|
current_cost: '',
|
||||||
|
forecast_quantity: '',
|
||||||
|
forecast_cost: '',
|
||||||
|
|
||||||
|
// Reasons and remarks
|
||||||
|
variation_reason_master_id: product.variationReason?.toString() || '',
|
||||||
|
other_variation_reason: product.otherVariationReason?.toString() || '',
|
||||||
|
zero_target_reason_master_id: product.zeroTargetReason?.toString() || '',
|
||||||
|
other_zero_target_reason: product.otherZeroTargetReason?.toString() || '',
|
||||||
|
remarks: product.remarks || remarks || ''
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
establishment_id: parseInt(establishment.id) || 0,
|
||||||
|
quarter: establishment.quarter || 'Q1', // Should come from your app state
|
||||||
|
year: parseInt(establishment.year) || new Date().getFullYear(),
|
||||||
|
emirati_male: emiratiMale,
|
||||||
|
emirati_female: emiratiFemale,
|
||||||
|
non_emirati_male: nonEmiratiMale,
|
||||||
|
non_emirati_female: nonEmiratiFemale,
|
||||||
|
total_emirati: totalEmirati,
|
||||||
|
total_employees: totalEmployees,
|
||||||
|
products: formattedProducts
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const ReviewSubmit = ({
|
const ReviewSubmit = ({
|
||||||
establishment,
|
establishment,
|
||||||
products = [],
|
products = [],
|
||||||
@ -253,15 +329,37 @@ const ReviewSubmit = ({
|
|||||||
isSubmitting = false,
|
isSubmitting = false,
|
||||||
hasSubmitted = false,
|
hasSubmitted = false,
|
||||||
submitButtonText = 'Submit',
|
submitButtonText = 'Submit',
|
||||||
|
quarter = 'Q1',
|
||||||
|
year = new Date().getFullYear()
|
||||||
}) => {
|
}) => {
|
||||||
const [confirm, setConfirm] = React.useState(false);
|
const [confirm, setConfirm] = React.useState(false);
|
||||||
const [remarks, setRemarks] = React.useState(() => {
|
const [remarks, setRemarks] = React.useState(() => {
|
||||||
// Load remarks from localStorage on component mount
|
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
return localStorage.getItem('surveyRemarks') || '';
|
return localStorage.getItem('surveyRemarks') || '';
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
try {
|
||||||
|
const submissionData = formatSubmissionData(
|
||||||
|
{ ...establishment, quarter, year },
|
||||||
|
products,
|
||||||
|
remarks
|
||||||
|
);
|
||||||
|
console.log('Submitting data:', submissionData);
|
||||||
|
onSubmit(submissionData);
|
||||||
|
setConfirm(false);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error formatting submission data:', error);
|
||||||
|
if (onToastClose) {
|
||||||
|
onToastClose({
|
||||||
|
type: 'error',
|
||||||
|
message: 'Failed to prepare data for submission. Please check your input.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
const establishmentDetails = React.useMemo(() => buildEstablishmentDetails(establishment), [establishment]);
|
const establishmentDetails = React.useMemo(() => buildEstablishmentDetails(establishment), [establishment]);
|
||||||
const employmentDetails = React.useMemo(() => buildEmploymentDetails(establishment), [establishment]);
|
const employmentDetails = React.useMemo(() => buildEmploymentDetails(establishment), [establishment]);
|
||||||
const productRows = React.useMemo(() => buildProductRows(products), [products]);
|
const productRows = React.useMemo(() => buildProductRows(products), [products]);
|
||||||
@ -689,7 +787,14 @@ const ReviewSubmit = ({
|
|||||||
-- --
|
-- --
|
||||||
</td>
|
</td>
|
||||||
<td colSpan="3" className="border border-gray-300 py-2 text-center bg-[#F3FAF4] text-[#2F663C]">
|
<td colSpan="3" className="border border-gray-300 py-2 text-center bg-[#F3FAF4] text-[#2F663C]">
|
||||||
{product.variationReasonName || product.variationReason || '—'}
|
<div className="flex flex-col items-center">
|
||||||
|
<div>{product.variationReasonName || product.variationReason || '—'}</div>
|
||||||
|
{product.otherVariationReason && (
|
||||||
|
<div className="mt-1 text-xs text-gray-600">
|
||||||
|
{product.otherVariationReason}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td colSpan="3" className="border border-gray-300 py-2 text-center">
|
<td colSpan="3" className="border border-gray-300 py-2 text-center">
|
||||||
-- --
|
-- --
|
||||||
@ -705,7 +810,14 @@ const ReviewSubmit = ({
|
|||||||
-- --
|
-- --
|
||||||
</td>
|
</td>
|
||||||
<td colSpan="3" className="border border-gray-300 py-2 text-center bg-[#FFF7E9] text-[#F29F0E]">
|
<td colSpan="3" className="border border-gray-300 py-2 text-center bg-[#FFF7E9] text-[#F29F0E]">
|
||||||
{product.zeroTargetReasonName || product.zeroTargetReason || '—'}
|
<div className="flex flex-col items-center">
|
||||||
|
<div>{product.zeroTargetReasonName || product.zeroTargetReason || '—'}</div>
|
||||||
|
{product.otherZeroTargetReason && (
|
||||||
|
<div className="mt-1 text-xs text-gray-600 ">
|
||||||
|
{product.otherZeroTargetReason}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@ -81,18 +81,80 @@ const Survey = () => {
|
|||||||
}, [initialStepFromState]);
|
}, [initialStepFromState]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// First check if we have survey data in the navigation state
|
||||||
|
if (locationState?.survey) {
|
||||||
|
const { quarter, year, establishment } = locationState.survey;
|
||||||
|
setSurveyData(locationState.survey);
|
||||||
|
|
||||||
|
// If we have establishment data in the navigation state, use it
|
||||||
|
if (establishment) {
|
||||||
|
setEstablishmentData(prev => ({
|
||||||
|
...prev,
|
||||||
|
quarter: quarter || '',
|
||||||
|
year: year || '',
|
||||||
|
establishmentName: establishment.establishmentName || prev.establishmentName,
|
||||||
|
permanentFactoryCode: establishment.permanentFactoryCode || prev.permanentFactoryCode,
|
||||||
|
industryCode: establishment.industryCode || prev.industryCode,
|
||||||
|
licenseNumber: establishment.licenseNumber || prev.licenseNumber,
|
||||||
|
isicCode: establishment.isicCode || prev.isicCode,
|
||||||
|
emirate: establishment.emirate || prev.emirate,
|
||||||
|
employeeInfo: {
|
||||||
|
emiratiMale: establishment.employeeInfo?.emiratiMale || prev.employeeInfo.emiratiMale,
|
||||||
|
emiratiFemale: establishment.employeeInfo?.emiratiFemale || prev.employeeInfo.emiratiFemale,
|
||||||
|
nonEmiratiMale: establishment.employeeInfo?.nonEmiratiMale || prev.employeeInfo.nonEmiratiMale,
|
||||||
|
nonEmiratiFemale: establishment.employeeInfo?.nonEmiratiFemale || prev.employeeInfo.nonEmiratiFemale,
|
||||||
|
totalEmirati: establishment.employeeInfo?.totalEmirati || prev.employeeInfo.totalEmirati,
|
||||||
|
totalEmployees: establishment.employeeInfo?.totalEmployees || prev.employeeInfo.totalEmployees
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
setEstablishmentData(prev => ({
|
||||||
|
...prev,
|
||||||
|
quarter: quarter || '',
|
||||||
|
year: year || ''
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also save to localStorage for page refreshes
|
||||||
|
localStorage.setItem('currentSurvey', JSON.stringify(locationState.survey));
|
||||||
|
} else {
|
||||||
|
// Fall back to localStorage if no data in navigation state
|
||||||
const savedSurvey = localStorage.getItem('currentSurvey');
|
const savedSurvey = localStorage.getItem('currentSurvey');
|
||||||
if (savedSurvey) {
|
if (savedSurvey) {
|
||||||
const surveyData = JSON.parse(savedSurvey);
|
const surveyData = JSON.parse(savedSurvey);
|
||||||
setSurveyData(surveyData);
|
setSurveyData(surveyData);
|
||||||
// Update the establishmentData with the saved survey data
|
|
||||||
|
if (surveyData.establishment) {
|
||||||
|
const { establishment } = surveyData;
|
||||||
|
setEstablishmentData(prev => ({
|
||||||
|
...prev,
|
||||||
|
quarter: surveyData.quarter || '',
|
||||||
|
year: surveyData.year || '',
|
||||||
|
establishmentName: establishment.establishmentName || prev.establishmentName,
|
||||||
|
permanentFactoryCode: establishment.permanentFactoryCode || prev.permanentFactoryCode,
|
||||||
|
industryCode: establishment.industryCode || prev.industryCode,
|
||||||
|
licenseNumber: establishment.licenseNumber || prev.licenseNumber,
|
||||||
|
isicCode: establishment.isicCode || prev.isicCode,
|
||||||
|
emirate: establishment.emirate || prev.emirate,
|
||||||
|
employeeInfo: {
|
||||||
|
emiratiMale: establishment.employeeInfo?.emiratiMale || prev.employeeInfo.emiratiMale,
|
||||||
|
emiratiFemale: establishment.employeeInfo?.emiratiFemale || prev.employeeInfo.emiratiFemale,
|
||||||
|
nonEmiratiMale: establishment.employeeInfo?.nonEmiratiMale || prev.employeeInfo.nonEmiratiMale,
|
||||||
|
nonEmiratiFemale: establishment.employeeInfo?.nonEmiratiFemale || prev.employeeInfo.nonEmiratiFemale,
|
||||||
|
totalEmirati: establishment.employeeInfo?.totalEmirati || prev.employeeInfo.totalEmirati,
|
||||||
|
totalEmployees: establishment.employeeInfo?.totalEmployees || prev.employeeInfo.totalEmployees
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
setEstablishmentData(prev => ({
|
setEstablishmentData(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
quarter: surveyData.quarter || '',
|
quarter: surveyData.quarter || '',
|
||||||
year: surveyData.year || ''
|
year: surveyData.year || ''
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}, []);
|
}
|
||||||
|
}
|
||||||
|
}, [locationState]);
|
||||||
|
|
||||||
// Function to fetch current quarter and year from dashboard
|
// Function to fetch current quarter and year from dashboard
|
||||||
const fetchCurrentQuarterAndYear = async () => {
|
const fetchCurrentQuarterAndYear = async () => {
|
||||||
@ -115,13 +177,28 @@ const Survey = () => {
|
|||||||
|
|
||||||
const initializeSurveyData = async () => {
|
const initializeSurveyData = async () => {
|
||||||
try {
|
try {
|
||||||
// If this is a resubmission, use the quarter and year from the submission
|
// If this is a resubmission, use the data from the submission
|
||||||
if (isResubmit && locationState?.submission) {
|
if (isResubmit && locationState?.submission) {
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
|
const submission = locationState.submission;
|
||||||
setEstablishmentData(prev => ({
|
setEstablishmentData(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
quarter: locationState.submission.quarter || '',
|
quarter: submission.quarter || '',
|
||||||
year: locationState.submission.year?.toString() || ''
|
year: submission.year?.toString() || '',
|
||||||
|
establishmentName: submission.establishment_name || prev.establishmentName,
|
||||||
|
permanentFactoryCode: submission.permanent_factory_code || prev.permanentFactoryCode,
|
||||||
|
industryCode: submission.industry_code || prev.industryCode,
|
||||||
|
licenseNumber: submission.license_number || prev.licenseNumber,
|
||||||
|
isicCode: submission.isic_code || prev.isicCode,
|
||||||
|
emirate: submission.emirate || prev.emirate,
|
||||||
|
employeeInfo: {
|
||||||
|
emiratiMale: submission.emirati_male || prev.employeeInfo.emiratiMale,
|
||||||
|
emiratiFemale: submission.emirati_female || prev.employeeInfo.emiratiFemale,
|
||||||
|
nonEmiratiMale: submission.non_emirati_male || prev.employeeInfo.nonEmiratiMale,
|
||||||
|
nonEmiratiFemale: submission.non_emirati_female || prev.employeeInfo.nonEmiratiFemale,
|
||||||
|
totalEmirati: submission.total_emirati || prev.employeeInfo.totalEmirati,
|
||||||
|
totalEmployees: submission.total_employees || prev.employeeInfo.totalEmployees
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user