Android_Retail/src/Pages/TableMapping/TableMapping.jsx

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;