Android_Retail/src/Pages/BookingScreen/Template/SalesCountComponent.jsx

745 lines
24 KiB
React
Raw Normal View History

2026-01-27 18:27:29 +05:30
import React, {
useMemo,
useState,
useEffect,
useRef,
useCallback,
2026-02-23 12:18:31 +05:30
lazy,
2026-03-13 16:31:12 +05:30
2026-01-27 18:27:29 +05:30
} from 'react';
import { Tooltip } from 'antd';
import {
dateFormatChange1,
extractLastNumberOrderId,
getSession,
} from '../../../Services/Others';
import { useDispatch } from 'react-redux';
2026-02-23 12:18:31 +05:30
import { MdOutlineCallReceived } from 'react-icons/md';
import { GoPackageDependencies } from 'react-icons/go';
import { Messages } from '../../../Components/Notifications/Messages';
import { useSelector } from 'react-redux';
2026-01-27 18:27:29 +05:30
import {
getCardDataWithoutSub,
getCardDataWithoutSubmodule,
getLayoutproductCard,
getSelectedFavItems,
GlobalProductCategorie,
GlobalProductSubCategorie,
GlobalSalesDetailData,
PreferenceData,
} from '../../../Features/BookingScreen/BookingData/BookingData';
import { ApplicationPreferences } from '../../../Features/BrachLogin/BranchLogin';
import {
getReceivedStocks,
PostReceiveStocks,
} from '../../../Features/stockReceivedGodown/ReceivedStock.js';
import { getTemplateData } from '../../../Features/ThemeChange/ThemeChange.js';
2026-02-23 12:18:31 +05:30
// Jsx Files
const CustomisedInvoiceChange = lazy(
() => import('../Components/UtillComponents/CustomisedInvoiceChange.jsx')
);
const AllSalesPageSettings = lazy(
() => import('../Components/UtillComponents/AllSalesPageSettings.jsx')
);
const ProductPriceChange = lazy(
() => import('../Components/UtillComponents/ProductPriceChange.jsx')
);
const ReceivedStocksModal = lazy(
() => import('../../../Components/Modal/ReceivedStocksModal.jsx')
);
const ProductDetailsModal = lazy(
() => import('../../../Components/Modal/ProductDetailsModal.jsx')
);
const ShortcutKeyHelper = lazy(
() => import('../Components/UtillComponents/ShortcutKeyHelper.jsx')
);
// Scss
import './SalesCountComponent.scss';
import {
SalesDetailsModal,
SalesNetAmountModal,
} from '../Components/UtillComponents/SalesDetailsNetAmountModal.jsx';
2026-01-27 18:27:29 +05:30
const SalesCountComponent = React.memo(
({ DineInAccess, GlobalsalesDetailData, BookingNavbar }) => {
2026-01-27 18:27:29 +05:30
// Destructure to simplify access to required values
console.log(
BookingNavbar,
2026-03-25 09:33:37 +05:30
'BookingNavbarBookingNavbar',
GlobalsalesDetailData
);
2026-01-27 18:27:29 +05:30
const {
DineInOrderCount,
TakeAwayOrderCount,
OverAllOrderCount,
SelfDineInOrderCount,
SelfTakeAwayOrderCount,
DineInAmount,
TakeAwayAmount,
OverAllTakeAwayOfferAmount,
OverAllDineInOfferAmount,
SelfTakeAwayAmount,
SelfDineInAmount,
PreOrderAmount,
2026-03-25 09:33:37 +05:30
RefundAmt
2026-01-27 18:27:29 +05:30
} = GlobalsalesDetailData.length > 0 ? GlobalsalesDetailData[0] : {};
const dispatch = useDispatch();
const appPreferences = useSelector(ApplicationPreferences);
const dailySalesData = useSelector(GlobalSalesDetailData);
const ProdSubCat = useSelector(GlobalProductSubCategorie);
const prodCat = useSelector(GlobalProductCategorie);
const templateData = useSelector(getTemplateData);
const preferencedata = useSelector(PreferenceData);
2026-03-25 09:33:37 +05:30
console.log(dailySalesData, 'preferencedatasalescount');
2026-01-27 18:27:29 +05:30
const bookingTypePreference = appPreferences?.find(
(preference) => preference?.PreferredCatName === 'Booking Type'
)?.PreferenceCatDetails;
const dinePreference = bookingTypePreference?.find(
(type) =>
type?.PreferredSubCatName?.toLowerCase() === 'dine in' &&
type?.PreferredStatus === 'Y'
);
const takeAwayPreference = bookingTypePreference?.find(
(type) =>
type?.PreferredSubCatName?.toLowerCase() === 'take away' &&
type?.PreferredStatus === 'Y'
);
2026-02-09 14:08:53 +05:30
const preferenceshortcutkey = preferencedata?.[0]?.[
2026-02-17 12:18:40 +05:30
'SettingDtlDetails'
]?.some(
(item) =>
item.SettingIdName.toLowerCase() === 'shortcutkeys' &&
item.SettingValue === 'Y'
);
2026-01-27 18:27:29 +05:30
const [messageType, setMessageType] = useState(null);
const [messageData, setMessageData] = useState(null);
const [page, setpage] = useState(1);
const formRef = useRef(null);
const [allowDecimal, setAllowDecimal] = useState(false);
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
const AppId = getSession('AppId');
const CompId = getSession('CompId');
const BranchId = getSession('BranchId');
const UserId = getSession('UserId');
const [TableData, setTableData] = useState([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isNetAmtModalOpen, setIsNetAmtModalOpen] = useState(false);
const [Customisebillno, setCustomisebillno] = useState(false);
const [isReceivedModelOpen, setIsReceivedModelOpen] = useState(false);
const [ProductDetailsModel, setProductDetailsModel] = useState(false);
const [modalProductDetails, setModalProductDetails] = useState([]);
const [AutoReceiveStock, setAutoReceiveStock] = useState(false);
const [SelectedIndex, setSelectedIndex] = useState(null);
const bookings = dailySalesData?.[0]?.BookedDetails;
const orderDetails = dailySalesData?.[0]?.OrderDetails;
const [currentPage, setCurrentPage] = useState(1);
const rowsPerPage = 10;
const totalPages = Math.ceil((bookings?.length || 0) / rowsPerPage);
const startIndex = (currentPage - 1) * rowsPerPage;
const currentData = bookings?.slice(startIndex, startIndex + rowsPerPage);
console.log(dailySalesData, 'dailySalesDatadailySalesData', bookings);
function safeRound(amountStr) {
if (amountStr == null) return allowDecimal ? '0.00' : '0';
const cleaned = String(amountStr).replace(/[^0-9.-]+/g, '');
const num = Number(cleaned);
if (isNaN(num)) return allowDecimal ? '0.00' : '0';
return allowDecimal ? num.toFixed(2) : Math.round(num).toString();
}
// Memoize the tooltip content
const tooltipContent = useMemo(() => {
if (
DineInAccess?.SettingValue === 'Y' &&
dinePreference &&
(DineInOrderCount > 0 ||
TakeAwayOrderCount > 0 ||
SelfTakeAwayOrderCount > 0 ||
SelfDineInOrderCount > 0)
) {
return (
<Tooltip
title={
<div style={{ display: 'flex', gap: '1rem' }}>
{takeAwayPreference && (
<p>
Take Away:{' '}
{TakeAwayOrderCount + SelfTakeAwayOrderCount || 0}
</p>
)}
<p>Dine In: {DineInOrderCount + SelfDineInOrderCount || 0}</p>
</div>
}
>
<p
style={{ fontSize: '14px', cursor: 'pointer' }}
onClick={() =>
(OverAllOrderCount || 0 > 0) && setIsModalOpen(true)
}
>
{isMobile ? 'SC' : 'Sales Count'}:{' '}
<span>{OverAllOrderCount || 0}</span>
</p>
</Tooltip>
);
}
return (
<p
style={{ fontSize: '14px' }}
onClick={() => (OverAllOrderCount || 0) > 0 && setIsModalOpen(true)}
>
{isMobile ? 'SC' : 'Sales Count'}:{' '}
<span>{OverAllOrderCount || 0}</span>
</p>
);
}, [
DineInAccess?.SettingValue,
DineInOrderCount,
TakeAwayOrderCount,
OverAllOrderCount,
isMobile,
]);
useEffect(() => {
2026-02-23 12:18:31 +05:30
if (preferencedata?.length > 0) {
getPreference();
2026-01-27 18:27:29 +05:30
2026-02-23 12:18:31 +05:30
let AutoReceiveStock = preferencedata?.[0]?.SettingDtlDetails?.some(
(s) =>
s?.SettingIdName?.toLowerCase() === 'autoreceivestock' &&
s?.SettingValue === 'N'
2026-02-23 12:18:31 +05:30
);
setAutoReceiveStock(!AutoReceiveStock);
if (AutoReceiveStock) {
getReceivedStock();
}
}
2026-01-27 18:27:29 +05:30
}, [preferencedata]);
const getPreference = async () => {
const decimalSetting = preferencedata?.[0]?.SettingDtlDetails?.find(
(setting) =>
setting?.SettingIdName?.toLowerCase() === 'decimal' &&
setting?.SettingValue === 'Y'
);
if (decimalSetting) {
setAllowDecimal(true);
}
let custombillsetting = preferencedata?.[0]?.SettingDtlDetails?.some(
(s) =>
s?.SettingIdName?.toLowerCase() === 'customisedbillnumber' &&
s?.SettingValue === 'Y'
);
setCustomisebillno(custombillsetting);
};
const getReceivedStock = async () => {
try {
const response = await dispatch(
getReceivedStocks({ CompId, BranchId, AppId })
).unwrap();
if (response?.data?.statusCode === 1) {
setTableData(
response.data.data?.map((e) => {
return {
...e,
DispatchStockDetails: e?.DispatchStockDetails?.map((e) => {
return {
...e,
AcceptedQty: e?.DispatchedQty,
};
}),
};
})
);
} else {
2026-02-17 12:18:40 +05:30
setTableData([]);
2026-01-27 18:27:29 +05:30
console.warn('API returned unsuccessful status', response);
}
} catch (error) {
console.error('Failed to fetch received stock:', error);
}
};
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth < 768);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const onComplete = useCallback(() => {
setMessageData(null);
setMessageType(null);
}, []);
const columns = [
{
title: 'SL.NO',
key: 'sno',
align: 'center',
width: '50px',
render: (text, object, index) => (
<a style={{ color: 'black' }}>{(page - 1) * 10 + index + 1}</a>
),
},
{
title: 'Req Id',
key: 'RequestId',
align: 'center',
width: '70px',
2026-02-17 12:18:40 +05:30
render: (text, record, index) => record?.RequestId?.split('-')?.pop(),
2026-01-27 18:27:29 +05:30
},
{
title: 'Date & Time',
dataIndex: 'dateTime',
key: 'dateTime',
align: 'center',
width: '150px',
render: (text, record, index) => dateFormatChange1(record.CreatedDate),
},
{
title: 'Received From',
dataIndex: 'FromBranchName',
key: 'FromBranchName',
align: 'center',
width: '120px',
},
{
title: 'Item',
dataIndex: 'FromBranchName',
key: 'FromBranchName',
align: 'center',
width: '50px',
render: (text, record, index) => (
<a style={{ color: 'black' }}>
{record?.DispatchStockDetails?.length || 0}
</a>
),
},
{
title: 'Qty',
dataIndex: 'FromBranchName',
key: 'FromBranchName',
align: 'center',
width: '50px',
render: (text, record, index) => (
<div>
{(record?.DispatchStockDetails ?? []).reduce(
(total, item) => total + (item?.DispatchedQty || 0),
0
)}
</div>
),
},
{
title: 'dispatched By',
dataIndex: 'DispatcherName',
key: 'DispatcherName',
align: 'center',
width: '120px',
},
{
title: 'Actions',
dataIndex: 'fromBranch',
key: 'fromBranch',
align: 'center',
width: '100px',
render: (_, record, index) => (
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<div
className="sr-stock-recieve-button"
title="Receive Stock"
onClick={() => handleModalOpen(index)}
2026-02-17 12:18:40 +05:30
>
{' '}
<span>Receive</span>
2026-01-27 18:27:29 +05:30
<GoPackageDependencies size={18} />
</div>
</div>
),
2026-02-17 12:18:40 +05:30
},
2026-01-27 18:27:29 +05:30
];
const handlePageChange = (current) => {
setpage(current);
};
const getstockbadge = async () => {
let data = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
};
await dispatch(getSelectedFavItems(data)).unwrap();
let data1 = {
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
ProdSubCat: ProdSubCat,
};
let data2 = {
compId: CompId,
branchId: BranchId,
appId: AppId,
prodCat: prodCat,
};
if (
templateData?.BookingLayout?.[1]?.some(
(item) => item?.OptionName === 'SubCategory'
) &&
ProdSubCat
) {
await dispatch(getLayoutproductCard(data1)).unwrap();
} else if (
!templateData?.BookingLayout?.[1]?.some(
(item) => item?.OptionName === 'SubCategory'
)
) {
await dispatch(getCardDataWithoutSubmodule(data2)).unwrap();
} else {
await dispatch(getCardDataWithoutSub(data2)).unwrap();
}
};
const postApi = async (data, index) => {
try {
let postData = {
AppId: AppId,
CompId: CompId,
FromLocationId: data?.FromLocationId,
ToLocationId: data?.ToLocationId,
RequestId: data?.RequestId,
DispatchId: data?.DispatchId,
ReceiveStockDetails: data?.DispatchStockDetails?.map((e) => {
return {
ProdId: e?.ProdId,
InwardDtlId: e?.InwardDtlId,
ReceivedQty: e?.DispatchedQty,
AcceptedQty: e?.AcceptedQty,
CreatedBy: UserId,
};
}),
CreatedBy: UserId,
};
let res = await dispatch(PostReceiveStocks(postData))?.unwrap();
if (res?.data?.statusCode == 1) {
setMessageData(res?.data?.response);
setMessageType('success');
await getReceivedStock();
await getstockbadge();
} else {
setMessageData(res?.data?.response);
setMessageType('error');
}
} catch (error) {
console.log(error);
}
};
const handleModalOpen = (index) => {
setSelectedIndex(index);
const pd = TableData?.[index]?.DispatchStockDetails || [];
setModalProductDetails(
Array.isArray(pd) ? JSON.parse(JSON.stringify(pd)) : []
);
setProductDetailsModel(true);
setIsReceivedModelOpen(false);
};
const handleModalCancel = () => {
setProductDetailsModel(false);
setModalProductDetails([]);
setIsReceivedModelOpen(true);
};
const handleModalSubmit = () => {
const updatedData = {
...TableData[SelectedIndex],
DispatchStockDetails: modalProductDetails,
};
setTableData((prev) => {
const copy = Array.isArray(prev) ? [...prev] : [];
const idx = SelectedIndex ?? 0;
if (copy[idx]) {
copy[idx] = updatedData;
}
return copy;
});
setProductDetailsModel(false);
// setIsReceivedModelOpen(true)
postApi(updatedData, SelectedIndex);
setModalProductDetails([]);
};
return (
2026-03-13 16:31:12 +05:30
<>
2026-02-23 12:18:31 +05:30
<Messages
messageType={messageType}
messageData={messageData}
onComplete={onComplete}
/>
<div className="SalesCountComponent-Master">
{tooltipContent}
{DineInAccess?.SettingValue === 'Y' &&
takeAwayPreference &&
(TakeAwayOrderCount > 0 ||
SelfTakeAwayOrderCount > 0 ||
PreOrderAmount > 0) && (
<Tooltip
title={
2026-01-27 18:27:29 +05:30
<div
style={{
display: 'flex',
2026-02-23 12:18:31 +05:30
gap: '0.5rem',
flexDirection: 'column',
2026-01-27 18:27:29 +05:30
}}
>
2026-02-23 12:18:31 +05:30
<div style={{ display: 'flex', gap: '1rem' }}>
<div>
<p>Admin + Staff : </p>
{SelfTakeAwayAmount != 0 && <p>Self Booking : </p>}
{PreOrderAmount != 0 && <p>Preorder : </p>}
{OverAllTakeAwayOfferAmount != 0 && (
<p>Offer(-) : </p>
)}
</div>
<div style={{ textAlign: 'right' }}>
<p>{safeRound(TakeAwayAmount)}</p>
{SelfTakeAwayAmount != 0 && (
<p>{safeRound(SelfTakeAwayAmount)}</p>
)}
{PreOrderAmount != 0 && (
<p>{safeRound(PreOrderAmount)}</p>
)}
{OverAllTakeAwayOfferAmount != 0 && (
<p>{safeRound(OverAllTakeAwayOfferAmount)}</p>
)}
</div>
</div>
<div
style={{
flexGrow: 1,
borderBottom: '1px dotted #fff',
height: 0,
}}
></div>
<div
style={{
display: 'flex',
gap: '1rem',
justifyContent: 'flex-end',
fontSize: '16px',
fontWeight: '600',
fontFamily: 'Poppins',
}}
>
<div>Total</div>
<div>
{safeRound(
TakeAwayAmount +
SelfTakeAwayAmount +
PreOrderAmount -
OverAllTakeAwayOfferAmount
2026-02-23 12:18:31 +05:30
)}
</div>
2026-01-27 18:27:29 +05:30
</div>
</div>
2026-02-23 12:18:31 +05:30
}
>
<p style={{ fontSize: '14px' }}>
{isMobile ? 'TA' : 'Take Away'}:{' '}
<span>
{safeRound(
(TakeAwayAmount ||
0 + SelfTakeAwayAmount ||
0 + PreOrderAmount ||
0) - OverAllTakeAwayOfferAmount
)}
</span>
</p>
2026-01-27 18:27:29 +05:30
2026-02-23 12:18:31 +05:30
{/* <p>
2026-01-27 18:27:29 +05:30
Take Away: <span>{Math.round(((TakeAwayAmount + SelfTakeAwayAmount + PreOrderAmount) - OverAllTakeAwayOfferAmount)) || 0}</span>
</p> */}
2026-02-23 12:18:31 +05:30
</Tooltip>
)}
{DineInAccess?.SettingValue === 'Y' &&
dinePreference &&
(DineInOrderCount > 0 || SelfDineInOrderCount > 0) && (
<Tooltip
title={
2026-01-27 18:27:29 +05:30
<div
style={{
display: 'flex',
2026-02-23 12:18:31 +05:30
gap: '0.5rem',
flexDirection: 'column',
2026-01-27 18:27:29 +05:30
}}
>
2026-02-23 12:18:31 +05:30
<div style={{ display: 'flex', gap: '1rem' }}>
<div>
<p>Admin + Staff : </p>
{SelfDineInAmount != 0 && <p>Self Booking : </p>}
{OverAllDineInOfferAmount != 0 && <p>Offer(-) : </p>}
</div>
<div style={{ textAlign: 'right' }}>
<p>{safeRound(DineInAmount)}</p>
{SelfDineInAmount != 0 && (
<p>{safeRound(SelfDineInAmount)}</p>
)}
{OverAllDineInOfferAmount != 0 && (
<p>{safeRound(OverAllDineInOfferAmount)}</p>
)}
</div>
</div>
<div
style={{
flexGrow: 1,
borderBottom: '1px dotted #fff',
height: 0,
}}
></div>
<div
style={{
display: 'flex',
gap: '1rem',
justifyContent: 'flex-end',
fontSize: '16px',
fontWeight: '600',
fontFamily: 'Poppins',
}}
>
<div>Total</div>
<div>
{safeRound(
DineInAmount +
SelfDineInAmount -
OverAllDineInOfferAmount
2026-02-23 12:18:31 +05:30
)}
</div>
2026-01-27 18:27:29 +05:30
</div>
</div>
2026-02-23 12:18:31 +05:30
}
>
<p style={{ fontSize: '14px' }}>
{isMobile ? 'DI' : 'Dine In'}:{' '}
<span>
{safeRound(
DineInAmount +
SelfDineInAmount -
OverAllDineInOfferAmount
2026-02-23 12:18:31 +05:30
)}
</span>
</p>
{/* <p>
2026-01-27 18:27:29 +05:30
Dine In: <span>{Math.round(((DineInAmount + SelfDineInAmount) - OverAllDineInOfferAmount)) || 0}</span>
</p> */}
2026-02-23 12:18:31 +05:30
</Tooltip>
2026-01-27 18:27:29 +05:30
)}
2026-02-23 12:18:31 +05:30
<p
style={{ fontSize: '14px', cursor: 'pointer' }}
onClick={() =>
safeRound(
(TakeAwayAmount +
SelfTakeAwayAmount +
PreOrderAmount -
OverAllTakeAwayOfferAmount || 0) +
(DineInAmount + SelfDineInAmount - OverAllDineInOfferAmount)
2026-02-23 12:18:31 +05:30
) > 0 && setIsNetAmtModalOpen(true)
}
>
{isMobile ? 'NA' : 'Net Amt'}:{' '}
<span>
{safeRound(
(TakeAwayAmount +
SelfTakeAwayAmount +
PreOrderAmount -
OverAllTakeAwayOfferAmount || 0) +
(DineInAmount + SelfDineInAmount - OverAllDineInOfferAmount)
2026-02-23 12:18:31 +05:30
)}
</span>
</p>
{Customisebillno && <CustomisedInvoiceChange />}
{/* Modal with table for multiple bookings */}
2026-02-26 12:54:08 +05:30
<SalesDetailsModal
isModalOpen={isModalOpen}
setIsModalOpen={setIsModalOpen}
currentData={currentData}
currentPage={currentPage}
totalPages={totalPages}
setCurrentPage={setCurrentPage}
startIndex={startIndex}
/>
2026-01-27 18:27:29 +05:30
2026-02-23 12:18:31 +05:30
{/* Modal with table for multiple Net Amt */}
2026-02-26 12:54:08 +05:30
<SalesNetAmountModal
isNetAmtModalOpen={isNetAmtModalOpen}
setIsNetAmtModalOpen={setIsNetAmtModalOpen}
orderDetails={orderDetails}
2026-03-25 09:33:37 +05:30
RefundAmt={RefundAmt}
2026-02-26 12:54:08 +05:30
/>
2026-02-23 12:18:31 +05:30
<Tooltip title="Receive Stock">
{TableData?.length > 0 && AutoReceiveStock && (
<button
className="blink blinkStock"
onClick={() => setIsReceivedModelOpen(true)}
title="Received Stock"
>
<MdOutlineCallReceived />
Stock
</button>
)}
</Tooltip>
2026-02-17 12:18:40 +05:30
</div>
2026-02-23 12:18:31 +05:30
{preferenceshortcutkey && (
<div className="keyboardShortcut">
<ShortcutKeyHelper />
</div>
)}
<AllSalesPageSettings />
2026-02-17 12:18:40 +05:30
<ProductPriceChange />
2026-02-23 12:18:31 +05:30
<ReceivedStocksModal
open={isReceivedModelOpen}
onClose={() => {
setIsReceivedModelOpen(false);
}}
columns={columns}
tableData={TableData}
handlePageChange={handlePageChange}
customTable={false}
/>
2026-01-27 18:27:29 +05:30
2026-02-23 12:18:31 +05:30
<ProductDetailsModal
open={ProductDetailsModel}
onClose={handleModalCancel}
productDetails={modalProductDetails}
headerData={{
dateTime: dateFormatChange1(
TableData?.[SelectedIndex]?.CreatedDate
),
fromBranch: TableData?.[SelectedIndex]?.FromBranchName,
Created_By: TableData?.[SelectedIndex]?.Created_By,
Dispatch_Id: TableData?.[SelectedIndex]?.DispatchId,
}}
onDataChange={(d) => setModalProductDetails(d)}
onSubmit={handleModalSubmit}
/>
</>
2026-03-13 16:31:12 +05:30
);
2026-01-27 18:27:29 +05:30
}
);
export default SalesCountComponent;