import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Table, Input, Select, Button } from 'antd'; import { PlusOutlined, 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 StickerPrintTemplates from '../../../Product/StickerTemplates.jsx'; import useBarcodeGenerator from './useBarcodeQRGenerator.js'; 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 (
{ 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;