import React, { useState, useEffect } from "react"; import { Modal, Radio, message, Checkbox, Button, Tag } from "antd"; import { BiGitMerge } from "react-icons/bi"; import { PlusOutlined, DeleteOutlined } from "@ant-design/icons"; import { useDispatch } from "react-redux"; import { getAllDineInTable, getSelfBookingOrderId, postMergeOrders } from "../../../Features/TableBooking/TableBooking"; import { getSession } from "../../../Services/Others"; import { DropDowns } from "../../../Components/Forms/DropDown"; import "./MergeBill.scss"; const MergeBill = (getDiningTypefun) => { const dispatch = useDispatch(); const AppId = getSession("AppId"); const CompId = getSession("CompId"); const BranchId = getSession("BranchId"); const [mergeModalVisible, setMergeModalVisible] = useState(false); const [AllTableData, setAllTableData] = useState([]); const [isLoading, setIsLoading] = useState(false); // New state for multiple selections const [selectedItems, setSelectedItems] = useState([ { id: 1, type: 'table', tableId: null, chairIds: [], orderId: null, orderIds: [], // Fixed: Initialize orderIds array tableData: null }, { id: 2, type: 'table', tableId: null, chairIds: [], orderId: null, orderIds: [], // Fixed: Initialize orderIds array tableData: null } ]); useEffect(() => { const fetchTables = async () => { try { let data = { AppId, CompId, BranchId }; let Response = await dispatch(getAllDineInTable(data)).unwrap(); if (Response?.data?.statusCode === 1) { setAllTableData(Response?.data?.data); } } catch (error) { console.error("Error fetching tables:", error); message.error("Failed to fetch table data"); } }; fetchTables(); }, [dispatch, AppId, CompId, BranchId]); const openModal = () => setMergeModalVisible(true); const closeModal = () => { setMergeModalVisible(false); // Reset all states setSelectedItems([ { id: 1, type: 'table', tableId: null, chairIds: [], orderId: null, orderIds: [], tableData: null }, { id: 2, type: 'table', tableId: null, chairIds: [], orderId: null, orderIds: [], tableData: null } ]); }; // Filter tables that have at least one occupied chair const UnchoosenTables = AllTableData?.filter((table) => table?.ChairLevelSerDetails?.some((chair) => chair?.SalesStatus === "Y") ); // Add new selection item const addSelectionItem = () => { const newId = Math.max(...selectedItems.map(item => item.id)) + 1; setSelectedItems([...selectedItems, { id: newId, type: 'table', tableId: null, chairIds: [], orderId: null, orderIds: [], // Fixed: Initialize orderIds array tableData: null }]); }; // Remove selection item const removeSelectionItem = (id) => { if (selectedItems.length > 2) { setSelectedItems(selectedItems.filter(item => item.id !== id)); } }; // Update selection type (table/chair) const updateSelectionType = (id, type) => { setSelectedItems(selectedItems.map(item => item.id === id ? { ...item, type, chairIds: [], orderId: null, orderIds: [] } // Fixed: Reset orderIds array : item )); }; // Update table selection const updateTableSelection = (id, tableId) => { const selectedTableData = AllTableData?.find(table => table.TableId === tableId); setSelectedItems(selectedItems.map(item => { if (item.id === id) { let orderId = null; let orderIds = []; // Fixed: Initialize orderIds array if (item.type === 'table' && selectedTableData) { // For table merge, get first available order ID orderId = selectedTableData.ChairLevelSerDetails?.find(chair => chair.OrderId)?.OrderId || null; // For table, orderIds contains just the single order ID orderIds = orderId ? [orderId] : []; } return { ...item, tableId, tableData: selectedTableData, chairIds: [], orderId, orderIds // Fixed: Set orderIds array }; } return item; })); }; // Update chair selection (multiple chairs) const updateChairSelection = (id, chairIds) => { setSelectedItems(selectedItems.map(item => { if (item.id === id) { let orderIds = []; if (item.tableData && chairIds.length > 0) { // Get all order IDs from selected chairs orderIds = chairIds.map(chairId => { const chair = item.tableData.ChairLevelSerDetails?.find(c => c.ChairId === chairId); return chair?.OrderId; }).filter(Boolean); // Remove duplicates orderIds = [...new Set(orderIds)]; } return { ...item, chairIds, orderId: orderIds.length > 0 ? orderIds[0] : null, // Use first order ID for primary reference orderIds // Fixed: Store all unique order IDs for multi-chair merge }; } return item; })); }; // Get available tables for a specific selection (excluding already selected ones) const getAvailableTablesForSelection = (currentId, type) => { const selectedTableIds = selectedItems .filter(item => item.id !== currentId && item.tableId) .map(item => item.tableId); if (type === 'table') { return UnchoosenTables?.filter(table => !selectedTableIds.includes(table.TableId)); } else { return UnchoosenTables; // For chair selection, allow same table } }; const handleConfirmedMerge = async () => { try { // Validate selections - Fixed: Use orderIds array for validation const validSelections = selectedItems.filter(item => item.orderIds && item.orderIds.length > 0); if (validSelections.length < 2) { message.error('Please select at least 2 tables/chairs to merge'); return; } setIsLoading(true); // Fetch full order details for all selected orders const fetchOrderDetails = async (orderId) => { const data = { AppId, CompId, BranchId, orderId }; try { const response = await dispatch(getSelfBookingOrderId(data)).unwrap(); if (response?.data?.statusCode === 1 && response?.data?.data?.length > 0) { return response.data.data[0]; } throw new Error('Order not found'); } catch (err) { console.error(`Failed to fetch order details for ${orderId}:`, err); throw err; } }; // Collect all unique order IDs - Fixed: Use orderIds array const allOrderIds = []; validSelections.forEach(item => { allOrderIds.push(...item.orderIds); }); // Remove duplicates const uniqueOrderIds = [...new Set(allOrderIds)]; // Fetch all order details const orderDetailsPromises = uniqueOrderIds.map(orderId => fetchOrderDetails(orderId)); const orderDetails = await Promise.all(orderDetailsPromises); if (orderDetails.some(detail => !detail)) { message.error('Failed to fetch some order details'); return; } // Build merge data const MergeData = { CompId, BranchId, AppId, CreatedBy: 0, MergeRequest: 'A', DeviceUniqueId: '', MergeOrderDetails: orderDetails.map(data => ({ OrderId: data.OrderId, SalesId: data.SalesId || '', OrderType: data.OrderType || 'S', CustSuppId: data.CustSuppId || '', Reference: data.Reference || '', BookingType: data.BookingType || 0, ServiceProvider: data.ServiceProvider || 0, ActiveStatus: data.ActiveStatus || 'Y', RefundAmount: data.RefundAmount || 0, AddlInfo: data.AddlInfo || '', BillAmount: data.BillAmount || 0, OverallDiscSales: data.OverallDiscSales || 0, OverallDiscEst: data.OverallDiscEst || 0, TaxAmount: data.TaxAmount || 0, VatAmount: data.VatAmount || 0, NetAmount: data.NetAmount || 0, GivenAmt: data.GivenAmt || 0, BalGiven: data.BalGiven || 0, BookingMedia: data.BookingMedia || '', PaymentStatus: 'P', ServiceCategory: data.ServiceCategory || 0, OtherServiceTicketId: data.OtherServiceTicketId || '', OtherServiceTicketAmount: data.OtherServiceTicketAmount || 0, OrderDtlDetails: data.productDetails?.map(item => ({ ProdId: item.ProdId, Type: item.Type || '', OrderQty: item.OrderQty || 0, OrderRate: item.OrderRate || 0, TotalAmt: item.TotalAmt || 0, TaxAmt: item.TaxAmt || 0, RefundQty: item.RefundQty || 0, InwardDtlId: item.InwardDtlId || '', TaxId: item.TaxId || '', ProdNameQty: item.ProdNameQty || '', OrderStatus: item.OrderStatus || '', OrderType: 'S', SinglePc: item.SinglePc || '', BookingType: item.BookingType || 0, OfferValue: item.OfferValue || 0, OfferAmt: item.OfferAmt || 0, SetCount: item.SetCount || 0, OfferType: item.OfferType || '', CounterName: item.CounterName || '', OfferMode: item.OfferMode || '', OfferMessage: item.OfferMessage || [{}], ProductIdentifierDtls: item.ProductIdentifierDtls?.map(prod => ({ SerialNumber: prod.SerialNumber || '', IMEI1: prod.IMEI1 || '', IMEI2: prod.IMEI2 || '', MacId: prod.MacId || '' })) || [], PackageDtl: item.PackageDtl?.map(pkg => ({ ProdId: pkg.ProdId || '', ParcelQty: pkg.ParcelQty || 0, ParcelCount: pkg.ParcelCount || 0, Total: pkg.Total || 0, ParcelType: pkg.ParcelType || '', ProdVariantName: pkg.ProdVariantName || '', InwardDtlId: pkg.InwardDtlId || '' })) || [] })) || [], SalesTableLinkDetails: data.SalesTableLinkDetails?.map(chair => ({ TableId: chair.TableId, WaiterId: chair.WaiterId, ChairId: chair.ChairId, TipsAmount: chair.TipsAmount || 0 })) || [], ExtraChargeDetails: data.ExtraChargeDetails?.map(extra => ({ ProdId: extra.ProdId || '', InwardDtlId: extra.InwardDtlId || '', OrderQty: extra.OrderQty || 0, OrderRate: extra.OrderRate || 0, TotalAmt: extra.TotalAmt || 0, TaxAmt: extra.TaxAmt || 0, ExtraChargeId: extra.ExtraChargeId || '', OrderType: extra.OrderType || 'S', BookingType: extra.BookingType || 0, SinglePc: extra.SinglePc || '', TaxId: extra.TaxId || '', TaxPercentage: extra.TaxPercentage || 0 })) || [], Type: data.Type || 0, ApprovalStatus: 'Y' })), PaymentDetail: [] }; console.log('MergeData being sent:', MergeData); // Call the merge API const postMerge = await dispatch(postMergeOrders(MergeData)).unwrap(); console.log('Merge API Response:', postMerge); if (postMerge?.data?.statusCode === 1) { message.success(`Successfully merged ${uniqueOrderIds.length} orders!`); await getDiningTypefun.getDiningTypefun(); closeModal(); } else { message.error(postMerge?.data?.message || 'Merge failed'); } } catch (err) { console.error('Merge error:', err); message.error('Something went wrong during merge.'); } finally { setIsLoading(false); } }; return ( <> Multi-Table/Chair Merge } onOk={handleConfirmedMerge} onCancel={closeModal} width={900} className="merge-modal" okText="Merge All Orders" cancelText="Cancel" confirmLoading={isLoading} okButtonProps={{ disabled: selectedItems.filter(item => item.orderIds && item.orderIds.length > 0).length < 2, className: "merge-ok-button" }} cancelButtonProps={{ className: "merge-cancel-button" }} >
{selectedItems.map((item, index) => (

Selection {index + 1}

{selectedItems.length > 2 && (
{/* Radio for merge type */}
updateSelectionType(item.id, e.target.value)} className="merge-radio-group" > Whole Table Multiple Chairs
{/* Table selection */}
({ value: option.TableId, label: option.TableName, })) || []} label={} optionsNames={{ value: "TypeId", label: "TypeName" }} className="merge-dropdown" isOnchanges={!!item.tableId} onChangeFunction={(selectedValues) => { updateTableSelection(item.id, selectedValues); }} valueData={item.tableId} />
{/* Chair selection if type = chair */} {item.type === "chair" && item.tableData && (
{item.tableData.ChairLevelSerDetails?.filter(chair => chair.SalesStatus === "Y").map(chair => (
{ const newChairIds = e.target.checked ? [...item.chairIds, chair.ChairId] : item.chairIds.filter(id => id !== chair.ChairId); updateChairSelection(item.id, newChairIds); }} >
{chair.ChairName} Order: {chair.OrderId}
))}
)} {/* Selection summary */}
{item.type === 'table' && item.tableData && (
Table: {item.tableData.TableName} Order ID: {item.orderId}
)} {item.type === 'chair' && item.chairIds.length > 0 && (
Selected Chairs: {item.chairIds.length}
Order IDs: {item.orderIds?.map((orderId, idx) => ( {orderId} ))}
)}
))} {/* Add more selection button */}
{/* Final Summary */}
Merge Summary:
{selectedItems.map((item, index) => { if (!item.orderIds || item.orderIds.length === 0) return null; return (
Selection {index + 1}:
{item.type === 'table' && ( <> Table: {item.tableData?.TableName}
{item.orderIds.map((orderId, idx) => ( Order: {orderId} ))}
)} {item.type === 'chair' && ( <> Chairs: {item.chairIds.length} selected from {item.tableData?.TableName}
{item.orderIds.map((orderId, idx) => ( Order: {orderId} ))}
)}
); })} {selectedItems.filter(item => item.orderIds && item.orderIds.length > 0).length < 2 && (
Please select at least 2 items with active orders to merge.
)}
); }; export default MergeBill;