import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState, } from 'react'; import { Input, Select, Button } from 'antd'; import { DeleteOutlined, SaveOutlined, PrinterOutlined, } from '@ant-design/icons'; import { Tables } from '../../../../Components/Tables/Table.jsx'; import { useDispatch } from 'react-redux'; import { postProductData, getDirectSaleProducts, getAllProductShortCodes, deleteProductData, getDirectSaleSearchedProduct, } from '../../../../Features/ProductPage/ProductPage.js'; import { getSession, printDiv } from '../../../../Services/Others.js'; import { Messages } from '../../../../Components/Notifications/Messages.jsx'; import { FaStarOfLife } from 'react-icons/fa6'; import { IoMdRefresh } from 'react-icons/io'; import StickerPrintModel from '../../../Product/StickerPrintModal.jsx'; import { getPageStyle, style } from '../../../Product/Printstyles.js'; import { getBarcodeSessionsIDs, getBarcodeTemplate, } from '../../../../Features/Barcode/Barcode.js'; import { generateBarcode, generateQRCode, generateQRCodeCopy, } from '../../../../Services/utils.js'; import useBarcodeGenerator from './useBarcodeQRGenerator.js'; // Jsx File const StickerPrintTemplates = lazy( () => import('../../../Product/StickerTemplates.jsx') ); // SCss import '../../../../Styles/BookingScreen/Components/OtherConponents/Reprint/BSReprint.scss'; const DirectSale = ({ UomData = [], TaxData = [], ProductTypeData = [], ProdCatData = [], ProdSubCatData = [], SupplierData = [], activeTab = null, }) => { const formRef = useRef(); const tableRef = useRef(); const searchInputRef = useRef(); const dispatch = useDispatch(); const [messageType, setMessageType] = useState(null); const [messageData, setMessageData] = useState(null); const [currentPage, setCurrentPage] = useState(1); const CompId = getSession('CompId'); const BranchId = getSession('BranchId'); const AppId = getSession('AppId'); const UserId = getSession('UserId'); const [dataSource, setDataSource] = useState([]); const [editingKey, setEditingKey] = useState(null); const [copies, setCopies] = useState(null); const [dropdownValue, setDropdownValue] = useState(null); const [multiProduct, setMultiProduct] = useState(false); const [printReady, setPrintReady] = useState(false); const [printProductName, setPrintProductName] = useState(false); const [productShortCodes, setAllProductShortCodes] = useState([]); const [searchText, setSearchText] = useState(''); console.log(searchText, 'searchText'); const [stickerPrintModalOpen, setStickerPrintModalOpen] = useState(false); const [barcodeTemplateDetails, setBarcodeTemplateDetails] = useState([]); const [filteredProducts, setFilteredProducts] = useState([]); const [labelPrintData, setLabelPrintData] = useState(null); const [prodId, setProdId] = useState(null); const [nickName, setNickName] = useState(null); const [crossData, setCrossData] = useState(null); const [triggerState, setTriggerState] = useState(1); const [templateOptions, setTemplateOptions] = useState({ mrp: false, barcode: false, color: false, eDate: false, mDate: false, sellingPrice: false, productName: false, value: '', secondValue: '', qrcode: false, codeType: '', }); console.log(searchText != null && searchText != '', 'filteredProducts'); const { qrBase64, barcodeBase64 } = useBarcodeGenerator(prodId); const handleAdd = () => { setDataSource([ { key: dataSource.length + 1, productName: '', shortCode: '', sellingPrice: '', uom: null, tax: null, prodId: null, size: null, uomName: null, activeStatus: 'A', }, ...dataSource, ]); }; const handleDelete = async (record) => { if (record?.prodId) { if (searchText != null && searchText !== '') { setSearchText(''); setCurrentPage(1); if (searchInputRef.current) { searchInputRef.current.value = ''; } } const deleteData = { ProdId: record.prodId, ActiveStatus: record.activeStatus === 'A' ? 'D' : 'A', UpdatedBy: UserId, }; const response = await dispatch(deleteProductData(deleteData))?.unwrap(); if (response?.data?.statusCode === 1) { setMessageData( record.activeStatus === 'A' ? 'Product De-Activated Successfully' : 'Product Activated Successfully' ); setMessageType('success'); await fetchDirectSaleProducts(); } else { setMessageData(response?.data?.response || 'Failed to update status'); setMessageType('error'); } return; } else { // const { key } = record; // setDataSource(dataSource.filter(item => item.key !== key)); setMessageData('Atleast one empty row should be in table.'); setMessageType('warning'); } }; const handleChange = useCallback( (key, field, value) => { if (searchText) { setFilteredProducts((prev) => prev.map((item) => item.key === key ? { ...item, [field]: value } : item ) ); } else { setDataSource((prev) => prev.map((item) => item.key === key ? { ...item, [field]: value } : item ) ); } }, [searchText] ); const handleSave = async (record) => { if ( !record.productName || !record.sellingPrice || !record.uom || !record.tax || !record?.shortCode ) { setMessageData('Please fill all the required fields!'); setMessageType('warning'); return; } const exists = isShortCodeDuplicate(record?.shortCode, record?.prodId); if (exists) { setMessageData('Short code already exists for another product'); setMessageType('error'); return; } const postData = { ProdName: record.productName, Size: '1', UOM: record.uom, MRP: record.sellingPrice, SellPrice: record.sellingPrice, TaxId: record.tax, CompId: CompId, BranchId: BranchId, AppId: AppId, ProdType: ProductTypeData?.find((item) => item.ConfigName === 'Product') ?.ConfigId, ProdCat: ProdCatData?.find((item) => item.ConfigName === 'General') ?.ConfigId, ProdSubCat: ProdSubCatData?.find((item) => item.ConfigName === 'General') ?.ConfigId, QtyBasedPrice: 'N', ProdQtywisePriceDetails: [], StockAvailable: 'N', TokenAvailable: 'N', InwardDate: new Date().toJSON(), SuppId: SupplierData?.find( (item) => item.SuppName?.toLowerCase() === 'self' )?.SuppId, AutoGenerateQr: 'N', QRCode: null, CreatedBy: UserId, ProdLogo: '', Cess: 0, ProdShortCode: record?.shortCode, }; try { if (record?.prodId) { console.log('Updating Product'); } else { const response = await dispatch(postProductData(postData)).unwrap(); if (response?.data?.statusCode === 1) { const prodId = response?.data?.ProductDetails?.[0]?.ProdId; const size = response?.data?.ProductDetails?.[0]?.Size; const uomName = response?.data?.ProductDetails?.[0]?.UomName; const totalProducts = response?.data?.ProductDetails?.[0]?.TotalCount; setSearchText((currentSearchText) => { if (currentSearchText != null && currentSearchText !== '') { setCurrentPage(1); setTriggerState((prev) => prev + 1); if (searchInputRef.current) { searchInputRef.current.value = ''; } return ''; } else { setDataSource((prev) => prev.map((item) => item.key === record.key ? { ...item, prodId, size, uomName, totalProducts } : { ...item, totalProducts } ) ); } return currentSearchText; }); setMessageData('Product saved successfully!'); setMessageType('success'); return; } } } catch (error) { console.error('Error saving product:', error); } }; const handlePrint = async (record) => { const exists = isShortCodeDuplicate(record?.shortCode, record?.prodId); if (exists) { setMessageData( 'Short code already exists for another product. Cannot print.' ); setMessageType('error'); return; } setStickerPrintModalOpen(true); setLabelPrintData({ ...record, MRP: record?.sellingPrice || 0, SellPrice: record?.sellingPrice || 0, }); setProdId(record?.shortCode + '' + record?.sellingPrice); }; const columns = useMemo( () => [ { title: 'SL.No', width: 50, align: 'center', render: (_, __, index) => (currentPage - 1) * 10 + index + 1, }, { title: () => (
Product Name
), dataIndex: 'productName', width: 150, render: (text, record) => record.prodId && editingKey !== record.key ? (
{text}
) : ( handleChange(record.key, 'productName', e.target.value) } placeholder="Enter product name" /> ), }, { title: () => (
Short Code
), dataIndex: 'shortCode', width: 100, render: (text, record) => record.prodId && editingKey !== record.key ? (
{text}
) : ( { const originalValue = e.target.value; const hasNonAlpha = /[^a-zA-Z]/.test(originalValue); if (hasNonAlpha) { setMessageData('Enter Alphabet Characters only'); setMessageType('warning'); } }} onChange={(e) => { const value = e.target.value .replace(/[^a-zA-Z]/g, '') .toUpperCase(); const exists = isShortCodeDuplicate(value, record?.prodId); if (exists && value) { setMessageData( 'Short code already exists for another product' ); setMessageType('error'); } handleChange(record.key, 'shortCode', value); }} placeholder="Short Code" /> ), }, { title: () => (
Selling Price
), dataIndex: 'sellingPrice', width: 120, render: (text, record) => record.prodId && editingKey !== record.key ? (
{text}
) : ( { const value = e.target.value.replace(/[^0-9.]/g, ''); const parts = value.split('.'); const formatted = parts.length > 2 ? `${parts[0]}.${parts.slice(1).join('')}` : value; handleChange(record.key, 'sellingPrice', formatted); }} placeholder="0.00" /> ), }, { title: () => (
UOM
), dataIndex: 'uom', width: 60, render: (text, record) => record.prodId && editingKey !== record.key ? (
{UomData?.find((item) => item.ConfigId === text)?.ConfigName || '-'}
) : ( handleChange(record.key, 'tax', value)} placeholder="Tax" style={{ width: '100%' }} options={TaxData?.map((item) => ({ value: item.TaxId, label: `${item.TaxIdName} - ${item.TaxPercentage}%`, }))} /> ); }, }, { title: 'Save / Print', width: 90, align: 'center', render: (_, record) => { const existingProduct = record?.prodId; return (
{!existingProduct && ( )} {existingProduct && ( )}
); }, }, { title: 'Action', width: 60, align: 'center', render: (_, record) => { if (record?.activeStatus === 'A') { return ( handleDelete(record)} style={{ color: 'red', cursor: 'pointer', fontSize: '18px' }} /> ); } else { return ( handleDelete(record)} /> ); } }, }, ], [searchText, editingKey, productShortCodes, UomData, TaxData] ); useEffect(() => { if (activeTab === 'directSale' && AppId && CompId && BranchId) { fetchDirectSaleProducts(); fetchAllProductShortCodes(); } }, [activeTab, AppId, BranchId, CompId, currentPage, triggerState]); useEffect(() => { if (dataSource.every((row) => row.prodId)) { handleAdd(); } }, [dataSource]); useEffect(() => { const timer = setTimeout(() => { if (searchText) { fetchSearchedProducts(); } else { setFilteredProducts([ { key: 1, productName: '', shortCode: '', sellingPrice: '', uom: null, tax: null, prodId: null, size: null, uomName: null, activeStatus: 'A', }, ]); } }, 500); return () => clearTimeout(timer); }, [searchText, AppId, BranchId, CompId]); useEffect(() => { const handleClickOutside = (event) => { if ( tableRef.current && !tableRef.current.contains(event.target) && !event.target.closest('.ant-select-dropdown') ) { setEditingKey(null); } }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); useEffect(() => { if ( activeTab === 'directSale' && AppId && CompId && BranchId && stickerPrintModalOpen ) { getBarcodeSessionData(); fetchBarcodeTemplateDetails(); } }, [activeTab, AppId, BranchId, CompId, stickerPrintModalOpen]); const fetchSearchedProducts = async () => { try { const data = { AppId: AppId, CompId: CompId, BranchId: BranchId, prodName: searchText, }; const response = await dispatch( getDirectSaleSearchedProduct(data) )?.unwrap(); if ( response?.data?.data?.length > 0 && response?.data?.statusCode === 1 ) { const products = response?.data?.data?.map((item, index) => ({ key: index + 1, productName: item.ProdName, shortCode: item.ProdShortCode, sellingPrice: item.SellPrice, uom: item.UOM, tax: item.TaxId, prodId: item.ProdId, activeStatus: item?.ActiveStatus, size: item.Size || 1, uomName: item.UomName || 'PCS', totalProducts: item?.TotalCount, })); setFilteredProducts([ { key: products.length + 1, productName: '', shortCode: '', sellingPrice: '', uom: null, tax: null, prodId: null, size: null, uomName: null, activeStatus: 'A', }, ...products, ]); } else { setFilteredProducts([ { key: 1, productName: '', shortCode: '', sellingPrice: '', uom: null, tax: null, prodId: null, size: null, uomName: null, activeStatus: 'A', }, ]); } } catch (error) { console.error(error?.message); } }; const isShortCodeDuplicate = useCallback( (code, prodId) => { return productShortCodes.some( (item) => item.ProdShortCode.toUpperCase() === code.toUpperCase() && item.ProdId !== prodId ); }, [productShortCodes] ); const fetchBarcodeTemplateDetails = async () => { const response = await dispatch( getBarcodeTemplate({ compId: CompId, appId: AppId, branchId: BranchId }) ).unwrap(); if (response?.data?.statusCode === 1 && response?.data?.data?.length > 0) { const { TemplateDetails } = response?.data?.data?.[0]; setBarcodeTemplateDetails(TemplateDetails); } else { setBarcodeTemplateDetails([]); } }; const getBarcodeSessionData = async () => { try { let response = await dispatch(getBarcodeSessionsIDs()).unwrap(); if ( response?.data?.statusCode === 1 && response?.data?.data?.length > 0 ) { setCrossData( response?.data?.data?.filter( (item) => !item.ConfigName?.includes('100X13 (55MM Printable Gold)') ) || [] ); } else { setCrossData([]); } } catch (error) { console.error('Error fetching barcode session data:', error); } }; const fetchDirectSaleProducts = async () => { try { const data = { AppId: AppId, CompId: CompId, BranchId: BranchId, page: currentPage, }; const response = await dispatch(getDirectSaleProducts(data))?.unwrap(); if ( response?.data?.statusCode === 1 && response?.data?.data?.length > 0 ) { const products = response?.data?.data?.map((item, index) => ({ key: index + 1, productName: item.ProdName, shortCode: item.ProdShortCode, sellingPrice: item.SellPrice, uom: item.UOM, tax: item.TaxId, prodId: item.ProdId, activeStatus: item?.ActiveStatus, size: item.Size || 1, uomName: item.UomName || 'PCS', totalProducts: item?.TotalCount, })); setDataSource([ { key: products.length + 1, productName: '', shortCode: '', sellingPrice: '', uom: null, tax: null, prodId: null, size: null, uomName: null, activeStatus: 'A', }, ...products, ]); } else { setDataSource([]); } } catch (error) { console.error('Error fetching direct sale products:', error); } }; const fetchAllProductShortCodes = async () => { try { const data = { AppId: AppId, CompId: CompId, BranchId: BranchId, }; const response = await dispatch(getAllProductShortCodes(data))?.unwrap(); if ( response?.data?.statusCode === 1 && response?.data?.data?.length > 0 ) { setAllProductShortCodes(response?.data?.data); } else { setAllProductShortCodes([]); } console.log(response); } catch (error) { console.error('Error fetching product short codes:', error); } }; const handlePageChange = (current) => { setCurrentPage(current); }; const onFinish = async () => { const template = barcodeTemplateDetails?.find( (find) => find.SessionName === dropdownValue ); const templateAvailable = template === undefined ? false : true; if (templateAvailable) { const checkComponent = (name) => template?.OptionDetails?.some((some) => some.OptionName === name); const mrp = checkComponent('MRP'); const barcode = checkComponent('Barcode'); const color = checkComponent('Color'); const eDate = checkComponent('E Date'); const mDate = checkComponent('M Date'); const sellingPrice = checkComponent('Selling Price'); const productName = checkComponent('Product Name'); const qrcode = checkComponent('Qrcode'); const position = template.Position !== '' ? template.Position : ''; const positionString = template.PositionString !== '' ? template.PositionString : ''; setTemplateOptions({ mrp: mrp, barcode: barcode, color: color, eDate: eDate, mDate: mDate, sellingPrice: sellingPrice, productName: productName, value: position, secondValue: positionString, qrcode: qrcode, codeType: template?.CodeType, }); } setPrintReady(true); setTimeout(async () => { switch (dropdownValue) { case '15X15 6cross': // COMPLETE await printDiv( templateAvailable ? 'label-15X156cross' : 'StickerPrints0', style + getPageStyle(92) ); handleModalClose(); break; case '22X35 3cross': // Need to check await printDiv( templateAvailable ? '22X353cross' : 'StickerPrints1', style + getPageStyle(105) ); handleModalClose(); break; case '25X25 4cross': // COMPLETE await printDiv( templateAvailable ? '25X254cross' : 'StickerPrints2', style + getPageStyle(100) ); handleModalClose(); break; case '25X50 2cross': //Need to check await printDiv( templateAvailable ? '25X502cross' : 'StickerPrints3', style + getPageStyle(100) ); handleModalClose(); break; case '50X30 Single': // COMPLETE await printDiv( templateAvailable ? '50X30Single' : 'StickerPrints4', style ); handleModalClose(); break; case '50X25 Single': // COMPLETE await printDiv( templateAvailable ? '50X25Single' : 'StickerPrints5', style ); handleModalClose(); break; case '100X13 (55MM Printable)': //Need to check await printDiv( templateAvailable ? '100X13(55MMPrintable)' : 'StickerPrints6', style ); handleModalClose(); break; case '100X15 (70MM Printable)': // COMPLETE await printDiv( templateAvailable ? '100X15(70MMPrintable)' : 'StickerPrints7', style ); handleModalClose(); break; case '100X150': // COMPLETE await printDiv( templateAvailable ? '100X150' : 'StickerPrints8', style ); handleModalClose(); setPrintReady(false); break; default: alert('! Select correct cross '); setPrintReady(false); } }, 100); }; const CoresOnChange = (params) => { setDropdownValue(params); formRef.current?.setFieldsValue({ Cross: params }); const template = barcodeTemplateDetails?.find( (find) => find.SessionName === params ); const checkComponent = (name) => template?.OptionDetails?.some((some) => some.OptionName === name); const productName = checkComponent('Product Name'); setPrintProductName(productName); }; const CopiesOnChange = (params) => { setCopies(params); formRef.current?.setFieldsValue({ Copies: params }); }; const handleModalClose = () => { setCopies(null); setDropdownValue(''); setStickerPrintModalOpen(false); setLabelPrintData(null); setNickName(null); setProdId(null); setMultiProduct(false); formRef?.current?.resetFields(); setPrintReady(false); }; const imageTagBarcodeAndQR = useCallback( (w = 'auto', fs = '6px', codeData = null) => { const currentCode = codeData || prodId; return ( (templateOptions.barcode || templateOptions.qrcode) && ( <> Barcode {templateOptions.codeType !== 'B' && (

{currentCode}

)} ) ); }, [templateOptions, multiProduct, barcodeBase64, qrBase64, prodId] ); const onComplete = useCallback(() => { setMessageType(null); setMessageData(null); }, []); return ( Loading ...}>
{ setSearchText(e.target.value); setCurrentPage(1); }} />
Note: Click on a row to modify the product details
({ onClick: () => record.prodId && setEditingKey(record.key), })} ownPagination={true} pagination={{ current: currentPage, onChange: handlePageChange, total: searchText != null && searchText != '' ? filteredProducts?.length : (dataSource[dataSource.length - 1]?.totalProducts || 0) + 1, pageSize: 11, showSizeChanger: false, hideOnSinglePage: true, }} bordered />
{stickerPrintModalOpen && ( {}} selectedRecords={null} coresdata={crossData} dropdownValue={dropdownValue} CoresOnChange={CoresOnChange} barcodeTemplateDetails={barcodeTemplateDetails} detail={labelPrintData} proName={labelPrintData?.productName} nickName={nickName} ProdId={ labelPrintData?.shortCode + '' + labelPrintData?.sellingPrice } size={labelPrintData?.size} // valueStyleColumn={valueStyleColumn} // secondValueStyle={secondValueStyle} // valueStyleRow={valueStyleRow} CopiesOnChange={CopiesOnChange} printProductName={printProductName} totalCopies={null} setstockWiseQrcode={null} setProductWiseQrcode={null} setNickName={setNickName} templateOptions={templateOptions} /> )} {printReady && ( generateQRCodeCopy(null, code)} generateCodeImage={(code, codeType = 'Q') => generateCodeImage(code, codeType, null) } imageTagBarcodeAndQR={imageTagBarcodeAndQR} dropdownValue={dropdownValue} barcodeTemplateDetails={barcodeTemplateDetails} /> )}
); }; export default DirectSale;