validation added
This commit is contained in:
parent
54aab3740c
commit
11abb7d77c
@ -20,8 +20,10 @@ const uae_currency = '/assets/images/UAE_Dirham_Symbol.svg';
|
|||||||
|
|
||||||
const Input = ({ placeholder = '', type = 'text', value = '', onChange = () => {}, required = false, error = false }) => {
|
const Input = ({ placeholder = '', type = 'text', value = '', onChange = () => {}, required = false, error = false }) => {
|
||||||
const [isFocused, setIsFocused] = React.useState(false);
|
const [isFocused, setIsFocused] = React.useState(false);
|
||||||
let borderColor = 'border-[#CBA344]';
|
|
||||||
let bgColor = 'bg-white';
|
// Simple red background when there's an error
|
||||||
|
let borderColor = error ? 'border-red-500' : 'border-[#CBA344]';
|
||||||
|
let bgColor = error ? 'bg-red-50' : 'bg-white';
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
borderColor = 'border-red-500';
|
borderColor = 'border-red-500';
|
||||||
@ -46,8 +48,6 @@ const Input = ({ placeholder = '', type = 'text', value = '', onChange = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const SearchableSelect = ({
|
const SearchableSelect = ({
|
||||||
placeholder = '',
|
placeholder = '',
|
||||||
options = [],
|
options = [],
|
||||||
@ -112,9 +112,10 @@ const SearchableSelect = ({
|
|||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
let borderColor = 'border-[#CBA344]';
|
// Simple red background when there's an error
|
||||||
let bgColor = 'bg-white';
|
let borderColor = error ? 'border-red-500' : 'border-[#CBA344]';
|
||||||
|
let bgColor = error ? 'bg-red-50' : 'bg-white';
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
borderColor = 'border-red-500';
|
borderColor = 'border-red-500';
|
||||||
bgColor = 'bg-red-50';
|
bgColor = 'bg-red-50';
|
||||||
@ -192,8 +193,9 @@ const Select = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const [isFocused, setIsFocused] = React.useState(false);
|
const [isFocused, setIsFocused] = React.useState(false);
|
||||||
|
|
||||||
let borderColor = 'border-[#CBA344]';
|
// Simple red background when there's an error
|
||||||
let bgColor = 'bg-white';
|
let borderColor = error ? 'border-red-500' : 'border-[#CBA344]';
|
||||||
|
let bgColor = error ? 'bg-red-50' : 'bg-white';
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
borderColor = 'border-red-500';
|
borderColor = 'border-red-500';
|
||||||
@ -571,53 +573,82 @@ const location = useLocation();
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateProduct = (product, index) => {
|
// Simple validation function
|
||||||
const errors = {};
|
const validateField = (fieldName, value, productIndex) => {
|
||||||
let hasError = false;
|
const errors = { ...formErrors };
|
||||||
|
const fieldKey = `${fieldName}_${productIndex}`;
|
||||||
|
|
||||||
// Check for duplicate products
|
if (!value || value.toString().trim() === '') {
|
||||||
const duplicateProductIndex = products.findIndex(
|
errors[fieldKey] = 'This field is required';
|
||||||
(p, i) => p.product === product.product && i !== index
|
} else {
|
||||||
);
|
delete errors[fieldKey];
|
||||||
|
|
||||||
if (duplicateProductIndex !== -1) {
|
|
||||||
errors[`product-${product.id}`] = 'This product has already been selected';
|
|
||||||
hasError = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate product selection
|
setFormErrors(errors);
|
||||||
if (!product.product) {
|
return Object.keys(errors).length === 0;
|
||||||
errors[`product-${product.id}`] = 'Product is required';
|
|
||||||
hasError = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate unit selection
|
|
||||||
if (!product.unit) {
|
|
||||||
errors[`unit-${product.id}`] = 'Unit is required';
|
|
||||||
hasError = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate capacity
|
|
||||||
if (!product.capacity) {
|
|
||||||
errors[`capacity-${product.id}`] = 'Capacity is required';
|
|
||||||
hasError = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { errors, hasError };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Simple validation for all required fields
|
||||||
const validateForm = () => {
|
const validateForm = () => {
|
||||||
let isValid = true;
|
|
||||||
const errors = {};
|
const errors = {};
|
||||||
|
let isValid = true;
|
||||||
|
|
||||||
products.forEach((product, index) => {
|
products.forEach((product, index) => {
|
||||||
const { errors: productErrors, hasError } = validateProduct(product, index);
|
// Validate product selection
|
||||||
if (hasError) {
|
if (!product.product) {
|
||||||
Object.assign(errors, productErrors);
|
errors[`product_${index}`] = 'Product is required';
|
||||||
isValid = false;
|
isValid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate unit selection
|
||||||
|
if (!product.unit) {
|
||||||
|
errors[`unit_${index}`] = 'Unit is required';
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate capacity
|
||||||
|
if (!product.capacity) {
|
||||||
|
errors[`capacity_${index}`] = 'Capacity is required';
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate current quarter quantities
|
||||||
|
const currentQuantityFields = ['janQuantity', 'febQuantity', 'marQuantity'];
|
||||||
|
currentQuantityFields.forEach(field => {
|
||||||
|
if (!product[field] && product[field] !== 0) {
|
||||||
|
errors[`${field}_${index}`] = 'Required';
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validate current quarter costs
|
||||||
|
const currentCostFields = ['janCost', 'febCost', 'marCost'];
|
||||||
|
currentCostFields.forEach(field => {
|
||||||
|
if (!product[field] && product[field] !== 0) {
|
||||||
|
errors[`${field}_${index}`] = 'Required';
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validate forecast quantities
|
||||||
|
const forecastQuantityFields = ['aprQuantity', 'mayQuantity', 'junQuantity'];
|
||||||
|
forecastQuantityFields.forEach(field => {
|
||||||
|
if (!product[field] && product[field] !== 0) {
|
||||||
|
errors[`${field}_${index}`] = 'Required';
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validate forecast costs
|
||||||
|
const forecastCostFields = ['aprCost', 'mayCost', 'junCost'];
|
||||||
|
forecastCostFields.forEach(field => {
|
||||||
|
if (!product[field] && product[field] !== 0) {
|
||||||
|
errors[`${field}_${index}`] = 'Required';
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
setFormErrors(errors);
|
setFormErrors(errors);
|
||||||
return isValid;
|
return isValid;
|
||||||
};
|
};
|
||||||
@ -625,6 +656,15 @@ const location = useLocation();
|
|||||||
const handleNext = () => {
|
const handleNext = () => {
|
||||||
if (validateForm()) {
|
if (validateForm()) {
|
||||||
onNext();
|
onNext();
|
||||||
|
} else {
|
||||||
|
// Scroll to first error
|
||||||
|
const firstErrorKey = Object.keys(formErrors)[0];
|
||||||
|
if (firstErrorKey) {
|
||||||
|
const element = document.querySelector(`[data-field="${firstErrorKey}"]`);
|
||||||
|
if (element) {
|
||||||
|
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -825,13 +865,6 @@ const location = useLocation();
|
|||||||
[field]: value
|
[field]: value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
...product,
|
|
||||||
variationReason: value,
|
|
||||||
variationReasonName: selectedReason?.label || selectedReason?.name || '',
|
|
||||||
[field]: value
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle product selection
|
// Handle product selection
|
||||||
@ -953,67 +986,68 @@ const location = useLocation();
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ...product, [field]: value };
|
return { ...product, [field]: value };
|
||||||
}
|
|
||||||
return product;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear error for the field being updated
|
|
||||||
const productIndex = products.findIndex(p => p.id === id);
|
|
||||||
if (productIndex !== -1) {
|
|
||||||
const errorKey = `${field}_${productIndex}`;
|
|
||||||
if (formErrors[errorKey] && value) {
|
|
||||||
const newErrors = { ...formErrors };
|
|
||||||
delete newErrors[errorKey];
|
|
||||||
setFormErrors(newErrors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onProductsChange(updatedProducts);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleProductSelect = async (productId, establishmentId, id) => {
|
|
||||||
if (!productId || !establishmentId) {
|
|
||||||
console.warn('Missing required parameters in handleProductSelect:', {
|
|
||||||
hasProductId: !!productId,
|
|
||||||
hasEstablishmentId: !!establishmentId
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const forecastData = await fetchPreviousForecastData(productId, establishmentId);
|
|
||||||
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;
|
return product;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Clear error for the field being updated
|
||||||
|
const productIndex = products.findIndex(p => p.id === id);
|
||||||
|
if (productIndex !== -1) {
|
||||||
|
const errorKey = `${field}_${productIndex}`;
|
||||||
|
if (formErrors[errorKey] && value) {
|
||||||
|
const newErrors = { ...formErrors };
|
||||||
|
delete newErrors[errorKey];
|
||||||
|
setFormErrors(newErrors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onProductsChange(updatedProducts);
|
onProductsChange(updatedProducts);
|
||||||
} catch (error) {
|
};
|
||||||
console.error('Error in handleProductSelect:', {
|
|
||||||
message: error.message,
|
const handleProductSelect = async (productId, establishmentId, id) => {
|
||||||
error: error,
|
if (!productId || !establishmentId) {
|
||||||
stack: error.stack
|
console.warn('Missing required parameters in handleProductSelect:', {
|
||||||
});
|
hasProductId: !!productId,
|
||||||
}
|
hasEstablishmentId: !!establishmentId
|
||||||
};
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const forecastData = await fetchPreviousForecastData(productId, establishmentId);
|
||||||
|
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:', {
|
||||||
|
message: error.message,
|
||||||
|
error: error,
|
||||||
|
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;
|
||||||
@ -1142,7 +1176,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<h3 className="font-semibold mb-4 text-base">Data definitions</h3>
|
<h3 className="font-semibold mb-4 text-base">Data definitions</h3>
|
||||||
<p className="mb-3"><strong>Product (HS Code – Name):</strong> Standard trade classification. Start typing to search by code or name.</p>
|
<p className="mb-3"><strong>Product (HS Code – Name):</strong> Standard trade classification. Start typing to search by code or name.</p>
|
||||||
<p className="mb-3"><strong>Quantity (Qty):</strong> Physical output produced in the month, measured in the selected unit.</p>
|
<p className="mb-3"><strong>Quantity (Qty):</strong> Physical output produced in the month, measured in the selected unit.</p>
|
||||||
<p className="mb-3"><strong>Cost (AED):</strong> Total production cost for that month, excluding VAT (e.g., materials, energy, direct labour, and manufacturing expenses). Do not include sales margins.</p>
|
<p className="mb-3"><strong>Cost (AED <img src={uae_currency} alt="AED" className="inline-block w-2 h-2 -mt-0.5" />):</strong> Total production cost for that month, excluding VAT (e.g., materials, energy, direct labour, and manufacturing expenses). Do not include sales margins.</p>
|
||||||
<p className="mb-0"><strong>Annual Installed Capacity:</strong> Maximum achievable annual output under normal operating conditions with existing equipment; do not include extraordinary overtime.</p>
|
<p className="mb-0"><strong>Annual Installed Capacity:</strong> Maximum achievable annual output under normal operating conditions with existing equipment; do not include extraordinary overtime.</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -1199,7 +1233,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
<div>
|
<div data-field={`product_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">Product (HS Code - Name) <span className="text-red-500">*</span></label>
|
<label className="block text-sm font-medium text-gray-700 mb-1">Product (HS Code - Name) <span className="text-red-500">*</span></label>
|
||||||
<div>
|
<div>
|
||||||
<SearchableSelect
|
<SearchableSelect
|
||||||
@ -1336,7 +1370,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<p className="mt-1 text-xs text-red-600">{productsError}</p>
|
<p className="mt-1 text-xs text-red-600">{productsError}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div data-field={`unit_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">Unit <span className="text-red-500">*</span></label>
|
<label className="block text-sm font-medium text-gray-700 mb-1">Unit <span className="text-red-500">*</span></label>
|
||||||
<SearchableSelect
|
<SearchableSelect
|
||||||
placeholder={isLoadingUnits ? 'Loading units...' : 'Select unit'}
|
placeholder={isLoadingUnits ? 'Loading units...' : 'Select unit'}
|
||||||
@ -1363,7 +1397,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div data-field={`capacity_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">Annual installed capacity (in unit) <span className="text-red-500">*</span></label>
|
<label className="block text-sm font-medium text-gray-700 mb-1">Annual installed capacity (in unit) <span className="text-red-500">*</span></label>
|
||||||
<Input
|
<Input
|
||||||
placeholder="Enter capacity"
|
placeholder="Enter capacity"
|
||||||
@ -1417,7 +1451,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<div className="flex items-end space-x-4 mt-4">
|
<div className="flex items-end space-x-4 mt-4">
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.previous_month?.previous_period_one } Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)
|
{quarterPeriods?.previous_month?.previous_period_one } Cost <img src={uae_currency} alt="AED" className="inline-block w-4 h-4 -mt-0.5 opacity-70" />
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24" style={{ border: '1px solid #E6D7A2' }}>
|
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24" style={{ border: '1px solid #E6D7A2' }}>
|
||||||
{p.octCost || '0'}
|
{p.octCost || '0'}
|
||||||
@ -1425,7 +1459,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.previous_month?.previous_period_two } Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)
|
{quarterPeriods?.previous_month?.previous_period_two } Cost (AED)
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24" style={{ border: '1px solid #E6D7A2' }}>
|
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24" style={{ border: '1px solid #E6D7A2' }}>
|
||||||
{p.novCost || '0'}
|
{p.novCost || '0'}
|
||||||
@ -1450,7 +1484,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
>
|
>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-end space-x-4">
|
<div className="flex items-end space-x-4">
|
||||||
<div>
|
<div data-field={`janQuantity_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.current_month?.current_period_one} Qty<span className="text-red-600">*</span>
|
{quarterPeriods?.current_month?.current_period_one} Qty<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1466,7 +1500,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<p className="mt-1 text-xs text-red-600">{formErrors[`janQuantity_${idx}`]}</p>
|
<p className="mt-1 text-xs text-red-600">{formErrors[`janQuantity_${idx}`]}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div data-field={`febQuantity_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.current_month?.current_period_two } Qty<span className="text-red-600">*</span>
|
{quarterPeriods?.current_month?.current_period_two } Qty<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1482,7 +1516,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<p className="mt-1 text-xs text-red-600">{formErrors[`febQuantity_${idx}`]}</p>
|
<p className="mt-1 text-xs text-red-600">{formErrors[`febQuantity_${idx}`]}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div data-field={`marQuantity_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.current_month?.current_period_three } Qty<span className="text-red-600">*</span>
|
{quarterPeriods?.current_month?.current_period_three } Qty<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1500,7 +1534,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-end space-x-4">
|
<div className="flex items-end space-x-4">
|
||||||
<div>
|
<div data-field={`janCost_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.current_month?.current_period_one } Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
{quarterPeriods?.current_month?.current_period_one } Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1516,7 +1550,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<p className="mt-1 text-xs text-red-600">{formErrors[`janCost_${idx}`]}</p>
|
<p className="mt-1 text-xs text-red-600">{formErrors[`janCost_${idx}`]}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div data-field={`febCost_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.current_month?.current_period_two} Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
{quarterPeriods?.current_month?.current_period_two} Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1532,7 +1566,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<p className="mt-1 text-xs text-red-600">{formErrors[`febCost_${idx}`]}</p>
|
<p className="mt-1 text-xs text-red-600">{formErrors[`febCost_${idx}`]}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div data-field={`marCost_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.current_month?.current_period_three} Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
{quarterPeriods?.current_month?.current_period_three} Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1592,7 +1626,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
>
|
>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-end space-x-3">
|
<div className="flex items-end space-x-3">
|
||||||
<div>
|
<div data-field={`aprQuantity_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.forecast_month?.forecast_period_one } Qty<span className="text-red-600">*</span>
|
{quarterPeriods?.forecast_month?.forecast_period_one } Qty<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1609,7 +1643,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<p className="mt-1 text-xs text-red-600">{formErrors[`aprQuantity_${idx}`]}</p>
|
<p className="mt-1 text-xs text-red-600">{formErrors[`aprQuantity_${idx}`]}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div data-field={`mayQuantity_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.forecast_month?.forecast_period_two } Qty<span className="text-red-600">*</span>
|
{quarterPeriods?.forecast_month?.forecast_period_two } Qty<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1626,7 +1660,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<p className="mt-1 text-xs text-red-600">{formErrors[`mayQuantity_${idx}`]}</p>
|
<p className="mt-1 text-xs text-red-600">{formErrors[`mayQuantity_${idx}`]}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div data-field={`junQuantity_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.forecast_month?.forecast_period_three } Qty<span className="text-red-600">*</span>
|
{quarterPeriods?.forecast_month?.forecast_period_three } Qty<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1645,7 +1679,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-end space-x-3">
|
<div className="flex items-end space-x-3">
|
||||||
<div>
|
<div data-field={`aprCost_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 w-26 mb-1">
|
<label className="block text-sm font-medium text-gray-700 w-26 mb-1">
|
||||||
{quarterPeriods?.forecast_month?.forecast_period_one} Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
{quarterPeriods?.forecast_month?.forecast_period_one} Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1662,7 +1696,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<p className="mt-1 text-xs text-red-600">{formErrors[`aprCost_${idx}`]}</p>
|
<p className="mt-1 text-xs text-red-600">{formErrors[`aprCost_${idx}`]}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div data-field={`mayCost_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 w-27 mb-1">
|
<label className="block text-sm font-medium text-gray-700 w-27 mb-1">
|
||||||
{quarterPeriods?.forecast_month?.forecast_period_two } Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
{quarterPeriods?.forecast_month?.forecast_period_two } Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1679,7 +1713,7 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
<p className="mt-1 text-xs text-red-600">{formErrors[`mayCost_${idx}`]}</p>
|
<p className="mt-1 text-xs text-red-600">{formErrors[`mayCost_${idx}`]}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div data-field={`junCost_${idx}`}>
|
||||||
<label className="block text-sm font-medium text-gray-700 w-27 mb-1">
|
<label className="block text-sm font-medium text-gray-700 w-27 mb-1">
|
||||||
{quarterPeriods?.forecast_month?.forecast_period_three } Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
{quarterPeriods?.forecast_month?.forecast_period_three } Cost (<img src={uae_currency} alt="AED" className="inline-block w-3.5 h-3 -mt-0.5 opacity-80" />)<span className="text-red-600">*</span>
|
||||||
</label>
|
</label>
|
||||||
@ -1786,4 +1820,4 @@ const handleProductSelect = async (productId, establishmentId, id) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ProductData;
|
export default ProductData;
|
||||||
Loading…
Reference in New Issue
Block a user