bug fixed in products
This commit is contained in:
parent
0d4ae03789
commit
52df438da4
@ -102,6 +102,7 @@ const EditCompanyProfile = () => {
|
|||||||
const [productSearchTerm, setProductSearchTerm] = useState('');
|
const [productSearchTerm, setProductSearchTerm] = useState('');
|
||||||
const [isLoadingProducts, setIsLoadingProducts] = useState(false);
|
const [isLoadingProducts, setIsLoadingProducts] = useState(false);
|
||||||
const [productError, setProductError] = useState("");
|
const [productError, setProductError] = useState("");
|
||||||
|
const [productLimitMessage, setProductLimitMessage] = useState("");
|
||||||
const [isLoadingCities, setIsLoadingCities] = useState(false);
|
const [isLoadingCities, setIsLoadingCities] = useState(false);
|
||||||
const [visibleProductCount, setVisibleProductCount] = useState(14);
|
const [visibleProductCount, setVisibleProductCount] = useState(14);
|
||||||
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
||||||
@ -157,8 +158,9 @@ const EditCompanyProfile = () => {
|
|||||||
|
|
||||||
// Special validation for Products step
|
// Special validation for Products step
|
||||||
if (stepIndex === 3) {
|
if (stepIndex === 3) {
|
||||||
if (selectedProducts.length === 0) {
|
const checkedCount = selectedProducts.filter(p => checkedProducts.has(p.value || p.id || p.product_id)).length;
|
||||||
setProductError("At least one product is required.");
|
if (checkedCount === 0) {
|
||||||
|
setProductError("At least one product must be checked.");
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
setProductError("");
|
setProductError("");
|
||||||
@ -181,7 +183,7 @@ const EditCompanyProfile = () => {
|
|||||||
return nextErrors;
|
return nextErrors;
|
||||||
});
|
});
|
||||||
return valid;
|
return valid;
|
||||||
}, [form, requiredFieldsByStep, selectedProducts]);
|
}, [form, requiredFieldsByStep, selectedProducts, checkedProducts]);
|
||||||
|
|
||||||
const handleFormChange = useCallback((field, value) => {
|
const handleFormChange = useCallback((field, value) => {
|
||||||
// Clear remarks if either industry code field is changed
|
// Clear remarks if either industry code field is changed
|
||||||
@ -409,15 +411,47 @@ const EditCompanyProfile = () => {
|
|||||||
return; // Don't add duplicate, don't modify available products
|
return; // Don't add duplicate, don't modify available products
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count current newly added products (excluding original products)
|
const MAX_TOTAL_SELECTED_PRODUCTS = 15;
|
||||||
const currentNewlyAdded = selectedProducts.filter(p => newlyAddedProductIds.has(p.value || p.id || p.product_id));
|
const MAX_NEW_PRODUCTS_PER_ACTION = 4;
|
||||||
|
|
||||||
// Allow up to 4 newly added products
|
const checkedCountTotal = selectedProducts.filter(p => checkedProducts.has(p.value || p.id || p.product_id)).length;
|
||||||
if (currentNewlyAdded.length >= 4) {
|
if (checkedCountTotal >= MAX_TOTAL_SELECTED_PRODUCTS) {
|
||||||
alert('Maximum of 4 replacement products can be added.');
|
setProductLimitMessage(`Maximum of ${MAX_TOTAL_SELECTED_PRODUCTS} products can be selected.`);
|
||||||
return; // Don't add product, don't modify available products
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count newly added products (current action) that are selected/checked
|
||||||
|
const newlyAddedCheckedCount = selectedProducts.filter(p => {
|
||||||
|
const productId = p.value || p.id || p.product_id;
|
||||||
|
return !p.isExisting && checkedProducts.has(productId);
|
||||||
|
}).length;
|
||||||
|
|
||||||
|
// Base count should represent selected products excluding the newly added ones
|
||||||
|
const baseSelectedCount = checkedCountTotal - newlyAddedCheckedCount;
|
||||||
|
|
||||||
|
// Allowed additions are capped by both per-action limit and remaining total slots (<= logic)
|
||||||
|
const allowedAddCount = Math.min(
|
||||||
|
MAX_NEW_PRODUCTS_PER_ACTION,
|
||||||
|
Math.max(0, MAX_TOTAL_SELECTED_PRODUCTS - baseSelectedCount)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (newlyAddedCheckedCount >= allowedAddCount) {
|
||||||
|
if (allowedAddCount === 0) {
|
||||||
|
setProductLimitMessage(`Maximum of ${MAX_TOTAL_SELECTED_PRODUCTS} products can be selected.`);
|
||||||
|
} else {
|
||||||
|
setProductLimitMessage(`You can add up to ${allowedAddCount} new product${allowedAddCount !== 1 ? 's' : ''}.`);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseSelectedCount + newlyAddedCheckedCount + 1 > MAX_TOTAL_SELECTED_PRODUCTS) {
|
||||||
|
setProductLimitMessage(`Maximum of ${MAX_TOTAL_SELECTED_PRODUCTS} products can be selected.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear any previous limit message when product can be added
|
||||||
|
setProductLimitMessage("");
|
||||||
|
|
||||||
// Only proceed with adding the product if we pass all checks
|
// Only proceed with adding the product if we pass all checks
|
||||||
setSelectedProducts(prev => [...prev, { ...product, isExisting: false }]);
|
setSelectedProducts(prev => [...prev, { ...product, isExisting: false }]);
|
||||||
|
|
||||||
@ -473,6 +507,9 @@ const EditCompanyProfile = () => {
|
|||||||
return newIds;
|
return newIds;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Clear limit message when product is removed
|
||||||
|
setProductLimitMessage("");
|
||||||
|
|
||||||
// Always add back to available products
|
// Always add back to available products
|
||||||
setAvailableProducts(prev => {
|
setAvailableProducts(prev => {
|
||||||
// Check if already in available products
|
// Check if already in available products
|
||||||
@ -1106,6 +1143,53 @@ const EditCompanyProfile = () => {
|
|||||||
<div className="bg-white rounded-lg border border-[#E5E7EB] overflow-hidden">
|
<div className="bg-white rounded-lg border border-[#E5E7EB] overflow-hidden">
|
||||||
<div className="bg-[#F9FAFB] px-4 py-3 border-b border-[#E5E7EB]">
|
<div className="bg-[#F9FAFB] px-4 py-3 border-b border-[#E5E7EB]">
|
||||||
<h5 className="text-sm font-medium text-[#111827]">Available Products</h5>
|
<h5 className="text-sm font-medium text-[#111827]">Available Products</h5>
|
||||||
|
{(() => {
|
||||||
|
const MAX_TOTAL_SELECTED_PRODUCTS = 15;
|
||||||
|
const MAX_NEW_PRODUCTS_PER_ACTION = 4;
|
||||||
|
|
||||||
|
const checkedCountTotal = selectedProducts.filter(p => checkedProducts.has(p.value || p.id || p.product_id)).length;
|
||||||
|
const newlyAddedCheckedCount = selectedProducts.filter(p => {
|
||||||
|
const productId = p.value || p.id || p.product_id;
|
||||||
|
return !p.isExisting && checkedProducts.has(productId);
|
||||||
|
}).length;
|
||||||
|
const baseSelectedCount = checkedCountTotal - newlyAddedCheckedCount;
|
||||||
|
const allowedAddCount = Math.min(
|
||||||
|
MAX_NEW_PRODUCTS_PER_ACTION,
|
||||||
|
Math.max(0, MAX_TOTAL_SELECTED_PRODUCTS - baseSelectedCount)
|
||||||
|
);
|
||||||
|
const remainingToAdd = Math.max(0, allowedAddCount - newlyAddedCheckedCount);
|
||||||
|
|
||||||
|
if (productLimitMessage) return null;
|
||||||
|
|
||||||
|
if (checkedCountTotal >= MAX_TOTAL_SELECTED_PRODUCTS || allowedAddCount === 0) {
|
||||||
|
return (
|
||||||
|
<p className="text-xs text-[#B91C1C] mt-1">Maximum of {MAX_TOTAL_SELECTED_PRODUCTS} products can be selected.</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newlyAddedCheckedCount >= allowedAddCount) {
|
||||||
|
return (
|
||||||
|
<p className="text-xs text-[#B91C1C] mt-1">You can add up to {allowedAddCount} new product{allowedAddCount !== 1 ? 's' : ''}.</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remainingToAdd < MAX_NEW_PRODUCTS_PER_ACTION) {
|
||||||
|
return (
|
||||||
|
<p className="text-xs text-[#B91C1C] mt-1">You can add {remainingToAdd} more product{remainingToAdd !== 1 ? 's' : ''}.</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowedAddCount < MAX_NEW_PRODUCTS_PER_ACTION) {
|
||||||
|
return (
|
||||||
|
<p className="text-xs text-[#B91C1C] mt-1">You can add up to {allowedAddCount} new product{allowedAddCount !== 1 ? 's' : ''}.</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
})()}
|
||||||
|
{productLimitMessage && (
|
||||||
|
<p className="text-xs text-[#B91C1C] mt-1">{productLimitMessage}</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<div className="relative mb-4">
|
<div className="relative mb-4">
|
||||||
@ -1149,7 +1233,39 @@ const EditCompanyProfile = () => {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleAddProduct(product)}
|
onClick={() => handleAddProduct(product)}
|
||||||
className="text-[#92722A] hover:text-[#7A5F1E] text-sm font-medium"
|
disabled={(() => {
|
||||||
|
const MAX_TOTAL_SELECTED_PRODUCTS = 15;
|
||||||
|
const MAX_NEW_PRODUCTS_PER_ACTION = 4;
|
||||||
|
const checkedCountTotal = selectedProducts.filter(p => checkedProducts.has(p.value || p.id || p.product_id)).length;
|
||||||
|
const newlyAddedCheckedCount = selectedProducts.filter(p => {
|
||||||
|
const productId = p.value || p.id || p.product_id;
|
||||||
|
return !p.isExisting && checkedProducts.has(productId);
|
||||||
|
}).length;
|
||||||
|
const baseSelectedCount = checkedCountTotal - newlyAddedCheckedCount;
|
||||||
|
const allowedAddCount = Math.min(
|
||||||
|
MAX_NEW_PRODUCTS_PER_ACTION,
|
||||||
|
Math.max(0, MAX_TOTAL_SELECTED_PRODUCTS - baseSelectedCount)
|
||||||
|
);
|
||||||
|
return checkedCountTotal >= MAX_TOTAL_SELECTED_PRODUCTS || newlyAddedCheckedCount >= allowedAddCount;
|
||||||
|
})()}
|
||||||
|
className={`text-sm font-medium ${(() => {
|
||||||
|
const MAX_TOTAL_SELECTED_PRODUCTS = 15;
|
||||||
|
const MAX_NEW_PRODUCTS_PER_ACTION = 4;
|
||||||
|
const checkedCountTotal = selectedProducts.filter(p => checkedProducts.has(p.value || p.id || p.product_id)).length;
|
||||||
|
const newlyAddedCheckedCount = selectedProducts.filter(p => {
|
||||||
|
const productId = p.value || p.id || p.product_id;
|
||||||
|
return !p.isExisting && checkedProducts.has(productId);
|
||||||
|
}).length;
|
||||||
|
const baseSelectedCount = checkedCountTotal - newlyAddedCheckedCount;
|
||||||
|
const allowedAddCount = Math.min(
|
||||||
|
MAX_NEW_PRODUCTS_PER_ACTION,
|
||||||
|
Math.max(0, MAX_TOTAL_SELECTED_PRODUCTS - baseSelectedCount)
|
||||||
|
);
|
||||||
|
const disabled = checkedCountTotal >= MAX_TOTAL_SELECTED_PRODUCTS || newlyAddedCheckedCount >= allowedAddCount;
|
||||||
|
return disabled
|
||||||
|
? 'text-gray-400 cursor-not-allowed'
|
||||||
|
: 'text-[#92722A] hover:text-[#7A5F1E]';
|
||||||
|
})()}`}
|
||||||
>
|
>
|
||||||
Add
|
Add
|
||||||
</button>
|
</button>
|
||||||
@ -1176,11 +1292,11 @@ const EditCompanyProfile = () => {
|
|||||||
<div className="bg-[#F9FAFB] px-4 py-3 border-b border-[#E5E7EB] flex justify-between items-center">
|
<div className="bg-[#F9FAFB] px-4 py-3 border-b border-[#E5E7EB] flex justify-between items-center">
|
||||||
<h5 className="text-sm font-medium text-[#111827]">Selected Products</h5>
|
<h5 className="text-sm font-medium text-[#111827]">Selected Products</h5>
|
||||||
|
|
||||||
{selectedProducts.length > 0 && (
|
<div className="flex items-center gap-2">
|
||||||
<span className="bg-[#FEF3C7] text-[#92400E] text-xs font-medium px-2 py-0.5 rounded-full">
|
<span className="bg-[#FEF3C7] text-[#92400E] text-xs font-medium px-2 py-0.5 rounded-full">
|
||||||
{selectedProducts.length} selected
|
{selectedProducts.filter(p => checkedProducts.has(p.value || p.id || p.product_id)).length}/15 selected
|
||||||
</span>
|
</span>
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
@ -1257,7 +1373,6 @@ const EditCompanyProfile = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user