2026-01-27 18:27:29 +05:30
|
|
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
|
|
|
import { useDispatch, useSelector } from 'react-redux';
|
2026-02-12 15:46:52 +05:30
|
|
|
import { Form, Tooltip, Tabs } from 'antd';
|
|
|
|
|
import DirectSale from './DirectSale.jsx';
|
2026-01-27 18:27:29 +05:30
|
|
|
import {
|
|
|
|
|
ArrowRightOutlined,
|
|
|
|
|
PlusCircleOutlined,
|
|
|
|
|
InfoCircleOutlined,
|
|
|
|
|
} from '@ant-design/icons';
|
2026-01-28 18:55:01 +05:30
|
|
|
import { IoSettingsOutline } from "react-icons/io5";
|
2026-01-27 18:27:29 +05:30
|
|
|
import Buttons from '../../../../Components/Forms/Buttons.jsx';
|
|
|
|
|
import { InputField } from '../../../../Components/Forms/InputField.jsx';
|
|
|
|
|
import { Messages } from '../../../../Components/Notifications/Messages';
|
|
|
|
|
import { DropDowns } from '../../../../Components/Forms/DropDown.jsx';
|
|
|
|
|
import { DatePic } from '../../../../Components/Forms/DatePicker.jsx';
|
|
|
|
|
import { DefaultModal } from '../../../../Components/Modal/DefaultModal.jsx';
|
2026-02-12 15:46:52 +05:30
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
import { getSession, validateSafeInput } from '../../../../Services/Others';
|
|
|
|
|
import {
|
|
|
|
|
getAdmin,
|
|
|
|
|
getProductTypeData,
|
|
|
|
|
getUomData,
|
|
|
|
|
getProdCatData,
|
|
|
|
|
getProdSubCatData,
|
|
|
|
|
getProdTaxData,
|
|
|
|
|
getSupplierData,
|
|
|
|
|
productTypeDataSelector,
|
|
|
|
|
uomDataSelector,
|
|
|
|
|
prodCatDataSelector,
|
|
|
|
|
prodSubCatDataSelector,
|
|
|
|
|
prodTaxDataSelector,
|
|
|
|
|
taxSelector,
|
|
|
|
|
supplierSelector,
|
|
|
|
|
postProductData,
|
|
|
|
|
postTax,
|
2026-01-28 18:55:01 +05:30
|
|
|
getHsnData,
|
|
|
|
|
getFieldSetupData,
|
|
|
|
|
postFieldSetup
|
2026-01-27 18:27:29 +05:30
|
|
|
} from '../../../../Features/ProductPage/ProductPage.js';
|
|
|
|
|
import {
|
|
|
|
|
ChangeNewQrProduct,
|
|
|
|
|
GlobalSearchData,
|
|
|
|
|
changeSearchedData,
|
|
|
|
|
getSelectedFavItems,
|
|
|
|
|
GlobalProductCategorie,
|
|
|
|
|
GlobalProductSubCategorie,
|
|
|
|
|
getLayoutproductCard,
|
|
|
|
|
getCardDataWithoutSub,
|
|
|
|
|
getCardDataWithoutSubmodule,
|
|
|
|
|
getLayoutCategories,
|
|
|
|
|
} from '../../../../Features/BookingScreen/BookingData/BookingData';
|
|
|
|
|
import {
|
|
|
|
|
IoCloseSharp,
|
|
|
|
|
} from 'react-icons/io5';
|
|
|
|
|
import '../../../../Styles/Product/Product.scss';
|
|
|
|
|
import { getTemplateData } from '../../../../Features/ThemeChange/ThemeChange';
|
|
|
|
|
import Imageupload from '../../../../Components/Forms/Upload.jsx';
|
|
|
|
|
import { ApplicationPreferences, getCommonAppPreference } from '../../../../Features/BrachLogin/BranchLogin.js';
|
|
|
|
|
const ProductForm = ({
|
|
|
|
|
formType,
|
|
|
|
|
handleCancelData,
|
|
|
|
|
ProductSearch,
|
|
|
|
|
ProductSearchType,
|
|
|
|
|
cardData,
|
2026-02-12 15:46:52 +05:30
|
|
|
activeTab = null
|
2026-01-27 18:27:29 +05:30
|
|
|
}) => {
|
|
|
|
|
const dispatch = useDispatch();
|
|
|
|
|
const formRef = useRef(null);
|
|
|
|
|
const formTaxRef = useRef(null);
|
|
|
|
|
|
|
|
|
|
const ProductTypeData = useSelector(productTypeDataSelector);
|
|
|
|
|
const UomData = useSelector(uomDataSelector);
|
|
|
|
|
const ProdCatData = useSelector(prodCatDataSelector);
|
|
|
|
|
const ProdSubCatData = useSelector(prodSubCatDataSelector);
|
|
|
|
|
const ProdTaxData = useSelector(prodTaxDataSelector);
|
|
|
|
|
const TaxData = useSelector(taxSelector);
|
|
|
|
|
const SupplierData = useSelector(supplierSelector);
|
|
|
|
|
const ProductSearchValue = useSelector(GlobalSearchData);
|
|
|
|
|
const templateData = useSelector(getTemplateData);
|
|
|
|
|
const prodCat = useSelector(GlobalProductCategorie);
|
|
|
|
|
const ProdSubCat = useSelector(GlobalProductSubCategorie);
|
|
|
|
|
const appPreferences = useSelector(ApplicationPreferences)
|
|
|
|
|
const productFieldPreferences = appPreferences?.find(
|
|
|
|
|
(preference) => preference?.PreferredCatName?.toLowerCase() === "product form fields"
|
|
|
|
|
)?.PreferenceCatDetails;
|
2026-01-28 18:55:01 +05:30
|
|
|
// const CustomQuickAddField = appPreferences?.find(
|
|
|
|
|
// (preference) => preference?.PreferredCatName?.toLowerCase() === "quick add custom fields"
|
|
|
|
|
// )?.PreferenceCatDetails;
|
|
|
|
|
const categoryId = appPreferences?.find(
|
|
|
|
|
p => p?.PreferredCatName?.toLowerCase() === "quick add custom fields"
|
|
|
|
|
)?.PreferredCatId;
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
const UomTypePreference = appPreferences?.find((preference) => preference?.PreferredCatName === 'Product Uom')?.PreferenceCatDetails
|
|
|
|
|
const UomPreference = UomData?.filter((item) => UomTypePreference?.some?.((e) => e?.PreferredSubCatName?.toLowerCase() == item?.ConfigName?.toLowerCase() && e?.PreferredStatus == "Y"))
|
|
|
|
|
|
|
|
|
|
const filteredFields = productFieldPreferences?.filter(
|
|
|
|
|
(field) => field?.PreferredStatus === 'Y'
|
|
|
|
|
);
|
2026-01-28 18:55:01 +05:30
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
const cessField = filteredFields?.find((field) => field?.PreferredSubCatName === 'Cess');
|
|
|
|
|
const hsnField = filteredFields?.find((field) => field?.PreferredSubCatName === 'HSN');
|
|
|
|
|
const taxField = filteredFields?.find((field) => field?.PreferredSubCatName === 'Tax');
|
|
|
|
|
|
|
|
|
|
//local states
|
|
|
|
|
const [messageType, setMessageType] = useState(null);
|
|
|
|
|
const [messageData, setMessageData] = useState(null);
|
|
|
|
|
const [SelectedUom, setSelectedUom] = useState(null);
|
2026-01-28 18:55:01 +05:30
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
const [SelectedTaxId, setSelectedTaxId] = useState(null);
|
|
|
|
|
const [SelectedTaxNameId, setSelectedTaxNameId] = useState(null);
|
|
|
|
|
const [OpenTaxModel, setOpenTaxModel] = useState(false);
|
2026-01-28 18:55:01 +05:30
|
|
|
// const [OpenAdd, setOpenAdd] = useState(false);
|
2026-01-27 18:27:29 +05:30
|
|
|
const [imageBrandUrl, setBrandImageUrl] = useState('');
|
|
|
|
|
const [selectedHsn, setSelectedHsn] = useState("");
|
|
|
|
|
const [HsnDetails, setHsnDetails] = useState([]);
|
2026-01-28 18:55:01 +05:30
|
|
|
const [selectedAdditionalColumn, setSelectedAdditionalColumn] = useState([]);
|
|
|
|
|
const [showColumnModal, setShowColumnModal] = useState(false);
|
|
|
|
|
const [tempSelectedColumns, setTempSelectedColumns] = useState([]);
|
|
|
|
|
const [tableFieldPreferences, setTableFieldPreferences] = useState([]);
|
|
|
|
|
const [selectedFields, setSelectedFields] = useState([]);
|
2026-02-12 15:46:52 +05:30
|
|
|
|
2026-01-28 18:55:01 +05:30
|
|
|
console.log(selectedAdditionalColumn, "selectedAdditionalColumn")
|
|
|
|
|
console.log(tempSelectedColumns, "tempSelectedColumns")
|
2026-01-27 18:27:29 +05:30
|
|
|
const CompId = getSession('CompId');
|
|
|
|
|
const BranchId = getSession('BranchId');
|
|
|
|
|
const AppId = getSession('AppId');
|
|
|
|
|
const UserId = getSession('UserId');
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
getApplicationPreference()
|
|
|
|
|
dispatch(getProductTypeData());
|
|
|
|
|
dispatch(getUomData());
|
|
|
|
|
dispatch(getProdCatData({ AppId: AppId }));
|
|
|
|
|
dispatch(
|
|
|
|
|
getSupplierData({ CompId: CompId, AppId: AppId, BranchId: BranchId })
|
|
|
|
|
);
|
|
|
|
|
dispatch(getProdTaxData({ AppId: AppId }));
|
|
|
|
|
dispatch(getAdmin({ CompId: CompId, AppId: AppId }));
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (formType == 'add') {
|
|
|
|
|
let ProductCatId = ProdCatData?.filter(
|
|
|
|
|
(item) => item.ConfigName?.toLowerCase() === 'General'?.toLowerCase()
|
|
|
|
|
)?.[0]?.['ConfigId'];
|
|
|
|
|
dispatch(getProdSubCatData({ ConfigId: ProductCatId }));
|
|
|
|
|
}
|
|
|
|
|
}, [ProdCatData]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (formType == 'add' && cardData?.length !== 1) {
|
|
|
|
|
let UomId = UomPreference?.filter(
|
|
|
|
|
(item) => item.ConfigName?.toLowerCase() === 'PCS'?.toLowerCase()
|
|
|
|
|
)?.[0]?.['ConfigId'];
|
|
|
|
|
formRef.current?.setFieldsValue({ UOM: UomId });
|
|
|
|
|
setSelectedUom(UomId);
|
|
|
|
|
}
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (formType == 'add') {
|
|
|
|
|
let TaxId = TaxData?.filter(
|
|
|
|
|
(item) => item.TaxIdName?.toLowerCase() === 'NIL'?.toLowerCase()
|
|
|
|
|
)?.[0]?.['TaxId'];
|
|
|
|
|
formRef.current?.setFieldsValue({ TaxId: TaxId });
|
|
|
|
|
setSelectedTaxId(TaxId);
|
|
|
|
|
}
|
|
|
|
|
}, [TaxData]);
|
2026-01-28 18:55:01 +05:30
|
|
|
useEffect(() => {
|
|
|
|
|
getFieldSetup();
|
|
|
|
|
}, [categoryId])
|
|
|
|
|
|
|
|
|
|
const getFieldSetup = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await dispatch(getFieldSetupData({ AppId, CompId, BranchId, categoryId, Type: "QA" })).unwrap();
|
|
|
|
|
if (response?.data?.statusCode === 1) {
|
|
|
|
|
console.log(response?.data?.data?.[0]?.ConfigDtl, "Field Setup Data");
|
|
|
|
|
setSelectedFields(response?.data?.data?.[0]?.ConfigDtl?.filter(c => c.ConfigId && c.Access === 'Y')?.map(c => c.ConfigId) || []);
|
|
|
|
|
setSelectedAdditionalColumn(response?.data?.data?.[0]?.ConfigDtl?.filter(c => c.ConfigId && c.Access === 'Y')?.map(c => c.ConfigName) || [])
|
|
|
|
|
setTableFieldPreferences(response?.data?.data?.[0]?.ConfigDtl?.map(c => ({
|
|
|
|
|
value: c.ConfigId,
|
|
|
|
|
label: c.ConfigName,
|
|
|
|
|
access: c.Access
|
|
|
|
|
})) || []);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Error fetching field setup:', error);
|
|
|
|
|
}
|
|
|
|
|
};
|
2026-01-27 18:27:29 +05:30
|
|
|
const onComplete = useCallback(() => {
|
|
|
|
|
setMessageData(null);
|
|
|
|
|
setMessageType(null);
|
|
|
|
|
}, []);
|
|
|
|
|
|
2026-01-28 18:55:01 +05:30
|
|
|
// const openAdditionalDetails = () => {
|
|
|
|
|
// if (OpenAdd) {
|
|
|
|
|
// setOpenAdd(false);
|
|
|
|
|
// } else {
|
|
|
|
|
// setOpenAdd(true);
|
|
|
|
|
// }
|
|
|
|
|
// };
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
const getApplicationPreference = async () => {
|
|
|
|
|
|
|
|
|
|
const response = await dispatch(getCommonAppPreference(AppId)).unwrap();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleSellPrice = (_, value) => {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
if (!value) {
|
|
|
|
|
return reject('Selling Price is required');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!/^\d+(\.\d{1,2})?$/.test(value)) {
|
|
|
|
|
return reject('Invalid format (Max 2 decimal places allowed)');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parseFloat(value) === 0) {
|
|
|
|
|
return reject('Selling Price cannot be 0');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (value.length > 10) {
|
|
|
|
|
return reject('MRP cannot exceed 10 digits');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const MRP = formRef?.current?.getFieldsValue()?.MRP || 0;
|
|
|
|
|
|
|
|
|
|
if (MRP !== undefined && parseFloat(MRP) < parseFloat(value)) {
|
|
|
|
|
return reject('Please enter Selling Price less than MRP');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return resolve();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (cardData?.length === 1) {
|
|
|
|
|
AutoProdFun();
|
|
|
|
|
}
|
|
|
|
|
}, [cardData]);
|
|
|
|
|
|
|
|
|
|
const getUOMConfigId = async (uomName) => {
|
|
|
|
|
if (!uomName) return getUOMConfigId('PCS');
|
|
|
|
|
|
|
|
|
|
const normalize = (str) => str?.toLowerCase().replace(/s$/, ''); // remove trailing 's'
|
|
|
|
|
|
|
|
|
|
const normalizedInput = normalize(uomName);
|
|
|
|
|
|
|
|
|
|
// Try exact match
|
|
|
|
|
let match = UomPreference.find(
|
|
|
|
|
(item) => normalize(item.ConfigName || '') === normalizedInput
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// If no exact match, try partial match (like "kg" in "KGS")
|
|
|
|
|
if (!match) {
|
|
|
|
|
match = UomPreference.find((item) =>
|
|
|
|
|
normalize(item.ConfigName || '').includes(normalizedInput)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return match ? match.ConfigId : getUOMConfigId('PCS'); // fallback to PCS
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const AutoProdFun = async () => {
|
|
|
|
|
const regex = /([\d.]+)\s*([a-zA-Z]+)\)?$/;
|
|
|
|
|
|
|
|
|
|
const match = cardData?.[0]?.ProdName.match(regex);
|
|
|
|
|
|
|
|
|
|
if (match) {
|
|
|
|
|
const quantity = parseFloat(match[1]);
|
|
|
|
|
const uom = match[2];
|
|
|
|
|
const name = cardData?.[0]?.ProdName.slice(0, match.index)
|
|
|
|
|
?.replace(/[\(\),]+$/, '')
|
|
|
|
|
?.trim();
|
|
|
|
|
// return { name, quantity, uom };
|
|
|
|
|
const configId = await getUOMConfigId(uom);
|
|
|
|
|
console.log(configId, 'configIdconfigIdconfigIdconfigId');
|
|
|
|
|
// setSelectedUom(configId)
|
|
|
|
|
handleUomDropDownChange(configId);
|
|
|
|
|
console.log(`ConfigId for ${uom}:`, configId);
|
|
|
|
|
formRef.current?.setFieldsValue({ ProdName: name });
|
|
|
|
|
formRef.current?.setFieldsValue({ Size: quantity });
|
|
|
|
|
formRef.current?.setFieldsValue({ BrandName: cardData?.[0]?.Brand });
|
|
|
|
|
setBrandImageUrl(cardData?.[0]?.ImageUrl);
|
|
|
|
|
} else {
|
|
|
|
|
const configId = await getUOMConfigId('PCS');
|
|
|
|
|
formRef.current?.setFieldsValue({
|
|
|
|
|
ProdName: cardData?.[0]?.ProdName.trim(),
|
|
|
|
|
});
|
|
|
|
|
formRef.current?.setFieldsValue({ Size: 1 });
|
|
|
|
|
handleUomDropDownChange(configId);
|
|
|
|
|
formRef.current?.setFieldsValue({ BrandName: cardData?.[0]?.Brand });
|
|
|
|
|
setBrandImageUrl(cardData?.[0]?.ImageUrl);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleUomDropDownChange = async (ConfigId) => {
|
|
|
|
|
formRef.current?.setFieldsValue({ UOM: ConfigId });
|
|
|
|
|
await setSelectedUom(ConfigId);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const submitTax = async () => {
|
|
|
|
|
const subTaxData = await formTaxRef?.current?.validateFields();
|
|
|
|
|
const effectiveDate = new Date(subTaxData.EffectiveFrom);
|
|
|
|
|
const formattedDate = effectiveDate.toLocaleDateString('en-CA');
|
|
|
|
|
const addTaxData = {
|
|
|
|
|
CompId: getSession('CompId'),
|
|
|
|
|
AppId: getSession('AppId'),
|
|
|
|
|
TaxName: subTaxData?.TaxName,
|
|
|
|
|
TaxPercentage: subTaxData?.TaxPercentage,
|
|
|
|
|
EffectiveFrom: formattedDate,
|
|
|
|
|
Reference: subTaxData.Reference,
|
|
|
|
|
CreatedBy: UserId,
|
|
|
|
|
};
|
|
|
|
|
let response = {};
|
|
|
|
|
response = await dispatch(postTax(addTaxData)).unwrap();
|
|
|
|
|
if (response?.data?.statusCode == 1) {
|
|
|
|
|
setMessageType('success');
|
|
|
|
|
setMessageData(response?.data?.response);
|
|
|
|
|
setOpenTaxModel(false);
|
|
|
|
|
dispatch(getAdmin({ CompId: CompId, AppId: AppId }));
|
|
|
|
|
formTaxRef?.current?.resetFields();
|
|
|
|
|
} else {
|
|
|
|
|
setMessageType('error');
|
|
|
|
|
setMessageData(response?.data?.response);
|
|
|
|
|
formTaxRef?.current?.resetFields();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
const handleTax = () => {
|
|
|
|
|
setOpenTaxModel(false);
|
|
|
|
|
};
|
|
|
|
|
const handleTaxDropDownChange = async (TaxId) => {
|
|
|
|
|
formRef.current?.setFieldsValue({ TaxId: TaxId });
|
|
|
|
|
await setSelectedTaxId(TaxId);
|
|
|
|
|
};
|
|
|
|
|
const handleTaxNameDropDownChange = async (ConfigId) => {
|
|
|
|
|
formTaxRef.current?.setFieldsValue({ TaxName: ConfigId });
|
|
|
|
|
await setSelectedTaxNameId(ConfigId);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getOptionLabel = (option, selected) => {
|
|
|
|
|
return selected
|
|
|
|
|
? option.TaxPercentage + ' %'
|
|
|
|
|
: option.TaxIdName + ' - ' + option.TaxPercentage + ' % ';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onFinish = async (values) => {
|
|
|
|
|
let postData = values;
|
|
|
|
|
postData['CompId'] = CompId;
|
|
|
|
|
postData['BranchId'] = BranchId;
|
|
|
|
|
postData['AppId'] = AppId;
|
|
|
|
|
postData['ProdType'] = ProductTypeData?.filter(
|
|
|
|
|
(item) => item.ConfigName === 'Product'
|
|
|
|
|
)?.[0]?.['ConfigId'];
|
|
|
|
|
postData['ProdCat'] = ProdCatData?.filter(
|
|
|
|
|
(item) => item.ConfigName === 'General'
|
|
|
|
|
)?.[0]?.['ConfigId'];
|
|
|
|
|
postData['ProdSubCat'] = ProdSubCatData?.filter(
|
|
|
|
|
(item) => item.ConfigName === 'General'
|
|
|
|
|
)?.[0]?.['ConfigId'];
|
|
|
|
|
postData['QtyBasedPrice'] = 'N';
|
|
|
|
|
postData['ProdQtywisePriceDetails'] = [];
|
|
|
|
|
postData['StockAvailable'] = 'N';
|
|
|
|
|
postData['TokenAvailable'] = 'N';
|
|
|
|
|
postData['TaxId'] = SelectedTaxId;
|
|
|
|
|
postData['InwardDate'] = new Date().toJSON();
|
|
|
|
|
postData['SuppId'] = SupplierData?.filter(
|
|
|
|
|
(item) => item.SuppName?.toLowerCase() === 'Self'?.toLowerCase()
|
|
|
|
|
)?.[0]?.['SuppId'];
|
|
|
|
|
postData['AutoGenerateQr'] = 'N';
|
|
|
|
|
postData['QRCode'] =
|
|
|
|
|
ProductSearchValue?.length > 0 ? ProductSearchValue : null;
|
|
|
|
|
postData['CreatedBy'] = UserId;
|
|
|
|
|
postData['ProdLogo'] = imageBrandUrl;
|
|
|
|
|
|
|
|
|
|
if (SelectedTaxId) {
|
|
|
|
|
postData['Cess'] =
|
|
|
|
|
values?.Cess == undefined || values?.Cess == null || values?.Cess == ''
|
|
|
|
|
? 0
|
|
|
|
|
: values?.Cess;
|
|
|
|
|
}
|
|
|
|
|
let response = {};
|
|
|
|
|
if (formType === 'add') {
|
|
|
|
|
try {
|
|
|
|
|
response = await dispatch(postProductData(postData)).unwrap();
|
|
|
|
|
} catch (err) {
|
|
|
|
|
if (err['message'] == 'Request failed with status code 422') {
|
|
|
|
|
response = {
|
|
|
|
|
data: {
|
|
|
|
|
statusCode: 0,
|
|
|
|
|
response: 'Please Give Required Fields',
|
|
|
|
|
data: [],
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (response?.data?.statusCode == 1) {
|
|
|
|
|
setMessageType('success');
|
|
|
|
|
setMessageData(response?.data?.response);
|
|
|
|
|
formRef.current?.resetFields();
|
|
|
|
|
setSelectedUom(null);
|
|
|
|
|
setSelectedTaxId(null);
|
|
|
|
|
handleCancelData();
|
2026-01-28 18:55:01 +05:30
|
|
|
// setOpenAdd(false);
|
2026-01-27 18:27:29 +05:30
|
|
|
if (ProductSearchType != 'C') {
|
|
|
|
|
let data = {
|
|
|
|
|
CompId: CompId,
|
|
|
|
|
BranchId: BranchId,
|
|
|
|
|
AppId: AppId,
|
|
|
|
|
};
|
|
|
|
|
await dispatch(getSelectedFavItems(data)).unwrap();
|
|
|
|
|
await dispatch(getLayoutCategories(data)).unwrap();
|
|
|
|
|
|
|
|
|
|
let data1 = {
|
|
|
|
|
CompId: CompId,
|
|
|
|
|
BranchId: BranchId,
|
|
|
|
|
AppId: AppId,
|
|
|
|
|
ProdSubCat: ProdSubCat,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let data2 = {
|
|
|
|
|
compId: CompId,
|
|
|
|
|
branchId: BranchId,
|
|
|
|
|
appId: AppId,
|
|
|
|
|
prodCat: prodCat,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
templateData?.BookingLayout?.[1]?.some(
|
|
|
|
|
(item) => item?.OptionName === 'SubCategory'
|
|
|
|
|
) &&
|
|
|
|
|
ProdSubCat
|
|
|
|
|
) {
|
|
|
|
|
await dispatch(getLayoutproductCard(data1)).unwrap();
|
|
|
|
|
} else if (
|
|
|
|
|
!templateData?.BookingLayout?.[1]?.some(
|
|
|
|
|
(item) => item?.OptionName === 'SubCategory'
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
await dispatch(getCardDataWithoutSubmodule(data2)).unwrap();
|
|
|
|
|
} else {
|
|
|
|
|
await dispatch(getCardDataWithoutSub(data2)).unwrap();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
let productData = response?.data?.ProductDetails?.[0];
|
|
|
|
|
dispatch(ChangeNewQrProduct({ ...productData, Quantity: parseInt(1) }));
|
|
|
|
|
if (
|
|
|
|
|
ProductSearchValue &&
|
|
|
|
|
(ProductSearchType == 'I' || ProductSearchType == 'C')
|
|
|
|
|
) {
|
|
|
|
|
dispatch(changeSearchedData([]));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
setMessageType('error');
|
|
|
|
|
setMessageData(response?.data?.response);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const addTax = () => {
|
|
|
|
|
setOpenTaxModel(true);
|
|
|
|
|
};
|
|
|
|
|
const updateBrandImageUrl = (url) => {
|
|
|
|
|
setBrandImageUrl(url);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleHsnData = async (value) => {
|
|
|
|
|
const response = await dispatch(getHsnData(value)).unwrap();
|
|
|
|
|
if (response?.data?.statusCode === 1) {
|
|
|
|
|
const data = response?.data?.data;
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
setHsnDetails(data);
|
|
|
|
|
}, 1000);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
setMessageData(response?.data?.response);
|
|
|
|
|
setMessageType('error');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2026-01-28 18:55:01 +05:30
|
|
|
const handleFieldSetupSubmit = async () => {
|
|
|
|
|
|
|
|
|
|
const postData = {
|
|
|
|
|
"AppId": AppId,
|
|
|
|
|
"CompId": CompId,
|
|
|
|
|
"BranchId": BranchId,
|
|
|
|
|
"Type": "QA",
|
|
|
|
|
"FormType": "Quick Add",
|
|
|
|
|
"TypeId": categoryId,
|
|
|
|
|
"ConfigDtl": selectedFields?.map((field) => ({
|
|
|
|
|
"ConfigId": field,
|
|
|
|
|
"Access": 'Y',
|
|
|
|
|
})),
|
|
|
|
|
"CreatedBy": UserId
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const response = await dispatch(postFieldSetup(postData))?.unwrap();
|
|
|
|
|
|
|
|
|
|
if (response?.data?.statusCode === 1) {
|
|
|
|
|
setSelectedAdditionalColumn([...tempSelectedColumns]);
|
|
|
|
|
setShowColumnModal(false);
|
|
|
|
|
setTempSelectedColumns([])
|
|
|
|
|
setMessageType("success");
|
|
|
|
|
setMessageData(response?.data?.response);
|
|
|
|
|
await getFieldSetup();
|
|
|
|
|
} else {
|
|
|
|
|
setMessageType("error");
|
|
|
|
|
setMessageData("Failed to set up fields");
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-27 18:27:29 +05:30
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<Messages
|
|
|
|
|
messageType={messageType}
|
|
|
|
|
messageData={messageData}
|
|
|
|
|
onComplete={onComplete}
|
|
|
|
|
/>
|
|
|
|
|
|
2026-02-12 15:46:52 +05:30
|
|
|
{activeTab === 'directSale' ? (
|
|
|
|
|
<DirectSale
|
|
|
|
|
UomData={UomPreference}
|
|
|
|
|
TaxData={TaxData}
|
|
|
|
|
ProductTypeData={ProductTypeData}
|
|
|
|
|
ProdCatData={ProdCatData}
|
|
|
|
|
ProdSubCatData={ProdSubCatData}
|
|
|
|
|
SupplierData={SupplierData}
|
|
|
|
|
activeTab={activeTab}
|
|
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
|
|
<div style={{
|
|
|
|
|
display: 'flex', alignItems: 'center', gap: '10px', justifyContent: "flex-end"
|
|
|
|
|
, fontFamily: "Poppins", fontWeight: "500", textDecoration: "underline", cursor: "Pointer", width: "100%"
|
|
|
|
|
}}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setTempSelectedColumns([...selectedAdditionalColumn]);
|
|
|
|
|
setShowColumnModal(true);
|
|
|
|
|
}}>
|
|
|
|
|
<Tooltip title="Add Fields" placement="left">
|
|
|
|
|
{/* <span>Additional Fields</span> */}
|
|
|
|
|
<IoSettingsOutline
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setTempSelectedColumns([...selectedAdditionalColumn]);
|
|
|
|
|
setShowColumnModal(true);
|
|
|
|
|
}}
|
|
|
|
|
style={{ cursor: 'pointer', fontSize: '20px' }}
|
|
|
|
|
/>
|
|
|
|
|
</Tooltip>
|
|
|
|
|
</div>
|
2026-01-27 18:27:29 +05:30
|
|
|
|
2026-02-12 15:46:52 +05:30
|
|
|
<Form ref={formRef} className="formDivAnt" onFinish={onFinish}>
|
|
|
|
|
<div>
|
|
|
|
|
<div className="productinputForm">
|
|
|
|
|
<div className="subColumnFlex">
|
|
|
|
|
{ProductSearch && <div>Qrcode : {ProductSearchValue}</div>}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
2026-02-12 15:46:52 +05:30
|
|
|
<div className="subRowFlex">
|
|
|
|
|
<Form.Item
|
|
|
|
|
name="ProdName"
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
pattern: /^(?!\s*$).+/,
|
|
|
|
|
message: 'Please Enter Product Name',
|
2026-01-27 18:27:29 +05:30
|
|
|
},
|
2026-02-12 15:46:52 +05:30
|
|
|
{
|
|
|
|
|
validator: async (_, value) => {
|
|
|
|
|
await validateSafeInput(value);
|
2026-01-27 18:27:29 +05:30
|
|
|
|
2026-02-12 15:46:52 +05:30
|
|
|
if (value && value.length > 50) {
|
|
|
|
|
return Promise.reject(
|
|
|
|
|
'Product Name should not exceed 50 characters'
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-01-27 18:27:29 +05:30
|
|
|
|
2026-02-12 15:46:52 +05:30
|
|
|
return Promise.resolve();
|
|
|
|
|
},
|
2026-01-27 18:27:29 +05:30
|
|
|
},
|
2026-02-12 15:46:52 +05:30
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
<InputField
|
|
|
|
|
autoComplete="off"
|
|
|
|
|
label={<label class="required">Product Name</label>}
|
|
|
|
|
isOnChange={cardData?.length === 1}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
2026-01-27 18:27:29 +05:30
|
|
|
<Form.Item
|
2026-02-12 15:46:52 +05:30
|
|
|
name="Size"
|
2026-01-27 18:27:29 +05:30
|
|
|
rules={[
|
2026-02-12 15:46:52 +05:30
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: 'Please Enter No.of.Units',
|
|
|
|
|
},
|
2026-01-27 18:27:29 +05:30
|
|
|
{
|
|
|
|
|
validator: async (_, value) => {
|
|
|
|
|
await validateSafeInput(value);
|
2026-02-12 15:46:52 +05:30
|
|
|
if (value && value.length > 10) {
|
|
|
|
|
return Promise.reject(
|
|
|
|
|
'No.of.Units should not exceed 10 characters'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Promise.resolve();
|
2026-01-27 18:27:29 +05:30
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
<InputField
|
|
|
|
|
autoComplete="off"
|
2026-02-12 15:46:52 +05:30
|
|
|
label={<label class="required">No.of.Units</label>}
|
|
|
|
|
// inputMode="decimal"
|
2026-01-27 18:27:29 +05:30
|
|
|
isOnChange={cardData?.length === 1}
|
2026-02-12 15:46:52 +05:30
|
|
|
// onInput={(e) => {
|
|
|
|
|
// const cleanedValue = e.target.value.replace(
|
|
|
|
|
// /[^0-9.]/g,
|
|
|
|
|
// ""
|
|
|
|
|
// );
|
|
|
|
|
// const parts = cleanedValue.split(".");
|
|
|
|
|
// e.target.value =
|
|
|
|
|
// parts.length > 2
|
|
|
|
|
// ? `${parts[0]}.${parts.slice(1).join("")}`
|
|
|
|
|
// : cleanedValue;
|
|
|
|
|
// }}
|
|
|
|
|
suffix={
|
|
|
|
|
<Tooltip
|
|
|
|
|
title={
|
|
|
|
|
<>
|
|
|
|
|
<div>Enter No.of.Units as:</div>
|
|
|
|
|
<div>
|
|
|
|
|
- Single number (<strong>5</strong>)
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
- Decimal (<strong>1.500 or 1.5</strong>)
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
- Width x Height (<strong>10x10</strong>)
|
|
|
|
|
</div>
|
|
|
|
|
</>
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
<InfoCircleOutlined
|
|
|
|
|
style={{
|
|
|
|
|
color: 'rgba(0,0,0,.45)',
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</Tooltip>
|
|
|
|
|
}
|
2026-01-27 18:27:29 +05:30
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
2026-02-12 15:46:52 +05:30
|
|
|
<Form.Item
|
|
|
|
|
name="UOM"
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: 'Please Select Uom',
|
|
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
<DropDowns
|
|
|
|
|
options={UomPreference?.map((option) => ({
|
|
|
|
|
value: option.ConfigId,
|
|
|
|
|
label: option.ConfigName,
|
|
|
|
|
}))}
|
|
|
|
|
label={<label class="required">Uom</label>}
|
|
|
|
|
className="field-DropDown"
|
|
|
|
|
isOnchanges={SelectedUom ? true : false}
|
|
|
|
|
onChangeFunction={handleUomDropDownChange}
|
|
|
|
|
valueData={SelectedUom}
|
|
|
|
|
disabled={formType == 'edit' ? true : false}
|
2026-01-27 18:27:29 +05:30
|
|
|
/>
|
2026-02-12 15:46:52 +05:30
|
|
|
</Form.Item>
|
|
|
|
|
<Form.Item
|
|
|
|
|
name="MRP"
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
// pattern: /^[1-9]\d*(\.\d+)?$/,
|
|
|
|
|
message: 'Please Enter MRP',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
validator: async (_, value) => {
|
|
|
|
|
await validateSafeInput(value);
|
2026-01-28 18:55:01 +05:30
|
|
|
|
2026-02-12 15:46:52 +05:30
|
|
|
if (value && value.length > 10) {
|
|
|
|
|
return Promise.reject(
|
|
|
|
|
'MRP should not exceed 10 characters'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Promise.resolve();
|
2026-01-27 18:27:29 +05:30
|
|
|
},
|
2026-02-12 15:46:52 +05:30
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
<InputField
|
|
|
|
|
autoComplete="off"
|
|
|
|
|
label={<label class="required">MRP</label>}
|
|
|
|
|
inputMode="decimal"
|
|
|
|
|
onInput={(e) => {
|
|
|
|
|
const cleanedValue = e.target.value?.replace(
|
|
|
|
|
/[^0-9.]/g,
|
|
|
|
|
''
|
|
|
|
|
);
|
|
|
|
|
const parts = cleanedValue.split('.');
|
|
|
|
|
e.target.value =
|
|
|
|
|
parts.length > 2
|
|
|
|
|
? `${parts[0]}.${parts.slice(1).join('')}`
|
|
|
|
|
: cleanedValue;
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
<Form.Item
|
|
|
|
|
name="SellPrice"
|
|
|
|
|
rules={[{ validator: handleSellPrice }]}
|
|
|
|
|
>
|
|
|
|
|
<InputField
|
|
|
|
|
autoComplete="off"
|
|
|
|
|
label={<label class="required">Sales Price</label>}
|
|
|
|
|
inputMode="decimal"
|
|
|
|
|
onInput={(e) => {
|
|
|
|
|
const cleanedValue = e.target.value?.replace(
|
|
|
|
|
/[^0-9.]/g,
|
|
|
|
|
''
|
|
|
|
|
);
|
|
|
|
|
const parts = cleanedValue.split('.');
|
|
|
|
|
e.target.value =
|
|
|
|
|
parts.length > 2
|
|
|
|
|
? `${parts[0]}.${parts.slice(1).join('')}`
|
|
|
|
|
: cleanedValue;
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
{cardData?.length === 1 && (
|
|
|
|
|
<Form.Item
|
|
|
|
|
name="BrandName"
|
|
|
|
|
rules={[
|
2026-01-27 18:27:29 +05:30
|
|
|
{
|
|
|
|
|
validator: async (_, value) => {
|
2026-02-12 15:46:52 +05:30
|
|
|
await validateSafeInput(value);
|
2026-01-27 18:27:29 +05:30
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
>
|
2026-02-12 15:46:52 +05:30
|
|
|
<InputField
|
|
|
|
|
autoComplete="off"
|
|
|
|
|
isOnChange={cardData?.length === 1}
|
|
|
|
|
label={<label class="required">Brand</label>}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
)}
|
|
|
|
|
{cardData?.length === 1 && (
|
|
|
|
|
<div className="upload_btn">
|
|
|
|
|
<p>Upload Icon</p>
|
|
|
|
|
<br></br>
|
|
|
|
|
<Imageupload
|
|
|
|
|
singleImage={true}
|
|
|
|
|
updateImageUrl={updateBrandImageUrl}
|
|
|
|
|
ImageLink={imageBrandUrl ? imageBrandUrl : ''}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{true && (
|
|
|
|
|
<>
|
|
|
|
|
{(taxField && selectedAdditionalColumn?.includes('Tax')) &&
|
|
|
|
|
<Form.Item name="TaxId">
|
|
|
|
|
<DropDowns
|
|
|
|
|
options={TaxData?.map((option) => ({
|
|
|
|
|
value: option.TaxId,
|
|
|
|
|
label: getOptionLabel(
|
|
|
|
|
option,
|
|
|
|
|
SelectedTaxId === option.TaxId
|
|
|
|
|
),
|
|
|
|
|
// label: option.TaxIdName + ' - ' + option.TaxPercentage + ' % ',
|
|
|
|
|
}))}
|
|
|
|
|
label="Tax"
|
|
|
|
|
className="field-DropDown"
|
|
|
|
|
isOnchanges={SelectedTaxId ? true : false}
|
|
|
|
|
onChangeFunction={handleTaxDropDownChange}
|
|
|
|
|
valueData={SelectedTaxId}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
}
|
|
|
|
|
{(taxField && selectedAdditionalColumn?.includes('Tax')) &&
|
|
|
|
|
<Form.Item name="TaxId">
|
|
|
|
|
<Tooltip title="Add Tax" placement="top">
|
|
|
|
|
<PlusCircleOutlined onClick={addTax} />
|
|
|
|
|
</Tooltip>
|
|
|
|
|
</Form.Item>}
|
|
|
|
|
|
|
|
|
|
{(cessField && selectedAdditionalColumn?.includes('Cess')) && <Form.Item
|
|
|
|
|
name="Cess"
|
2026-01-28 18:55:01 +05:30
|
|
|
rules={[
|
|
|
|
|
{
|
2026-02-12 15:46:52 +05:30
|
|
|
pattern: /^\d*\.?\d+$/,
|
|
|
|
|
message: 'Please Enter Cess',
|
2026-01-27 18:27:29 +05:30
|
|
|
},
|
2026-01-28 18:55:01 +05:30
|
|
|
{
|
|
|
|
|
validator: async (_, value) => {
|
|
|
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
>
|
2026-02-12 15:46:52 +05:30
|
|
|
<InputField autoComplete="off" label="Cess" />
|
|
|
|
|
</Form.Item>}
|
|
|
|
|
|
|
|
|
|
{(hsnField && selectedAdditionalColumn?.includes('Hsn Code')) &&
|
|
|
|
|
<Form.Item
|
|
|
|
|
name="HSNCode"
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
message: 'Please enter HSN',
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
<InputField
|
|
|
|
|
label={<label>HSN Code</label>}
|
|
|
|
|
id="HSNCode"
|
|
|
|
|
value={selectedHsn}
|
|
|
|
|
type="text"
|
|
|
|
|
list="hsnList"
|
|
|
|
|
maxLength={100}
|
|
|
|
|
autoComplete="off"
|
|
|
|
|
isOnChange={selectedHsn ? true : false}
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
const value = e?.target?.value || "";
|
|
|
|
|
setSelectedHsn(value);
|
|
|
|
|
if (value.length >= 1) {
|
|
|
|
|
formRef.current?.setFieldsValue({
|
|
|
|
|
HSNCode: value,
|
|
|
|
|
});
|
|
|
|
|
handleHsnData(value);
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
suffix={
|
|
|
|
|
selectedHsn?.length >= 1 ? (
|
|
|
|
|
<IoCloseSharp onClick={() => setSelectedHsn("")} />
|
|
|
|
|
) : (
|
|
|
|
|
<div />
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
{HsnDetails?.length > 0 && (
|
|
|
|
|
<datalist id="hsnList">
|
|
|
|
|
{HsnDetails
|
|
|
|
|
.filter((item) => {
|
|
|
|
|
const search = selectedHsn?.toLowerCase() || "";
|
|
|
|
|
return (
|
|
|
|
|
item.HSN_CD?.toLowerCase()?.includes(search) ||
|
|
|
|
|
item.Description?.toLowerCase()?.includes(search)
|
|
|
|
|
);
|
|
|
|
|
})
|
|
|
|
|
.map((item, index) => (
|
|
|
|
|
<option
|
|
|
|
|
key={index}
|
|
|
|
|
value={item.HSN_CD}
|
|
|
|
|
label={item.Description}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
// setSelectedHsn(item.HSN_CD);
|
|
|
|
|
formRef.current?.setFieldsValue({
|
|
|
|
|
HSNCode: item.HSN_CD,
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
))}
|
|
|
|
|
</datalist>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{selectedAdditionalColumn?.includes('WholeSale') &&
|
|
|
|
|
<Form.Item
|
|
|
|
|
name="WhSalePrice"
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
pattern: /^[0-9]\d*(\.\d+)?$/,
|
|
|
|
|
message: 'Please Enter WholeSale',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
validator: async (_, value) => {
|
|
|
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
<InputField
|
|
|
|
|
autoComplete="off"
|
|
|
|
|
label={<label>WholeSale</label>}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
}
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
{/* <div className="prodAddDetails" onClick={openAdditionalDetails}>
|
2026-01-27 18:27:29 +05:30
|
|
|
Additional Details
|
2026-01-28 18:55:01 +05:30
|
|
|
</div> */}
|
2026-02-12 15:46:52 +05:30
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
|
|
|
|
<Buttons
|
|
|
|
|
buttonText="SUBMIT"
|
|
|
|
|
color="901D77"
|
|
|
|
|
icon={<ArrowRightOutlined />}
|
|
|
|
|
htmlType={true}
|
|
|
|
|
/>
|
2026-01-27 18:27:29 +05:30
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-02-12 15:46:52 +05:30
|
|
|
</Form>
|
|
|
|
|
|
|
|
|
|
<DefaultModal
|
|
|
|
|
title="Add Tax"
|
|
|
|
|
open={OpenTaxModel}
|
|
|
|
|
footer={true}
|
|
|
|
|
buttonText="Submit"
|
|
|
|
|
destroyOnClose={true}
|
|
|
|
|
children={
|
|
|
|
|
<Form ref={formTaxRef} className="formDivAnt">
|
|
|
|
|
<div className="subRowFlex">
|
|
|
|
|
<Form.Item name="TaxName">
|
|
|
|
|
<DropDowns
|
|
|
|
|
options={ProdTaxData?.map((option) => ({
|
|
|
|
|
value: option.ConfigId,
|
|
|
|
|
label: option.ConfigName,
|
|
|
|
|
}))}
|
|
|
|
|
label="Tax Name"
|
|
|
|
|
className="field-DropDown"
|
|
|
|
|
onChangeFunction={handleTaxNameDropDownChange}
|
|
|
|
|
valueData={SelectedTaxNameId}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
<Form.Item
|
|
|
|
|
name="TaxPercentage"
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
pattern: /^(?:100(?:\.0+)?|\d{1,2}(?:\.\d+)?)$/,
|
|
|
|
|
message: 'Please Enter Valid Percentage',
|
2026-01-27 18:27:29 +05:30
|
|
|
},
|
2026-02-12 15:46:52 +05:30
|
|
|
{
|
|
|
|
|
validator: async (_, value) => {
|
|
|
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
},
|
2026-01-27 18:27:29 +05:30
|
|
|
},
|
2026-02-12 15:46:52 +05:30
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
<InputField autoComplete="off" label="Tax Percentage" />
|
|
|
|
|
</Form.Item>
|
2026-01-27 18:27:29 +05:30
|
|
|
|
|
|
|
|
<Form.Item
|
2026-02-12 15:46:52 +05:30
|
|
|
name="Reference"
|
2026-01-27 18:27:29 +05:30
|
|
|
rules={[
|
|
|
|
|
{
|
2026-02-12 15:46:52 +05:30
|
|
|
pattern: /^(?!\s*$).+/,
|
|
|
|
|
message: 'Please Enter Reference',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
validator: async (_, value) => {
|
|
|
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
|
|
|
return Promise.resolve();
|
|
|
|
|
},
|
2026-01-27 18:27:29 +05:30
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
>
|
2026-02-12 15:46:52 +05:30
|
|
|
<InputField label="Reference No" autoComplete="off" />
|
2026-01-27 18:27:29 +05:30
|
|
|
</Form.Item>
|
2026-02-12 15:46:52 +05:30
|
|
|
<div style={{ display: 'flex', marginTop: '30px' }}>
|
|
|
|
|
<label className="required">Effective From :</label>
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
name="EffectiveFrom"
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: 'Please Enter Effective From',
|
|
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
<DatePic
|
|
|
|
|
field="EffectiveFrom"
|
|
|
|
|
type="number"
|
|
|
|
|
min={1}
|
|
|
|
|
max={100}
|
|
|
|
|
fieldState={true}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</div>
|
2026-01-27 18:27:29 +05:30
|
|
|
</div>
|
2026-02-12 15:46:52 +05:30
|
|
|
</Form>
|
|
|
|
|
}
|
|
|
|
|
handleSubmit={submitTax}
|
|
|
|
|
handleCancel={handleTax}
|
|
|
|
|
></DefaultModal>
|
|
|
|
|
|
|
|
|
|
<DefaultModal
|
|
|
|
|
title="Select Additional Fields"
|
|
|
|
|
open={showColumnModal}
|
|
|
|
|
footer={true}
|
|
|
|
|
buttonText="Apply"
|
|
|
|
|
destroyOnClose={true}
|
|
|
|
|
handleSubmit={handleFieldSetupSubmit}
|
|
|
|
|
handleCancel={() => {
|
|
|
|
|
setShowColumnModal(false);
|
|
|
|
|
setSelectedFields([...selectedAdditionalColumn.map(col =>
|
|
|
|
|
tableFieldPreferences?.find(pref => pref.label === col)?.value
|
|
|
|
|
).filter(Boolean)]);
|
|
|
|
|
setTempSelectedColumns([...selectedAdditionalColumn]);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<div style={{ padding: '20px' }}>
|
|
|
|
|
{tableFieldPreferences?.map((option) => (
|
|
|
|
|
<div key={option.value} className='Customized_QuickAdd'>
|
|
|
|
|
<label>
|
|
|
|
|
<input
|
|
|
|
|
type="checkbox"
|
|
|
|
|
checked={selectedFields?.includes(option.value)}
|
|
|
|
|
onChange={(e) => {
|
|
|
|
|
const isChecked = e.target.checked;
|
|
|
|
|
setSelectedFields(prev =>
|
|
|
|
|
isChecked
|
|
|
|
|
? [...prev, option.value]
|
|
|
|
|
: prev.filter(item => item !== option.value)
|
|
|
|
|
);
|
|
|
|
|
setTempSelectedColumns(prev =>
|
|
|
|
|
isChecked
|
|
|
|
|
? [...prev, option.label]
|
|
|
|
|
: prev.filter(item => item !== option.label)
|
|
|
|
|
);
|
|
|
|
|
}}
|
|
|
|
|
style={{ marginRight: '8px' }}
|
|
|
|
|
/>
|
|
|
|
|
{option.label}
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</DefaultModal>
|
2026-01-28 18:55:01 +05:30
|
|
|
|
2026-02-12 15:46:52 +05:30
|
|
|
</div>
|
|
|
|
|
)}
|
2026-01-27 18:27:29 +05:30
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default ProductForm;
|