diff --git a/src/Features/ProductPage/ProductPage.js b/src/Features/ProductPage/ProductPage.js index 054cfda..b2bc405 100644 --- a/src/Features/ProductPage/ProductPage.js +++ b/src/Features/ProductPage/ProductPage.js @@ -205,6 +205,17 @@ export const getProdSubCatData = createAsyncThunk( } ); +export const getActiveProdSubCatData = createAsyncThunk( + 'product/getActiveProdSubCatData', + async ({ AppId }) => { + if (AppId !== null && AppId !== undefined) { + return await axiosRetailInstanceData.get( + `/configMaster?TypeName=Product Sub-Category&AppId=${AppId}` + ); + } + } +); + export const getProductData = createAsyncThunk( 'product/getProductData', async (ProdData) => { @@ -661,6 +672,7 @@ const initialState = { uomData: [], prodCatData: [], prodSubCatData: [], + allProdSubCatData: [], productData: [], prodTaxData: [], taxData: [], @@ -723,6 +735,13 @@ const productSlice = createSlice({ state.prodSubCatData = []; } }), + builder.addCase(getActiveProdSubCatData.fulfilled, (state, action) => { + if (action?.payload?.status) { + state.allProdSubCatData = action?.payload?.data?.data; + } else { + state.allProdSubCatData = []; + } + }), builder.addCase(getBrandData.fulfilled, (state, action) => { if (action?.payload?.status) { state.brandData = action?.payload?.data?.data; @@ -768,6 +787,8 @@ export const uomDataSelector = (state) => state.productPage?.uomData; export const prodCatDataSelector = (state) => state.productPage?.prodCatData; export const prodSubCatDataSelector = (state) => state.productPage?.prodSubCatData; +export const allProdSubCatDataSelector = (state) => + state.productPage?.allProdSubCatData; export const productDataSelector = (state) => state.productPage?.productData; export const brandDataSelector = (state) => state.productPage?.brandData; export const taxSelector = (state) => state.productPage?.taxData; diff --git a/src/Pages/BookingScreen/Components/OtherConponents/Reprint/BSReprint.jsx b/src/Pages/BookingScreen/Components/OtherConponents/Reprint/BSReprint.jsx index eb3b0d8..90856a4 100644 --- a/src/Pages/BookingScreen/Components/OtherConponents/Reprint/BSReprint.jsx +++ b/src/Pages/BookingScreen/Components/OtherConponents/Reprint/BSReprint.jsx @@ -97,7 +97,7 @@ import { ImShare } from 'react-icons/im'; const RetailApiurl = import.meta.env.ENV_API_URL; -function BSReprint({ setOpenModel = () => {} }) { +function BSReprint({ setOpenModel = () => { } }) { const dispatch = useDispatch(); const queryClient = useQueryClient(); const appPreferences = useSelector(ApplicationPreferences); @@ -133,7 +133,7 @@ function BSReprint({ setOpenModel = () => {} }) { const SettingDataSelector = useSelector(PreferenceData); const salesBillEdit = useSelector(GlobalSalesBillEdit); const custDisable = useSelector(GlobalSelectedCustDisable); - console.log(SettingDataSelector, 'SettingDataSelectoraa'); + console.log(DefReason, 'DefReason'); const MobileA4Print = SettingDataSelector?.[0]?.SettingDtlDetails?.find( (setting) => setting?.SettingIdName?.toLowerCase() === 'mobilea4' && @@ -292,6 +292,7 @@ function BSReprint({ setOpenModel = () => {} }) { } else { setDefReason({}); reprintReasonRef?.current?.resetFields(); + reprintReasonRef?.current?.setFieldsValue({ SetAsDefault: false }); setIsDuplicate('Original'); } }; @@ -607,7 +608,7 @@ function BSReprint({ setOpenModel = () => {} }) { const selectedStyle = stylesMap[ - printerTemplateStyle == undefined ? 'Style 13' : printerTemplateStyle + printerTemplateStyle == undefined ? 'Style 13' : printerTemplateStyle ]; if (selectedStyle) { if (data === 'without') { @@ -1054,7 +1055,7 @@ function BSReprint({ setOpenModel = () => {} }) { } }} > - + 0 ? '#52c41a' : ''} className="BSC1Payment-icon" /> Bill Without Token {} }) { } }} > - + 0 ? '#52c41a' : ''} className="BSC1Payment-icon" /> Bill With Token ) : ( 0 ? '#52c41a' : ''} onClick={() => { setReprintData([row]); if (Object.keys(DefReason)?.length > 0) { @@ -1529,7 +1531,7 @@ function BSReprint({ setOpenModel = () => {} }) { {countOfProduct > 10 && ( { @@ -127,7 +131,7 @@ const ProductForm = ({ formType }) => { UomTypePreference?.some?.( (e) => e?.PreferredSubCatName?.toLowerCase() == - item?.ConfigName?.toLowerCase() && e?.PreferredStatus == 'Y' + item?.ConfigName?.toLowerCase() && e?.PreferredStatus == 'Y' ) ); console.log(UomTypePreference, 'UomTypePreference'); @@ -1008,20 +1012,11 @@ const ProductForm = ({ formType }) => { setMessageData('Please add at least one Sub-Category.'); return; } - const subCategoryData = await formSubCategoryRef?.current?.validateFields(); + const subCategoryTypeId = await dispatch( getConfigTypeData({ TypeName: 'Product Sub-Category' }) ).unwrap(); - // const addSubCategoryData = { - // TypeId: subCategoryTypeId?.data?.data?.[0]?.TypeId, - // ConfigName: subCategoryData?.SubConfigName, - // AlphaNumFId: AppId, - // NumFId: SelectedCategory, - // // SmallIcon: imageSubCategoryUrl, - // CreatedBy: UserId, - // } - const addSubCategoryData = { TypeId: subCategoryTypeId?.data?.data?.[0]?.TypeId || 0, ConfigDetails: Tabledata.map((item) => ({ @@ -1141,7 +1136,7 @@ const ProductForm = ({ formType }) => { (item) => parseFloat(item.MRP) === parseFloat(subVariantPriceData?.MRP) && parseFloat(item.SellPrice) === - parseFloat(subVariantPriceData?.SellPrice) && + parseFloat(subVariantPriceData?.SellPrice) && //dhana 18-02-2025 item.ProdVariantName == subVariantPriceData?.ProdVariantName ); @@ -1156,20 +1151,20 @@ const ProductForm = ({ formType }) => { SellPrice: subVariantPriceData?.SellPrice, WhSalePrice: subVariantPriceData?.WhSalePrice == undefined || - subVariantPriceData?.WhSalePrice == null || - subVariantPriceData?.WhSalePrice == '' + subVariantPriceData?.WhSalePrice == null || + subVariantPriceData?.WhSalePrice == '' ? 0 : subVariantPriceData?.WhSalePrice, OfferPrice: subVariantPriceData?.OfferPrice == undefined || - subVariantPriceData?.OfferPrice == null || - subVariantPriceData?.OfferPrice == '' + subVariantPriceData?.OfferPrice == null || + subVariantPriceData?.OfferPrice == '' ? 0 : subVariantPriceData?.OfferPrice, SpecialPrice: subVariantPriceData?.SpecialPrice == undefined || - subVariantPriceData?.SpecialPrice == null || - subVariantPriceData?.SpecialPrice == '' + subVariantPriceData?.SpecialPrice == null || + subVariantPriceData?.SpecialPrice == '' ? 0 : subVariantPriceData?.SpecialPrice, InwardDtlId: null, @@ -1225,20 +1220,20 @@ const ProductForm = ({ formType }) => { SellPrice: subVariantPriceData?.SellPrice, WhSalePrice: subVariantPriceData?.WhSalePrice == undefined || - subVariantPriceData?.WhSalePrice == null || - subVariantPriceData?.WhSalePrice == '' + subVariantPriceData?.WhSalePrice == null || + subVariantPriceData?.WhSalePrice == '' ? 0 : subVariantPriceData?.WhSalePrice, OfferPrice: subVariantPriceData?.OfferPrice == undefined || - subVariantPriceData?.OfferPrice == null || - subVariantPriceData?.OfferPrice == '' + subVariantPriceData?.OfferPrice == null || + subVariantPriceData?.OfferPrice == '' ? 0 : subVariantPriceData?.OfferPrice, SpecialPrice: subVariantPriceData?.SpecialPrice == undefined || - subVariantPriceData?.SpecialPrice == null || - subVariantPriceData?.SpecialPrice == '' + subVariantPriceData?.SpecialPrice == null || + subVariantPriceData?.SpecialPrice == '' ? 0 : subVariantPriceData?.SpecialPrice, InwardDtlId: null, @@ -1304,20 +1299,20 @@ const ProductForm = ({ formType }) => { SellPrice: subVariantPriceData?.SellPrice, WhSalePrice: subVariantPriceData?.WhSalePrice == undefined || - subVariantPriceData?.WhSalePrice == null || - subVariantPriceData?.WhSalePrice == '' + subVariantPriceData?.WhSalePrice == null || + subVariantPriceData?.WhSalePrice == '' ? 0 : subVariantPriceData?.WhSalePrice, OfferPrice: subVariantPriceData?.OfferPrice == undefined || - subVariantPriceData?.OfferPrice == null || - subVariantPriceData?.OfferPrice == '' + subVariantPriceData?.OfferPrice == null || + subVariantPriceData?.OfferPrice == '' ? 0 : subVariantPriceData?.OfferPrice, SpecialPrice: subVariantPriceData?.SpecialPrice == undefined || - subVariantPriceData?.SpecialPrice == null || - subVariantPriceData?.SpecialPrice == '' + subVariantPriceData?.SpecialPrice == null || + subVariantPriceData?.SpecialPrice == '' ? 0 : subVariantPriceData?.SpecialPrice, InwardDtlId: null, @@ -1372,20 +1367,20 @@ const ProductForm = ({ formType }) => { SellPrice: subVariantPriceData?.SellPrice, WhSalePrice: subVariantPriceData?.WhSalePrice == undefined || - subVariantPriceData?.WhSalePrice == null || - subVariantPriceData?.WhSalePrice == '' + subVariantPriceData?.WhSalePrice == null || + subVariantPriceData?.WhSalePrice == '' ? 0 : subVariantPriceData?.WhSalePrice, OfferPrice: subVariantPriceData?.OfferPrice == undefined || - subVariantPriceData?.OfferPrice == null || - subVariantPriceData?.OfferPrice == '' + subVariantPriceData?.OfferPrice == null || + subVariantPriceData?.OfferPrice == '' ? 0 : subVariantPriceData?.OfferPrice, SpecialPrice: subVariantPriceData?.SpecialPrice == undefined || - subVariantPriceData?.SpecialPrice == null || - subVariantPriceData?.SpecialPrice == '' + subVariantPriceData?.SpecialPrice == null || + subVariantPriceData?.SpecialPrice == '' ? 0 : subVariantPriceData?.SpecialPrice, InwardDtlId: null, @@ -1454,17 +1449,17 @@ const ProductForm = ({ formType }) => { (item) => parseFloat(item.MRP) === parseFloat(subVariantPriceData?.MRP) && parseFloat(item.SellPrice) === - parseFloat(subVariantPriceData?.SellPrice) + parseFloat(subVariantPriceData?.SellPrice) ); if ( existsData?.length == 0 || (parseFloat(variantPriceData[variantEditIndex]?.MRP) === parseFloat(subVariantPriceData?.MRP) && parseFloat(variantPriceData[variantEditIndex]?.SellPrice) === - parseFloat(subVariantPriceData?.SellPrice) && + parseFloat(subVariantPriceData?.SellPrice) && //dhana 18-02-2025 variantPriceData[variantEditIndex]?.ProdVariantName == - subVariantPriceData?.ProdVariantName) + subVariantPriceData?.ProdVariantName) ) { let editVariantData = [...variantPriceData]; if ( @@ -1482,20 +1477,20 @@ const ProductForm = ({ formType }) => { SellPrice: subVariantPriceData?.SellPrice, WhSalePrice: subVariantPriceData?.WhSalePrice == undefined || - subVariantPriceData?.WhSalePrice == null || - subVariantPriceData?.WhSalePrice == '' + subVariantPriceData?.WhSalePrice == null || + subVariantPriceData?.WhSalePrice == '' ? 0 : subVariantPriceData?.WhSalePrice, OfferPrice: subVariantPriceData?.OfferPrice == undefined || - subVariantPriceData?.OfferPrice == null || - subVariantPriceData?.OfferPrice == '' + subVariantPriceData?.OfferPrice == null || + subVariantPriceData?.OfferPrice == '' ? 0 : subVariantPriceData?.OfferPrice, SpecialPrice: subVariantPriceData?.SpecialPrice == undefined || - subVariantPriceData?.SpecialPrice == null || - subVariantPriceData?.SpecialPrice == '' + subVariantPriceData?.SpecialPrice == null || + subVariantPriceData?.SpecialPrice == '' ? 0 : subVariantPriceData?.SpecialPrice, InwardDtlId: editVariantData[variantEditIndex]?.InwardDtlId, @@ -1509,20 +1504,20 @@ const ProductForm = ({ formType }) => { SellPrice: subVariantPriceData?.SellPrice, WhSalePrice: subVariantPriceData?.WhSalePrice == undefined || - subVariantPriceData?.WhSalePrice == null || - subVariantPriceData?.WhSalePrice == '' + subVariantPriceData?.WhSalePrice == null || + subVariantPriceData?.WhSalePrice == '' ? 0 : subVariantPriceData?.WhSalePrice, OfferPrice: subVariantPriceData?.OfferPrice == undefined || - subVariantPriceData?.OfferPrice == null || - subVariantPriceData?.OfferPrice == '' + subVariantPriceData?.OfferPrice == null || + subVariantPriceData?.OfferPrice == '' ? 0 : subVariantPriceData?.OfferPrice, SpecialPrice: subVariantPriceData?.SpecialPrice == undefined || - subVariantPriceData?.SpecialPrice == null || - subVariantPriceData?.SpecialPrice == '' + subVariantPriceData?.SpecialPrice == null || + subVariantPriceData?.SpecialPrice == '' ? 0 : subVariantPriceData?.SpecialPrice, InwardDtlId: editVariantData[variantEditIndex]?.InwardDtlId, @@ -1650,20 +1645,20 @@ const ProductForm = ({ formType }) => { SellPrice: row?.SellPrice, WhSalePrice: row?.WhSalePrice == undefined || - row?.WhSalePrice == null || - row?.WhSalePrice == '' + row?.WhSalePrice == null || + row?.WhSalePrice == '' ? 0 : row?.WhSalePrice, OfferPrice: row?.OfferPrice == undefined || - row?.OfferPrice == null || - row?.OfferPrice == '' + row?.OfferPrice == null || + row?.OfferPrice == '' ? 0 : row?.OfferPrice, SpecialPrice: row?.SpecialPrice == undefined || - row?.SpecialPrice == null || - row?.SpecialPrice == '' + row?.SpecialPrice == null || + row?.SpecialPrice == '' ? 0 : row?.SpecialPrice, InwardDtlId: row?.InwardDtlId, @@ -1677,20 +1672,20 @@ const ProductForm = ({ formType }) => { SellPrice: row?.SellPrice, WhSalePrice: row?.WhSalePrice == undefined || - row?.WhSalePrice == null || - row?.WhSalePrice == '' + row?.WhSalePrice == null || + row?.WhSalePrice == '' ? 0 : row?.WhSalePrice, OfferPrice: row?.OfferPrice == undefined || - row?.OfferPrice == null || - row?.OfferPrice == '' + row?.OfferPrice == null || + row?.OfferPrice == '' ? 0 : row?.OfferPrice, SpecialPrice: row?.SpecialPrice == undefined || - row?.SpecialPrice == null || - row?.SpecialPrice == '' + row?.SpecialPrice == null || + row?.SpecialPrice == '' ? 0 : row?.SpecialPrice, InwardDtlId: row?.InwardDtlId, @@ -1827,14 +1822,14 @@ const ProductForm = ({ formType }) => { postData['InwardDate'] = new Date().toJSON(); postData['AutoGenerateQr'] = values?.QRCode === undefined || - values?.QRCode === null || - values?.QRCode === '' + values?.QRCode === null || + values?.QRCode === '' ? QrcodeAuto : 'N'; postData['AutoGenerateSingleQr'] = values?.OnePcQR === undefined || - values?.OnePcQR === null || - values?.OnePcQR === '' + values?.OnePcQR === null || + values?.OnePcQR === '' ? QrcodeAutoSingle : 'N'; postData['CreatedBy'] = UserId; @@ -1980,67 +1975,7 @@ const ProductForm = ({ formType }) => { // setOpenTour(false) // } // } - const Columns = [ - { - title: 'Sl.No', - key: 'sno', - align: 'center', - render: (text, object, index) => ( - {(page - 1) * 10 + index + 1} - ), - }, - { - title: 'SubCategory Name', - dataIndex: 'SubCategory', - key: 'SubCategory', - editable: true, - render: (text) => {text}, - filteredValue: [searchedText], - onFilter: (value, record) => { - return ( - String(record.TableName) - ?.toLowerCase() - ?.includes(value?.toLowerCase()) || - String(record.TableName) - ?.toLowerCase() - ?.includes(value?.toLowerCase()) || - String(record.ChairCount) - ?.toLowerCase() - ?.includes(value?.toLowerCase()) || - String(record.ChairLevelSer) - ?.toLowerCase() - ?.includes(value?.toLowerCase()) || - String(record.DineInTypeName) - ?.toLowerCase() - ?.includes(value?.toLowerCase()) - ); - }, - sorter: (a, b) => a?.ProdName?.length - b?.ProdName?.length, - sortOrder: - sortedInfo.columnKey === 'SubCategory' ? sortedInfo.order : null, - ellipsis: true, - }, - { - title: 'Action', - key: 'Action', - dataIndex: 'Action', - align: 'center', - render: (_, record, index) => ( - // Tabledata.length >= 1 ? ( - - - {/* {record.ActiveStatus === "A" ? ( */} - statusFormatter(record, index)} - /> - - - ), - }, - ]; + const Onchangeoffertype = (a) => { setDiscountType(a); @@ -2224,8 +2159,8 @@ const ProductForm = ({ formType }) => { label={Product Name} isOnChange={ editstate?.ProdName || - QrcodeExistsData?.[0]?.ProdName || - voiceData?.product + QrcodeExistsData?.[0]?.ProdName || + voiceData?.product ? true : false } @@ -2261,8 +2196,8 @@ const ProductForm = ({ formType }) => { label={No. of Units} isOnChange={ editstate?.Size || - QrcodeExistsData?.[0]?.Size || - voiceData?.qty + QrcodeExistsData?.[0]?.Size || + voiceData?.qty ? true : false } @@ -2290,20 +2225,20 @@ const ProductForm = ({ formType }) => { /> } - // inputMode="decimal" - // onInput={(e) => { - // let cleanedValue = e.target.value.replace(/[^0-9.]/g, ""); // Remove invalid characters - // const parts = cleanedValue.split("."); + // inputMode="decimal" + // onInput={(e) => { + // let cleanedValue = e.target.value.replace(/[^0-9.]/g, ""); // Remove invalid characters + // const parts = cleanedValue.split("."); - // if (cleanedValue.startsWith(".")) { - // cleanedValue = "0" + cleanedValue; - // } + // if (cleanedValue.startsWith(".")) { + // cleanedValue = "0" + cleanedValue; + // } - // e.target.value = - // parts.length > 2 - // ? `${parts[0]}.${parts.slice(1).join("")}` - // : cleanedValue; - // }} + // e.target.value = + // parts.length > 2 + // ? `${parts[0]}.${parts.slice(1).join("")}` + // : cleanedValue; + // }} /> { label={Sales Price} isOnChange={ editstate?.SellPrice || - QrcodeExistsData?.[0]?.SellPrice + QrcodeExistsData?.[0]?.SellPrice ? true : false } @@ -2473,12 +2408,12 @@ const ProductForm = ({ formType }) => { } onChangeFunction={handleProdCatDropDownChange} valueData={SelectedProdCat} - // disabled={ - // editstate?.ProdTypeName == 'Others' || - // formType == 'add' - // ? false - // : true - // } + // disabled={ + // editstate?.ProdTypeName == 'Others' || + // formType == 'add' + // ? false + // : true + // } /> { } onChangeFunction={handleProdSubCatDropDownChange} valueData={SelectedProdSubCat} - // disabled={ - // editstate?.ProdTypeName == 'Others' || - // formType == 'add' - // ? false - // : true - // } + // disabled={ + // editstate?.ProdTypeName == 'Others' || + // formType == 'add' + // ? false + // : true + // } /> { {imagedata?.map((item, index) => ( setSelectedImage(item)} > @@ -2665,20 +2599,20 @@ const ProductForm = ({ formType }) => { {qrAndTokenDtlsFields?.includes( 'Auto Generate QRCode' ) && ( - - openQrcodeAuto(e)} - disabled={editstate?.QRCode ? true : false} - /> - - )} + + openQrcodeAuto(e)} + disabled={editstate?.QRCode ? true : false} + /> + + )} {(QrcodeAuto == 'N' || editstate?.QRCode) && qrAndTokenDtlsFields?.includes( 'Auto Generate QRCode' @@ -2723,19 +2657,19 @@ const ProductForm = ({ formType }) => { {qrAndTokenDtlsFields?.includes( 'Stock Maintenance' ) && ( - - openStock(e)} - /> - - )} + + openStock(e)} + /> + + )} {StockOpen === 'Y' && qrAndTokenDtlsFields?.includes( 'Stock Maintenance' @@ -2766,35 +2700,35 @@ const ProductForm = ({ formType }) => { {qrAndTokenDtlsFields?.includes( 'Token Maintenance' ) && ( - - openToken(e)} - /> - - )} + + openToken(e)} + /> + + )} {qrAndTokenDtlsFields?.includes( 'Rack Maintenance' ) && ( - - openRack(e)} - /> - - )} + + openRack(e)} + /> + + )} {RackOpen === 'Y' && qrAndTokenDtlsFields?.includes( @@ -2805,15 +2739,15 @@ const ProductForm = ({ formType }) => { options={ formType === 'edit' ? RackData?.map((option) => ({ - value: option.RackId, - label: option.RackName, - })) + value: option.RackId, + label: option.RackName, + })) : RackData?.filter( - (item) => item.ActiveStatus === 'A' - )?.map((option) => ({ - value: option.RackId, - label: option.RackName, - })) + (item) => item.ActiveStatus === 'A' + )?.map((option) => ({ + value: option.RackId, + label: option.RackName, + })) } label={ Rack @@ -2839,21 +2773,21 @@ const ProductForm = ({ formType }) => { {qrAndTokenDtlsFields?.includes( 'Amount Per Piece' ) && ( - - - openAmountPerPieceAvailable(e) - } - /> - - )} + + + openAmountPerPieceAvailable(e) + } + /> + + )} {AmountPerPieceAvailable == 'Y' && qrAndTokenDtlsFields?.includes( @@ -2886,7 +2820,7 @@ const ProductForm = ({ formType }) => { } isOnChange={ editstate?.OnePcsPrice || - editstate?.OnePcsPrice == 0 + editstate?.OnePcsPrice == 0 ? true : false } @@ -2910,39 +2844,39 @@ const ProductForm = ({ formType }) => { {(QrcodeAutoSingle == 'N' || editstate?.OnePcQR) && ( - - - { - await validateSafeInput(value); // To block HTML tags & SQL keywords - return Promise.resolve(); + + + { + await validateSafeInput(value); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, }, - }, - ]} - > - - - - )} + ]} + > + + + + )} > )} @@ -2991,134 +2925,134 @@ const ProductForm = ({ formType }) => { {(priceDtlsFields?.length > 0 || hsnAndMoreDtlsFields?.length > 0 || dateAndTimeDtlsFields?.length > 0) && ( - - - - - - - ({ + + + + + + + ({ value: option.ConfigId, label: option.ConfigName, })) - : ProductTypeData.filter( + : ProductTypeData.filter( (item) => item.ConfigName !== 'Others' )?.map((option) => ({ value: option.ConfigId, label: option.ConfigName, })) - } - label={ - Product Type - } - className="field-DropDown" - isOnchanges={ - editstate?.ProdType || SelectedProductType - ? true - : false - } - onChangeFunction={ - handleProductTypeDropDownChange - } - valueData={SelectedProductType} - disabled={ - editstate?.ProdTypeName == 'Others' || - formType == 'add' - ? false - : true - } - /> - - - {priceDtlsFields?.includes('Tax') && ( - - ({ - value: option.TaxId, - label: getOptionLabel( - option, - SelectedTaxId === option.TaxId - ), - }))} - label="Tax" + } + label={ + Product Type + } className="field-DropDown" isOnchanges={ - editstate?.TaxId || SelectedTaxId + editstate?.ProdType || SelectedProductType ? true : false } - onChangeFunction={handleTaxDropDownChange} - valueData={SelectedTaxId} + onChangeFunction={ + handleProductTypeDropDownChange + } + valueData={SelectedProductType} + disabled={ + editstate?.ProdTypeName == 'Others' || + formType == 'add' + ? false + : true + } /> - - - - )} - {SelectedTaxId && - priceDtlsFields?.includes('Cess') && ( - { - await validateSafeInput(value); - if (!value) { - return Promise.resolve(); // Skip validation if the field is empty - } + {priceDtlsFields?.includes('Tax') && ( + + ({ + value: option.TaxId, + label: getOptionLabel( + option, + SelectedTaxId === option.TaxId + ), + }))} + label="Tax" + className="field-DropDown" + isOnchanges={ + editstate?.TaxId || SelectedTaxId + ? true + : false + } + onChangeFunction={handleTaxDropDownChange} + valueData={SelectedTaxId} + /> + + + + + )} - if ( - !/^\d{1,3}(\.\d{1,2})?$/.test(value) - ) { - return Promise.reject( - 'Cess should be a number with up to 2 decimal places' - ); - } + {SelectedTaxId && + priceDtlsFields?.includes('Cess') && ( + { + await validateSafeInput(value); + if (!value) { + return Promise.resolve(); // Skip validation if the field is empty + } - const cessValue = parseFloat(value); - if (cessValue < 0 || cessValue > 100) { - return Promise.reject( - 'Cess cannot be greater than 100%' - ); - } + if ( + !/^\d{1,3}(\.\d{1,2})?$/.test(value) + ) { + return Promise.reject( + 'Cess should be a number with up to 2 decimal places' + ); + } - return Promise.resolve(); + const cessValue = parseFloat(value); + if (cessValue < 0 || cessValue > 100) { + return Promise.reject( + 'Cess cannot be greater than 100%' + ); + } + + return Promise.resolve(); + }, }, - }, - ]} - > - - - )} - {priceDtlsFields?.includes('Discount Type') && ( - - + + + )} + {priceDtlsFields?.includes('Discount Type') && ( + + { padding: '5px', backgroundColor: '#fff', } - : { opacity: '0.6', boxShadow: 'none' } - } - onClick={() => { - Onchangeoffertype('P'); - }} - > - - { + Onchangeoffertype('P'); }} > - Percentage - - - + + Percentage + + + { padding: '5px', backgroundColor: '#fff', } - : { opacity: '0.6', boxShadow: 'none' } - } - onClick={() => { - Onchangeoffertype('F'); - }} - > - - - Fixed - - - - )} - - {priceDtlsFields?.includes('Discount Limit') && ( - - - Sales Limit} - autocomplete="off" - onChange={Handleoffervalue} - isOnChange={ - DiscountValue || DiscountValue == 0 - ? true - : false + : { opacity: '0.6', boxShadow: 'none' } } - 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; - }} - value={DiscountValue} - /> - - - )} - - - {(hsnAndMoreDtlsFields?.length > 0 || - dateAndTimeDtlsFields?.length > 0 || - priceDtlsFields?.includes('Add Variant')) && ( - - {(hsnAndMoreDtlsFields?.length > 0 || - dateAndTimeDtlsFields?.length > 0) && ( - - {OpenAdd ? : } - { + Onchangeoffertype('F'); }} > - {OpenAdd - ? 'Hide Additional Details' - : 'Show Additional Details'} - + + + Fixed + + )} - {priceDtlsFields?.includes('Add Variant') && ( - - Add Variant + + {priceDtlsFields?.includes('Discount Limit') && ( + + + Sales Limit} + autocomplete="off" + onChange={Handleoffervalue} + isOnChange={ + DiscountValue || DiscountValue == 0 + ? true + : false + } + 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; + }} + value={DiscountValue} + /> + )} - )} - - - {(hsnAndMoreDtlsFields?.length > 0 || - dateAndTimeDtlsFields?.length > 0) && ( - - {OpenAdd && ( - - {hsnAndMoreDtlsFields?.length > 0 && ( - - 0 || + dateAndTimeDtlsFields?.length > 0 || + priceDtlsFields?.includes('Add Variant')) && ( + + {(hsnAndMoreDtlsFields?.length > 0 || + dateAndTimeDtlsFields?.length > 0) && ( + - - - {hsnAndMoreDtlsFields?.includes( - 'HSN' - ) && ( - { - await validateSafeInput( - value - ); - return Promise.resolve(); - }, - }, - ]} - > - - HSN Code - - } - id="HSNCode" - value={selectedHsn} - type="text" - list="hsnList" - maxLength={100} - autoComplete="off" - isOnChange={ - editstate?.HSNCode - ? true - : true - } - onChange={(e) => { - const value = - e?.target?.value || ''; - setSelectedHsn(value); - if (value.length >= 1) { - formRef.current?.setFieldsValue( - { - HSNCode: value, - } - ); - handleHsnData(value); - } - }} - suffix={ - selectedHsn?.length >= 1 ? ( - - setSelectedHsn('') - } - /> - ) : ( - - ) - } - /> - {HsnDetails?.length > 0 && ( - - {HsnDetails.filter( - (item) => { - const search = - selectedHsn?.toLowerCase() || - ''; - return ( - item.HSN_CD?.toLowerCase()?.includes( - search - ) || - item.Description?.toLowerCase()?.includes( - search - ) - ); - } - ).map((item, index) => ( - { - // setSelectedHsn(item.HSN_CD); - formRef.current?.setFieldsValue( - { - HSNCode: - item.HSN_CD, - } - ); - }} - /> - ))} - - )} - - )} - {hsnAndMoreDtlsFields?.includes( - 'Part Number' - ) && ( - { - await validateSafeInput( - value - ); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - - - )} - - {hsnAndMoreDtlsFields?.includes( - 'Batch Number' - ) && ( - { - await validateSafeInput( - value - ); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - - - )} - {hsnAndMoreDtlsFields?.includes( - 'Model Number' - ) && ( - { - await validateSafeInput( - value - ); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - - - )} - {hsnAndMoreDtlsFields?.includes( - 'IMEI 1' - ) && ( - { - await validateSafeInput( - value - ); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - - - )} - {hsnAndMoreDtlsFields?.includes( - 'IMEI 2' - ) && ( - { - await validateSafeInput( - value - ); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - - - )} - {hsnAndMoreDtlsFields?.includes( - 'Serial Number' - ) && ( - { - await validateSafeInput( - value - ); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - - - )} - {hsnAndMoreDtlsFields?.includes( - 'MacId' - ) && ( - { - await validateSafeInput( - value - ); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - - - )} - - - + {OpenAdd ? : } + + {OpenAdd + ? 'Hide Additional Details' + : 'Show Additional Details'} + + + )} + {priceDtlsFields?.includes('Add Variant') && ( + + Add Variant )} - - {dateAndTimeDtlsFields?.length > 0 && ( - - - - - {dateAndTimeDtlsFields?.includes( - 'Manufacture Date' - ) && ( - - Manufacture Date - - - - - )} - {/* {(dateAndTimeDtlsFields?.includes('Expiry Notification Days') && */} + + )} - { - await validateSafeInput( - value - ); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - Warranty Days - } - isOnChange={true} - /> - - {/* } */} - {dateAndTimeDtlsFields?.includes( - 'Expire Date' - ) && ( - - Expire Date - - - - - )} + + + {(hsnAndMoreDtlsFields?.length > 0 || + dateAndTimeDtlsFields?.length > 0) && ( + + {OpenAdd && ( + + {hsnAndMoreDtlsFields?.length > 0 && ( + + + + + {hsnAndMoreDtlsFields?.includes( + 'HSN' + ) && ( + { + await validateSafeInput( + value + ); + return Promise.resolve(); + }, + }, + ]} + > + + HSN Code + + } + id="HSNCode" + value={selectedHsn} + type="text" + list="hsnList" + maxLength={100} + autoComplete="off" + isOnChange={ + editstate?.HSNCode + ? true + : true + } + onChange={(e) => { + const value = + e?.target?.value || ''; + setSelectedHsn(value); + if (value.length >= 1) { + formRef.current?.setFieldsValue( + { + HSNCode: value, + } + ); + handleHsnData(value); + } + }} + suffix={ + selectedHsn?.length >= 1 ? ( + + setSelectedHsn('') + } + /> + ) : ( + + ) + } + /> + {HsnDetails?.length > 0 && ( + + {HsnDetails.filter( + (item) => { + const search = + selectedHsn?.toLowerCase() || + ''; + return ( + item.HSN_CD?.toLowerCase()?.includes( + search + ) || + item.Description?.toLowerCase()?.includes( + search + ) + ); + } + ).map((item, index) => ( + { + // setSelectedHsn(item.HSN_CD); + formRef.current?.setFieldsValue( + { + HSNCode: + item.HSN_CD, + } + ); + }} + /> + ))} + + )} + + )} + {hsnAndMoreDtlsFields?.includes( + 'Part Number' + ) && ( + { + await validateSafeInput( + value + ); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + + + )} + + {hsnAndMoreDtlsFields?.includes( + 'Batch Number' + ) && ( + { + await validateSafeInput( + value + ); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + + + )} + {hsnAndMoreDtlsFields?.includes( + 'Model Number' + ) && ( + { + await validateSafeInput( + value + ); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + + + )} + {hsnAndMoreDtlsFields?.includes( + 'IMEI 1' + ) && ( + { + await validateSafeInput( + value + ); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + + + )} + {hsnAndMoreDtlsFields?.includes( + 'IMEI 2' + ) && ( + { + await validateSafeInput( + value + ); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + + + )} + {hsnAndMoreDtlsFields?.includes( + 'Serial Number' + ) && ( + { + await validateSafeInput( + value + ); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + + + )} + {hsnAndMoreDtlsFields?.includes( + 'MacId' + ) && ( + { + await validateSafeInput( + value + ); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + + + )} + + + + + )} + + {dateAndTimeDtlsFields?.length > 0 && ( + + + + + {dateAndTimeDtlsFields?.includes( + 'Manufacture Date' + ) && ( + + Manufacture Date + + + + + )} + {/* {(dateAndTimeDtlsFields?.includes('Expiry Notification Days') && */} - {dateAndTimeDtlsFields?.includes( - 'Expiry Notification Days' - ) && - dateAndTimeDtlsFields?.includes( - 'Expire Date' - ) && ( { - Expiry Notification Days - + Warranty Days } isOnChange={true} /> - )} + {/* } */} + {dateAndTimeDtlsFields?.includes( + 'Expire Date' + ) && ( + + Expire Date + + + + + )} - {dateAndTimeDtlsFields?.includes( - 'Available From' - ) && ( - - Available From - - - - - )} - {dateAndTimeDtlsFields?.includes( - 'Available To' - ) && ( - - Available To - - - - - )} - - - + {dateAndTimeDtlsFields?.includes( + 'Expiry Notification Days' + ) && + dateAndTimeDtlsFields?.includes( + 'Expire Date' + ) && ( + { + await validateSafeInput( + value + ); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + + Expiry Notification Days + + } + isOnChange={true} + /> + + )} + + {dateAndTimeDtlsFields?.includes( + 'Available From' + ) && ( + + Available From + + + + + )} + {dateAndTimeDtlsFields?.includes( + 'Available To' + ) && ( + + Available To + + + + + )} + + + + + )} + )} - )} - - )} - - {openVariant && ( - - - - - - Variant Name - - } - isOnChange={true} - disabled={ - formType == 'edit' && - variantPriceData[variantEditIndex]?.[ - 'ProdVariantName' - ] && - variantPriceData[variantEditIndex] - ?.InwardDtlId != null && - variantEdit - ? true - : false - } - /> - - { - await validateSafeInput(value); - if (parseFloat(value) === 0) { - return Promise.reject( - 'Please enter valid MRP' - ); - } - - if (value && value?.length > 10) { - return Promise.reject( - 'MRP should not exceed 10 chars' - ); - } - - return Promise.resolve(); - }, - }, - ]} - > - MRP - } - isOnChange={variantEdit ? true : false} - onChange={handleDynamicMRP} - onInput={(e) => { - let cleanedValue = - e.target.value.replace( - /[^0-9.]/g, - '' - ); // Remove invalid characters - const parts = cleanedValue.split('.'); - - if (cleanedValue.startsWith('.')) { - cleanedValue = '0' + cleanedValue; - } - - e.target.value = - parts.length > 2 - ? `${parts[0]}.${parts.slice(1).join('')}` - : cleanedValue; - }} - /> - - - - Sales Price - - } - isOnChange={variantEdit ? true : false} - onInput={(e) => { - let cleanedValue = - e.target.value.replace( - /[^0-9.]/g, - '' - ); // Remove invalid characters - const parts = cleanedValue.split('.'); - - if (cleanedValue.startsWith('.')) { - cleanedValue = '0' + cleanedValue; - } - - e.target.value = - parts.length > 2 - ? `${parts[0]}.${parts.slice(1).join('')}` - : cleanedValue; - }} - /> - - { - await validateSafeInput(value); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - WholeSale} - isOnChange={variantEdit ? true : false} - /> - - { - await validateSafeInput(value); - if (value?.length > 10) { - return Promise.reject( - 'Offer cannot exceed 10 chars' - ); - } - return Promise.resolve(); - }, - }, - ]} - > - Offer} - isOnChange={variantEdit ? true : false} - /> - - { - await validateSafeInput(value); - if (value?.length > 10) { - return Promise.reject( - 'Special Price cannot exceed 10 chars' - ); - } - return Promise.resolve(); - }, - }, - ]} - > - Special Price} - isOnChange={variantEdit ? true : false} - /> - - {AmountPerPieceAvailable == 'Y' && ( + + {openVariant && ( + + + + + Variant Name + + } + isOnChange={true} + disabled={ + formType == 'edit' && + variantPriceData[variantEditIndex]?.[ + 'ProdVariantName' + ] && + variantPriceData[variantEditIndex] + ?.InwardDtlId != null && + variantEdit + ? true + : false + } + /> + + { + await validateSafeInput(value); + if (parseFloat(value) === 0) { + return Promise.reject( + 'Please enter valid MRP' + ); + } + + if (value && value?.length > 10) { + return Promise.reject( + 'MRP should not exceed 10 chars' + ); + } + + return Promise.resolve(); + }, + }, + ]} + > + MRP + } + isOnChange={variantEdit ? true : false} + onChange={handleDynamicMRP} + onInput={(e) => { + let cleanedValue = + e.target.value.replace( + /[^0-9.]/g, + '' + ); // Remove invalid characters + const parts = cleanedValue.split('.'); + + if (cleanedValue.startsWith('.')) { + cleanedValue = '0' + cleanedValue; + } + + e.target.value = + parts.length > 2 + ? `${parts[0]}.${parts.slice(1).join('')}` + : cleanedValue; + }} + /> + + + + Sales Price + + } + isOnChange={variantEdit ? true : false} + onInput={(e) => { + let cleanedValue = + e.target.value.replace( + /[^0-9.]/g, + '' + ); // Remove invalid characters + const parts = cleanedValue.split('.'); + + if (cleanedValue.startsWith('.')) { + cleanedValue = '0' + cleanedValue; + } + + e.target.value = + parts.length > 2 + ? `${parts[0]}.${parts.slice(1).join('')}` + : cleanedValue; + }} + /> + + { @@ -4002,56 +3861,131 @@ const ProductForm = ({ formType }) => { > WholeSale} + isOnChange={variantEdit ? true : false} /> - )} + { + await validateSafeInput(value); + if (value?.length > 10) { + return Promise.reject( + 'Offer cannot exceed 10 chars' + ); + } + return Promise.resolve(); + }, + }, + ]} + > + Offer} + isOnChange={variantEdit ? true : false} + /> + + { + await validateSafeInput(value); + if (value?.length > 10) { + return Promise.reject( + 'Special Price cannot exceed 10 chars' + ); + } + return Promise.resolve(); + }, + }, + ]} + > + Special Price} + isOnChange={variantEdit ? true : false} + /> + + {AmountPerPieceAvailable == 'Y' && ( + { + await validateSafeInput(value); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + + + )} - { - try { - await formVariantRef.current?.validateFields(); - if (!variantEdit) { - addVariantPriceData(); - } else { - editVariantPrice(); + { + try { + await formVariantRef.current?.validateFields(); + if (!variantEdit) { + addVariantPriceData(); + } else { + editVariantPrice(); + } + } catch (err) { + setMessageType('error'); + setMessageData( + 'Please fix the validation errors before submitting.' + ); } - } catch (err) { - setMessageType('error'); - setMessageData( - 'Please fix the validation errors before submitting.' - ); - } - }} - > - {!variantEdit ? 'Add' : 'Update'} + }} + > + {!variantEdit ? 'Add' : 'Update'} + - - + + )} + + + + {variantPriceData?.length > 0 && ( + + {' '} + )} - - - {variantPriceData?.length > 0 && ( - - {' '} - - )} - - - - - )} + + + + )} { - - - - - - { - await validateSafeInput(value); - - if (value && value.length > 50) { - return Promise.reject( - 'Category Name should not exceed 50 characters' - ); - } - - return Promise.resolve(); - }, - }, - ]} - > - Category Name - } - autocomplete="off" - /> - - - - - - - Upload Icon - - - - - - - - - } - handleSubmit={submitCategory} - handleCancel={handleCategory} - > - - + - - - - - ({ - value: option.ConfigId, - label: option.ConfigName, - }))} - label={Category} - className="field-DropDown" - onChangeFunction={handleCatDropDownChange} - valueData={SelectedCategory} - disabled={Tabledata.length >= 1} - /> - - - {/* - Upload Icon - - - */} - - - - - - - SubCategory Name - } - autocomplete="off" - /> - - - - - - - { - try { - const values = - await formSubCategoryRef.current?.validateFields( - ['CategoryId', 'SubConfigName'] - ); - const trimmedValue = values?.SubConfigName - ? values.SubConfigName.trim() - : ''; - if (!values?.CategoryId) { - throw new Error('Please Select Category'); - } - if (!trimmedValue) { - throw new Error('SubCategory Name is required'); - } - await validateSafeInput(trimmedValue); - if (trimmedValue.length > 50) { - throw new Error( - 'SubCategory Name should not exceed 50 characters' - ); - } - !editDataval ? handleEdit() : handleadd(); - } catch (error) { - message.error( - error.message || 'Please fill required fields' - ); - } - }} - /> - - - - - - - - - } - > - + close={setOpenSubCategoryModel} + categoryData={ProdCatData} + ref={formSubCategoryRef} + /> { } > - - - - - - ({ - value: option.ConfigId, - label: option.ConfigName, - }))} - label={Sub-Category} - className="field-DropDown" - onChangeFunction={handleSubCatDropDownChange} - valueData={SelectedSubCategory} - /> - - - - Upload Icon - - - - - - - - - - - { - await validateSafeInput(value); - - if (value && value.length > 50) { - return Promise.reject( - 'Brand Name should not exceed 50 characters' - ); - } - - return Promise.resolve(); - }, - }, - ]} - > - Brand Name} - autocomplete="off" - /> - - - - - - } - > - - + - - - ({ - value: option.ConfigId, - label: option.ConfigName, - }))} - label="Tax Name" - className="field-DropDown" - onChangeFunction={handleTaxNameDropDownChange} - valueData={SelectedTaxNameId} - /> - - - { - await validateSafeInput(value); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - { - let cleanedValue = e.target.value.replace( - /[^0-9.]/g, - '' - ); // Remove invalid characters - const parts = cleanedValue.split('.'); - - if (cleanedValue.startsWith('.')) { - cleanedValue = '0' + cleanedValue; - } - - e.target.value = - parts.length > 2 - ? `${parts[0]}.${parts.slice(1).join('')}` - : cleanedValue; - }} - /> - - - { - await validateSafeInput(value); // To block HTML tags & SQL keywords - return Promise.resolve(); - }, - }, - ]} - > - - - - Effective From : - - - - - - - - } - handleSubmit={submitTax} - handleCancel={handleTax} - > - + close={setOpenTaxModel} + prodTaxData={ProdTaxData} + ref={formTaxRef} + /> ({ const TurboAddForm = () => { const dispatch = useDispatch(); // Redux selectors - const taxData = useSelector(taxSelector); + const taxRef = useRef(); + const brandRef = useRef(); + const categoryRef = useRef(); + const subCategoryRef = useRef(); const scannerRef = useRef(); - console.log(taxData, 'taxData'); + const prodTaxData = useSelector(prodTaxDataSelector); + const taxData = useSelector(taxSelector); const UomData = useSelector(uomDataSelector); const productTypeData = useSelector(productTypeDataSelector); const ApplicationPreferenceData = useSelector(ApplicationPreferences); @@ -164,8 +175,8 @@ const TurboAddForm = () => { )?.PreferredCatId; const prodCategories = useSelector(prodCatDataSelector); const prodSubCategories = useSelector(prodSubCatDataSelector); + const allProdSubCategories = useSelector(allProdSubCatDataSelector); const searchText = useSelector(GlobalSearchData); - // Session data const AppId = useMemo(() => getSession('AppId'), []); const CompId = useMemo(() => getSession('CompId'), []); @@ -173,6 +184,11 @@ const TurboAddForm = () => { const UserId = useMemo(() => getSession('UserId'), []); // State + const [openTaxModal, setOpenTaxModal] = useState(false); + const [openCategoryModal, setOpenCategoryModal] = useState(false); + const [openSubCategoryModal, setOpenSubCategoryModal] = useState(false); + const [openBrandModal, setOpenBrandModal] = useState(false); + const [imageCategoryUrl, setImageCategoryUrl] = useState(''); const [voiceData, setVoiceData] = useState(null); const [messageType, setMessageType] = useState(null); const [messageData, setMessageData] = useState(null); @@ -257,7 +273,7 @@ const TurboAddForm = () => { uomPref?.some?.( (e) => e?.PreferredSubCatName?.toLowerCase() === - item?.ConfigName?.toLowerCase() && e?.PreferredStatus === 'Y' + item?.ConfigName?.toLowerCase() && e?.PreferredStatus === 'Y' ) ); @@ -372,6 +388,8 @@ const TurboAddForm = () => { [UomPreference, taxData, prodCategories, prodSubCategories] ); + console.log(selectOptions?.tax, taxData, "selectOptions tax"); + // Filtered products for search const filteredProducts = useMemo(() => { if (!searchTerm.trim()) return products; @@ -953,14 +971,14 @@ const TurboAddForm = () => { prev.map((p) => p.id === productId ? { - ...p, - availableSubCategories, - subCategory: subCategoryId, - subCategoryName, - availableBrands, - brand: '', - brandName: '', - } + ...p, + availableSubCategories, + subCategory: subCategoryId, + subCategoryName, + availableBrands, + brand: '', + brandName: '', + } : p ) ); @@ -1013,7 +1031,7 @@ const TurboAddForm = () => { return p; }); }); - } catch (error) {} + } catch (error) { } } }, [handleInputChange, selectOptions.subCategories] @@ -1189,7 +1207,7 @@ const TurboAddForm = () => { (p, i) => i !== idx && p.productName?.trim().toLowerCase() === - product.productName?.trim().toLowerCase() && + product.productName?.trim().toLowerCase() && p.uom === product.uom && p.nou === product.nou && p?.category === product?.category && @@ -1613,11 +1631,11 @@ const TurboAddForm = () => { rowIndex === 0 && !isMobile ? rowIndex + 1 : rowIndex; return idx === index ? { - ...p, - productName: found.ProdName, - barcode: enteredValue, - productImage: found.ImageUrl, - } + ...p, + productName: found.ProdName, + barcode: enteredValue, + productImage: found.ImageUrl, + } : p; }) ); @@ -1687,7 +1705,7 @@ const TurboAddForm = () => { const duplicateExists = products.some( (row) => row.productName?.trim().toLowerCase() === - baseData.productName?.trim().toLowerCase() && + baseData.productName?.trim().toLowerCase() && row.nou === baseData.nou && row.uom === baseData.uom ); @@ -1936,12 +1954,12 @@ const TurboAddForm = () => { // onClick={() => handleQrcode()} // style={{ cursor: 'pointer', marginLeft: '8px' }} // /> - { - changeSearchedData(value); - }} - /> + changeSearchedData(value); + }} + /> )} { field="category" options={defaultCategories} onSubmit={handleDefaultSetting} + triggerModal={setOpenCategoryModal} + Component={} /> {hasField('Sub Category') && ( @@ -2039,6 +2063,15 @@ const TurboAddForm = () => { ? `Selected Category : ${defaultCategories?.find((cat) => cat.value === selectedDefaultCategory)?.label}` : null } + triggerModal={setOpenSubCategoryModal} + Component={} /> )} @@ -2048,7 +2081,7 @@ const TurboAddForm = () => { 0 && - selectedDefaultSubCategory + selectedDefaultSubCategory ? `Selected Sub-Category : ${defaultSubCategories?.find((subCat) => subCat.value === selectedDefaultSubCategory)?.label}` : null } @@ -2060,6 +2093,16 @@ const TurboAddForm = () => { checkBoxHeading={ 'Apply to all selected sub-category rows' } + triggerModal={setOpenBrandModal} + needAllSubCategories={true} + Component={} /> )} @@ -2090,6 +2133,14 @@ const TurboAddForm = () => { options={selectOptions.tax} onSubmit={handleDefaultSetting} currentDefault={defaults.tax} + triggerModal={setOpenTaxModal} + Component={} /> )} @@ -2195,7 +2246,7 @@ const TurboAddForm = () => { (p) => p.barcode && p.barcode.toLowerCase() === - newValue?.toLowerCase() + newValue?.toLowerCase() ); if (barcodeExists) { diff --git a/src/Pages/Product/Utils/AddBrandModal.jsx b/src/Pages/Product/Utils/AddBrandModal.jsx new file mode 100644 index 0000000..31aabef --- /dev/null +++ b/src/Pages/Product/Utils/AddBrandModal.jsx @@ -0,0 +1,204 @@ +import { Form } from 'antd'; +import { DefaultModal } from '../../../Components/Modal/DefaultModal'; +import { getSession, validateSafeInput } from '../../../Services/Others'; +import { DropDowns } from '../../../Components/Forms/DropDown'; +import Imageupload from '../../../Components/Forms/Upload.jsx'; +import { InputField } from '../../../../ownLib/my-ui-lib'; +import { forwardRef, useCallback, useState } from 'react'; +import { getConfigTypeData, postConfiguration } from '../../../Features/ConfigMasterPage/ConfigMasterPage.js'; +import { useDispatch } from 'react-redux'; +import { getBrandData } from '../../../Features/ProductPage/ProductPage.js'; +import { Messages } from '../../../Components/Notifications/Messages.jsx'; + +const AddBrandModal = forwardRef(( + { + open = false, + close = () => { }, + subCategories = [], + products = [], + setProducts = () => { }, + }, ref) => { + + const dispatch = useDispatch(); + const AppId = getSession('AppId'); + const UserId = getSession('UserId'); + + const [messageType, setMessageType] = useState(null); + const [messageData, setMessageData] = useState(null); + const [imageBrandUrl, setBrandImageUrl] = useState(''); + const [selectedSubCategory, setSelectedSubCategory] = useState(null); + + const handleBrandModalClose = () => { + close(false); + setBrandImageUrl(''); + setSelectedSubCategory(null); + ref?.current?.resetFields(); + }; + + const handleBrandImageUrlUpdate = (url) => { + setBrandImageUrl(url); + }; + + const handleSubCatDropDownChange = (value) => { + setSelectedSubCategory(value); + ref?.current?.setFieldsValue({ SubCategoryId: value }); + }; + + const handleBrandSubmit = async () => { + + const subBrandData = await ref?.current?.validateFields(); + const subBrandTypeId = await dispatch( + getConfigTypeData({ TypeName: 'Product Brand' }) + ).unwrap(); + + const addBrandData = { + TypeId: subBrandTypeId?.data?.data?.[0]?.TypeId, + ConfigName: subBrandData?.SubConfigName, + AlphaNumFId: AppId, + NumFId: selectedSubCategory, + SmallIcon: imageBrandUrl, + CreatedBy: UserId, + }; + + const response = await dispatch(postConfiguration(addBrandData)).unwrap(); + if (response?.data?.statusCode == 1) { + setBrandImageUrl(''); + setMessageType('success'); + setMessageData(response?.data?.response); + close(false); + const brandResponse = await dispatch(getBrandData({ ConfigId: selectedSubCategory }))?.unwrap(); + ref?.current?.resetFields(); + if (products?.length > 0) { + const hasTheSubCategory = products.some(product => product.subCategory === selectedSubCategory); + if (hasTheSubCategory) { + if (brandResponse?.data?.statusCode == 1) { + const brands = brandResponse?.data?.data || []; + const availableBrands = brands?.filter( + (subCat) => + subCat.NumFId === parseInt(selectedSubCategory) && !!subCat?.ConfigName + )?.map((subCat) => ({ + label: subCat.ConfigName, + value: subCat.ConfigId, + })); + + const updatedProducts = products?.map((product) => { + if (product.subCategory === selectedSubCategory) { + return { + ...product, + availableBrands, + }; + } + return product; + }); + + setProducts(updatedProducts); + } + + } + } + setSelectedSubCategory(null); + } else { + setBrandImageUrl(''); + setSelectedSubCategory(null); + setMessageType('error'); + setMessageData(response?.data?.response); + ref?.current?.resetFields(); + } + }; + + const onComplete = useCallback(() => { + setMessageType(null); + setMessageData(null); + }, []); + + return ( + <> + + + + + + + ({ + value: option.ConfigId, + label: option.ConfigName, + }))} + label={Sub-Category} + className="field-DropDown" + onChangeFunction={handleSubCatDropDownChange} + valueData={selectedSubCategory} + /> + + + + Upload Icon + + + + + + + + + + + { + await validateSafeInput(value); + + if (value && value.length > 50) { + return Promise.reject( + 'Brand Name should not exceed 50 characters' + ); + } + + return Promise.resolve(); + }, + }, + ]} + > + Brand Name} + autocomplete="off" + /> + + + + + + } + /> + > + ) +}); + +export default AddBrandModal \ No newline at end of file diff --git a/src/Pages/Product/Utils/AddCategoryModal.jsx b/src/Pages/Product/Utils/AddCategoryModal.jsx new file mode 100644 index 0000000..d7f1d84 --- /dev/null +++ b/src/Pages/Product/Utils/AddCategoryModal.jsx @@ -0,0 +1,147 @@ +import { forwardRef, useCallback, useState } from "react"; +import Imageupload from '../../../Components/Forms/Upload.jsx'; +import { DefaultModal } from "../../../Components/Modal/DefaultModal"; +import { InputField } from "../../../Components/Forms/InputField"; +import { Form } from "antd"; +import { getSession, validateSafeInput } from "../../../Services/Others.js"; +import { useDispatch } from "react-redux"; +import { getConfigTypeData, postConfiguration } from "../../../Features/ConfigMasterPage/ConfigMasterPage.js"; +import { getProdCatData } from "../../../Features/ProductPage/ProductPage.js"; +import { Messages } from "../../../Components/Notifications/Messages.jsx"; + +const AddCategoryModal = forwardRef(( + { + open = false, + close = () => { }, + }, ref) => { + + const dispatch = useDispatch(); + const AppId = getSession('AppId'); + const UserId = getSession('UserId'); + + const [messageType, setMessageType] = useState(''); + const [messageData, setMessageData] = useState(''); + + const [imageCategoryUrl, setImageCategoryUrl] = useState(''); + + const handleImageCategoryUrlUpdate = (url) => { + setImageCategoryUrl(url); + }; + + const handleSubmitCategory = async () => { + try { + const values = await ref?.current?.validateFields(); + + const categoryTypeId = await dispatch( + getConfigTypeData({ TypeName: 'Product Category' }) + ).unwrap(); + + const data = { + TypeId: categoryTypeId?.data?.data?.[0]?.TypeId, + ConfigName: values?.ConfigName, + AlphaNumFId: AppId, + SmallIcon: imageCategoryUrl, + CreatedBy: UserId, + }; + const response = await dispatch(postConfiguration(data)).unwrap(); + if (response?.data?.statusCode === 1) { + await dispatch(getProdCatData({ AppId: AppId })); + close(false); + setImageCategoryUrl(''); + setMessageType('success'); + setMessageData(response?.data?.response); + ref?.current?.resetFields(); + } else { + setMessageType('error'); + setMessageData(response?.data?.response); + } + return; + } + catch (error) { + console.log('Error:', error?.message); + return; + } + } + + const handleModalClose = () => { + close(false); + setImageCategoryUrl(''); + ref?.current?.resetFields(); + }; + + const onComplete = useCallback(() => { + setMessageData(null); + setMessageType(null); + }, []); + + + return ( + <> + + + + + + { + await validateSafeInput(value); + + if (value && value.length > 50) { + return Promise.reject( + 'Category Name should not exceed 50 characters' + ); + } + + return Promise.resolve(); + }, + }, + ]} + > + Category Name + } + autocomplete="off" + /> + + + + + + + Upload Icon + + + + + + + + + } + handleSubmit={handleSubmitCategory} + handleCancel={handleModalClose} + /> + > + ) +}); + +export default AddCategoryModal; \ No newline at end of file diff --git a/src/Pages/Product/Utils/AddSubCategoryModal.jsx b/src/Pages/Product/Utils/AddSubCategoryModal.jsx new file mode 100644 index 0000000..6979b31 --- /dev/null +++ b/src/Pages/Product/Utils/AddSubCategoryModal.jsx @@ -0,0 +1,337 @@ +import { Form, Table } from 'antd'; +import { forwardRef, useCallback, useState } from 'react'; +import { DropDowns } from '../../../Components/Forms/DropDown'; +import { getSession, validateSafeInput } from '../../../Services/Others'; +import { InputField } from '../../../Components/Forms/InputField'; +import { PlusCircleOutlined, DeleteFilled } from '@ant-design/icons'; +import { Tooltip, message, Space } from 'antd'; +import { DefaultModal } from '../../../Components/Modal/DefaultModal'; +import { Messages } from '../../../Components/Notifications/Messages'; +import { getProdSubCatData, postConfigurationmultiple } from '../../../Features/ProductPage/ProductPage'; +import { useDispatch } from 'react-redux'; +import { getConfigTypeData } from '../../../Features/ConfigMasterPage/ConfigMasterPage'; + +const AddSubCategoryModal = forwardRef(( + { + open = false, + close = () => { }, + categoryData = [], + products = [], + setProducts = () => { }, + flag = false, + }, ref) => { + + const AppId = getSession('AppId'); + const UserId = getSession('UserId'); + + const dispatch = useDispatch(); + + const [page, setPage] = useState(1); + const [searchedText, setSearchedText] = useState(''); + const [sortedInfo, setSortedInfo] = useState({}); + const [editDataval, setEditDataVal] = useState(true); + const [messageType, setMessageType] = useState(''); + const [messageData, setMessageData] = useState(''); + const [imageSubCategoryUrl, setSubCategoryImageUrl] = useState(''); + + const [selectedCategory, setSelectedCategory] = useState(null); + const [tableData, setTableData] = useState([]); + + const Columns = [ + { + title: 'Sl.No', + key: 'sno', + align: 'center', + render: (text, object, index) => ( + {(page - 1) * 10 + index + 1} + ), + }, + { + title: 'SubCategory Name', + dataIndex: 'SubCategory', + key: 'SubCategory', + editable: true, + render: (text) => {text}, + filteredValue: [searchedText], + onFilter: (value, record) => { + return ( + String(record.TableName) + ?.toLowerCase() + ?.includes(value?.toLowerCase()) || + String(record.TableName) + ?.toLowerCase() + ?.includes(value?.toLowerCase()) || + String(record.ChairCount) + ?.toLowerCase() + ?.includes(value?.toLowerCase()) || + String(record.ChairLevelSer) + ?.toLowerCase() + ?.includes(value?.toLowerCase()) || + String(record.DineInTypeName) + ?.toLowerCase() + ?.includes(value?.toLowerCase()) + ); + }, + sorter: (a, b) => a?.ProdName?.length - b?.ProdName?.length, + sortOrder: + sortedInfo.columnKey === 'SubCategory' ? sortedInfo.order : null, + ellipsis: true, + }, + { + title: 'Action', + key: 'Action', + dataIndex: 'Action', + align: 'center', + render: (_, record, index) => ( + // Tabledata.length >= 1 ? ( + + + {/* {record.ActiveStatus === "A" ? ( */} + statusFormatter(record, index)} + /> + + + ), + }, + ]; + + const handleAddSubCategory = async () => { + const subCategoryData = await ref?.current?.validateFields(); + + const alreadyExists = tableData.some( + (item) => item.SubCategory === subCategoryData?.SubConfigName + ); + + if (!alreadyExists) { + setTableData((prev) => { + const newIndex = prev.length + 1; + + const datas = { + category: selectedCategory, + SubCategory: subCategoryData?.SubConfigName, + key: newIndex, // Push index here + }; + + return [...prev, datas]; + }); + } else { + setMessageType('error'); + setMessageData('Sub Category Already Exist'); + } + ref.current.resetFields(['SubConfigName']); + }; + + const handleSubmitSubCategory = async () => { + if (!tableData || tableData.length === 0) { + setMessageType('error'); + setMessageData('Please add at least one Sub-Category.'); + return; + } + + const subCategoryTypeId = await dispatch( + getConfigTypeData({ TypeName: 'Product Sub-Category' }) + ).unwrap(); + + const addSubCategoryData = { + TypeId: subCategoryTypeId?.data?.data?.[0]?.TypeId || 0, + ConfigDetails: tableData.map((item) => ({ + ConfigName: item.SubCategory, + })), + AlphaNumFId: AppId, + NumFId: selectedCategory, + CreatedBy: UserId, + }; + + const response = await dispatch( + postConfigurationmultiple(addSubCategoryData) + ).unwrap(); + + if (response?.data?.statusCode == 1) { + setSubCategoryImageUrl(''); + setMessageType('success'); + setMessageData('Sub-Category Added Successfully'); + close(false); + setSelectedCategory(null); + const subCatResponse = await dispatch(getProdSubCatData({ ConfigId: selectedCategory })).unwrap(); + setTableData([]); + ref?.current?.resetFields(); + if (products?.length > 0) { + const hasTheCategory = products.some(product => product.category === selectedCategory); + if (hasTheCategory) { + if (subCatResponse?.data?.statusCode == 1) { + const subCategories = subCatResponse?.data?.data || []; + const availableSubCategories = subCategories?.filter( + (subCat) => + subCat.NumFId === parseInt(selectedCategory) && !!subCat?.ConfigName + )?.map((subCat) => ({ + label: subCat.ConfigName, + value: subCat.ConfigId, + })); + + const updatedProducts = products?.map((product) => { + if (product.category === selectedCategory) { + return { + ...product, + availableSubCategories, + }; + } + return product; + }); + + setProducts(updatedProducts); + } + + } + } + console.log(products, "selectedCategory", selectedCategory) + } else { + setMessageType('error'); + setMessageData(response?.data?.response); + ref?.current?.resetFields(); + } + }; + + const handleCatDropDownChange = (value) => { + setSelectedCategory(value); + ref?.current?.setFieldsValue({ CategoryId: value }); + }; + + const statusFormatter = (record, index) => { + let filteredData = tableData.filter( + (item) => item.SubCategory != record?.SubCategory + ); + setTableData(filteredData); + }; + + const handleSubCatModalClose = () => { + close(false); + setSubCategoryImageUrl(''); + setSelectedCategory(null); + setTableData([]); + ref?.current?.resetFields(); + }; + + const handleEdit = () => { + + }; + + const onComplete = useCallback(() => { + setMessageData(null); + setMessageType(null); + }, []); + + return ( + <> + + + + + + + ({ + value: option?.ConfigId, + label: option?.ConfigName, + }))} + label={Category} + className="field-DropDown" + onChangeFunction={handleCatDropDownChange} + valueData={selectedCategory} + disabled={tableData?.length >= 1} + /> + + + + + + + + SubCategory Name + } + autocomplete="off" + /> + + + + + + + { + try { + const values = + await ref.current?.validateFields( + ['CategoryId', 'SubConfigName'] + ); + const trimmedValue = values?.SubConfigName + ? values.SubConfigName.trim() + : ''; + if (!values?.CategoryId) { + throw new Error('Please Select Category'); + } + if (!trimmedValue) { + throw new Error('SubCategory Name is required'); + } + await validateSafeInput(trimmedValue); + if (trimmedValue.length > 50) { + throw new Error( + 'SubCategory Name should not exceed 50 characters' + ); + } + !editDataval ? handleEdit() : handleAddSubCategory(); + } catch (error) { + message.error( + error.message || 'Please fill required fields' + ); + } + }} + /> + + + + + + + + + } + /> + > + ) +}); + +export default AddSubCategoryModal \ No newline at end of file diff --git a/src/Pages/Product/Utils/AddTaxModal.jsx b/src/Pages/Product/Utils/AddTaxModal.jsx new file mode 100644 index 0000000..e093b45 --- /dev/null +++ b/src/Pages/Product/Utils/AddTaxModal.jsx @@ -0,0 +1,193 @@ +import { forwardRef, useCallback, useState } from "react"; +import { DefaultModal } from "../../../Components/Modal/DefaultModal"; +import { Form } from "antd"; +import { DropDowns } from "../../../Components/Forms/DropDown"; +import { InputField } from "../../../Components/Forms/InputField"; +import { getSession, validateSafeInput } from "../../../Services/Others"; +import { useDispatch } from "react-redux"; +import { Messages } from "../../../Components/Notifications/Messages"; +import { DatePic } from '../../../Components/Forms/DatePicker.jsx'; +import { getAdmin as getTax } from "../../../Features/Tax/Tax.js"; +import { getAdmin, postTax } from "../../../Features/ProductPage/ProductPage.js"; +const AddTaxModal = forwardRef(( + { + open = false, + close = () => { }, + prodTaxData = [], + flag = false, + }, ref) => { + + const dispatch = useDispatch(); + console.log(prodTaxData, 'prodTaxData in modal'); + const AppId = getSession('AppId'); + const CompId = getSession('CompId'); + const UserId = getSession('UserId'); + + const [messageType, setMessageType] = useState(null); + const [messageData, setMessageData] = useState(null); + const [selectedTaxNameId, setSelectedTaxNameId] = useState(null); + + const handleTaxNameDropDownChange = async (ConfigId) => { + ref.current?.setFieldsValue({ TaxName: ConfigId }); + await setSelectedTaxNameId(ConfigId); + }; + + const handleTaxModalClose = () => { + close(false); + setSelectedTaxNameId(null); + ref.current?.resetFields(); + } + + const handleSubmitTax = async () => { + try { + const subTaxData = await ref?.current?.validateFields(); + const effectiveDate = new Date(subTaxData.EffectiveFrom); + const formattedDate = effectiveDate.toLocaleDateString('en-CA'); + const addTaxData = { + CompId: CompId, + AppId: AppId, + TaxName: subTaxData?.TaxName, + TaxPercentage: subTaxData?.TaxPercentage, + EffectiveFrom: formattedDate, + Reference: subTaxData.Reference, + CreatedBy: UserId, + }; + + const response = await dispatch(postTax(addTaxData)).unwrap(); + if (response?.data?.statusCode == 1) { + setMessageType('success'); + setMessageData(response?.data?.response); + close(false); + if (flag) { + await dispatch(getTax({ CompId: CompId, AppId: AppId })); + } else { + await dispatch(getAdmin({ CompId: CompId, AppId: AppId })); + } + ref?.current?.resetFields(); + setSelectedTaxNameId(null); + } else { + setMessageType('error'); + setMessageData(response?.data?.response); + } + } catch (error) { + console.log('Error:', error?.message); + } + }; + + const onComplete = useCallback(() => { + setMessageType(null); + setMessageData(null); + }, []); + + return ( + <> + + + + + ({ + value: option.ConfigId, + label: option.ConfigName, + }))} + label="Tax Name" + className="field-DropDown" + onChangeFunction={handleTaxNameDropDownChange} + valueData={selectedTaxNameId} + /> + + + { + await validateSafeInput(value); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + { + let cleanedValue = e.target.value.replace( + /[^0-9.]/g, + '' + ); // Remove invalid characters + const parts = cleanedValue.split('.'); + + if (cleanedValue.startsWith('.')) { + cleanedValue = '0' + cleanedValue; + } + + e.target.value = + parts.length > 2 + ? `${parts[0]}.${parts.slice(1).join('')}` + : cleanedValue; + }} + /> + + + { + await validateSafeInput(value); // To block HTML tags & SQL keywords + return Promise.resolve(); + }, + }, + ]} + > + + + + Effective From : + + + + + + + + } + handleSubmit={handleSubmitTax} + handleCancel={handleTaxModalClose} + /> + > + ) +}); + +export default AddTaxModal; \ No newline at end of file diff --git a/src/Pages/Product/Utils/DefaultSettingPopover.jsx b/src/Pages/Product/Utils/DefaultSettingPopover.jsx index 72bd4cb..34801b6 100644 --- a/src/Pages/Product/Utils/DefaultSettingPopover.jsx +++ b/src/Pages/Product/Utils/DefaultSettingPopover.jsx @@ -2,12 +2,19 @@ import { memo, useState, useEffect } from "react"; import { DropDowns } from "../../../Components/Forms/DropDown"; import { Checkbox, Popover } from "antd"; import { Settings, X } from "lucide-react"; +import { PlusCircleOutlined } from '@ant-design/icons'; +import { Tooltip } from 'antd'; +import { getActiveProdSubCatData } from "../../../Features/ProductPage/ProductPage"; +import { useDispatch } from "react-redux"; +import { getSession } from "../../../Services/Others"; -const DefaultSettingPopover = memo(({ field, options, onSubmit, currentDefault, popOverHeading, checkBoxHeading = 'Apply to all existing rows', showField }) => { +const DefaultSettingPopover = memo(({ field, options, onSubmit, currentDefault, popOverHeading, checkBoxHeading = 'Apply to all existing rows', showField, Component = null, triggerModal = () => { }, needAllSubCategories = false }) => { + const dispatch = useDispatch(); const [selectedValue, setSelectedValue] = useState(currentDefault); const [applyToAll, setApplyToAll] = useState(false); const [open, setOpen] = useState(false); - console.log(showField, "showField") + const [fetchSubCategoriesData, setFetchSubCategoriesData] = useState(false); + console.log(Component, "showField") useEffect(() => { if (open) { setSelectedValue(currentDefault); @@ -15,6 +22,17 @@ const DefaultSettingPopover = memo(({ field, options, onSubmit, currentDefault, } }, [open, currentDefault]); + useEffect(() => { + + const fetchAllSubCategories = async () => { + await (dispatch(getActiveProdSubCatData({ AppId: getSession('AppId') })))?.unwrap(); + } + + if (fetchSubCategoriesData) { + fetchAllSubCategories(); + } + }, [fetchSubCategoriesData]); + const handleSubmit = () => { onSubmit(field, selectedValue, applyToAll); setOpen(false); @@ -39,21 +57,34 @@ const DefaultSettingPopover = memo(({ field, options, onSubmit, currentDefault, setOpen(false)} /> - {showField && {showField}} - + + {Component && ( + + { + triggerModal(true); + if (needAllSubCategories) { + setFetchSubCategoriesData(true); + } + }} + /> + + )} - + {Component} - - + <> + + + + > ); });
{ + Onchangeoffertype('P'); }} > - Percentage -
+ Percentage +
- Fixed -
+ Fixed +
Upload Icon