2500 lines
85 KiB
JavaScript
2500 lines
85 KiB
JavaScript
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
import { useLocation, useNavigate } from 'react-router-dom';
|
|
import {
|
|
ArrowRightOutlined,
|
|
PlusCircleOutlined,
|
|
DeleteFilled,
|
|
EditFilled,
|
|
} from '@ant-design/icons';
|
|
import { Messages } from '../../Components/Notifications/Messages';
|
|
import { Form, Tooltip, Space, Input, Button, AutoComplete } from 'antd';
|
|
import { IoWarningOutline } from 'react-icons/io5';
|
|
import {
|
|
getSession,
|
|
pdfDiv,
|
|
printDiv,
|
|
validateSafeInput,
|
|
} from '../../Services/Others.js';
|
|
import FormHeader from '../PageComponents/FormHeader.jsx';
|
|
import Buttons from '../../Components/Forms/Buttons.jsx';
|
|
import { InputField } from '../../Components/Forms/InputField.jsx';
|
|
import { DropDowns } from '../../Components/Forms/DropDown.jsx';
|
|
import {
|
|
getPurProductData,
|
|
getPurProdvaraiantdata,
|
|
getPurcProdTaxData,
|
|
getPurcTaxTypeData,
|
|
getPurchaseSupplierData,
|
|
postPurcOrderData,
|
|
getProductData,
|
|
Emailsend,
|
|
getPurchaseSupplierAndWareHouseData,
|
|
getProductStockDetails,
|
|
} from '../../Features/PurchaseOrder/PurchaseOrder.js';
|
|
import { Tables } from '../../Components/Tables/Table.jsx';
|
|
import { DefaultModal } from '../../Components/Modal/DefaultModal.jsx';
|
|
import { postSupplier } from '../../Features/ProductPage/ProductPage.js';
|
|
import { changeBreadCrumb } from '../../Features/AppPage/CenterPage.js';
|
|
import { DropDowns1 } from '../../Components/Forms/DropDown1.jsx';
|
|
import PurchaseOrderPrint from './PurchaseOrderPrint.jsx';
|
|
import { FaEye, FaLink, FaPrint } from 'react-icons/fa';
|
|
import { MdOutlineMail } from 'react-icons/md';
|
|
import { getSupplaierIdwithTypeBasedProducts } from '../../Features/SupplierProductMapping/SupplierProductMapping.js';
|
|
import SupplierProductMappingForm from '../SupplierProductMapping/SuplierProductMappingForm.jsx';
|
|
import { getConfigType } from '../../Features/BookingScreen/BookingData/BookingData.js';
|
|
import FloatLabel from '../../Components/Forms/FloatLabel/index.jsx';
|
|
import '../../Styles/OverAllStyle/OverAllStyle.scss';
|
|
import { BsUpcScan } from 'react-icons/bs';
|
|
import { debounce } from 'lodash';
|
|
import { getPrintSelectionComponentData } from '../../Features/ThemeChange/ThemeChange.js';
|
|
import { PrintStyleFunction } from '../paymentpdfPage/PrintStyleFunction.js';
|
|
import { PurchaseOrderMobilePrint } from './PurchsasePrintStyle/PurchaseOrderMobilePrint.js';
|
|
import { isMobile } from 'react-device-detect';
|
|
import { CiEdit } from 'react-icons/ci';
|
|
|
|
const subDirectory = import.meta.env.BASE_URL;
|
|
const stylesMap = {
|
|
'Style 1': 'PurchaseStyle1',
|
|
'Style 2': 'PrintStyle2',
|
|
'Style 3': 'PrintStyle3',
|
|
'Style 4': 'PrintStyle4',
|
|
'Style 5': 'PrintStyle5',
|
|
'Style 6': 'PrintStyle6',
|
|
'Style 7': 'PrintStyle7',
|
|
'Style 8': 'PrintStyle8',
|
|
'Style 9': 'PrintStyle9',
|
|
'Style 10': 'PrintStyle10',
|
|
'Style 11': 'PrintStyle11',
|
|
'Style 12': 'PrintStyle12',
|
|
'Style 13': 'Pur-Order-Print',
|
|
A4: 'PrintStyleA4',
|
|
A5: 'PrintStyleA5',
|
|
A4Standard: 'A4Standard',
|
|
TaxInvoice: 'TaxInvoice',
|
|
};
|
|
const PurchaseOrder = () => {
|
|
const [form] = Form.useForm();
|
|
const navigate = useNavigate();
|
|
const formRef = useRef(null);
|
|
const location = useLocation();
|
|
const formProductRef = useRef(null);
|
|
const formSupplierRef = useRef(null);
|
|
const deliveryAddressRef = useRef(null);
|
|
const dispatch = useDispatch();
|
|
const CompId = getSession('CompId');
|
|
const BranchId = getSession('BranchId');
|
|
const AppId = getSession('AppId');
|
|
const UserId = getSession('UserId');
|
|
const [message, setMessage] = useState({ type: null, data: null });
|
|
const [Supplierdata, setSupplierdata] = useState([]);
|
|
const [selecPurSupplier, setselecPurSupplier] = useState(null);
|
|
const [selectedProductName, setSelectedProductName] = useState(null);
|
|
const [productSearchText, setProductSearchText] = useState('');
|
|
const [scanner, setScanner] = useState(false);
|
|
const [selecPurSupplierDetails, setselecPurSupplierDetails] = useState(null);
|
|
const [selecSuppDetails, setselecSuppDetails] = useState(null);
|
|
const [OpenPurSupplierModel, setOpenPurSupplierModel] = useState(false);
|
|
const [PurProductdata, setPurProductdata] = useState([]);
|
|
const [selectedPurProductData, setselectedPurProductData] = useState(null);
|
|
const [VariantDetails, setVariantDetails] = useState(null);
|
|
const [SelProductVariant, setSelProductVariant] = useState(null);
|
|
const [ProductTableData, setProductTableData] = useState([]);
|
|
const [zipCodeData, setZipCodeData] = useState(false);
|
|
const [Edit, setEdit] = useState(false);
|
|
const [currentIndex, setCurrentIndex] = useState(null);
|
|
const [PrintData, setPrintData] = useState([]);
|
|
const [printTrigger, setPrintTrigger] = useState(false); // <-- add this line
|
|
const [isSubmitted, setIsSubmitted] = useState(false);
|
|
const [submittedOrderData, setSubmittedOrderData] = useState(null);
|
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
const [isLowStockModel, setisLowStockModel] = useState(false);
|
|
const [addressModel, setAddressModel] = useState(false);
|
|
const [deliveryAddress, setDeliveryAddress] = useState('');
|
|
const [searchedText, setSearchedText] = useState('');
|
|
const [iSEmail, setiSEmail] = useState(false);
|
|
const [enteredEmail, setEnteredEmail] = useState('');
|
|
const [pendingOrderDetails, setPendingOrderDetails] = useState(null);
|
|
const [pendingRecord, setPendingRecord] = useState(null);
|
|
const [deliveryPerformanceData, SetDeleveryPerformanceData] = useState([]);
|
|
const [DiscountData, setDiscountData] = useState([]);
|
|
const [QualityData, setQualityData] = useState([]);
|
|
const [Delivery, setDeliveryValue] = useState();
|
|
const [DicountValue, setDicountValue] = useState();
|
|
const [QualityValue, setQualityValue] = useState();
|
|
const [ViewDtl, setViewDtl] = useState(false);
|
|
const [selectedStyleData, setselectedStyleData] = useState();
|
|
const [ProductStockData, seProductStockData] = useState([]);
|
|
const [selectedStockDetails, setSelectedStockDetails] = useState({
|
|
StockDetails: [],
|
|
});
|
|
|
|
console.log(ProductStockData, 'ProductStockData');
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
const [itemsPerPage] = useState(20);
|
|
const [searchTerm, setSearchTerm] = useState('');
|
|
const [minQty, setMinQty] = useState('');
|
|
|
|
// const filteredData = currentData.filter((item) => {
|
|
// const matchesSearch =
|
|
// item.ProdName.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
// item.ProdVariantName.toLowerCase().includes(searchTerm.toLowerCase());
|
|
// const matchesMinQty = minQty === "" || item.BalanceQty <= Number(minQty);
|
|
// return matchesSearch && matchesMinQty;
|
|
// });
|
|
|
|
// const styleName = selectedStyleData == undefined ? 'Pur-Order-Print' : selectedStyleData;
|
|
// const selectedStyle = stylesMap[styleName] || 'Pur-Order-Print';
|
|
const items = [
|
|
{
|
|
name: 'Home',
|
|
link: `${subDirectory}app-page/home`,
|
|
},
|
|
|
|
{
|
|
name: 'Purchase Order',
|
|
link: `${subDirectory}setting/purchase-order/new`,
|
|
},
|
|
{
|
|
name: 'New',
|
|
link: null,
|
|
},
|
|
];
|
|
useEffect(() => {
|
|
dispatch(changeBreadCrumb({ items: items }));
|
|
getSupplierData();
|
|
}, []);
|
|
useEffect(() => {
|
|
dispatch(changeBreadCrumb({ items: items }));
|
|
getSupplierData();
|
|
|
|
// Handle incoming navigation state
|
|
if (location.state) {
|
|
const { selecPurSupplierDetails, OrderId, ProductTableData } =
|
|
location.state;
|
|
if (selecPurSupplierDetails) {
|
|
setselecPurSupplierDetails(selecPurSupplierDetails);
|
|
if (selecPurSupplierDetails[0]?.SuppId) {
|
|
setselecPurSupplier(selecPurSupplierDetails[0].SuppId);
|
|
getProductDatas(selecPurSupplierDetails[0].SuppId);
|
|
formRef.current?.setFieldsValue({
|
|
SuppId: selecPurSupplierDetails[0].SuppId,
|
|
});
|
|
}
|
|
}
|
|
if (ProductTableData) {
|
|
setProductTableData(ProductTableData);
|
|
}
|
|
}
|
|
}, [location.state]);
|
|
useEffect(() => {
|
|
SetSelfSupplier();
|
|
}, [Supplierdata]);
|
|
|
|
useEffect(() => {
|
|
deliveryPerformance();
|
|
discountLevel();
|
|
qualityofSupp();
|
|
printsyleget();
|
|
ProductStockFun();
|
|
}, []);
|
|
|
|
const handleSaveLowStock = () => {
|
|
let ChoosenLowStockProd = ProductStockData?.filter(
|
|
(e) => e?.needQty > 0
|
|
)?.map((e) => ({
|
|
OrderQty: e?.needQty,
|
|
ProdId: e?.ProdId,
|
|
ProdName: `${e?.ProdName}(${e?.Size}${e?.UOMName})`,
|
|
ProdVariantName: e?.ProdVariantName,
|
|
}));
|
|
setProductTableData((prev) => [...ChoosenLowStockProd]);
|
|
setisLowStockModel(false);
|
|
};
|
|
const ProductStockFun = async (qty = 5) => {
|
|
console.log(qty, 'qtyqty');
|
|
try {
|
|
const Data = { AppId, CompId, BranchId, qty: qty };
|
|
let response = await dispatch(getProductStockDetails(Data)).unwrap();
|
|
if (response?.data?.statusCode === 1) {
|
|
seProductStockData(response?.data?.data);
|
|
}
|
|
} catch (err) {
|
|
console.error('Error fetching stock details:', err);
|
|
}
|
|
};
|
|
console.log('hi');
|
|
|
|
const debouncedFetchStock = useMemo(() => debounce(ProductStockFun, 600), []);
|
|
const handleMinQtyChange = (e) => {
|
|
const value = e.target.value;
|
|
setMinQty(value);
|
|
debouncedFetchStock(value || 0);
|
|
};
|
|
|
|
const filteredData = ProductStockData.filter(
|
|
(row) =>
|
|
!searchTerm ||
|
|
(row.ProdName &&
|
|
row.ProdName?.toLowerCase()?.includes(searchTerm?.toLowerCase()))
|
|
);
|
|
|
|
const totalPages = Math.ceil(filteredData.length / itemsPerPage);
|
|
const startIndex = (currentPage - 1) * itemsPerPage;
|
|
const endIndex = startIndex + itemsPerPage;
|
|
const currentData = filteredData.slice(startIndex, endIndex);
|
|
const printsyleget = async () => {
|
|
const Data = { AppId, CompId, BranchId };
|
|
|
|
let response = await dispatch(
|
|
getPrintSelectionComponentData(Data)
|
|
).unwrap();
|
|
if (response?.data?.statusCode == 1) {
|
|
setselectedStyleData(
|
|
response?.data?.data?.[0]?.ComponentDetails?.find(
|
|
(e) => e?.PrintTypeName == 'Purchase Order' && e?.SetasDefault == 'Y'
|
|
)?.StyleName
|
|
);
|
|
} else {
|
|
setselectedStyleData(null);
|
|
}
|
|
};
|
|
|
|
const debouncedScannerSearch = useCallback(
|
|
debounce((value) => {
|
|
const qr = value?.trim();
|
|
if (qr === '') return;
|
|
const matchedProduct = PurProductdata.find(
|
|
(p) => p.QRCode?.toLowerCase() === qr?.toLowerCase()
|
|
);
|
|
if (matchedProduct) {
|
|
let productName = {};
|
|
productName.label = `${matchedProduct?.ProdName} (${matchedProduct.Size} ${matchedProduct.UomName})${matchedProduct?.BrandName ? ` - ${matchedProduct?.BrandName}` : ''}`;
|
|
PurcProductDropDownChange(matchedProduct.ProdId, productName);
|
|
if (matchedProduct?.ProdVariantPriceDetails?.length < 2) {
|
|
setSelProduct(null);
|
|
}
|
|
} else {
|
|
setMessage({
|
|
type: 'error',
|
|
data: 'The Scanned Product not Available in Product List',
|
|
});
|
|
}
|
|
}, 300),
|
|
[PurProductdata]
|
|
);
|
|
const handlePrevious = () => {
|
|
if (currentPage > 1) {
|
|
setCurrentPage(currentPage - 1);
|
|
}
|
|
};
|
|
|
|
const handleNext = () => {
|
|
if (currentPage < totalPages) {
|
|
setCurrentPage(currentPage + 1);
|
|
}
|
|
};
|
|
const SetSelfSupplier = async () => {
|
|
let SupplierId = Supplierdata?.filter(
|
|
(item) => item.SuppName?.toLowerCase() === 'self'
|
|
)?.[0]?.['SuppId'];
|
|
let SelectSupDetails = Supplierdata?.filter(
|
|
(item) => item.SuppName?.toLowerCase() === 'self'
|
|
); //naresh
|
|
|
|
setselecPurSupplierDetails(SelectSupDetails);
|
|
formRef.current?.setFieldsValue({ SuppId: SupplierId });
|
|
setselecPurSupplier(SupplierId);
|
|
getProductDatas(SupplierId);
|
|
};
|
|
|
|
const getSupplierData = async () => {
|
|
try {
|
|
let Supplier = await dispatch(
|
|
getPurchaseSupplierAndWareHouseData({
|
|
CompId,
|
|
AppId,
|
|
BranchId,
|
|
})
|
|
).unwrap();
|
|
if (Supplier?.statusCode == 1) {
|
|
setSupplierdata(Supplier?.data);
|
|
} else {
|
|
setSupplierdata([]);
|
|
}
|
|
} catch (error) {
|
|
setMessage({
|
|
type: 'error',
|
|
data: error,
|
|
});
|
|
}
|
|
};
|
|
const getProductDatas = async (SuppId) => {
|
|
if (!SuppId) {
|
|
setPurProductdata([]);
|
|
return;
|
|
}
|
|
// Supplierdata
|
|
const Type = Supplierdata?.find((find) => find.SuppId === SuppId)?.Type;
|
|
const LocationType =
|
|
Type === 'Supplier'
|
|
? 'S'
|
|
: Type === 'Branch'
|
|
? 'B'
|
|
: Type === 'WareHouse'
|
|
? 'W'
|
|
: '';
|
|
|
|
const productResponse = await dispatch(
|
|
getSupplaierIdwithTypeBasedProducts({
|
|
CompId,
|
|
AppId,
|
|
BranchId,
|
|
SuppId,
|
|
LocationType,
|
|
})
|
|
).unwrap();
|
|
if (productResponse?.data?.statusCode == 1) {
|
|
setPurProductdata(productResponse?.data?.data);
|
|
} else {
|
|
// setMessage({
|
|
// type: "error",
|
|
// data: productResponse?.data?.response
|
|
// })
|
|
setPurProductdata([]);
|
|
}
|
|
};
|
|
const handleSupplierDropDownChange = async (SuppId) => {
|
|
let SelectSupDetails = Supplierdata?.filter(
|
|
(item) => item.SuppId?.toLowerCase() === SuppId?.toLowerCase()
|
|
); //naresh
|
|
setselecPurSupplierDetails(SelectSupDetails);
|
|
formRef.current?.setFieldsValue({ SuppId: SuppId });
|
|
setselecPurSupplier(SuppId);
|
|
getProductDatas(SuppId);
|
|
formProductRef.current.resetFields(['ProdId']);
|
|
setselectedPurProductData(null);
|
|
setProductTableData([]);
|
|
let SelectSuppData = Supplierdata?.filter((item) => item.SuppId === SuppId);
|
|
if (SelectSuppData?.length > 0) {
|
|
setselecSuppDetails(SelectSuppData?.[0]);
|
|
setIsSubmitted(false);
|
|
} else {
|
|
setselecSuppDetails(null);
|
|
}
|
|
// let productdtl = await dispatch(getPurProductData({ SuppId: SuppId })).unwrap();
|
|
// if (productdtl?.data?.statusCode == 1) {
|
|
// console.log(productdtl?.data?.data, "setPurProductdata")
|
|
// setPurProductdata(productdtl?.data?.data)
|
|
// }
|
|
// else {
|
|
// setPurProductdata(null)
|
|
// }
|
|
};
|
|
const addPurSupplier = () => {
|
|
setOpenPurSupplierModel(true);
|
|
};
|
|
const PurcProductDropDownChange = async (Prodid, option) => {
|
|
setSelProductVariant(null);
|
|
setProductSearchText('');
|
|
setSelectedProductName(option?.label ? option?.label : '');
|
|
formProductRef?.current?.resetFields(['ProdVariantName']);
|
|
formProductRef.current?.setFieldsValue({ ProdId: Prodid });
|
|
setselectedPurProductData(Prodid);
|
|
let x = PurProductdata.find((e) => e.ProdId == Prodid)?.ProdName;
|
|
let variantValues1 = await dispatch(
|
|
getPurProdvaraiantdata({
|
|
CompId: CompId,
|
|
AppId: AppId,
|
|
BranchId: BranchId,
|
|
prodName: x,
|
|
})
|
|
).unwrap();
|
|
if (variantValues1?.data?.statusCode === 1) {
|
|
console.log(variantValues1?.data?.data, 'productdetail');
|
|
setVariantDetails(
|
|
variantValues1?.data?.data?.[0]?.ProductDetail?.[0]?.ProdVariantDetails
|
|
);
|
|
} else {
|
|
setVariantDetails(null);
|
|
}
|
|
};
|
|
const handleQRCodeChange = async (e) => {
|
|
let qrcode = e.target.value;
|
|
formProductRef.current?.setFieldsValue({ QRCode: qrcode });
|
|
console.log(PurProductdata, 'PurProductdata');
|
|
let x = PurProductdata.find((e) => e.QRCode === qrcode);
|
|
if (x !== undefined) {
|
|
formProductRef.current?.setFieldsValue({ ProdId: x?.ProdId });
|
|
setselectedPurProductData(x?.ProdId);
|
|
let variantValues1 = await dispatch(
|
|
getPurProdvaraiantdata({
|
|
CompId: CompId,
|
|
AppId: AppId,
|
|
BranchId: BranchId,
|
|
prodName: x?.ProdName,
|
|
})
|
|
).unwrap();
|
|
if (variantValues1?.data?.statusCode === 1) {
|
|
console.log(variantValues1?.data?.data, 'productdetail');
|
|
setVariantDetails(
|
|
variantValues1?.data?.data?.[0]?.ProductDetail?.[0]
|
|
?.ProdVariantDetails
|
|
);
|
|
} else {
|
|
setVariantDetails(null);
|
|
}
|
|
}
|
|
};
|
|
|
|
const ProductVariantDropDownChange = async (Variant) => {
|
|
setSelProductVariant(Variant);
|
|
formProductRef.current?.setFieldsValue({ ProdVariantName: Variant });
|
|
console.log(Variant, 'VariantVariant');
|
|
};
|
|
const handleProductSearch = (value) => {
|
|
if (scanner) {
|
|
debouncedScannerSearch(value);
|
|
}
|
|
setProductSearchText(value);
|
|
setSelectedProductName(value);
|
|
setVariantDetails([]);
|
|
};
|
|
const handleScanSearch = () => {
|
|
if (scanner === false) {
|
|
setMessage({ type: 'success', data: 'Search by QrCode/BarCode Enabled' });
|
|
} else {
|
|
setMessage({
|
|
type: 'success',
|
|
data: 'Search by QrCode/BarCode Disabled',
|
|
});
|
|
}
|
|
setScanner((prev) => !prev);
|
|
setSelectedProductName(null);
|
|
setVariantDetails(null);
|
|
formRef?.current?.setFieldsValue({
|
|
ProdId: null,
|
|
VarProdId: null,
|
|
});
|
|
};
|
|
const PurchaseOrderStyle = `<style>
|
|
@media print {
|
|
@page {
|
|
size: A4;
|
|
margin: 0;
|
|
}
|
|
|
|
.Quo-Print-Body {
|
|
width: 195mm;
|
|
margin: 0 auto;
|
|
padding: 10mm;
|
|
}
|
|
}
|
|
|
|
.Quo-Print-Body {
|
|
margin: 0;
|
|
padding: 10px;
|
|
background: white;
|
|
font-family: Poppins, sans-serif;
|
|
}
|
|
|
|
.Quo-Print-Content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
max-width: 240mm;
|
|
margin: 0 auto;
|
|
border: 1px solid rgb(170, 164, 164);
|
|
padding: 10px;
|
|
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
|
min-height: 257mm;
|
|
background-color: white;
|
|
}
|
|
|
|
.Quo-print-Logo {
|
|
width: 50px;
|
|
height: 50px;
|
|
margin: 5px 0 0 5px;
|
|
}
|
|
|
|
.Quo-Print-ComCus {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.Quo-Print-Tabsum {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.Quo-Print-Header {
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: space-between;
|
|
|
|
}
|
|
|
|
.Quo-Print-Company {
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 10px;
|
|
gap: 0.1rem;
|
|
}
|
|
|
|
.Quo-Print-Cname {
|
|
font-size: 25px;
|
|
}
|
|
|
|
.Quo-Print-address {
|
|
font-size: 19px;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.Quo-Print-Qno {
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 5px;
|
|
gap: 0.1rem;
|
|
}
|
|
|
|
.Quo-Print-Customer {
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding-left: 10px;
|
|
gap: 0.1rem;
|
|
/* Removed fixed height */
|
|
/* height: 18vh; */
|
|
}
|
|
|
|
.Horizondal-line {
|
|
border-bottom: 0.5px solid rgb(170, 164, 164);
|
|
}
|
|
|
|
.Quo-Print-Table {
|
|
display: flex;
|
|
}
|
|
|
|
.Quo-Print-ProTable {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 15px;
|
|
}
|
|
|
|
.Quo-Print-DataRow {
|
|
border-bottom: 1px solid #eee;
|
|
}
|
|
|
|
.Quo-Print-tableheader {
|
|
background-color: #f8f9fa;
|
|
border-top: 1px solid rgb(170, 164, 164);
|
|
border-bottom: 1px solid rgb(170, 164, 164);
|
|
line-height: 3rem;
|
|
}
|
|
|
|
.Quo-Print-TableData {
|
|
text-align: right;
|
|
padding: 8px;
|
|
font-size: 20px;
|
|
}
|
|
|
|
.Quo-Print-TableDataSno {
|
|
text-align: center;
|
|
padding: 8px;
|
|
font-size: 14px;
|
|
width: 60px;
|
|
}
|
|
|
|
.Quo-Print-TableDataName {
|
|
text-align: left;
|
|
padding: 8px;
|
|
font-size: 20px;
|
|
}
|
|
|
|
.Quo-Print-headingData {
|
|
text-align: center;
|
|
padding: 8px;
|
|
font-size: 22px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.Quo-Print-TableDataAmt {
|
|
text-align: right;
|
|
padding-right: 5px;
|
|
font-size: 25px;
|
|
}
|
|
|
|
.Quo-Print-Summary {
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.Quo-Print-SummTableData {
|
|
text-align: right;
|
|
padding: 1px;
|
|
font-size: 22px;
|
|
}
|
|
|
|
.Quo-Print-Total {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
border: 0.5px solid black;
|
|
width: 300px;
|
|
margin-right: 10px;
|
|
font-size: 20px;
|
|
}
|
|
</style>`;
|
|
|
|
const AddProduct = async () => {
|
|
let ProductNameadd = {};
|
|
let variant;
|
|
let ProductDetail = formProductRef.current?.getFieldsValue();
|
|
console.log(typeof ProductDetail?.ProdVariantName, 'ProductDetail');
|
|
if (
|
|
ProductDetail?.OrderQty &&
|
|
ProductDetail?.ProdId &&
|
|
new RegExp(`^P${AppId}(-[0-9]+)+$`).test(ProductDetail.ProdId)
|
|
) {
|
|
let ProductName = PurProductdata?.find(
|
|
(item) => item?.ProdId === ProductDetail?.ProdId
|
|
);
|
|
if (!ProductName) {
|
|
setMessage({ type: 'error', data: 'Please Enter Product Details' });
|
|
return;
|
|
}
|
|
if (ProductDetail?.hasOwnProperty('ProdVariantName')) {
|
|
variant = ProductDetail?.ProdVariantName
|
|
? ProductDetail?.ProdVariantName
|
|
: 'Variant 1';
|
|
delete ProductDetail?.ProdVariantName;
|
|
ProductNameadd = {
|
|
ProdName:
|
|
ProductName?.ProdName +
|
|
'(' +
|
|
ProductName?.Size +
|
|
ProductName?.UomName +
|
|
')',
|
|
ProdVariantName: variant,
|
|
...ProductDetail,
|
|
};
|
|
} else {
|
|
ProductNameadd = {
|
|
ProdName:
|
|
ProductName?.ProdName +
|
|
'(' +
|
|
ProductName?.Size +
|
|
ProductName?.UomName +
|
|
')',
|
|
ProdVariantName: 'Variant 1',
|
|
UomName: ProductName?.UomName,
|
|
...ProductDetail,
|
|
};
|
|
}
|
|
|
|
if (ProductTableData?.length > 0) {
|
|
let filterTableData = ProductTableData?.filter(
|
|
(item) =>
|
|
!(
|
|
item.ProdId === ProductNameadd?.ProdId &&
|
|
item.ProdVariantName === ProductNameadd?.ProdVariantName
|
|
)
|
|
);
|
|
setProductTableData([ProductNameadd, ...filterTableData]);
|
|
} else {
|
|
setProductTableData([ProductNameadd]);
|
|
}
|
|
|
|
console.log(ProductTableData, 'ProductDetailProductDetail');
|
|
} else if (ProductDetail?.OrderQty && ProductDetail?.QRCode) {
|
|
let ProductName = PurProductdata?.find(
|
|
(item) => item?.QRCode === ProductDetail?.QRCode
|
|
);
|
|
|
|
if (ProductDetail?.hasOwnProperty('ProdVariantName')) {
|
|
variant = ProductDetail?.ProdVariantName
|
|
? ProductDetail?.ProdVariantName
|
|
: 'Variant 1';
|
|
delete ProductDetail?.ProdVariantName;
|
|
ProductNameadd = {
|
|
ProdName:
|
|
ProductName?.ProdName +
|
|
'(' +
|
|
ProductName?.Size +
|
|
ProductName?.UomName +
|
|
')',
|
|
ProdVariantName: variant,
|
|
...ProductDetail,
|
|
};
|
|
} else {
|
|
ProductNameadd = {
|
|
ProdName:
|
|
ProductName?.ProdName +
|
|
'(' +
|
|
ProductName?.Size +
|
|
ProductName?.UomName +
|
|
')',
|
|
ProdVariantName: 'Variant 1',
|
|
...ProductDetail,
|
|
};
|
|
}
|
|
|
|
if (ProductTableData?.length > 0) {
|
|
let filterTableData = ProductTableData?.filter(
|
|
(item) =>
|
|
!(
|
|
item.ProdId === ProductNameadd?.ProdId &&
|
|
item.ProdVariantName === ProductNameadd?.ProdVariantName
|
|
)
|
|
);
|
|
|
|
setProductTableData([ProductNameadd, ...filterTableData]);
|
|
} else {
|
|
setProductTableData([ProductNameadd]);
|
|
}
|
|
} else {
|
|
setMessage({ type: 'error', data: 'Please Enter Product Details' });
|
|
}
|
|
// after adding reset field values
|
|
formProductRef?.current?.resetFields();
|
|
setselectedPurProductData(null);
|
|
setSelProductVariant(null);
|
|
setEdit(false);
|
|
setSelectedProductName(null);
|
|
};
|
|
|
|
const cancelEdit = (e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
formProductRef.current?.resetFields();
|
|
setCurrentIndex(null);
|
|
setEdit(false);
|
|
setSelectedProductName(null);
|
|
setSelProductVariant(null);
|
|
};
|
|
|
|
const updateProduct = async (e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
let productDetail = formProductRef.current?.getFieldsValue();
|
|
console.log(productDetail, 'productDetail');
|
|
|
|
if (!productDetail?.OrderQty || !productDetail?.ProdId) {
|
|
console.error('Please fill all required product details');
|
|
return;
|
|
}
|
|
|
|
// Find product name from PurProductdata
|
|
let ProductName = PurProductdata?.find(
|
|
(item) => item?.ProdId === productDetail?.ProdId
|
|
);
|
|
|
|
// Determine variant
|
|
let variant = productDetail?.ProdVariantName
|
|
? productDetail?.ProdVariantName
|
|
: 'Variant 1';
|
|
|
|
let updatedProduct = {
|
|
ProdName:
|
|
ProductName?.ProdName +
|
|
'(' +
|
|
ProductName?.Size +
|
|
ProductName?.UomName +
|
|
')',
|
|
ProdVariantName: variant,
|
|
...productDetail,
|
|
};
|
|
|
|
// Check if product already exists (excluding current index)
|
|
let exists = ProductTableData.some(
|
|
(item, index) =>
|
|
index !== currentIndex && // exclude current editing row
|
|
item.ProdId === updatedProduct.ProdId &&
|
|
item.ProdVariantName === updatedProduct.ProdVariantName
|
|
);
|
|
|
|
if (exists) {
|
|
setMessage({ type: 'error', data: 'Product Already Exists' });
|
|
return;
|
|
}
|
|
|
|
// Update product in the table
|
|
let newData = [...ProductTableData];
|
|
newData[currentIndex] = updatedProduct;
|
|
setProductTableData(newData);
|
|
|
|
// Reset form state
|
|
formProductRef?.current?.resetFields();
|
|
setselectedPurProductData(null);
|
|
setSelProductVariant(null);
|
|
setEdit(false);
|
|
setCurrentIndex(null);
|
|
setSelectedProductName(null);
|
|
};
|
|
|
|
console.log(ProductTableData, 'ProductDetailProductDetail');
|
|
const onComplete = useCallback(() => {
|
|
setMessage({ type: null, data: null });
|
|
}, []);
|
|
const columns = [
|
|
{
|
|
title: 'Sl.No',
|
|
align: 'center',
|
|
key: 'sno',
|
|
width: '50px',
|
|
render: (text, object, index) => (
|
|
<a style={{ color: 'black' }}>{index + 1}</a>
|
|
),
|
|
},
|
|
{
|
|
title: 'Product Name',
|
|
dataIndex: 'ProdName',
|
|
key: 'ProdName',
|
|
width: '50px',
|
|
// align: "right",
|
|
render: (text) => <a style={{ color: 'black' }}>{text}</a>,
|
|
},
|
|
{
|
|
title: 'Variant Name',
|
|
dataIndex: 'ProdVariantName',
|
|
key: 'ProdVariantName',
|
|
width: '50px',
|
|
// align: "right",
|
|
render: (text) => <a style={{ color: 'black' }}>{text}</a>,
|
|
},
|
|
{
|
|
title: 'Quantity',
|
|
dataIndex: 'OrderQty',
|
|
key: 'OrderQty',
|
|
width: '20px',
|
|
align: 'right',
|
|
render: (text) => <a style={{ color: 'black' }}>{text}</a>,
|
|
},
|
|
|
|
{
|
|
title: 'Action',
|
|
dataIndex: 'Action',
|
|
width: '60px',
|
|
key: 'Action',
|
|
render: (_, record, index) => (
|
|
<Space size="middle">
|
|
<a>
|
|
<EditFilled
|
|
style={{
|
|
color: isSubmitted ? '#ccc' : '#1292EE',
|
|
cursor: isSubmitted ? 'not-allowed' : 'pointer',
|
|
}}
|
|
onClick={() => !isSubmitted && actionsFormatter(record, index)}
|
|
/>
|
|
</a>
|
|
<a>
|
|
<DeleteFilled
|
|
style={{
|
|
color: isSubmitted ? '#ccc' : '#FF4D4F',
|
|
cursor: isSubmitted ? 'not-allowed' : 'pointer',
|
|
}}
|
|
onClick={() => !isSubmitted && statusFormatter(index)}
|
|
/>
|
|
</a>
|
|
</Space>
|
|
),
|
|
},
|
|
];
|
|
|
|
const statusFormatter = (index) => {
|
|
setProductTableData((prevData) => {
|
|
const rows = [...prevData];
|
|
rows.splice(index, 1);
|
|
|
|
if (index === currentIndex) {
|
|
formProductRef.current?.resetFields();
|
|
setCurrentIndex(null);
|
|
setEdit(false);
|
|
setSelectedProductName(null);
|
|
setSelProductVariant(null);
|
|
} else if (index < currentIndex) {
|
|
setCurrentIndex((prev) => prev - 1);
|
|
}
|
|
|
|
return rows;
|
|
});
|
|
};
|
|
|
|
const actionsFormatter = async (record, index) => {
|
|
setEdit(true);
|
|
setCurrentIndex(index);
|
|
console.log(record, index, 'actionsFormatter');
|
|
let x = PurProductdata.find((e) => e.ProdId == record?.ProdId)?.ProdName;
|
|
let variantValues1 = await dispatch(
|
|
getPurProdvaraiantdata({
|
|
CompId: CompId,
|
|
AppId: AppId,
|
|
BranchId: BranchId,
|
|
prodName: x,
|
|
})
|
|
).unwrap();
|
|
if (variantValues1?.data?.statusCode === 1) {
|
|
console.log(variantValues1?.data?.data, 'productdetail');
|
|
setVariantDetails(
|
|
variantValues1?.data?.data?.[0]?.ProductDetail?.[0]?.ProdVariantDetails
|
|
);
|
|
} else {
|
|
setVariantDetails(null);
|
|
}
|
|
formProductRef.current?.setFieldsValue({
|
|
ProdId: record?.ProdId,
|
|
OrderQty: record?.OrderQty,
|
|
ProdVariantName: record?.ProdVariantName,
|
|
});
|
|
|
|
setselectedPurProductData(record?.ProdId);
|
|
setSelProductVariant(record?.ProdVariantName);
|
|
setSelectedProductName(record?.ProdName);
|
|
};
|
|
|
|
const onFinish = async () => {
|
|
if (ProductTableData?.length === 0) {
|
|
setMessage({ type: 'error', data: 'Please Enter Product Detail' });
|
|
} else {
|
|
let PostData = {};
|
|
PostData = formRef.current?.getFieldsValue();
|
|
PostData['OrderDetails'] = ProductTableData;
|
|
PostData['AppId'] = AppId;
|
|
PostData['CompId'] = CompId;
|
|
PostData['BranchId'] = BranchId;
|
|
PostData['PurOrderDate'] = new Date().toJSON();
|
|
PostData['CreatedBy'] = UserId;
|
|
PostData['LocationType'] = Supplierdata?.find(
|
|
(find) => find.SuppId === selecPurSupplier
|
|
)?.Type;
|
|
PostData['DeliveryAddressDetails'] = deliveryAddress;
|
|
let PostPurOrder = await dispatch(postPurcOrderData(PostData)).unwrap();
|
|
if (PostPurOrder?.data?.statusCode === 1) {
|
|
setMessage({ type: 'success', data: PostPurOrder?.data?.response });
|
|
ProductStockFun();
|
|
const orderData = {
|
|
OrderId: PostPurOrder?.data?.OrderId,
|
|
PurOrderDate: PostData.PurOrderDate,
|
|
SupplierName: selecPurSupplierDetails?.[0]?.SuppName,
|
|
SuppMobile: selecPurSupplierDetails?.[0]?.SuppMobile,
|
|
SuppGSTIN: selecPurSupplierDetails?.[0]?.SuppGSTIN,
|
|
SuppEmail: selecPurSupplierDetails?.[0]?.SuppEmail,
|
|
Remarks: PostData.Remarks,
|
|
ProductDetails: ProductTableData,
|
|
};
|
|
|
|
// Set all necessary states
|
|
setSubmittedOrderData(orderData);
|
|
setPrintData([orderData]);
|
|
setIsSubmitted(true);
|
|
|
|
// Reset form fields
|
|
formProductRef?.current?.resetFields();
|
|
formRef?.current?.resetFields();
|
|
deliveryAddressRef?.current?.resetFields();
|
|
setDeliveryAddress('');
|
|
setselecPurSupplier(null);
|
|
getProductDatas(null);
|
|
setselecSuppDetails(null);
|
|
setselectedPurProductData(null);
|
|
setSelProductVariant(null);
|
|
setProductTableData([]);
|
|
setSelectedProductName(null);
|
|
// navigate(`${subDirectory}purchaseordermail`, {
|
|
// state: {
|
|
// selecPurSupplierDetails: selecPurSupplierDetails,
|
|
// OrderId: PostPurOrder?.data?.OrderId,
|
|
// ProductTableData: ProductTableData,
|
|
// },
|
|
// });
|
|
} else {
|
|
setMessage({ type: 'error', data: PostPurOrder?.data?.response });
|
|
}
|
|
}
|
|
};
|
|
|
|
// Suppier details
|
|
const pinCodeChange = async (e) => {
|
|
if (e.target.value?.length < 6) {
|
|
setZipCodeData(false);
|
|
return false;
|
|
}
|
|
await getPincodeValues(e?.target?.value);
|
|
};
|
|
const getPincodeValues = async (pinCode) => {
|
|
let response = '';
|
|
await fetch(`https://api.postalpincode.in/pincode/${pinCode}`)
|
|
.then((res) => res.text())
|
|
.then((text) => (response = JSON.parse(text)));
|
|
|
|
if (response[0]['Status'] === 'Success') {
|
|
setZipCodeData(true);
|
|
formSupplierRef.current?.setFieldsValue({
|
|
City: response[0]['PostOffice'][0]['Block'],
|
|
Dist: response[0]['PostOffice'][0]['District'],
|
|
State: response[0]['PostOffice'][0]['State'],
|
|
});
|
|
deliveryAddressRef.current?.setFieldsValue({
|
|
City: response[0]['PostOffice'][0]['Block'],
|
|
Dist: response[0]['PostOffice'][0]['District'],
|
|
State: response[0]['PostOffice'][0]['State'],
|
|
});
|
|
} else {
|
|
setZipCodeData(false);
|
|
}
|
|
};
|
|
|
|
const submitSupplier = async () => {
|
|
const subSupplierData = await formSupplierRef?.current?.validateFields();
|
|
const addSupplierData = {
|
|
CompId: getSession('CompId'),
|
|
AppId: getSession('AppId'),
|
|
BranchId: getSession('BranchId'),
|
|
SuppName: subSupplierData?.SuppName,
|
|
SuppGSTIN: subSupplierData?.SuppGSTIN,
|
|
SuppPOC: subSupplierData?.SuppPOC,
|
|
SuppMobile: subSupplierData?.SuppMobile,
|
|
SuppEmail: subSupplierData?.SuppEmail,
|
|
Address1: subSupplierData?.Address1,
|
|
Address2: subSupplierData?.Address1,
|
|
Zip: subSupplierData?.Zip,
|
|
City: subSupplierData?.City,
|
|
State: subSupplierData?.State,
|
|
Dist: subSupplierData?.Dist,
|
|
SuppPOCMobile: subSupplierData?.SuppPOCMobile,
|
|
SuppPOCEmail: subSupplierData?.SuppPOCEmail,
|
|
DeliveryPerformance: subSupplierData?.DeliveryPerformance,
|
|
DiscountLevel: subSupplierData?.DiscountLevel,
|
|
QualityofSupp: subSupplierData?.QualityofSupp,
|
|
CreatedBy: UserId,
|
|
};
|
|
let response = {};
|
|
response = await dispatch(postSupplier(addSupplierData)).unwrap();
|
|
if (response?.data?.statusCode == 1) {
|
|
setMessage({ type: 'success', data: response?.data?.response });
|
|
formSupplierRef?.current?.resetFields();
|
|
setZipCodeData(false);
|
|
setOpenPurSupplierModel(false);
|
|
setDeliveryValue();
|
|
setDicountValue();
|
|
setQualityValue();
|
|
setViewDtl(false);
|
|
let response1 = await dispatch(
|
|
getSupplierData({
|
|
CompId: CompId,
|
|
AppId: AppId,
|
|
BranchId: BranchId,
|
|
ActiveStatus: 'A',
|
|
})
|
|
).unwrap();
|
|
if (response1.data?.statusCode == 1) {
|
|
setOpenPurSupplierModel(false);
|
|
}
|
|
} else {
|
|
setMessage({ type: 'error', data: response?.data?.response });
|
|
formSupplierRef?.current?.resetFields();
|
|
}
|
|
};
|
|
const handleSupplier = () => {
|
|
setOpenPurSupplierModel(false);
|
|
formSupplierRef?.current?.resetFields();
|
|
setZipCodeData(false);
|
|
};
|
|
|
|
// const handleEmailClick = () => {
|
|
// if (!submittedOrderData) {
|
|
// setMessage({ type: 'error', data: 'Please submit the order first before sending email' });
|
|
// return;
|
|
// }
|
|
|
|
// navigate(`${subDirectory}purchaseordermail`, {
|
|
// state: {
|
|
// selecPurSupplierDetails: selecPurSupplierDetails,
|
|
// ProductTableData: ProductTableData,
|
|
// orderData: submittedOrderData,
|
|
// },
|
|
// });
|
|
// };
|
|
|
|
const handleEmailClick = async (ProductDetails, record) => {
|
|
const toEmail = record?.SuppEmail;
|
|
|
|
if (toEmail) {
|
|
try {
|
|
const blob = await pdfDiv('Pur-Order-Print', PurchaseOrderStyle);
|
|
console.log(blob, 'blobblob');
|
|
|
|
const payload = {
|
|
fileBlob: blob,
|
|
toEmail: toEmail,
|
|
type: 'PurchaseOrder',
|
|
messageTemplatesList: [],
|
|
};
|
|
|
|
const res = await dispatch(Emailsend(payload))?.unwrap();
|
|
|
|
console.log('✅ API Response:', res?.data || res);
|
|
setMessage({ type: 'success', data: 'Email sent successfully' });
|
|
} catch (error) {
|
|
setMessage({ type: 'error', data: 'Email failed to send' });
|
|
console.error('❌ Email send failed:', error);
|
|
}
|
|
} else {
|
|
setPendingOrderDetails(ProductDetails);
|
|
setPendingRecord(record);
|
|
setiSEmail(true);
|
|
}
|
|
};
|
|
|
|
const handleSendEmailWithEnteredEmail = async (values) => {
|
|
const recordWithEmail = { ...pendingRecord, SuppEmail: values.email };
|
|
setiSEmail(false);
|
|
await handleEmailClick(pendingOrderDetails, recordWithEmail);
|
|
|
|
setPendingOrderDetails(null);
|
|
setPendingRecord(null);
|
|
form.resetFields();
|
|
};
|
|
const handlePrint = () => {
|
|
setPrintData([submittedOrderData]);
|
|
setPrintTrigger(true); // trigger print after render
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (printTrigger && PrintData.length > 0) {
|
|
setTimeout(() => {
|
|
let style;
|
|
if (selectedStyleData) {
|
|
style = stylesMap[selectedStyleData]
|
|
? PrintStyleFunction(selectedStyleData)
|
|
: PurchaseOrderStyle;
|
|
} else {
|
|
style = PurchaseOrderStyle;
|
|
}
|
|
const styleName =
|
|
selectedStyleData == undefined ? 'Style 13' : selectedStyleData;
|
|
const selectedStyle = stylesMap[styleName] || 'Style 13';
|
|
|
|
// printDiv(`${selectedStyle}`, style);
|
|
setPrintTrigger(false);
|
|
|
|
if (isMobile) {
|
|
PurchaseOrderMobilePrint({
|
|
PrintTempData: selectedStyleData,
|
|
PrintOrderDetails: PrintData,
|
|
setPrintOrderDetails: setPrintData,
|
|
});
|
|
} else {
|
|
printDiv(selectedStyle, style);
|
|
}
|
|
}, 100);
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [printTrigger, PrintData, selectedStyleData]);
|
|
|
|
const handleModalSubmited = () => {
|
|
setIsModalOpen(false);
|
|
getProductDatas(selecPurSupplier);
|
|
};
|
|
|
|
const validatePhoneNumber = (rule, value, callback) => {
|
|
if (value && value?.length !== 10) {
|
|
callback();
|
|
} else {
|
|
callback();
|
|
}
|
|
};
|
|
|
|
const validateEmail = (rule, value, callback) => {
|
|
const regex = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
|
|
|
|
if (!value || regex.test(value)) {
|
|
callback();
|
|
} else {
|
|
callback('Please enter a valid Mail Id');
|
|
}
|
|
};
|
|
|
|
const deliveryPerformance = async () => {
|
|
let response = await dispatch(
|
|
getConfigType({ TypeName: 'Delivery Performance' })
|
|
).unwrap();
|
|
SetDeleveryPerformanceData(response?.data?.data);
|
|
};
|
|
|
|
const discountLevel = async () => {
|
|
let response = await dispatch(
|
|
getConfigType({ TypeName: 'Discount Level' })
|
|
).unwrap();
|
|
setDiscountData(response?.data?.data);
|
|
};
|
|
|
|
const qualityofSupp = async () => {
|
|
let response = await dispatch(
|
|
getConfigType({ TypeName: 'Quality Of Supplier' })
|
|
).unwrap();
|
|
setQualityData(response?.data?.data);
|
|
};
|
|
|
|
const handleDeliveryPerformanceChange = (value) => {
|
|
formSupplierRef?.current?.setFieldsValue({ DeliveryPerformance: value });
|
|
setDeliveryValue(value);
|
|
};
|
|
|
|
const handleDiscountLevelChange = (value) => {
|
|
formSupplierRef?.current?.setFieldsValue({ DiscountLevel: value });
|
|
setDicountValue(value);
|
|
};
|
|
|
|
const handleQualityofSuppChange = (value) => {
|
|
formSupplierRef?.current?.setFieldsValue({ QualityofSupp: value });
|
|
setQualityValue(value);
|
|
};
|
|
|
|
const ViewMoreFields = () => {
|
|
if (ViewDtl) {
|
|
setViewDtl(false);
|
|
} else {
|
|
setViewDtl(true);
|
|
}
|
|
};
|
|
|
|
const handleAddressSubmit = async () => {
|
|
try {
|
|
const values = await deliveryAddressRef.current?.validateFields();
|
|
const formattedAddress = {
|
|
Address1: values.Address1,
|
|
Address2: values.Address2,
|
|
Zip: Number(values.Zip),
|
|
City: values.City,
|
|
Dist: values.Dist,
|
|
State: values.State,
|
|
Latitude: values.Latitude ?? 0,
|
|
Longitude: values.Longitude ?? 0,
|
|
CreatedBy: UserId
|
|
};
|
|
setDeliveryAddress(formattedAddress);
|
|
setAddressModel(false);
|
|
} catch (err) {
|
|
console.log('Validation error:', err);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
<div className="pageOverAll">
|
|
<div className="userPage">
|
|
<div className="userPageContent">
|
|
<Messages
|
|
messageType={message.type}
|
|
messageData={message.data}
|
|
onComplete={onComplete}
|
|
/>
|
|
<div
|
|
className="formName"
|
|
style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
marginTop: '5px',
|
|
}}
|
|
>
|
|
<FormHeader title={'Purchase Order'} />
|
|
<div
|
|
className="pruchaseCatBTN"
|
|
onClick={() => navigate(`${subDirectory}setting/purchase-order`)}
|
|
>
|
|
<FaEye /> <p>View Order</p>
|
|
</div>
|
|
</div>
|
|
<div className="formDiv" style={{ paddingTop: '0px', rowGap: '0px' }}>
|
|
<Form
|
|
ref={formRef}
|
|
// initialValues={editstate}
|
|
className="formDivAnt"
|
|
onFinish={onFinish}
|
|
>
|
|
<div
|
|
className="formDivS"
|
|
style={{ paddingTop: '0px', rowGap: '0px' }}
|
|
>
|
|
<div className="inputForm">
|
|
<Form.Item
|
|
name="SuppId"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please Select Supplier',
|
|
},
|
|
]}
|
|
>
|
|
<div
|
|
className="supplierRating"
|
|
style={{ position: 'relative', width: '250px' }}
|
|
>
|
|
<DropDowns1
|
|
className="field-DropDown"
|
|
value={selecPurSupplier}
|
|
onChange={handleSupplierDropDownChange}
|
|
label={'Supplier Name'}
|
|
isOnchanges={selecPurSupplier ? true : false}
|
|
options={Supplierdata?.map((option) => ({
|
|
value: option.SuppId,
|
|
label: (
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
width: '100%',
|
|
}}
|
|
>
|
|
<label>
|
|
{option.SuppName + ' ' + `(${option.Type})`}
|
|
</label>
|
|
{option.DeliveryPerformanceImage && (
|
|
<img
|
|
src={option.DeliveryPerformanceImage}
|
|
alt=""
|
|
style={{
|
|
width: 20,
|
|
height: 20,
|
|
marginLeft: 8,
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
),
|
|
searchLabel: option.SuppName, // <<--- Add this line
|
|
}))}
|
|
/>
|
|
|
|
{/* {renderPerformanceImg(selecSuppDetails?.DeliveryPerformance)} */}
|
|
</div>
|
|
|
|
<Tooltip title="Add Supplier" placement="top">
|
|
<PlusCircleOutlined onClick={addPurSupplier} />
|
|
</Tooltip>
|
|
</Form.Item>
|
|
|
|
<div className='deliveryaddress'>
|
|
{selecSuppDetails !== null &&
|
|
(() => {
|
|
const fields = [];
|
|
if (selecSuppDetails?.SuppName) {
|
|
fields.push(
|
|
<p>
|
|
<strong>Name:</strong> {selecSuppDetails.SuppName}
|
|
</p>
|
|
);
|
|
}
|
|
if (selecSuppDetails?.Address1) {
|
|
fields.push(
|
|
<p>
|
|
<strong>Address:</strong>{' '}
|
|
{selecSuppDetails.Address1}
|
|
</p>
|
|
);
|
|
}
|
|
if (selecSuppDetails?.SuppMobile) {
|
|
fields.push(
|
|
<p>
|
|
<strong>Mobile Number:</strong>{' '}
|
|
{selecSuppDetails.SuppMobile}
|
|
</p>
|
|
);
|
|
}
|
|
if (selecSuppDetails?.DiscountLevel) {
|
|
fields.push(
|
|
<p>
|
|
<strong>Discount Level:</strong>{' '}
|
|
{selecSuppDetails.DiscountLevel}
|
|
</p>
|
|
);
|
|
}
|
|
if (selecSuppDetails?.QualityofSupp) {
|
|
fields.push(
|
|
<p>
|
|
<strong>Quality of Supplier:</strong>{' '}
|
|
{selecSuppDetails.QualityofSupp}
|
|
</p>
|
|
);
|
|
}
|
|
if (selecSuppDetails?.OtherInfo) {
|
|
fields.push(
|
|
<p>
|
|
<strong>Other Info:</strong>{' '}
|
|
{selecSuppDetails.OtherInfo}
|
|
</p>
|
|
);
|
|
}
|
|
const firstColumn = fields.slice(0, 3);
|
|
const secondColumn = fields.slice(3);
|
|
return (
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
columnGap: '2rem',
|
|
flexWrap: 'wrap',
|
|
}}
|
|
>
|
|
<div>
|
|
<h3>{`${selecSuppDetails?.Type} Details:`}</h3>
|
|
{firstColumn}
|
|
</div>
|
|
{secondColumn.length > 0 && (
|
|
<div>
|
|
<p>
|
|
<br />
|
|
</p>
|
|
{secondColumn}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
})()}
|
|
</div>
|
|
<div
|
|
className="lowStock-button"
|
|
onClick={() => setisLowStockModel(true)}
|
|
>
|
|
<IoWarningOutline size={18} />
|
|
<span>Low Stock</span>
|
|
</div>
|
|
{!deliveryAddress && <div
|
|
className="Address-button"
|
|
onClick={() => setAddressModel(true)}
|
|
>
|
|
<span>Delivery Address</span>
|
|
</div>}
|
|
{deliveryAddress && (
|
|
<div className="deliveryaddress">
|
|
<strong className='deliveryaddress_edit' onClick={() => setAddressModel(true)}>Delivery Address Details: <CiEdit size={18} /></strong>
|
|
{deliveryAddress?.Address1 && <p>
|
|
<strong>Address:</strong>{' '}
|
|
{deliveryAddress?.Address1}
|
|
</p>}
|
|
{deliveryAddress?.City && <p>
|
|
<strong>City:</strong> {deliveryAddress?.City}
|
|
</p>}
|
|
{deliveryAddress?.Dist && <p>
|
|
<strong>district:</strong> {deliveryAddress?.Dist}
|
|
</p>}
|
|
{deliveryAddress?.State && <p>
|
|
<strong>State:</strong> {deliveryAddress?.State}
|
|
</p>}
|
|
{deliveryAddress?.Zip && <p>
|
|
<strong>Zip:</strong> {deliveryAddress?.Zip}
|
|
</p>}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{(() => {
|
|
const styleName =
|
|
selectedStyleData === undefined
|
|
? 'Style 13'
|
|
: selectedStyleData;
|
|
const selectedStyle =
|
|
stylesMap[styleName] || stylesMap['Style 13'];
|
|
return (
|
|
<div style={{ display: 'none' }}>
|
|
<PurchaseOrderPrint
|
|
PrintingData={PrintData}
|
|
selectedStyleData={selectedStyle}
|
|
/>
|
|
</div>
|
|
);
|
|
})()}
|
|
|
|
{/* <div style={{ display: 'none' }} >
|
|
<PurchaseOrderPrint
|
|
PrintingData={PrintData}
|
|
selectedStyleData={selectedStyleData}
|
|
/>
|
|
</div> */}
|
|
|
|
<Form ref={formProductRef}>
|
|
<div className="inputForm" style={{ marginTop: '2rem' }}>
|
|
<Form.Item
|
|
name="ProdId"
|
|
// rules={[
|
|
// {
|
|
// required: true,
|
|
// message: "Please Select Product Name",
|
|
// },
|
|
// ]}
|
|
>
|
|
{/* <DropDowns
|
|
// options={PurProductdata?.map((option) => ({
|
|
// value: option.ProdId,
|
|
// label: option.ProdName + "( " + option.Size + " " + option.UomName + " )",
|
|
// }))}
|
|
options={PurProductdata?.map((option) => ({
|
|
value: option.ProdId,
|
|
label:
|
|
option.ProdName +
|
|
'( ' +
|
|
option.Size +
|
|
' ' +
|
|
option.UomName +
|
|
' )',
|
|
}))}
|
|
filterOption={(input, option) => {
|
|
const product = PurProductdata.find(
|
|
(p) => p.ProdId === option.value
|
|
);
|
|
const nameMatch = option.label
|
|
.toLowerCase()
|
|
.includes(input.toLowerCase());
|
|
const qrMatch =
|
|
product?.QRCode?.toLowerCase() ==
|
|
input.toLowerCase();
|
|
console.log(
|
|
qrMatch,
|
|
'qrMatch',
|
|
product?.QRCode?.toLowerCase(),
|
|
input.toLowerCase()
|
|
);
|
|
return nameMatch || qrMatch;
|
|
}}
|
|
label={'Product Name'}
|
|
className="field-DropDown"
|
|
onChangeFunction={(e) => PurcProductDropDownChange(e)}
|
|
valueData={selectedPurProductData}
|
|
disabled={Edit ? true : false}
|
|
/> */}
|
|
|
|
<div className="product-name-scan">
|
|
<FloatLabel
|
|
label={'Product Name'}
|
|
value={selectedProductName}
|
|
>
|
|
<AutoComplete
|
|
className="field-DropDown productNameDDAuto"
|
|
value={selectedProductName}
|
|
filterOption={(input, option) => {
|
|
const product = PurProductdata.find(
|
|
(p) => p.ProdId === option.value
|
|
);
|
|
const nameMatch = option.label
|
|
?.toLowerCase()
|
|
?.includes(productSearchText?.toLowerCase());
|
|
const qrMatch =
|
|
product?.QRCode?.toLowerCase() ==
|
|
productSearchText?.toLowerCase();
|
|
return nameMatch || qrMatch;
|
|
}}
|
|
options={
|
|
!scanner
|
|
? PurProductdata?.map((option) => ({
|
|
value: option.ProdId,
|
|
label: `${option.ProdName} (${option.Size} ${option.UomName})${option?.BrandName ? ` - ${option?.BrandName}` : ''}`,
|
|
}))
|
|
: []
|
|
}
|
|
onSelect={PurcProductDropDownChange}
|
|
onChange={handleProductSearch}
|
|
onKeyDown={(e) => {
|
|
if (scanner && e.key === 'Enter') {
|
|
e.preventDefault();
|
|
}
|
|
}}
|
|
></AutoComplete>
|
|
</FloatLabel>
|
|
<Tooltip title={'BarCode/QrCode'} placement={'top'}>
|
|
<BsUpcScan
|
|
strokeWidth={0.5}
|
|
color="#000"
|
|
style={{
|
|
fontSize: '16px',
|
|
color: scanner ? '#52c41a' : '#888',
|
|
fontWeight: '600',
|
|
}}
|
|
className="product-scan-Icon"
|
|
onClick={handleScanSearch}
|
|
/>
|
|
</Tooltip>
|
|
</div>
|
|
</Form.Item>
|
|
<Tooltip
|
|
title={'Supplier Product Mapping'}
|
|
placement={'top'}
|
|
>
|
|
<FaLink onClick={() => setIsModalOpen(true)} />
|
|
</Tooltip>
|
|
|
|
{isModalOpen && (
|
|
<SupplierProductMappingForm
|
|
isModalOpen={isModalOpen}
|
|
setIsModalOpen={() => setIsModalOpen(false)}
|
|
CompId={CompId}
|
|
BranchId={BranchId}
|
|
AppId={AppId}
|
|
setMessage={setMessage}
|
|
onMappingAdded={handleModalSubmited}
|
|
/>
|
|
)}
|
|
{/* <Form.Item
|
|
name="QRCode"
|
|
rules={[
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
autoComplete="off"
|
|
label={"QR Code"}
|
|
onChange={(e) => handleQRCodeChange(e)}
|
|
|
|
/>
|
|
</Form.Item> */}
|
|
{VariantDetails?.length > 1 && (
|
|
<Form.Item name="ProdVariantName">
|
|
<DropDowns
|
|
options={VariantDetails?.map((option) => ({
|
|
value: option.ProdVariantName,
|
|
label: option.ProdVariantName,
|
|
}))}
|
|
label={'Variant Name'}
|
|
className="field-DropDown"
|
|
onChangeFunction={(e) =>
|
|
ProductVariantDropDownChange(e)
|
|
}
|
|
valueData={SelProductVariant}
|
|
// disabled={Edit ? true : false}
|
|
/>
|
|
</Form.Item>
|
|
)}
|
|
<div style={{ width: '160px' }}>
|
|
<Form.Item
|
|
name="OrderQty"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
pattern: /^[1-9]\d*(\.\d+)?$/,
|
|
message: 'Please Enter Quantity',
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value);
|
|
if (value?.length > 10) {
|
|
return Promise.reject(
|
|
'Quantity cannot exceeds more than 10 chars'
|
|
);
|
|
}
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
label={
|
|
<label class="required">Purchase Quantity</label>
|
|
}
|
|
autocomplete="off"
|
|
isOnChange={
|
|
formProductRef.current?.getFieldsValue()?.OrderQty
|
|
? true
|
|
: false
|
|
}
|
|
inputMode="numeric"
|
|
onInput={(e) =>
|
|
(e.target.value = e.target.value.replace(
|
|
/[^0-9]/g,
|
|
''
|
|
))
|
|
}
|
|
/>
|
|
</Form.Item>
|
|
</div>
|
|
|
|
{!Edit ? (
|
|
<div
|
|
className="addVariant"
|
|
onClick={() => !isSubmitted && AddProduct()}
|
|
style={{
|
|
cursor: isSubmitted ? 'not-allowed' : 'pointer',
|
|
opacity: isSubmitted ? 0.5 : 1,
|
|
}}
|
|
>
|
|
{'Add'}
|
|
</div>
|
|
) : (
|
|
<div className="update-and-cancel">
|
|
<button onClick={updateProduct}>Update</button>
|
|
<button onClick={cancelEdit}>Cancel</button>
|
|
</div>
|
|
)}
|
|
<div className="component-table-purchae">
|
|
<Tables
|
|
columns={columns}
|
|
data={ProductTableData}
|
|
dataSource={ProductTableData}
|
|
/>{' '}
|
|
</div>
|
|
</div>
|
|
</Form>
|
|
</div>
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
gap: '2rem',
|
|
alignItems: 'center',
|
|
width: '100%',
|
|
justifyContent: 'flex-end',
|
|
}}
|
|
>
|
|
<Buttons
|
|
buttonText="SUBMIT"
|
|
color="901D77"
|
|
icon={<ArrowRightOutlined />}
|
|
/>
|
|
{isSubmitted && (
|
|
<>
|
|
<div>
|
|
<MdOutlineMail
|
|
size={39}
|
|
color="#25D366"
|
|
style={{ cursor: 'pointer' }}
|
|
onClick={() =>
|
|
handleEmailClick(
|
|
submittedOrderData.ProductDetails,
|
|
submittedOrderData
|
|
)
|
|
}
|
|
title="Share by Email"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<FaPrint
|
|
size={32}
|
|
color="#1292EE"
|
|
style={{ cursor: 'pointer' }}
|
|
onClick={handlePrint}
|
|
title="Print"
|
|
/>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</Form>
|
|
</div>
|
|
<DefaultModal
|
|
title="Add Supplier"
|
|
open={OpenPurSupplierModel}
|
|
footer={true}
|
|
buttonText="Submit"
|
|
children={
|
|
<Form ref={formSupplierRef} className="formDivAnt">
|
|
<div className="subRowFlex">
|
|
<Form.Item
|
|
name="SuppName"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
pattern: /^(?!\s*$).+/,
|
|
message: 'Please Enter Supplier Name',
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value);
|
|
|
|
if (value && value.length > 30) {
|
|
return Promise.reject(
|
|
'Supplier Name should not exceed 30 characters'
|
|
);
|
|
}
|
|
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
label={<label class="required">Supplier Name</label>}
|
|
autocomplete="off"
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="Address1"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
pattern: /^(?!\s*$).+/,
|
|
message: 'Please Enter Address1',
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
autoComplete="off"
|
|
label={<label class="required">Address</label>}
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="Zip"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
pattern: /^(?!\s*$).+/,
|
|
message: 'Please Enter Zipcode',
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
autoComplete="off"
|
|
label={<label class="required">Zipcode</label>}
|
|
maxLength="6"
|
|
onChange={pinCodeChange}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<p
|
|
style={{ color: '#1292ee', justifyContent: 'end', cursor: 'pointer' }}
|
|
onClick={ViewMoreFields}
|
|
>
|
|
{' '}
|
|
{ViewDtl ? 'View Less' : 'View More'}
|
|
</p>
|
|
|
|
{ViewDtl && (
|
|
<>
|
|
<Form.Item
|
|
name="SuppGSTIN"
|
|
rules={[
|
|
{
|
|
pattern:
|
|
/^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9A-Za-z]{1}$/,
|
|
message: 'Enter a valid GSTIN',
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
style={{ textTransform: 'uppercase' }}
|
|
autoComplete="off"
|
|
label="GST No"
|
|
autocapitalize="on"
|
|
// isOnChange={formType == 'edit' ? true : false}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="SuppMobile"
|
|
rules={[
|
|
{
|
|
pattern: /^\d{10}$/,
|
|
message: 'Please Enter a Valid Mobile Number',
|
|
},
|
|
|
|
{ validator: validatePhoneNumber },
|
|
]}
|
|
>
|
|
<InputField
|
|
label={<label>Mobile Number</label>}
|
|
maxLength="10"
|
|
autocomplete="off"
|
|
// isOnChange={formType == 'edit' ? true : false}
|
|
inputMode="numeric"
|
|
onInput={(e) =>
|
|
(e.target.value = e.target.value.replace(
|
|
/[^0-9]/g,
|
|
''
|
|
))
|
|
}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="SuppEmail"
|
|
rules={[{ validator: validateEmail }]}
|
|
>
|
|
<InputField
|
|
label={<label>MailId</label>}
|
|
autocomplete="off"
|
|
// isOnChange={formType == 'edit' ? true : false}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="SuppPOC"
|
|
rules={[
|
|
{
|
|
pattern: /^(?!\s*$).+/,
|
|
message: 'Please Enter Point of Contact Name',
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value);
|
|
if (value?.length > 30) {
|
|
return Promise.reject(
|
|
'Point of Contact cannot exceeds more than 30 chars'
|
|
);
|
|
}
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
label={<label class="">Point of Contact</label>}
|
|
autocomplete="off"
|
|
// isOnChange={formType == 'edit' ? true : false}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="SuppPOCMobile"
|
|
rules={[
|
|
{
|
|
pattern: /^\d{10}$/,
|
|
message: 'Please Enter a Valid Mobile Number',
|
|
},
|
|
{
|
|
// required: true,
|
|
message: 'Please Enter Mobile Number',
|
|
},
|
|
{ validator: validatePhoneNumber },
|
|
]}
|
|
>
|
|
<InputField
|
|
label={<label class="">POC Mobile Number</label>}
|
|
autocomplete="off"
|
|
maxLength="10"
|
|
// isOnChange={formType == 'edit' ? true : false}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="SuppPOCEmail"
|
|
rules={[{ validator: validateEmail }]}
|
|
>
|
|
<InputField
|
|
label={<label class="">POC MailId</label>}
|
|
autocomplete="off"
|
|
// isOnChange={formType == 'edit' ? true : false}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="DeliveryPerformance"
|
|
rules={[
|
|
{
|
|
required: false,
|
|
message: 'Please Select DeliveryPerformance',
|
|
},
|
|
]}
|
|
>
|
|
<DropDowns
|
|
options={deliveryPerformanceData?.map((option) => ({
|
|
value: option.ConfigId,
|
|
label: option.ConfigName,
|
|
}))}
|
|
label={<label>Delivery Performance</label>}
|
|
className="field-DropDown"
|
|
id="DeliveryPerformance"
|
|
onChangeFunction={(e) =>
|
|
handleDeliveryPerformanceChange(e)
|
|
}
|
|
// isOnChange={formType == 'edit' ? true : false}
|
|
valueData={Delivery}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="DiscountLevel"
|
|
rules={[
|
|
{
|
|
required: false,
|
|
message: 'Please Select DiscountLevel',
|
|
},
|
|
]}
|
|
>
|
|
<DropDowns
|
|
options={DiscountData?.map((option) => ({
|
|
value: option.ConfigId,
|
|
label: option.ConfigName,
|
|
}))}
|
|
label={<label>Discount Level</label>}
|
|
className="field-DropDown"
|
|
id="DiscountLevel"
|
|
onChangeFunction={(e) => handleDiscountLevelChange(e)}
|
|
// isOnChange={formType == 'edit' ? true : false}
|
|
valueData={DicountValue}
|
|
/>
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
name="QualityofSupp"
|
|
rules={[
|
|
{
|
|
required: false,
|
|
message: 'Please Select QualityofSupp',
|
|
},
|
|
]}
|
|
>
|
|
<DropDowns
|
|
options={QualityData?.map((option) => ({
|
|
value: option.ConfigId,
|
|
label: option.ConfigName,
|
|
}))}
|
|
label={<label>Quality of Supplier</label>}
|
|
className="field-DropDown"
|
|
id="QualityofSupp"
|
|
onChangeFunction={(e) => handleQualityofSuppChange(e)}
|
|
// isOnChange={formType == 'edit' ? true : false}
|
|
valueData={QualityValue}
|
|
/>
|
|
</Form.Item>
|
|
</>
|
|
)}
|
|
{zipCodeData ? (
|
|
<>
|
|
<Form.Item
|
|
name="City"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
disabled={true}
|
|
isOnChange={true}
|
|
label="City"
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="Dist"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
disabled={true}
|
|
isOnChange={true}
|
|
label="District"
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="State"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
disabled={true}
|
|
isOnChange={true}
|
|
label="State"
|
|
/>
|
|
</Form.Item>
|
|
</>
|
|
) : (
|
|
''
|
|
)}
|
|
</div>
|
|
</Form>
|
|
}
|
|
handleSubmit={submitSupplier}
|
|
handleCancel={handleSupplier}
|
|
></DefaultModal>
|
|
|
|
<DefaultModal
|
|
width={400}
|
|
open={iSEmail}
|
|
title="User Mail"
|
|
handleCancel={() => setiSEmail(false)}
|
|
footer={false}
|
|
children={
|
|
<div>
|
|
<Form
|
|
form={form}
|
|
layout="vertical"
|
|
onFinish={handleSendEmailWithEnteredEmail}
|
|
>
|
|
<Form.Item
|
|
label="Mail ID"
|
|
name="email"
|
|
rules={[
|
|
{ required: true, message: 'Email is required' },
|
|
{ type: 'email', message: 'Enter a valid email address' },
|
|
]}
|
|
>
|
|
<Input autoComplete="off" placeholder="Enter your email" />
|
|
</Form.Item>
|
|
|
|
<Button type="primary" htmlType="submit">
|
|
Submit
|
|
</Button>
|
|
</Form>
|
|
</div>
|
|
}
|
|
/>
|
|
<DefaultModal
|
|
width={600}
|
|
open={isLowStockModel}
|
|
title="Low Stock Products"
|
|
handleCancel={() => setisLowStockModel(false)}
|
|
footer={false}
|
|
children={
|
|
<div>
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
alignItems: 'center',
|
|
marginBottom: '15px',
|
|
}}
|
|
>
|
|
<input
|
|
type="text"
|
|
placeholder="Search Product..."
|
|
value={searchTerm}
|
|
onChange={(e) => setSearchTerm(e.target.value)}
|
|
style={{
|
|
padding: '8px 10px',
|
|
width: '60%',
|
|
border: '1px solid #ccc',
|
|
borderRadius: '6px',
|
|
}}
|
|
/>
|
|
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: '8px',
|
|
}}
|
|
>
|
|
<label style={{ fontSize: '14px' }}>Min Qty:</label>
|
|
<input
|
|
type="number"
|
|
placeholder="0"
|
|
value={minQty}
|
|
onChange={handleMinQtyChange}
|
|
style={{
|
|
padding: '8px 10px',
|
|
width: '80px',
|
|
border: '1px solid #ccc',
|
|
borderRadius: '6px',
|
|
textAlign: 'center',
|
|
}}
|
|
min="0"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="ItemWiseReport-table">
|
|
<table
|
|
className="custom-table"
|
|
style={{ width: '100%', borderCollapse: 'collapse' }}
|
|
>
|
|
<thead>
|
|
<tr>
|
|
<th style={{ textAlign: 'center' }}>SI NO</th>
|
|
<th style={{ textAlign: 'center' }}>Product Name</th>
|
|
<th style={{ textAlign: 'center' }}>Balance Qty</th>
|
|
<th style={{ textAlign: 'center' }}>Required Qty</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{currentData.length > 0 ? (
|
|
currentData.map((row, idx) => (
|
|
<tr key={idx}>
|
|
<td style={{ textAlign: 'center' }}>
|
|
{startIndex + idx + 1}
|
|
</td>
|
|
<td style={{ textAlign: 'left' }}>
|
|
{row.ProdName} ({row.ProdVariantName})
|
|
</td>
|
|
<td style={{ textAlign: 'center' }}>
|
|
{row.BalanceQty}
|
|
</td>
|
|
<td style={{ textAlign: 'center' }}>
|
|
<input
|
|
type="number"
|
|
style={{ width: '80px', textAlign: 'center' }}
|
|
value={row.needQty || ''}
|
|
onChange={(e) => {
|
|
const newQty = e.target.value;
|
|
seProductStockData((prev) =>
|
|
prev.map((item, i) =>
|
|
i === startIndex + idx
|
|
? { ...item, needQty: newQty }
|
|
: item
|
|
)
|
|
);
|
|
}}
|
|
min="0"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
))
|
|
) : (
|
|
<tr>
|
|
<td
|
|
colSpan="4"
|
|
style={{ textAlign: 'center', padding: '10px' }}
|
|
>
|
|
Data not found
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
marginTop: '20px',
|
|
gap: '10px',
|
|
}}
|
|
>
|
|
<p
|
|
onClick={handlePrevious}
|
|
style={{
|
|
padding: '8px 12px',
|
|
border: '1px solid #ccc',
|
|
cursor: currentPage === 1 ? 'not-allowed' : 'pointer',
|
|
opacity: currentPage === 1 ? 0.5 : 1,
|
|
}}
|
|
>
|
|
<
|
|
</p>
|
|
|
|
<span
|
|
style={{
|
|
margin: '0',
|
|
fontFamily: 'Poppins',
|
|
fontSize: '14px',
|
|
}}
|
|
>
|
|
Page {currentPage} of {totalPages}
|
|
</span>
|
|
|
|
<p
|
|
onClick={handleNext}
|
|
style={{
|
|
padding: '8px 12px',
|
|
border: '1px solid #ccc',
|
|
cursor:
|
|
currentPage === totalPages ? 'not-allowed' : 'pointer',
|
|
opacity: currentPage === totalPages ? 0.5 : 1,
|
|
}}
|
|
>
|
|
>
|
|
</p>
|
|
</div>
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'end' }}>
|
|
<div
|
|
onClick={handleSaveLowStock}
|
|
className="lowStock-SaveButton"
|
|
>
|
|
SAVE
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
/>
|
|
{/* Address model */}
|
|
<DefaultModal
|
|
width={600}
|
|
open={addressModel}
|
|
title="Delivery Address"
|
|
handleSubmit={handleAddressSubmit}
|
|
buttonText="Submit"
|
|
handleCancel={() => setAddressModel(false)}
|
|
footer={true}
|
|
children={
|
|
<div>
|
|
<Form ref={deliveryAddressRef} className="formDivAnt">
|
|
<div className="subRowFlex">
|
|
<Form.Item
|
|
name="Address1"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
pattern: /^(?!\s*$).+/,
|
|
message: 'Please Enter Address1',
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
autoComplete="off"
|
|
label={<label class="required">Address</label>}
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="Address2"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
pattern: /^(?!\s*$).+/,
|
|
message: 'Please Enter Address2',
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
autoComplete="off"
|
|
label={<label class="required">Address</label>}
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="Zip"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
pattern: /^(?!\s*$).+/,
|
|
message: 'Please Enter Zipcode',
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
autoComplete="off"
|
|
label={<label class="required">Zipcode</label>}
|
|
maxLength="6"
|
|
onChange={pinCodeChange}
|
|
/>
|
|
</Form.Item>
|
|
{zipCodeData ? (
|
|
<>
|
|
<Form.Item
|
|
name="City"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
disabled={true}
|
|
isOnChange={true}
|
|
label="City"
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="Dist"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
disabled={true}
|
|
isOnChange={true}
|
|
label="District"
|
|
/>
|
|
</Form.Item>
|
|
<Form.Item
|
|
name="State"
|
|
rules={[
|
|
{
|
|
required: true,
|
|
},
|
|
{
|
|
validator: async (_, value) => {
|
|
await validateSafeInput(value); // To block HTML tags & SQL keywords
|
|
return Promise.resolve();
|
|
},
|
|
},
|
|
]}
|
|
>
|
|
<InputField
|
|
disabled={true}
|
|
isOnChange={true}
|
|
label="State"
|
|
/>
|
|
</Form.Item>
|
|
</>
|
|
) : (
|
|
''
|
|
)}
|
|
</div>
|
|
</Form>
|
|
|
|
</div>
|
|
}
|
|
/>
|
|
</div>
|
|
</div >
|
|
</div >
|
|
);
|
|
};
|
|
|
|
export default PurchaseOrder;
|