538 lines
20 KiB
JavaScript
538 lines
20 KiB
JavaScript
import React, { useCallback, useEffect, useState } from 'react';
|
|
import { useDispatch } from 'react-redux';
|
|
import { Space, Checkbox } from 'antd';
|
|
import {
|
|
EditFilled,
|
|
DeleteFilled,
|
|
PlusOutlined,
|
|
CheckOutlined,
|
|
CloseOutlined,
|
|
} from '@ant-design/icons';
|
|
import { Messages } from '../../Components/Notifications/Messages';
|
|
import { Tables } from '../../Components/Tables/Table';
|
|
import {
|
|
changeBreadCrumb,
|
|
getEmpAccess,
|
|
} from '../../Features/AppPage/CenterPage.js';
|
|
import Buttons from '../../Components/Forms/Buttons';
|
|
import { ExtractDateFormate, getSession } from '../../Services/Others';
|
|
import {
|
|
getDineinTableData,
|
|
} from '../../Features/Dinein/Dinein';
|
|
import FormHeader from '../PageComponents/FormHeader.jsx';
|
|
import { useAuth } from '../../AuthContext.jsx';
|
|
import '../../Styles/OverAllStyle/OverAllStyle.scss';
|
|
import { DropDowns } from '../../Components/Forms/DropDown.jsx';
|
|
import { getServerNames } from '../../Features/TableBooking/TableBooking.js';
|
|
import {
|
|
getTableMappings,
|
|
postTableMapping,
|
|
putTableMapping,
|
|
} from '../../Features/TableMapping/TableMapping.js';
|
|
import { useLocation, useNavigate } from 'react-router-dom';
|
|
import "./TableMapping.scss"
|
|
|
|
const subDirectory = import.meta.env.ENV_BASE_URL;
|
|
const items = [
|
|
{
|
|
name: 'Home',
|
|
link: `${subDirectory}app-page/home`,
|
|
},
|
|
|
|
{
|
|
name: 'TableMapping',
|
|
link: `${subDirectory}setting/TableMapping`,
|
|
},
|
|
{
|
|
name: 'new',
|
|
link: `${subDirectory}setting/TableMapping/update`,
|
|
},
|
|
];
|
|
|
|
const TableMapping = ({ formType }) => {
|
|
const { SadminuserAccess } = useAuth();
|
|
let SAAccessCommonMaster = SadminuserAccess?.find(
|
|
(e) => e?.MenuName === 'Dine In'
|
|
);
|
|
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
const state = location?.state;
|
|
const editstate = state?.editstate;
|
|
const CompId = getSession('CompId');
|
|
const BranchId = getSession('BranchId');
|
|
const AppId = getSession('AppId');
|
|
const UserId = getSession('UserId');
|
|
const UserType = getSession('UserType');
|
|
|
|
const dispatch = useDispatch();
|
|
const [ServerNames, setServerNames] = useState();
|
|
const [tabledata, setTabledata] = useState();
|
|
const [waiterId, setWaiterId] = useState();
|
|
const [messageType, setMessageType] = useState(null);
|
|
const [messageData, setMessageData] = useState(null);
|
|
const [empData, setEmpData] = useState();
|
|
|
|
const [selectedTables, setSelectedTables] = useState([]);
|
|
const [selectAllTables, setSelectAllTables] = useState(false);
|
|
const [mappingData, setMappingData] = useState([]);
|
|
const [formErrors, setFormErrors] = useState({});
|
|
const [editingMapping, setEditingMapping] = useState(null);
|
|
console.log(editstate, "mappingData")
|
|
|
|
useEffect(() => {
|
|
if (editstate && tabledata && ServerNames) {
|
|
// Initialize form with edit data
|
|
setWaiterId(editstate?.WaiterId);
|
|
const tableIds = editstate?.TableDtls?.map(table => table.TableId) || [];
|
|
setSelectedTables(tableIds);
|
|
|
|
// Set select all if all tables are selected
|
|
if (tableIds.length === tabledata?.length) {
|
|
setSelectAllTables(true);
|
|
}
|
|
|
|
// Create mapping object for the table and set it as the editing mapping
|
|
const waiterName = ServerNames?.find(server => server.UniqueId === editstate?.WaiterId)?.EmpFirstName || '';
|
|
const selectedTableNames = tabledata?.filter(table => tableIds.includes(table.TableId))
|
|
.map(table => table.TableName) || [];
|
|
|
|
const existingMapping = {
|
|
id: editstate?.UniqueId || Date.now(), // Use UniqueId from editstate
|
|
WaiterId: editstate?.WaiterId,
|
|
UniqueId: editstate?.UniqueId,
|
|
WaiterName: waiterName,
|
|
TableIds: tableIds,
|
|
TableNames: selectedTableNames,
|
|
CreatedAt: editstate?.CreatedAt || new Date().toISOString(),
|
|
UpdatedAt: new Date().toISOString()
|
|
};
|
|
|
|
// Set this as the current mapping data and editing mapping
|
|
setMappingData([existingMapping]);
|
|
setEditingMapping(existingMapping);
|
|
}
|
|
}, [editstate, tabledata, ServerNames]);
|
|
|
|
useEffect(() => {
|
|
dispatch(changeBreadCrumb({ items: items }));
|
|
TableData();
|
|
getEmpAccessData();
|
|
}, []);
|
|
|
|
const getEmpAccessData = useCallback(async () => {
|
|
let data = {
|
|
MenuName: 'Dine In',
|
|
UserId: getSession('UserId'),
|
|
CompId: getSession('CompId'),
|
|
BranchId: getSession('BranchId'),
|
|
AppId: getSession('AppId'),
|
|
};
|
|
let response = await dispatch(getEmpAccess(data)).unwrap();
|
|
setEmpData(response?.data?.data);
|
|
}, [dispatch]);
|
|
|
|
const onComplete = () => {
|
|
setMessageType(null);
|
|
setMessageData(null);
|
|
};
|
|
|
|
const TableData = async () => {
|
|
try {
|
|
// Load table data
|
|
let response = await dispatch(
|
|
getDineinTableData({ CompId: CompId, BranchId: BranchId, AppId: AppId })
|
|
).unwrap();
|
|
|
|
if (response?.data?.statusCode == 1) {
|
|
setTabledata(response?.data?.data);
|
|
}
|
|
|
|
// Load server/waiter data
|
|
let data = {
|
|
ActiveStatus: "A",
|
|
CompId: CompId,
|
|
BranchId: BranchId,
|
|
AppId: AppId,
|
|
};
|
|
let Response = await dispatch(getServerNames(data)).unwrap();
|
|
setServerNames(Response?.data?.data);
|
|
|
|
// Load existing mappings
|
|
// await loadMappingData();
|
|
} catch (error) {
|
|
console.error('Error loading data:', error);
|
|
setMessageType('error');
|
|
setMessageData('Failed to load data');
|
|
}
|
|
};
|
|
|
|
|
|
const WaitherSelect = (e) => {
|
|
setWaiterId(e);
|
|
if (e) {
|
|
setFormErrors(prev => ({ ...prev, waiterId: null }));
|
|
}
|
|
};
|
|
|
|
const handleSelectAllTables = (checked) => {
|
|
setSelectAllTables(checked);
|
|
if (checked) {
|
|
const allTableIds = tabledata?.map(table => table.TableId) || [];
|
|
setSelectedTables(allTableIds);
|
|
} else {
|
|
setSelectedTables([]);
|
|
}
|
|
};
|
|
|
|
const handleTableSelection = (tableIds) => {
|
|
setSelectedTables(tableIds);
|
|
setSelectAllTables(tableIds.length === tabledata?.length);
|
|
if (tableIds.length > 0) {
|
|
setFormErrors(prev => ({ ...prev, selectedTables: null }));
|
|
}
|
|
};
|
|
|
|
const validateForm = () => {
|
|
const errors = {};
|
|
|
|
if (!waiterId) {
|
|
errors.waiterId = 'Please select a waiter';
|
|
}
|
|
|
|
if (selectedTables.length === 0) {
|
|
errors.selectedTables = 'Please select at least one table';
|
|
}
|
|
|
|
// Check for duplicate mappings, but exclude the current editing mapping
|
|
const existingMapping = mappingData.find(mapping =>
|
|
mapping.WaiterId === waiterId &&
|
|
mapping.TableIds.some(tableId => selectedTables.includes(tableId)) &&
|
|
(!editingMapping || mapping.id !== editingMapping.id) // Exclude current editing mapping
|
|
);
|
|
|
|
if (existingMapping) {
|
|
errors.duplicate = 'This waiter is already assigned to one or more of the selected tables';
|
|
}
|
|
|
|
setFormErrors(errors);
|
|
return Object.keys(errors).length === 0;
|
|
};
|
|
|
|
const handleSaveMapping = () => {
|
|
if (!validateForm()) {
|
|
setMessageType('error');
|
|
setMessageData('Please fix the validation errors');
|
|
return;
|
|
}
|
|
|
|
const waiterName = ServerNames?.find(server => server.UniqueId === waiterId)?.EmpFirstName || '';
|
|
const UniQueId = ServerNames?.find(server => server.UniqueId === waiterId)?.UniqueId || '';
|
|
const selectedTableNames = tabledata?.filter(table => selectedTables.includes(table.TableId))
|
|
.map(table => table.TableName) || [];
|
|
|
|
const newMapping = {
|
|
id: editingMapping ? editingMapping.id : Date.now(),
|
|
WaiterId: waiterId,
|
|
UniqueId: editingMapping ? editingMapping.UniqueId : UniQueId, // Preserve UniqueId for edit
|
|
WaiterName: waiterName,
|
|
TableIds: selectedTables,
|
|
TableNames: selectedTableNames,
|
|
CreatedAt: editingMapping ? editingMapping.CreatedAt : new Date().toISOString(),
|
|
UpdatedAt: new Date().toISOString()
|
|
};
|
|
|
|
let updatedMappings;
|
|
if (editingMapping) {
|
|
updatedMappings = mappingData.map(mapping =>
|
|
mapping.id === editingMapping.id ? newMapping : mapping
|
|
);
|
|
setMessageType('success');
|
|
setMessageData('Mapping updated successfully');
|
|
} else {
|
|
updatedMappings = [...mappingData, newMapping];
|
|
setMessageType('success');
|
|
setMessageData('Mapping added to table successfully');
|
|
}
|
|
|
|
setMappingData(updatedMappings);
|
|
|
|
// Reset form only if not in edit state
|
|
if (!editstate) {
|
|
setSelectAllTables(false);
|
|
setSelectedTables([]);
|
|
setWaiterId(null);
|
|
setEditingMapping(null);
|
|
setFormErrors({});
|
|
} else {
|
|
// In edit state, just clear the editing mapping to show updated data
|
|
setEditingMapping(null);
|
|
setFormErrors({});
|
|
}
|
|
};
|
|
|
|
const handleEditMapping = (mapping) => {
|
|
setEditingMapping(mapping);
|
|
setWaiterId(mapping.WaiterId);
|
|
setSelectedTables(mapping.TableIds);
|
|
setSelectAllTables(mapping.TableIds.length === tabledata?.length);
|
|
setFormErrors({});
|
|
};
|
|
|
|
const handleDeleteMapping = (mappingId) => {
|
|
const updatedMappings = mappingData.filter(mapping => mapping.id !== mappingId);
|
|
setMappingData(updatedMappings);
|
|
setMessageType('success');
|
|
setMessageData('Mapping removed from table successfully');
|
|
};
|
|
|
|
|
|
|
|
const handleFinalSubmit = async () => {
|
|
if (mappingData.length === 0) {
|
|
setMessageType('error');
|
|
setMessageData('No mappings to save. Please add at least one mapping.');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
let postData = {
|
|
"CompId": CompId,
|
|
"BranchId": BranchId,
|
|
"AppId": AppId,
|
|
"waiterTableDtls": mappingData.map((item) => ({
|
|
...(editstate ? { "UniqueId": item?.UniqueId, } : {}),
|
|
"WaiterId": item?.WaiterId,
|
|
"TableDtls": item?.TableIds.map(id => ({ "TableId": id }))
|
|
|
|
})
|
|
),
|
|
...(!editstate ? { "CreatedBy": UserId, } : {}),
|
|
...(editstate ? { "UpdatedBy": UserId } : {}),
|
|
|
|
|
|
}
|
|
let response
|
|
if (editstate) {
|
|
response = await dispatch(putTableMapping(postData)).unwrap()
|
|
}
|
|
else {
|
|
response = await dispatch(postTableMapping(postData)).unwrap()
|
|
}
|
|
|
|
if (response?.data?.statusCode === 1) {
|
|
setMessageType('success');
|
|
setMessageData(response?.data?.response);
|
|
navigate(`${subDirectory}setting/TableMapping`);
|
|
setMappingData([]);
|
|
}
|
|
else {
|
|
throw new Error('Some mappings failed to save');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error saving mappings:', error);
|
|
setMessageType('error');
|
|
setMessageData('Failed to save mappings. Please try again.');
|
|
}
|
|
};
|
|
|
|
// Updated columns for mapping data display
|
|
const mappingColumns = [
|
|
{
|
|
title: 'Sl.No',
|
|
key: 'sno',
|
|
align: 'center',
|
|
width: '80px',
|
|
render: (_, __, index) => (
|
|
<span style={{ color: 'black' }}>{index + 1}</span>
|
|
),
|
|
},
|
|
{
|
|
title: 'Captain Name',
|
|
dataIndex: 'WaiterName',
|
|
key: 'WaiterName',
|
|
width: '200px',
|
|
render: (text) => <span style={{ color: 'black' }}>{text}</span>,
|
|
},
|
|
{
|
|
title: 'Assigned Tables',
|
|
dataIndex: 'TableNames',
|
|
key: 'TableNames',
|
|
width: '300px',
|
|
render: (tableNames) => (
|
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '4px' }}>
|
|
{tableNames?.map((tableName, index) => (
|
|
<span
|
|
key={index}
|
|
style={{
|
|
backgroundColor: '#f0f0f0',
|
|
padding: '2px 8px',
|
|
borderRadius: '4px',
|
|
fontSize: '12px',
|
|
color: '#333'
|
|
}}
|
|
>
|
|
{tableName}
|
|
</span>
|
|
))}
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
title: 'Created At',
|
|
dataIndex: 'CreatedAt',
|
|
key: 'CreatedAt',
|
|
width: '150px',
|
|
render: (date) => (
|
|
<span style={{ color: 'black' }}>
|
|
{ExtractDateFormate(new Date(date).toLocaleDateString())}
|
|
</span>
|
|
),
|
|
},
|
|
{
|
|
title: 'Action',
|
|
key: 'Action',
|
|
width: '120px',
|
|
render: (_, record) => (
|
|
<Space size="middle">
|
|
<EditFilled
|
|
style={{ color: '#1292EE', cursor: 'pointer' }}
|
|
onClick={() => handleEditMapping(record)}
|
|
title="Edit Mapping"
|
|
/>
|
|
<DeleteFilled
|
|
style={{ color: '#FF4D4F', cursor: 'pointer' }}
|
|
onClick={() => handleDeleteMapping(record.id)}
|
|
title="Delete Mapping"
|
|
/>
|
|
</Space>
|
|
),
|
|
},
|
|
];
|
|
|
|
return (
|
|
<div className="userPageTable TableMappingMaster">
|
|
<div className="userPageContent">
|
|
<div>
|
|
<FormHeader title={'Table Mapping'} />
|
|
</div>
|
|
<div className="formAddNew">
|
|
<Messages
|
|
messageType={messageType}
|
|
messageData={messageData}
|
|
onComplete={onComplete}
|
|
/>
|
|
|
|
{/* Enhanced Mapping Form */}
|
|
<div className="mapping-form" >
|
|
<div className='mapping-form2'>
|
|
<div >
|
|
<DropDowns
|
|
options={[
|
|
// { value: "", label: "Select Captain" },
|
|
...(ServerNames || [])?.map((option) => ({
|
|
value: option.UniqueId,
|
|
label: option.EmpFirstName,
|
|
})),
|
|
]}
|
|
disabled={editstate}
|
|
defaultValue={waiterId}
|
|
valueData={waiterId}
|
|
label="Select Captain"
|
|
onChangeFunction={(e) => WaitherSelect(e)}
|
|
isOnchanges={waiterId ? true : false}
|
|
className="field-DropDown"
|
|
/>
|
|
{formErrors.waiterId && (
|
|
<div style={{ color: '#ff4d4f', fontSize: '12px', marginTop: '4px' }}>
|
|
{formErrors.waiterId}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div style={{ minWidth: '300px' }}>
|
|
{/* Select All Checkbox */}
|
|
|
|
|
|
{/* Table Selection Checkboxes */}
|
|
<div className='TablCheckboxeseSelection'>
|
|
<div style={{ marginBottom: '16px' }}>
|
|
<Checkbox
|
|
checked={selectAllTables}
|
|
onChange={(e) => handleSelectAllTables(e.target.checked)}
|
|
style={{ fontWeight: '500' }}
|
|
>
|
|
Select All Tables
|
|
</Checkbox>
|
|
</div>
|
|
<Checkbox.Group
|
|
value={selectedTables}
|
|
onChange={handleTableSelection}
|
|
style={{ width: '100%', display: "flex", gap: "1rem" }}
|
|
>
|
|
<div style={{ display: 'flex', gap: '4px', alignItems: "center", flexWrap: "wrap" }}>
|
|
{tabledata?.map((table) => (
|
|
<Checkbox
|
|
key={table.TableId}
|
|
value={table.TableId}
|
|
style={{ margin: 0 }}
|
|
>
|
|
{table.TableName}
|
|
</Checkbox>
|
|
))}
|
|
</div>
|
|
</Checkbox.Group>
|
|
</div>
|
|
|
|
{formErrors.selectedTables && (
|
|
<div style={{ color: '#ff4d4f', fontSize: '12px', marginTop: '4px' }}>
|
|
{formErrors.selectedTables}
|
|
</div>
|
|
)}
|
|
{formErrors.duplicate && (
|
|
<div style={{ color: '#ff4d4f', fontSize: '12px', marginTop: '4px' }}>
|
|
{formErrors.duplicate}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div style={{ display: 'flex', gap: '8px', width: "100%", justifyContent: "flex-end" }}>
|
|
<Buttons
|
|
buttonText={editingMapping ? 'Update Mapping' : 'Save Mapping'}
|
|
handleSubmit={handleSaveMapping}
|
|
disabled={!waiterId || selectedTables.length === 0}
|
|
color="901D77"
|
|
icon={editingMapping ? <CheckOutlined /> : <PlusOutlined />}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Mapping Data Table */}
|
|
<div className="reportTable">
|
|
<Tables
|
|
columns={mappingColumns}
|
|
data={mappingData}
|
|
dataSource={mappingData}
|
|
pagination={false}
|
|
/>
|
|
{((!editstate && !editingMapping) || (editstate)) && mappingData.length > 0 && (
|
|
<div style={{ display: 'flex', gap: '8px', float: "right", marginRight: "1rem" }}>
|
|
<Buttons
|
|
buttonText="Save All Mappings"
|
|
handleSubmit={handleFinalSubmit}
|
|
color="28a745"
|
|
icon={<CheckOutlined />}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div >
|
|
);
|
|
};
|
|
|
|
export default TableMapping;
|