From 281d98cf1370051be4118302725fafe30b02c888 Mon Sep 17 00:00:00 2001 From: Malini Date: Mon, 2 Mar 2026 18:56:28 +0530 Subject: [PATCH] CR Bug fixed --- .../survey/ProductData/ProductData.jsx | 106 ++++++++++++------ 1 file changed, 69 insertions(+), 37 deletions(-) diff --git a/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx b/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx index 34fb2f6..9133f8a 100644 --- a/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx +++ b/ipi-survey-platform/src/components/survey/ProductData/ProductData.jsx @@ -92,7 +92,8 @@ const SearchableSelect = ({ error = false, className = '', displayValue = undefined, - allowNull = false // New prop to allow null values for no selection + allowNull = false, // New prop to allow null values for no selection + allowClear = false // New prop to show clear button }) => { const [isOpen, setIsOpen] = React.useState(false); const [searchTerm, setSearchTerm] = React.useState(''); @@ -176,6 +177,28 @@ const SearchableSelect = ({ const displayValueToShow = internalDisplayValue; + // Handle clear functionality + const handleClear = (event) => { + event.preventDefault(); + event.stopPropagation(); + if (onChange) { + const event = { + target: { + value: allowNull ? null : '' + } + }; + onChange(event); + } + setSearchTerm(''); + setIsOpen(false); + }; + + // Check if clear button should be shown + // Show clear button when value is not null, not undefined, and not empty string + // Note: value can be 0 (user-selected) but should still show clear button + const hasValue = value !== null && value !== undefined && value !== ''; + const showClear = allowClear && hasValue && !disabled && !loading; + // Handle option selection const handleSelect = (option) => { if (onChange) { @@ -211,12 +234,24 @@ const SearchableSelect = ({ className={`flex items-center justify-between h-10 px-4 py-2 text-sm rounded-md border-2 ${borderColor} ${bgColor} ${disabled ? 'bg-gray-50 cursor-not-allowed' : 'cursor-pointer'}`} onClick={() => !disabled && !loading && setIsOpen(!isOpen)} > - {displayValueToShow || placeholder} - {loading ? ( -
- ) : ( - open - )} + {displayValueToShow || placeholder} +
+ {showClear ? ( + + ) : loading ? ( +
+ ) : null} + {!showClear && !loading && ( + open + )} +
{isOpen && ( @@ -1424,56 +1459,49 @@ useEffect(() => { const errors = {}; let isValid = true; + // Check if all available products have been added + const availableProductsCount = productOptions.length; + const currentProductsCount = products.length; + const remainingProducts = availableProductsCount - currentProductsCount; + + if (currentProductsCount < availableProductsCount) { + errors['products_general'] = `Please fill remaining ${remainingProducts} product${remainingProducts > 1 ? 's' : ''} before proceeding`; + isValid = false; + } + products.forEach((product, index) => { - // Validate product selection + // Only validate fields that are marked as mandatory (with asterisk in UI) + // Product selection is mandatory if (!product.product) { errors[`product_${index}`] = 'Product is required'; isValid = false; } - // Validate unit selection + // Unit selection is mandatory if (!product.unit) { errors[`unit_${index}`] = 'Unit is required'; isValid = false; } - // Validate capacity - if (!product.capacity) { + // Annual installed capacity is mandatory + if (!product.capacity || product.capacity === '0' || parseFloat(product.capacity) === 0) { 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) { + // Only quantity fields with asterisk (*) are mandatory (current and next quarter) + const mandatoryQuantityFields = ['janQuantity', 'febQuantity', 'marQuantity', 'aprQuantity', 'mayQuantity', 'junQuantity']; + mandatoryQuantityFields.forEach(field => { + if (!product[field] || product[field] === '0' || parseFloat(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) { + // Only value fields with asterisk (*) are mandatory (current and next quarter) + const mandatoryCostFields = ['janCost', 'febCost', 'marCost', 'aprCost', 'mayCost', 'junCost']; + mandatoryCostFields.forEach(field => { + if (!product[field] || product[field] === '0' || parseFloat(product[field]) === 0) { errors[`${field}_${index}`] = 'Required'; isValid = false; } @@ -2613,6 +2641,7 @@ useEffect(() => { value={p.novCost || ''} error={!!formErrors[`novCost_${idx}`]} onChange={(e) => updateProductField(p.id, 'novCost', e.target.value)} + allowClear={true} /> {formErrors[`novCost_${idx}`] && (

{formErrors[`novCost_${idx}`]}

@@ -2761,6 +2790,7 @@ useEffect(() => { loading={isLoadingReasons} error={!!formErrors[`variationReason_${idx}`]} allowNull={true} + allowClear={true} /> {formErrors[`variationReason_${idx}`] && (

{formErrors[`variationReason_${idx}`]}

@@ -2920,6 +2950,7 @@ useEffect(() => { onChange={(e) => updateProductField(p.id, 'zeroTargetReason', e.target.value, zeroTargetReasons)} loading={isLoadingZeroReasons} allowNull={true} + allowClear={true} /> {(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'))))) && (
@@ -3008,6 +3039,7 @@ useEffect(() => { {productsError &&

{productsError}

} {unitsError &&

{unitsError}

} {formErrors['draft_general'] &&

{formErrors['draft_general']}

} + {formErrors['products_general'] &&

{formErrors['products_general']}

}
)}