Android_Retail/src/Pages/ComboPack/ComboMasterlist.jsx

981 lines
26 KiB
JavaScript

import React, {
useCallback,
useEffect,
useState,
useRef,
useContext,
} from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { Space } from 'antd';
import {
EditFilled,
DeleteFilled,
PlusOutlined,
ReloadOutlined,
PrinterFilled,
} from '@ant-design/icons';
import { Messages } from '../../Components/Notifications/Messages';
import { Search } from '../../Components/Forms/Search';
import {
changeBreadCrumb,
getEmpAccess,
} from '../../Features/AppPage/CenterPage.js';
import Buttons from '../../Components/Forms/Buttons';
import { getSession, printDiv, validateSafeInput } from '../../Services/Others';
import {
deleteCombo,
putComboName,
getCombolist,
} from '../../Features/ComboMaster/ComboMaster.js';
import FormHeader from '../PageComponents/FormHeader.jsx';
import { IoEye } from 'react-icons/io5';
import { Table, Form, Input } from 'antd';
import { DefaultModal } from '../../Components/Modal/DefaultModal.jsx';
import { useAuth } from '../../AuthContext.jsx';
import { DropDowns } from '../../Components/Forms/DropDown.jsx';
import { InputField } from '../../Components/Forms/InputField.jsx';
import QRCode from 'qrcode';
const subDirectory = import.meta.env.ENV_BASE_URL;
const items = [
{
name: 'Home',
link: `${subDirectory}app-page/home`,
},
{
name: 'ComboProduct',
link: `${subDirectory}setting/combo-master`,
},
];
const ComboList = () => {
const { SadminuserAccess } = useAuth();
let SAAccessCommonMaster = SadminuserAccess?.find(
(e) => e?.MenuName === 'Add Product'
);
console.log(SadminuserAccess, 'SadminuserAccessSadminuserAccess');
const navigateTo = useNavigate();
const dispatch = useDispatch();
const location = useLocation();
const formRef = useRef(null);
const [form] = Form.useForm();
const CompId = getSession('CompId');
const BranchId = getSession('BranchId');
const AppId = getSession('AppId');
const UserId = getSession('UserId');
const UserType = getSession('UserType');
const [tabledata, setTabledata] = useState([]);
const [messageType, setMessageType] = useState(null);
const [messageData, setMessageData] = useState(null);
const [filteredInfo, setFilteredInfo] = useState({});
const [searchedText, setSearchedText] = useState('');
const [sortedInfo, setSortedInfo] = useState({});
const [page, setpage] = useState(1);
const [OrderProductdata, setOrderProductdata] = useState([]);
const [OrderDataModel, setOrderDataModal] = useState(false);
const [editableRowIndex, setEditableRowIndex] = useState(null);
const [empData, setEmpData] = useState();
const [addnewAccess, setaddnewAccess] = useState(true);
const [proName, setProName] = useState();
const [ProdId, setProdId] = useState();
const [open, setOpen] = useState(false);
const [dropdownValue, setDropdownValue] = useState();
const [copies, setCopies] = useState();
const [base64Image, setBase64Image] = useState(null);
const [qrCodeUrl, setQrCodeUrl] = useState('');
console.log(tabledata, 'tabledatatabledata');
const handelAddButton = () => {
navigateTo(`${subDirectory}setting/combo-master/new`);
};
const Coresdata = [
{
option: '15X15 6cross',
id: 0,
},
{
option: '22X35 3cross',
id: 1,
},
{
option: '25X25 4cross',
id: 2,
},
{
option: '25X50 2cross',
id: 3,
},
];
useEffect(() => {
try {
if (location?.state?.Notiffy) {
setMessageType(location?.state?.Notiffy.messageType);
setMessageData(location?.state?.Notiffy.messageData);
}
} catch (err) {
console.log(err, 'err');
}
}, []);
const handleChange = (pagination, filters, sorter) => {
setFilteredInfo(filters);
setSortedInfo(sorter);
};
const handlePageChange = (current) => {
setpage(current);
};
useEffect(() => {
dispatch(changeBreadCrumb({ items: items }));
TableData();
// if (UserType === "Employee") {
// fetchApi()
// }
}, []);
useEffect(() => {
if (UserType === 'Employee') {
fetchApi();
}
}, [UserType]);
useEffect(() => {
let hasAccess = false;
if (UserType === 'Admin' || UserType === 'Super Admin') {
hasAccess = true;
} else if (UserType === 'Employee') {
hasAccess = empData?.AddAccess === 'Y';
} else if (UserType === 'Super Admin User') {
hasAccess = SAAccessCommonMaster?.AddAccess === 'Y';
}
setaddnewAccess(!hasAccess);
}, [empData, SAAccessCommonMaster, UserType]);
useEffect(() => {
QRCode?.toDataURL(ProdId)
.then((url) => {
setQrCodeUrl(url);
})
.catch((error) => {
console.error('Error generating QR code:', error);
});
}, [ProdId]);
useEffect(() => {
async function fetchImage() {
try {
const base64 = await imageUrlToBase64(qrCodeUrl);
setBase64Image(base64);
} catch (error) {
setConversionError(error.message || 'Error converting image');
}
}
if (qrCodeUrl) {
fetchImage();
}
}, [qrCodeUrl]);
const imageUrlToBase64 = async (url) => {
try {
const response = await fetch(url);
const blob = await response.blob();
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
} catch (error) {
console.error('Error fetching or converting image:', error);
throw error;
}
};
const fetchApi = async () => {
let data = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
EmpId: UserId,
};
let response = await dispatch(getEmpAccess(data)).unwrap();
let datas = response?.data?.data?.[0]?.EmpAccessDetails?.filter(
(item) => item.ConfigName === 'Add Product'
);
setEmpData(datas?.[0]);
};
// GETTTING TABLE GET
const TableData = async () => {
let data = { CompId: CompId, BranchId: BranchId, AppId: AppId };
let response = await dispatch(getCombolist(data)).unwrap();
if (response?.data?.statusCode == 1) {
setTabledata(
response?.data?.data?.filter((item) => item.ActiveStatus == 'A')
);
}
};
//EDIT FUNCTION
const actionsFormatter = (row, rowIndex) => {
setEditableRowIndex(rowIndex);
let tabledatasss = tabledata.map((item) => ({
...item,
key: `${item.ComboId}`,
}));
setTabledata(tabledatasss);
};
const onSearch = (value) => {
setSearchedText(value);
};
const onSearchChange = (e) => {
setSearchedText(e?.target?.value);
};
const statusFormatter = async (row) => {
let deleteData = {
ComboId: row.ComboId,
ComboInwardDetails: row.ComboInwardDetails,
UpdatedBy: UserId,
};
let response = await dispatch(deleteCombo(deleteData)).unwrap();
if (response?.data?.statusCode == 1) {
TableData();
setMessageType('success');
setMessageData(
row.ActiveStatus === 'A'
? 'In-Activated Successfully'
: 'Activated Successfully'
);
await dispatch(
getCombolist({
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
ActiveStatus: 'A',
})
).unwrap();
} else {
setMessageType('error');
setMessageData('Operation failed. Please try again.');
}
};
const onComplete = useCallback(() => {
setMessageData(null);
setMessageType(null);
}, []);
const ViewOrderdetails = (ComboDetails, record, ComboInwardDetails) => {
setOrderProductdata(ComboDetails);
setOrderDataModal(true);
};
const handleOrdermodalCancel = () => {
setOrderDataModal(false);
setOrderProductdata([]);
};
const OrderdataColumns = [
{
title: 'Sl.No',
key: 'sno',
align: 'center',
width: '60px',
render: (text, object, index) => (
<a style={{ color: 'black' }}>{(page - 1) * 10 + index + 1}</a>
),
},
{
title: 'Batch No',
dataIndex: 'ComboInwardDtlId',
key: 'ComboInwardDtlId',
align: 'left',
render: (text, record) => <a style={{ color: 'black' }}>{text}</a>,
},
{
title: 'Count',
dataIndex: 'ReceivedQty',
key: 'ReceivedQty',
align: 'right',
render: (text, record) => <a style={{ color: 'black' }}>{text}</a>,
},
{
title: 'Product Name',
dataIndex: 'ProdName',
key: 'ProdName',
align: 'left',
render: (text, record) => (
<div>
{record.ComboDetails.map((detail, idx) => (
<a
key={idx}
style={{ color: 'black', display: 'block', marginBottom: '4px' }}
>
{`${detail.ProdName} - ${detail.ProductQty}`}{' '}
{detail.VariantName && `(${detail.VariantName}) `}
</a>
))}
</div>
),
},
{
title: 'UOM',
dataIndex: 'UOM',
key: 'UOM',
width: '100px',
align: 'center',
render: (text, record) => (
<div>
{record.ComboDetails.map((detail, idx) => (
<a
style={{ color: 'black', display: 'block', marginBottom: '4px' }}
>
{' '}
{detail.Size} ({detail.UomName})
</a>
))}
</div>
),
},
];
const EditableCell = ({
title,
editable,
children,
dataIndex,
record,
index, // Add index to props to identify the row
handleSave,
editableRowIndex, // Pass the editable row index
setEditableRowIndex, // Function to set editable row index
...restProps
}) => {
const [editing, setEditing] = useState(false);
const inputRef = useRef(null);
const form = useContext(EditableContext);
// useEffect(() => {
// if (editable && index === editableRowIndex ) {
// form.setFieldsValue({ [dataIndex]: record[dataIndex] });
// setEditing(true); // Enter edit mode
// }
// // if (editing) {
// // inputRef?.current?.focus();
// // }
// }, [editableRowIndex, index, dataIndex, editable, editing, record, form]);
useEffect(() => {
if (editable && index === editableRowIndex) {
form.setFieldsValue({ [dataIndex]: record[dataIndex] });
setEditing(true); // Enter edit mode
inputRef?.current && inputRef?.current?.focus();
}
// if (editing) {
// inputRef?.current?.focus();
// }
}, [editableRowIndex, index, dataIndex, editable, editing, record, form]);
const toggleEdit = () => {
setEditing(!editing);
form.setFieldsValue({
[dataIndex]: record[dataIndex],
});
};
const save = async () => {
try {
const values = await form.validateFields();
toggleEdit();
setEditing(false); // Stop editing after save
setEditableRowIndex(null);
handleSave({
...record,
...values,
});
} catch (errInfo) {
console.log('Save failed:', errInfo);
}
};
let childNode = children;
if (editable && index === editableRowIndex) {
childNode = editing ? (
<Form.Item
style={{ margin: 0 }}
name={dataIndex}
// rules={[
// {
// pattern: /^\d*\.?\d+$/,
// message: "Please enter numbers only.",
// },
// ]}
>
<Input
ref={inputRef}
onPressEnter={save}
onBlur={save}
value={
Array.isArray(record[dataIndex]) ? undefined : record[dataIndex]
}
/>
</Form.Item>
) : (
<div
className="editable-cell-value-wrap"
style={{ paddingRight: 24 }}
onClick={toggleEdit}
>
{children}
</div>
);
}
return <td {...restProps}>{childNode}</td>;
};
const EditableContext = React.createContext(null);
const EditableRow = ({ index, ...props }) => {
const [form] = Form.useForm();
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
</Form>
);
};
const handleSave = async (row) => {
const newData = [...tabledata]; // Clone the current table data
const index = newData.findIndex((item) => row.key === item.key); // Find the row by its key
if (index > -1) {
// Update the ComboName in the row
newData[index] = {
...newData[index],
ComboName: row.ComboName,
};
// Set the updated data back to the state
setTabledata(newData);
}
let changedcombo = newData.find((item) => item.key === row.key);
let putdata = {
ComboName: changedcombo.ComboName,
ComboId: changedcombo.ComboId,
ValidFrom: changedcombo.ValidFrom,
ValidTo: changedcombo.ValidTo,
UpdatedBy: UserId,
};
let res = await dispatch(putComboName(putdata)).unwrap();
if (res?.data?.statusCode == 1) {
TableData();
setMessageType('success');
setMessageData(res?.data?.response);
} else {
setMessageType('error');
setMessageData(res?.data?.response);
TableData();
}
};
const components = {
body: {
row: EditableRow,
cell: EditableCell,
},
};
const defaultColumns = [
{
title: 'Sl.No',
key: 'sno',
align: 'center',
width: '60px',
render: (text, object, index) => (
<a style={{ color: 'black' }}>{(page - 1) * 10 + index + 1}</a>
),
},
{
title: 'Combo Name',
dataIndex: 'ComboName',
key: 'ComboName',
// width: "150px",
editable: true,
render: (text) => <a style={{ color: 'black' }}>{text}</a>,
filteredValue: [searchedText],
onFilter: (value, record) => {
return String(record.ComboName)
?.toLowerCase()
?.includes(value?.toLowerCase());
},
sorter: (a, b) => a?.TableName?.length - b?.TableName?.length,
sortOrder: sortedInfo.columnKey === 'TableName' ? sortedInfo.order : null,
ellipsis: true,
},
{
title: 'Combo Count',
dataIndex: 'SetCount',
key: 'SetCount',
align: 'right',
width: '120px',
render: (text) => <a style={{ color: 'black' }}>{text}</a>,
},
{
title: 'Product Details',
key: 'ComboInwardDetails',
dataIndex: 'ComboInwardDetails',
width: '200px',
align: 'center',
render: (ComboDetails, ComboInwardDetails, record) => (
<IoEye
style={{ color: '#1292EE', fontSize: '25px', cursor: 'pointer' }}
onClick={() =>
ViewOrderdetails(ComboDetails, record, ComboInwardDetails)
}
/>
),
},
{
title: 'QR Code',
key: 'QRCode',
dataIndex: 'QRCode',
align: 'center',
width: '200px',
render: (text, record) => (
<a style={{ color: 'black' }}>
{record.ComboInwardDetails?.[0]?.QRCode}
</a>
),
},
{
title: 'Print QRCode',
key: 'QRCode',
dataIndex: 'QRCode',
align: 'center',
width: '200px',
render: (_, record, index) => {
return (
<Space size="middle">
{record.ComboInwardDetails?.[0].QRCode ? (
<a>
<PrinterFilled
style={{ fontSize: '20px' }}
onClick={() => {
Qrcode(record);
}}
/>
</a>
) : (
'-'
)}
</Space>
);
},
},
{
title: 'Action',
key: 'Action',
dataIndex: 'Action',
align: 'center',
width: '100px',
render: (_, record, index) =>
tabledata.length >= 1 ? (
<Space size="middle">
{record.ActiveStatus === 'A' ? (
<a>
<EditFilled
style={{ color: '#1292EE' }}
onClick={() =>
UserType === 'Super Admin' ||
(UserType === 'Super Admin User' &&
SAAccessCommonMaster?.UpdateAccess === 'Y') ||
(UserType === 'Employee' &&
empData?.UpdateAccess === 'Y') ||
UserType === 'Admin'
? actionsFormatter(record, index)
: null
}
/>
</a>
) : (
''
)}
<a>
{record.ActiveStatus === 'A' ? (
<DeleteFilled
style={{
color: '#FF4D4F',
}}
onClick={() =>
UserType === 'Super Admin' ||
(UserType === 'Super Admin User' &&
SAAccessCommonMaster?.DeleteAccess === 'Y') ||
(UserType === 'Employee' &&
empData?.DeleteAccess === 'Y') ||
UserType === 'Admin'
? statusFormatter(record)
: null
}
/>
) : (
<ReloadOutlined
style={{
color: '#ff4d4f',
pointerEvents: 'none',
}}
/>
)}
</a>
</Space>
) : null,
},
];
const columns = defaultColumns?.map((col, index) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record, rowIndex) => ({
record,
editable: col.editable,
dataIndex: col.dataIndex,
title: col.title,
handleSave,
index: rowIndex, // Pass the row index
editableRowIndex, // Pass the current editable row index
setEditableRowIndex, //Pass the current editable row index
}),
};
});
const Qrcode = (record) => {
console.log(record, 'recordrecord');
setProName(record?.ComboName);
setProdId(record?.ComboInwardDetails?.[0]?.QRCode);
setOpen(true);
};
const CoresOnChange = (params) => {
setDropdownValue(params);
formRef.current?.setFieldsValue({ Cross: params });
};
const CopiesOnChange = (params) => {
setCopies(params);
formRef.current?.setFieldsValue({ Copies: params });
};
const style = `<style>
.heading
{
color: #1292EE;
}
.container
{
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.barcode
{
font-family:'Libre Barcode 39';
font-size: 4px;
}
.Sticker0
{
padding: 5px;
padding-left: 7px;
width:47px;
height:47px;
text-align: center;
font-size: 6px;
//border:1px solid black;
}
.Sticker1
{
padding: 5px ;
width:110px;
height:72px;
text-align: center;
font-size: 9px;
display:flex;
flex-direction:row;
}
.Sticker2
{
padding: 5px;
width:80px;
height:80px;
text-align: center;
font-size: 10px;
}
.Sticker3
{
padding: 5px;
width:170px;
height:86px;
text-align: center;
font-size: 12px;
display:flex;
flex-direction:row;
}
</style>`;
const Print = async () => {
switch (dropdownValue) {
case 0:
await printDiv('StickerPrint0', style);
break;
case 1:
await printDiv('StickerPrint1', style);
break;
case 2:
await printDiv('StickerPrint2', style);
break;
case 3:
await printDiv('StickerPrint3', style);
break;
default:
alert('! Select correct cross ');
}
};
return (
<div className="userPageTable">
<div className="userPageContent">
<div className="formAddNew">
<Messages
messageType={messageType}
messageData={messageData}
onComplete={onComplete}
/>
{/* <div>
<FormHeader title={'Combo Product'} />
</div> */}
<div className="searchAddDiv">
<div className="formSearch">
<Search
placeholder="Search"
onSearch={onSearch}
onSearchChange={onSearchChange}
/>
</div>
<Buttons
buttonText={'Add New'}
disabled={addnewAccess}
handleSubmit={() => handelAddButton()}
color="901D77"
icon={<PlusOutlined />}
>
OPEN
</Buttons>
</div>
</div>
<div className="reportTable comboProductList">
{/* <Tables
columns={columns}
data={tabledata}
dataSource={tabledata}
pagination={handlePageChange}
onChange={handleChange}
/> */}
<Form form={form} component={false}>
<Table
bordered
components={components}
rowClassName={() => 'editable-row'}
columns={columns}
dataSource={tabledata}
pagination={handlePageChange}
onChange={handleChange}
/>
</Form>
</div>
<DefaultModal
open={OrderDataModel}
title="Product Details"
handleCancel={handleOrdermodalCancel}
footer={false}
// width={1000}
children={
<div style={{ height: '400px', overflowY: 'scroll' }}>
<Table
dataSource={OrderProductdata}
columns={OrderdataColumns}
pagination={handlePageChange}
/>
</div>
}
/>
<DefaultModal
open={open}
title="Sticker Print"
handleCancel={() => {
setOpen(false);
}}
footer={false}
children={
<Form ref={formRef} onFinish={Print}>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '1rem' }}>
<Form.Item
name="Cross"
rules={[
{
required: true,
message: 'Please Enter Cross',
},
]}
>
<DropDowns
options={[
// { value: "Select", label: "All" }, // Add "Select" option
...Coresdata?.map((item) => ({
value: item.id,
label: item.option,
})),
]}
placeholder="Please Enter Cross"
label={<label class="required">Cross</label>}
optionsNames={{ value: 'option', label: 'option' }}
className="field-DropDown"
isOnchanges={true}
onChangeFunction={(e) => {
CoresOnChange(e);
}}
valueData={dropdownValue}
defaultValue="Select" // Set "Select" as the default value
/>
</Form.Item>
<Form.Item
name="Copies"
rules={[
{
required: true,
pattern: /^[1-9]\d*(\.\d+)?$/,
message: 'Please Enter Copies',
},
{
validator: async (_, value) => {
await validateSafeInput(value); // To block HTML tags & SQL keywords
return Promise.resolve();
},
},
]}
>
<InputField
autoComplete="off"
label={<label class="required">Copies</label>}
isOnChange={false}
onChange={(e) => {
CopiesOnChange(e?.target?.value);
}}
/>
</Form.Item>
</div>
<div
style={{
width: '100%',
display: 'flex',
justifyContent: 'flex-end',
}}
>
<Buttons
buttonText={'Submit'}
color="901D77"
disabled={addnewAccess}
></Buttons>
</div>
</Form>
}
/>
<div style={{ display: 'none' }}>
<div id="StickerPrint0">
<div className="container">
{Array.from({ length: copies }).map((_, index) => (
<div className="Sticker0" key={`sticker0-${index}`}>
<img
src={base64Image}
style={{ width: '52px', height: '52px' }}
/>
</div>
))}
</div>
</div>
<div id="StickerPrint1">
<div className="container">
{Array.from({ length: copies }).map((_, index) => (
<div className="Sticker1" key={`sticker1-${index}`}>
<div>
<p>{proName} </p>
<p>{ProdId}</p>
</div>
<img
src={base64Image}
style={{ width: '52px', height: '52px' }}
/>
</div>
))}
</div>
</div>
<div id="StickerPrint2">
<div className="container">
{Array.from({ length: copies }).map((_, index) => (
<div className="Sticker2" key={`sticker2-${index}`}>
<p style={{ marginTop: '-3px' }}>{proName} </p>
<img
src={base64Image}
style={{ width: '35px', height: '35px' }}
/>
<p>{ProdId}</p>
</div>
))}
</div>
</div>
<div id="StickerPrint3">
<div className="container">
{Array.from({ length: copies }).map((_, index) => (
<div className="Sticker3" key={`sticker3-${index}`}>
<div>
<p>{proName} </p>
<p>{ProdId}</p>
</div>
<img
src={base64Image}
style={{ width: '75px', height: '75px' }}
/>
</div>
))}
</div>
</div>
</div>
</div>
</div>
);
};
export default ComboList;