Android_Retail/src/Pages/Kiosk/Components/SelfBookingFooter.jsx

1510 lines
50 KiB
React
Raw Normal View History

2026-01-27 18:27:29 +05:30
import React, { useCallback, useEffect, useState } from 'react';
import { Popconfirm, Drawer, Badge, Modal } from 'antd';
2026-01-27 18:27:29 +05:30
import { QuestionCircleOutlined } from '@ant-design/icons';
import { useDispatch, useSelector } from 'react-redux';
import { IoIosArrowForward } from 'react-icons/io';
import { MdCurrencyRupee } from 'react-icons/md';
import PozoDineInIcon from '../KioskIcons/KioskDineIn';
import TakeAway from '../KioskIcons/KioskTakeAway';
import {
changeisKioskCartOpen,
changeKioskPageName,
getKioskDarkColour,
globalCurrentKioskPageName,
globalisKioskCartOpen,
} from '../../../Features/Kiosk/kiosk';
import {
GlobalBookingTypeKiosk,
GlobalKioskOrderDetails,
GlobalOrderbtnClicked,
changeAllGlbStatustData,
GlobalPaymentgatewayRedirect,
changeBookingType,
GlobalOrderId,
GlobalSalesId,
changeOrderId,
changeSalesId,
changeKioskOrderDetails,
GlobalMergeData,
changeMergeData,
getPaymentGatewayDetails,
getPaymentGatewayAccessData,
changeMembershipDetail,
GlobalOrderOfferDetails,
GlobalMembershipDetail,
getPaymentVerfication,
} from '../../../Features/BookingScreen/BookingData/KioskBookingData';
import Cookies from 'js-cookie';
import SelfKisokOrderCart1 from '../OrderCart/SelfBookingOrderCart1';
import OrderCart2 from '../OrderCart/OrderCart2';
import OrderCart3 from '../OrderCart/OrderCart3';
import '../../../Styles/Kiosk/Components/SelfBookingKioskFooter.scss';
import KioskPayment from '../Payment/KioskPaymentWithModal';
import { ApplicationPreferences } from '../../../Features/BrachLogin/BranchLogin';
import { FaAngleUp, FaCircleCheck } from 'react-icons/fa6';
import { FaAngleDown } from 'react-icons/fa';
import { PostBookingData, PostCancelPayment } from '../../../Features/BookingScreen/BookingData/BookingData';
2026-01-27 18:27:29 +05:30
import {
generateRandomKey,
getSession,
removeCookieData,
encryptedValuesFun,
encryptObject,
} from '../../../Services/Others';
import {
getSelfBooking,
getTableDtlsForSelfBooking,
postSelfBooking,
putSelfBooking,
} from '../../../Features/TableBooking/TableBooking';
import { Messages } from '../../../Components/Notifications/Messages';
import { useNavigate } from 'react-router-dom';
import Tick from '../../../Images/tick.gif';
import { DefaultModal } from '../../../Components/Modal/DefaultModal';
import { Input, message } from 'antd';
import { getItem } from '../../../Components/Menu/SideMenu';
import SelfBookingPayment from '../Payment/SelfBookingPaymementwithModal';
import OrderQR from './QrCodeSelfBooking';
import { getAddCustomerDetails } from '../../../Features/BookingScreen/Customer/addCustomer';
import { PublicQrCodepost } from '../../../Features/ConfigMasterPage/ConfigMasterPage';
import { AiOutlineShoppingCart } from 'react-icons/ai';
const subDirectory = import.meta.env.ENV_BASE_URL;
const CustomPaymentUrl = import.meta.env.ENV_CUSTOM_PAYMENT_URL;
const MainHomeUrl = import.meta.env.ENV_MAIN_BASE_URL;
const selfKioskFooter = (props) => {
const dispatch = useDispatch();
const navigate = useNavigate();
const MergeData = useSelector(GlobalMergeData);
const OrderofferDetails = useSelector(GlobalOrderOfferDetails);
const KioskOrderDetails = useSelector(GlobalKioskOrderDetails);
console.log(KioskOrderDetails, 'KioskOrderDetails ');
const KioskCurrentPage = useSelector(globalCurrentKioskPageName);
const GeneratedOrderId = useSelector(GlobalOrderId);
const GeneratedSalesId = useSelector(GlobalSalesId);
const getKioskDarkColourdata = useSelector(getKioskDarkColour);
const BookingType = useSelector(GlobalBookingTypeKiosk);
const [TotalTaxAmount, setTotalTaxAmount] = useState(null);
const [TotalBillAmount, setBillAmount] = useState(null);
const [TotalNetAmount, setTotalNetAmount] = useState(null);
let WaiterINformation = sessionStorage.getItem('WaiterId');
const clicked = useSelector(GlobalOrderbtnClicked);
const getmobilepage = useSelector(GlobalPaymentgatewayRedirect);
const appPreferences = useSelector(ApplicationPreferences);
const isKioskCartOpen = useSelector(globalisKioskCartOpen);
const [isPayViaOpen, setPayViaOpen] = useState(false);
const [messageType, setMessageType] = useState(null);
const [messageData, setMessageData] = useState(null);
const [open, setOpen] = useState(false);
const [placement, setPlacement] = useState('right');
const [showPaymentSuccess, setShowPaymentSuccess] = useState(false);
const [OrderMethod, setOrderMethod] = useState('inPerson');
const [showPaymentSuccessAfterPayment, setshowPaymentSuccessAfterPayment] =
useState(false);
const [showQrCode, setshowQrCode] = useState(false);
const [paymentOrderId, setPaymentOrderId] = useState(null);
const [isOrderMethodModalOpen, setIsOrderMethodModalOpen] = useState(false);
const [Paymentvia, setPaymentvia] = useState(null);
// Phone Number Modal State
const [isPhoneModalOpen, setIsPhoneModalOpen] = useState(false);
const [phoneNumber, setPhoneNumber] = useState('');
const [isPhoneLoading, setIsPhoneLoading] = useState(false);
const [pendingOrderType, setPendingOrderType] = useState(null);
const [qrTimer, setQrTimer] = useState(60);
const [qrTimerActive, setQrTimerActive] = useState(false);
const bookingTypePreference = appPreferences?.find(
(preference) => preference?.PreferredCatName === 'Booking Type'
)?.PreferenceCatDetails;
const dinePreference = bookingTypePreference?.find(
(type) =>
type?.PreferredSubCatName?.toLowerCase() === 'dine in' &&
type?.PreferredStatus === 'Y'
);
const CompId = getSession('CompId');
const AppId = getSession('AppId');
const BranchId = getSession('BranchId');
const kioskTemplateData = props?.data;
const sessionData = props?.SessionDtl;
let isSelfBookingOpen = sessionStorage.getItem('SelfBookingId');
const [chairInformation, setChairInformation] = useState();
const [TableINformation, setTableINformation] = useState();
const [paymentUrl, setpaymentUrl] = useState(null);
const [showCancelConfirm, setShowCancelConfirm] = useState(null);
2026-01-27 18:27:29 +05:30
const [TransctionId, setTransctionId] = useState(null);
const [paymentGatewayAccess, setPaymentGatewayAccess] = useState([]);
// let chairInformation = getSession('table');
// let TableINformation = sessionStorage.getItem('tableID');
const storedBookingMethod = getSession('bookingMethod');
const bookingTypeName = sessionStorage.getItem('bookingTypeName');
const [allchairData, setAllchairData] = useState([]);
console.log('chairInformation', TableINformation);
useEffect(() => {
// If no payment URL → do nothing
if (!paymentUrl) {
console.log('paymentUrl is null → No listener / No interval');
return;
}
console.log('paymentUrl exists → Setting Listener + Polling');
// -------------------------
// 1) MESSAGE LISTENER
// -------------------------
function handleMessage(event) {
const data = event.data;
if (!data || data.type !== 'PAYMENT_STATUS') return;
console.log('Received message from iframe:', data);
if (data.status === 'TIMEOUT') {
setTimeout(() => {
console.log('TIMEOUT → Clearing paymentUrl');
setpaymentUrl(null);
}, 4000);
}
}
window.addEventListener('message', handleMessage);
// -------------------------
// 2) POLLING INTERVAL
// -------------------------
const interval = setInterval(async () => {
try {
const response = await dispatch(
getPaymentVerfication(TransctionId)
).unwrap();
console.log('Payment verification:', response);
const status = response?.data?.response?.[0]?.STATUS;
if (response?.data?.statusCode === 1 && status === 'TXN_SUCCESS') {
console.log('Payment Success → Stopping interval + clearing URL');
clearInterval(interval);
setpaymentUrl(null);
clearsDatas(TransctionId, 'UPI');
}
} catch (error) {
console.error('Payment check error:', error);
}
}, 4000);
// -------------------------
// CLEANUP → remove listener + interval
// -------------------------
return () => {
console.log('Cleanup → Removing listener & clearing interval');
window.removeEventListener('message', handleMessage);
clearInterval(interval);
};
}, [paymentUrl]);
useEffect(() => {
setChairInformation(getSession('table'));
setTableINformation(sessionStorage.getItem('tableID'));
fetchPaymentAccess();
}, [sessionStorage]);
useEffect(() => {
TotalCalculation();
}, [KioskOrderDetails]);
const selfBookingId = sessionStorage.getItem('SelfBookingId');
useEffect(() => {
if (getmobilepage) {
MobileNumberPage();
}
}, [getmobilepage]);
useEffect(() => {
if (isKioskCartOpen) {
setOpen(true);
}
}, [isKioskCartOpen]);
useEffect(() => {
fetchTableData(TableINformation);
}, [TableINformation]);
useEffect(() => {
if (qrTimerActive && qrTimer > 0) {
const interval = setInterval(() => {
setQrTimer((prev) => prev - 1);
}, 1000);
return () => clearInterval(interval);
} else if (qrTimer === 0) {
setshowQrCode(false);
setQrTimerActive(false);
setQrTimer(60);
}
}, [qrTimerActive, qrTimer]);
async function processBookings(bookings, MembershipDetail, CustId) {
let MemberShipData = MembershipDetail?.[0];
let remainingHrs = MemberShipData?.RemainingSessionHrs;
const processedBookings = bookings?.map((booking) => {
const from = booking.AvailableFrom
? booking.AvailableFrom.split(':')
: [0, 0];
const to = booking.AvailableTo ? booking.AvailableTo.split(':') : [0, 0];
const slotHrs = +to[0] + +to[1] / 60 - (+from[0] + +from[1] / 60);
const totalSessionHrs = slotHrs * booking.Size;
let membershipApplied = false;
let cost = booking.MRP;
if (remainingHrs >= totalSessionHrs) {
membershipApplied = true;
cost = 0;
remainingHrs -= totalSessionHrs;
} else {
membershipApplied = false;
cost = booking.MRP * 0.95;
}
return {
OfferId: MemberShipData?.MembershipId,
OfferAmount: booking?.TotalAmt,
OfferValue: 0,
TableName: 'MemberShip',
TableUniqueName: 'MemberShip',
TableUniqueId: 'string',
ProdId: booking?.ProdId,
SinglePc: booking?.SinglePc,
StockAvailable: booking?.StockAvailable,
ProdVariantName: booking?.ProdVariantName,
ActualFreeQty: 0,
Type: 'string',
BookingType: booking?.BookingType,
InwardDtlId: booking?.InwardDtlId,
OfferType: 'M',
PlanId: MemberShipData?.PlanId,
Detail: [],
ProdCat: booking?.ProdCat,
OfferCode: 'string',
CustId: CustId,
UsedCount: slotHrs,
AppliesTo: 'string',
FreeProductsList: {},
};
});
return processedBookings;
// setOrderOfferDetails(processedBookings);
}
const fetchPaymentAccess = async () => {
const paymentGatewayAccessResponse = await dispatch(
getPaymentGatewayAccessData({
AppId: sessionData.AppId,
CompId: sessionData.CompId,
BranchId: sessionData.BranchId,
ActiveStatus: 'A',
})
).unwrap();
setPaymentGatewayAccess(paymentGatewayAccessResponse?.data?.data);
// fetchPaymentOptionsData(
// paymentGatewayAccessResponse?.data?.data,
// paymentGatewayAccessResponse?.data?.data
// );
};
const fetchTableData = async (TableId) => {
const res = await dispatch(
getTableDtlsForSelfBooking({
tableId: TableId,
AppId,
CompId,
BranchId,
})
).unwrap();
if (res?.data?.statusCode === 1) {
setAllchairData(
res.data.data?.[0]?.ChairLevelSerDetails?.map((item) => item.ChairId) ||
[]
);
}
};
const handleShareWhatsAppFn = async (OrderId) => {
try {
// Validate required data
if (!OrderId) {
console.error('OrderId is required');
setMessageType('error');
setMessageData('Order ID not found. Please try again.');
return;
}
let orderIdsArray = [OrderId];
// Validate encryptObject function exists
if (typeof encryptObject !== 'function') {
console.error('encryptObject function not available');
setMessageType('error');
setMessageData('Encryption service unavailable. Please try again.');
return;
}
const encrypted = encryptObject(orderIdsArray);
const postData = {
Url: encrypted,
CreatedBy: 0,
};
const res = await dispatch(PublicQrCodepost(postData)).unwrap();
if (res?.data?.statusCode === 1) {
const urlData = res?.data?.ReferenceNo;
if (urlData) {
const documentUrl = `${MainHomeUrl}viewbill?code=${urlData}`;
// window.location.href = documentUrl;
window.open(documentUrl, '_blank');
} else {
setMessageType('error');
setMessageData('Receipt URL not generated. Please try again.');
}
} else {
setMessageType('error');
setMessageData('Failed to generate receipt. Please try again.');
}
} catch (err) {
console.error('Error while calling PublicQrCodepost:', err);
setMessageType('error');
setMessageData(
'Failed to load receipt. Please check your connection and try again.'
);
}
};
const TotalCalculation = () => {
const totalwithouttax = KioskOrderDetails?.reduce((accumulator, card) => {
return (
accumulator +
parseFloat(card.WithoutTaxRate || card.TotalAmt - card.TaxAmt || 0)
);
}, 0);
setBillAmount(parseFloat(totalwithouttax)?.toFixed(2));
const totalPrice = KioskOrderDetails?.reduce((accumulator, card) => {
return accumulator + parseFloat(card.TotalAmt || 0);
}, 0);
setTotalNetAmount(parseFloat(totalPrice)?.toFixed(2));
const totalTaxAmt = KioskOrderDetails?.reduce((accumulator, card) => {
return accumulator + parseFloat(card.TaxAmt || 0);
}, 0);
setTotalTaxAmount(parseFloat(totalTaxAmt)?.toFixed(2));
};
const MobileNumberPage = async (type) => {
placeOrder(type);
};
const handleClick = (type) => {
if (KioskCurrentPage === 'OrderView') {
if (KioskOrderDetails?.length > 0) {
if (!GeneratedOrderId && !GeneratedSalesId) {
setPendingOrderType(type);
setIsPhoneModalOpen(true);
} else if (type != 'Pay') {
MobileNumberPage(type);
} else {
let defaultBehaviour = sessionStorage.getItem('notselectcus');
if (defaultBehaviour == 'true') {
setShowPaymentSuccess(true);
} else {
setIsOrderMethodModalOpen(true);
}
// defaultBehaviour ? setShowPaymentSuccess(true) : setIsOrderMethodModalOpen(true);
}
}
} else {
dispatch(changeKioskPageName('OrderView'));
}
};
// Drawer code
const showDrawer = () => {
setOpen(true);
// OrderApiCall();
};
// Phone Number Modal Functions
const handlePhoneModalCancel = () => {
setIsPhoneModalOpen(false);
setPhoneNumber('');
setPendingOrderType(null);
};
const handlePhoneModalSubmit = async () => {
if (!phoneNumber.trim()) {
message.error('Please enter your phone number');
return;
}
// Basic phone number validation
if (!/^\d{10}$/.test(phoneNumber.trim())) {
message.error('Please enter a valid 10-digit phone number');
return;
}
setIsPhoneLoading(true);
try {
sessionStorage.setItem('CustomerPhoneNumber', phoneNumber.trim());
// let CustomerDetails = await dispatch(getAddCustomerDetails({
// CompId: CompId,
// BranchId: BranchId,
// AppId: AppId,
// MobileNo: phoneNumber.trim(),
// })).unwrap();
setIsPhoneModalOpen(false);
setPhoneNumber('');
// setPendingOrderType(null);
// if (CustomerDetails?.data?.statusCode == 1 && CustomerDetails?.data?.data?.[0]?.MembershipDetail?.length > 0) {
// await dispatch(changeMembershipDetail(CustomerDetails?.data?.data?.[0]));
// let res = await processBookings(KioskOrderDetails, CustomerDetails?.data?.data?.[0]?.MembershipDetail, CustomerDetails?.data?.data?.[0]?.CustId)
// await placeOrder(pendingOrderType, null, 'PC', null, res);
// }
// else
if (pendingOrderType) {
await placeOrder(pendingOrderType);
}
} catch (error) {
console.error('Phone number save error:', error);
message.error('Failed to save phone number. Please try again.');
} finally {
setIsPhoneLoading(false);
}
};
// Function to handle card payment processing
const processCardPayment = async (cardDetails) => {
try {
// Get payment gateway details
const paymentGatewayDetails = await dispatch(
getPaymentGatewayDetails({
AppId: AppId,
CompId: CompId,
BranchId: BranchId,
DetailType: 'P',
})
).unwrap();
// Get mode ID for the selected card
const modeId = await getModeId(
cardDetails.paymentOptionsData,
cardDetails.bankDetails.CardType === 'CRDC'
? 'CreditCard'
: 'DebitCard',
'Payment Gateway'
);
return {
paymentGatewayDetails,
modeId,
bankDetails: cardDetails.bankDetails,
};
} catch (error) {
console.error('Error processing card payment:', error);
throw error;
}
};
// Function to handle UPI payment processing
const processUpiPayment = async (upiData) => {
try {
// Get payment gateway details
const paymentGatewayDetails = await dispatch(
getPaymentGatewayDetails({
AppId: AppId,
CompId: CompId,
BranchId: BranchId,
DetailType: 'P',
})
).unwrap();
// For UPI, the upiData is already the mode details array
// We need to find the UPI mode ID from the data
let modeId = null;
if (upiData && upiData.length > 0) {
// Find the UPI mode ID from the first UPI mode detail
const upiMode = upiData.find((mode) => mode.ModeName === 'UPI');
if (upiMode) {
modeId = upiMode.ModeId;
}
}
return {
paymentGatewayDetails,
modeId,
upiData: upiData,
};
} catch (error) {
console.error('Error processing UPI payment:', error);
throw error;
}
};
// Function to get mode ID (copied from payment component)
const getModeId = async (paymentDetails, option, optionName) => {
const paymentDeviceOption = paymentDetails.OptionDetails.find(
(option) => option.OptionName === optionName
);
if (!paymentDeviceOption) {
return null;
}
const selectedMode = paymentDeviceOption.ModeDetails.find(
(mode) => mode.ModeName === option
);
if (!selectedMode) {
return null;
}
return selectedMode.ModeId;
};
// Function to handle UPI payment gateway form submission
const handleUpiPaymentGateway = async (response, processedUpiData) => {
try {
let PaymentOrderDetails = response?.data?.PaymentOrderDtl?.filter(
(item) => item.PaymentOptionType == 'PG' && item.PaymentStatus == 'P'
);
let PaymentOrderIndividualDetails =
PaymentOrderDetails?.length == 1 ? PaymentOrderDetails?.[0] : [];
const form = document.createElement('form');
form.method = 'POST';
form.action = `${CustomPaymentUrl}/ccavRetailRequestHandler`;
form.style.display = 'none'; // Hide the form
const customerPhoneNumber = sessionStorage.getItem('CustomerPhoneNumber');
const data1 = {
merchant_id: paymentGatewayAccess?.[0]?.['MerchantId'],
order_id: PaymentOrderIndividualDetails?.PaymentOrderId,
currency: 'INR',
amount: TotalNetAmount,
redirect_url:
'https://pozo.app/CustomPaymentGateway/CustomPaymentGateway/ccavRetailResponseHandler',
cancel_url:
'https://pozo.app/CustomPaymentGateway/CustomPaymentGateway/ccavRetailResponseHandler',
payment_option: processedUpiData.upiData?.[0]?.PayOpt,
card_type: processedUpiData.upiData?.[0]?.CardType,
card_name: 'UPI',
data_accept:
processedUpiData.upiData?.[0]?.MethodDetails?.[0]?.DataAcceptedAt ==
'CCAvenue'
? 'Y'
: 'N',
language: 'EN',
billing_name: 'User',
billing_address: 'xyz',
billing_city: 'xyz',
billing_state: 'xyz',
billing_zip: '000000',
billing_country: 'India',
billing_tel: customerPhoneNumber,
billing_email: 'xyz@gmail.com',
delivery_name: '',
delivery_address: AppId,
delivery_city: 'K',
delivery_zip: BranchId,
delivery_country: processedUpiData.modeId,
delivery_tel: customerPhoneNumber,
merchant_param1: '',
merchant_param2: PaymentOrderIndividualDetails?.OrderId,
merchant_param3: 0,
merchant_param4: CompId,
merchant_param5: 'paymentRetailHandler.html',
promo_code: '',
customer_identifier: '',
workingKey: paymentGatewayAccess?.[0]?.['WorkingKey'], // Include the working key
accessCode: paymentGatewayAccess?.[0]?.['AccessCode'],
};
Object.keys(data1).forEach((key) => {
const input = document.createElement('input');
input.type = 'hidden';
input.name = key;
input.value = encryptedValuesFun(data1[key]);
form.appendChild(input);
});
document.body.appendChild(form);
form.submit();
// Close payment modal
setShowPaymentSuccess(false);
} catch (error) {
console.error('Error handling UPI payment gateway:', error);
setMessageType('error');
setMessageData('Error processing UPI payment. Please try again.');
}
};
const placeOrder = async (
type,
paymentMethod = null,
paymentOptionType = 'PC',
upiData = null,
OrderOfferDetail = []
) => {
let BusinessUpi =
OrderOfferDetail &&
typeof OrderOfferDetail === 'object' &&
!Array.isArray(OrderOfferDetail)
? OrderOfferDetail?.ModeDetails?.[0] || {}
: {};
console.log(OrderOfferDetail, 'OrderOfferDetail');
// Process card payment details if it's a card payment
let processedCardData = null;
if (paymentMethod === 'Card' && upiData && upiData.bankDetails) {
try {
processedCardData = await processCardPayment(upiData);
} catch (error) {
console.error('Error processing card payment:', error);
setMessageType('error');
setMessageData('Error processing card payment. Please try again.');
return;
}
}
// Process UPI payment details if it's a UPI payment
let processedUpiData = null;
if (paymentMethod === 'UPI' && upiData) {
try {
console.log('UPI Data received:', upiData);
processedUpiData = await processUpiPayment(upiData);
console.log('Processed UPI Data:', processedUpiData);
} catch (error) {
console.error('Error processing UPI payment:', error);
setMessageType('error');
setMessageData('Error processing UPI payment. Please try again.');
return;
}
}
const map = new Map();
KioskOrderDetails.forEach((item) => {
const key = `${item.InwardDtlId}-${item.ProdId}`;
if (map.has(key)) {
const existing = map.get(key);
existing.OrderQty += item.OrderQty;
existing.TotalAmt += item.TotalAmt;
} else {
map.set(key, { ...item });
}
});
// Get phone number from session storage
const customerPhoneNumber = sessionStorage.getItem('CustomerPhoneNumber');
const now = new Date();
const formattedDate = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
let data = {
ActiveStatus: 'A',
AddlInfo: 'test',
AppId: AppId,
BalGiven: 0,
BillAmount: TotalBillAmount,
BookingMedia: 'DW',
BookingType: 129,
BranchId: BranchId,
CompId: CompId,
CustSuppId: null,
ExtraChargeDetails: null,
GivenAmt: 0,
NetAmount: TotalNetAmount,
OrderDate: formattedDate,
MobileNo: customerPhoneNumber || '',
OrderDtlDetails: Array.from(map.values())?.map((item) => ({
BookingType: item?.BookingType,
CounterName: item?.CounterName,
InwardDtlId: item?.InwardDtlId,
OfferAmt: item?.OfferAmt,
OfferType: item?.OfferType,
OfferValue: item?.OfferValue,
OrderQty: item?.OrderQty,
OrderRate: item?.OrderRate,
OrderStatus: item?.OrderStatus,
OrderType: 'S',
ProdId: item?.ProdId,
ProdNameQty: item?.ProdNameQty,
ProductIdentifierDtls: item?.ProductIdentifierDtls,
RefundQty: item?.RefundQty,
SinglePc: item?.SinglePc,
TaxAmt: item?.TaxAmt,
TaxId: item?.TaxId,
TotalAmt: item?.TotalAmt,
Type: item?.Type,
})),
OrderOfferDetail: OrderOfferDetail,
OrderType: 'S',
OtherServiceTicketAmount: null,
OtherServiceTicketId: null,
OverallDiscEst: 0,
OverallDiscSales: 0,
PaymentDetail:
type != 'Pay'
? []
: [
{
AccountDtl:
paymentMethod === 'UPI' && processedUpiData
? processedUpiData?.paymentGatewayDetails?.data?.data || []
: [],
Amount: TotalNetAmount,
Credit: 0,
Debit: 0,
PaymentOptionType: paymentOptionType,
PaymentStatus: 'P',
PaymentType:
paymentMethod === 'UPI' && processedUpiData
? processedUpiData?.modeId
: BusinessUpi?.ModeId
? BusinessUpi?.ModeId
: 0,
ModeOfPayment: null,
MerchantId: BusinessUpi?.MerchantId,
},
],
PaymentStatus: 'P',
PaymentType: processedUpiData?.modeId || BusinessUpi?.ModeId || 0,
Reference: 'test',
RefundAmount: 0,
SalesPaymentType: 'normal',
SalesTableLinkDetails:
storedBookingMethod === 'individualChair'
? chairInformation?.map((chairId) => ({
ChairId: chairId,
TableId: TableINformation,
WaiterId:
WaiterINformation != undefined ? WaiterINformation : null,
}))
: allchairData?.map((chairId) => ({
ChairId: chairId,
TableId: TableINformation,
WaiterId:
WaiterINformation != undefined ? WaiterINformation : null,
})),
ServiceCategory: null,
ServiceProvider: 0,
TaxAmount: TotalTaxAmount,
VatAmount: 0,
};
let response;
if (GeneratedOrderId && GeneratedSalesId && type == 'Pay') {
if (Cookies.get('DeviceStatusId')) {
data['DeviceStatusId'] = Cookies.get('DeviceStatusId');
} else {
let DeviceStatusId = generateRandomKey();
Cookies.set('DeviceStatusId', DeviceStatusId || 'unknown', {
expires: 365,
});
data['DeviceStatusId'] = DeviceStatusId;
}
Cookies.set('LastorderId', GeneratedOrderId || 'unknown', {
expires: 365,
});
data['OrderId'] = GeneratedOrderId;
data['SalesId'] = GeneratedSalesId;
data['UpdatedBy'] = 0;
response = await dispatch(putSelfBooking(data)).unwrap();
if (response?.data?.statusCode == 1) {
// Handle UPI payment gateway form submission
if (paymentMethod === 'UPI' && processedUpiData) {
await handleUpiPaymentGateway(response, processedUpiData);
} else if (paymentOptionType == 'BU') {
let OrderId = response?.data?.OrderId;
setTransctionId(OrderId);
let Amt = response?.data?.PaymentOrderDtl?.[0]?.Amount;
setShowPaymentSuccess(false);
setpaymentUrl(response?.data?.PaymentPageLink);
} else {
setTransctionId(response?.data?.OrderId);
clearsDatas(response?.data?.OrderId);
}
}
} else if (GeneratedOrderId && GeneratedSalesId) {
data['OrderId'] = GeneratedOrderId;
data['SalesId'] = GeneratedSalesId;
data['UpdatedBy'] = 0;
response = await dispatch(putSelfBooking(data)).unwrap();
if (response?.data?.statusCode === 1) {
setMessageType('success');
setMessageData('Order Placed Successfully');
}
let random = Cookies.get('UniqueId');
await dispatch(
getSelfBooking({
uniqueId: random,
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
})
);
} else {
let Randomkey = generateRandomKey();
data['CreatedBy'] = 0;
data['DeviceUniqueId'] = Randomkey;
response = await dispatch(postSelfBooking(data)).unwrap();
if (response?.data?.statusCode === 1) {
Cookies.set('UniqueId', Randomkey || 'unknown', { expires: 1 });
setMessageType('success');
setMessageData('Order Placed Successfully');
let response1 = await dispatch(
getSelfBooking({
uniqueId: Randomkey,
CompId: CompId,
BranchId: BranchId,
AppId: AppId,
})
).unwrap();
if (
response1?.data?.statusCode === 1 &&
response1?.data?.data?.length > 0
) {
dispatch(changeOrderId(response1?.data?.data?.[0]?.OrderId));
dispatch(changeSalesId(response1?.data?.data?.[0]?.SalesId));
}
}
}
};
const clearsDatas = (OrderId, Method = null) => {
let Randomkey = generateRandomKey();
Cookies.set('LastorderId', OrderId || 'unknown', { expires: 365 });
Cookies.set('UniqueId', Randomkey || 'unknown', { expires: 1 });
setMessageType('success');
setMessageData('Order Placed Successfully');
setShowPaymentSuccess(false);
setshowQrCode(true);
if (Method) {
setPaymentvia(Method);
} else {
setQrTimer(60);
setQrTimerActive(true);
}
const orderId = OrderId;
setPaymentOrderId(orderId);
setTimeout(() => {
setPaymentvia(null);
localStorage.clear();
// setshowPaymentSuccessAfterPayment(false)
setshowQrCode(false);
setTransctionId(null);
setPaymentOrderId(null);
Cookies.remove('UniqueId');
sessionStorage.clear();
dispatch(changeKioskOrderDetails([]));
dispatch(changeKioskPageName());
dispatch(changeOrderId());
dispatch(changeSalesId());
dispatch(changeisKioskCartOpen(false));
dispatch(changeMergeData([]));
dispatch(changeMembershipDetail([]));
// dispatch(changeOrderOfferDetail([]));
// dispatch(changeSelfBookingCustomerDtls([]));
// changeSelfBookingCustomerDtls([])
navigate(`${subDirectory}selfBooking/${isSelfBookingOpen}`);
}, 60000);
};
const onClose = () => {
dispatch(changeisKioskCartOpen(false));
setOpen(false);
};
const ChangeType = async (Type) => {
await dispatch(changeBookingType(Type));
};
const onComplete = useCallback(() => {
setMessageData(null);
setMessageType(null);
}, []);
// PostCancelPayment
const CancelPayment = async () => {
const response = await dispatch(PostCancelPayment({OrderId: TransctionId})).unwrap()
if (response?.data?.statusCode) {
// setBusinessUPI(false);
setpaymentUrl(null)
}
}
2026-01-27 18:27:29 +05:30
return (
<div>
<Messages
messageType={messageType}
messageData={messageData}
onComplete={onComplete}
/>
<div className="kioskpaymentmain">
<div className="selfkioskFootertopMain">
<div className="selfkioskFootertop1">
{KioskCurrentPage !== 'OrderView' && bookingTypeName == 'Both' && (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
cursor: 'pointer',
gap: ' 5px',
}}
onClick={() =>
BookingType === 'TakeAway' && ChangeType('Dine In')
}
>
<PozoDineInIcon
className={
BookingType == 'Dine In'
? 'BSBillingNav-icon-table pulse-element'
: 'BSBillingNav-icon'
}
/>
<p style={{ fontSize: '12px', fontWeight: '500' }}>DineIn</p>
</div>
)}
{KioskCurrentPage !== 'OrderView' && bookingTypeName == 'Both' && (
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
cursor: 'pointer',
gap: ' 5px',
}}
onClick={() =>
BookingType !== 'TakeAway' && ChangeType('TakeAway')
}
>
<TakeAway
className={
BookingType != 'Dine In'
? 'BSBillingNav-icon-table pulse-element'
: 'BSBillingNav-icon'
}
/>
<p style={{ fontSize: '12px', fontWeight: '500' }}>TakeAway</p>
</div>
)}
{/* {KioskOrderDetails?.length > 0 &&
KioskCurrentPage !== 'OrderView' && ( */}
<div
className="kioskpaymentviewsummary"
onClick={() => showDrawer()}
>
<Badge
count={KioskOrderDetails?.length}
style={{ marginTop: '7px' }}
>
<AiOutlineShoppingCart className="CarticonFooterKiosk" />
</Badge>
</div>
{/* )} */}
</div>
<table className="kiosksummarytable">
<tr>
<td className="kiosk-table-cell">
<div>
<span>Qty</span>
<span>: </span>
<span>
{' '}
{KioskOrderDetails?.reduce(
(total, item) => total + item?.OrderQty,
0
)}
</span>
</div>
</td>
<td className="kiosk-table-cell">
<div>
<span>Bill Amt</span>
<span>:</span>
<span>{Math.round(TotalBillAmount)}</span>
</div>
</td>
</tr>
<tr>
<td className="kiosk-table-cell">
<div>
<span>Items</span>
<span>:</span>
<span>{KioskOrderDetails?.length}</span>
</div>
</td>
<td
className="kiosk-table-cell"
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
border: 'none',
}}
>
<div>
<span>Tax</span>
<span> : </span>
<span> {TotalTaxAmount}</span>
</div>
{/* <MdCurrencyRupee size={16} style={{ marginBottom: '1px' }} /> */}
</td>
</tr>
</table>
</div>
<div className="selfkioskFooterBottomMain">
<div className="actionbuttonscontainer">
<p
className={
KioskOrderDetails?.length > 0 &&
KioskOrderDetails?.some((e) => !e?.disabled)
? 'orderbtnenabled'
: 'orderbtndisabled'
}
onClick={() => {
handleClick('Order');
}}
style={{
cursor:
KioskOrderDetails?.length > 0 && !clicked
? 'pointer'
: 'default',
// backgroundColor:
// KioskOrderDetails?.length > 0 &&
// !clicked &&
// getKioskDarkColourdata,
}}
>
Order
</p>
<>
{GeneratedOrderId && KioskOrderDetails?.length > 0 && (
<p
className={
KioskOrderDetails?.length > 0 && !clicked
? 'paybtnenabled'
: 'paybtndisabled'
}
onClick={() => {
handleClick('Pay');
}}
style={{
cursor:
KioskOrderDetails?.length > 0 && !clicked
? 'pointer'
: 'default',
// backgroundColor:
// KioskOrderDetails?.length > 0 &&
// !clicked &&
// getKioskDarkColourdata,
}}
>
Pay
</p>
)}
</>
<Drawer
title="Order View"
placement={placement}
width={480}
onClose={onClose}
open={open}
className="my-cls"
>
<SelfKisokOrderCart1 KioskOrderDetails={KioskOrderDetails} />
</Drawer>
{/* <div className="payVia" onClick={handlePayVia}>
PAY VIA {isPayViaOpen ? <FaAngleUp /> : <FaAngleDown />}
</div>
{isPayViaOpen && (
<div className="kiosk-action-buttons" style={{ padding: '10px' }}>
<button
className="kiosk-pay-btn"
onClick={() => {
// Handle pay functionality
console.log('Pay button clicked');
}}
>
Pay
</button>
<button
className="kiosk-merge-btn"
onClick={() => {
// Handle merge bill functionality
console.log('Merge Bill button clicked');
}}
>
Merge Bill
</button>
<button
className="kiosk-pay-request-btn"
onClick={() => {
// Handle pay request functionality
console.log('Pay Request button clicked');
}}
>
Pay Request
</button>
<button
className="kiosk-change-table-btn"
onClick={() => {
// Handle change table functionality
console.log('Change Table button clicked');
}}
>
Change Table
</button>
</div>
)} */}
</div>
<div className="actionbuttons2">
<p>Total Amount</p>
<div className="total-amount-display">
:{' '}
<MdCurrencyRupee
size={20}
style={{ marginBottom: '1px', marginRight: '-5px' }}
/>
{TotalNetAmount}{' '}
</div>
</div>
</div>
{/* <div className="payment-summary">
<div
style={{
display: 'flex',
width: '100%',
fontFamily: 'Poppins',
alignItems: 'center',
gap: '16px',
justifyContent: 'center',
}}
>
<p>
Qty :{' '}
{KioskOrderDetails?.reduce(
(total, item) => total + item?.OrderQty,
0
)}
</p>
<p>Items : {KioskOrderDetails?.length}</p>
</div>
<div
style={{
display: 'flex',
width: '100%',
alignItems: 'center',
gap: '10px',
justifyContent: 'center',
}}
>
<p style={{ color: '#37943c' }}>
Bill Amount : {TotalBillAmount}
</p>
{TotalTaxAmount > 0 && (
<p style={{ color: '#37943c' }}>
Tax :{' '}
<MdCurrencyRupee
style={{ marginTop: '2px', marginRight: '-5px' }}
/>{' '}
{TotalTaxAmount}
</p>
)}
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
<p style={{ color: '#37943C' }}>Total Amount</p>
<div style={{ display: 'flex' }}>
<div className="total-bill-SelfBooking">
{' '}
<MdCurrencyRupee
size={20}
style={{ marginBottom: '1px', marginRight: '-5px' }}
/>
{TotalNetAmount}{' '}
</div>
</div>
</div>
</div> */}
</div>
{showPaymentSuccess && (
<div
className="payment-success-popup"
style={{ display: 'flex', flexDirection: 'column', zIndex: '100' }}
>
{/* <div className="payment-success-content">
<span role="img" aria-label="success" style={{fontSize: 40, color: '#4BB543'}}></span>
<h2>Payment Successful!</h2>
<p>Your payment was processed successfully.</p>
</div> */}
{showPaymentSuccess && (
<SelfBookingPayment
modalOpen={showPaymentSuccess}
handleCancel={() => {
setShowPaymentSuccess(false);
}}
sessionData={sessionData}
HandlePayatCounter={placeOrder}
OrderMethod={OrderMethod}
/>
)}
</div>
)}
{showQrCode && paymentOrderId && Paymentvia && (
<>
<div className="qr-popup-overlay" />
<div className="qr-code-popup">
<p className="success-header">
Your payment has successfully completed! <br />
<FaCircleCheck size={50} color="#4BB543" className="success-icon" />
</p>
<div
onClick={async (e) => {
try {
e.preventDefault();
if (!TransctionId) {
setMessageType('error');
setMessageData('Transaction ID not found. Please contact support.');
return;
}
await handleShareWhatsAppFn(TransctionId);
} catch (error) {
console.error('Error in View Receipt click handler:', error);
setMessageType('error');
setMessageData('Failed to process receipt request. Please try again.');
}
}}
className="receipt-link"
>
View Receipt
</div>
<div className="order-id-display">
<p className="order-id-text">
Order ID: <span className="order-id-number">{paymentOrderId?.split('-').pop()}</span>
</p>
</div>
</div>
</>
)}
{showQrCode && paymentOrderId && !Paymentvia && (
<>
<div className="qr-popup-overlay" />
<div className="qr-code-popup">
<div className="counter-header">
<h2 className="counter-title">Go to counter for payment </h2>
</div>
<p className="qr-instruction">
Scan this QR code to view your order details
</p>
<div className="qr-container">
<OrderQR orderId={paymentOrderId} />
</div>
<div className="order-id-display">
<p className="order-id-text">
Order ID: <span className="order-id-number">{paymentOrderId?.split('-').pop()}</span>
</p>
</div>
<div className="qr-timer-display">
<div className="timer-circle">
<svg className="timer-svg" viewBox="0 0 100 100">
<circle
className="timer-circle-bg"
cx="50"
cy="50"
r="45"
/>
<circle
className="timer-circle-progress"
cx="50"
cy="50"
r="45"
style={{
strokeDashoffset: `${283 - (283 * qrTimer) / 60}`
}}
/>
</svg>
<div className="timer-text">{qrTimer}s</div>
</div>
</div>
</div>
</>
)}
<DefaultModal
open={isPhoneModalOpen}
title="Enter Your Phone Number"
handleCancel={handlePhoneModalCancel}
handleSubmit={handlePhoneModalSubmit}
buttonText={isPhoneLoading ? 'Processing...' : 'Continue'}
width={520}
footer={true}
className="phone-number-modal enhanced-phone-modal"
>
<div className="phone-modal-content">
<div className="phone-input-section">
<div className="input-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M6.62 10.79C8.06 13.62 10.38 15.94 13.21 17.38L15.41 15.18C15.69 14.9 16.08 14.82 16.43 14.93C17.55 15.3 18.75 15.5 20 15.5C20.55 15.5 21 15.95 21 16.5V20C21 20.55 20.55 21 20 21C10.61 21 3 13.39 3 4C3 3.45 3.45 3 4 3H7.5C8.05 3 8.5 3.45 8.5 4C8.5 5.25 8.7 6.45 9.07 7.57C9.18 7.92 9.1 8.31 8.82 8.59L6.62 10.79Z" fill="#4BB543"/>
</svg>
</div>
<label className="phone-label">Phone Number</label>
<Input
placeholder="Enter your 10-digit phone number"
value={phoneNumber}
onChange={(e) => setPhoneNumber(e.target.value)}
size="large"
className="phone-input"
maxLength={10}
type="tel"
prefix={<span className="country-code">+91</span>}
/>
</div>
<div className="phone-info-card">
<div className="info-icon">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
<path d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM13 17H11V11H13V17ZM13 9H11V7H13V9Z" fill="#1890ff"/>
</svg>
</div>
<p className="info-text">
We need your phone number for order tracking and delivery updates.
</p>
</div>
</div>
</DefaultModal>
{/* Order method modal: ask whether customer will come in person or needs home delivery */}
<DefaultModal
open={isOrderMethodModalOpen}
title="How would you like to receive your order?"
handleCancel={() => setIsOrderMethodModalOpen(false)}
handleSubmit={() => setShowPaymentSuccess(true)}
buttonText={null}
width={480}
footer={false}
className="order-method-modal"
>
<div
style={{
padding: '10px 0',
display: 'flex',
flexDirection: 'column',
gap: '12px',
}}
>
<p style={{ margin: 0, fontSize: '15px', color: '#333' }}>
Will you come in person, or do you need home delivery?
</p>
<div style={{ display: 'flex', gap: '12px', marginTop: '8px' }}>
<button
onClick={() => {
(setIsOrderMethodModalOpen(false),
setShowPaymentSuccess(true),
setOrderMethod('inPerson'));
}}
style={{
flex: 1,
padding: '12px 10px',
background: '#4BB543',
color: 'white',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
fontWeight: 600,
}}
>
I'll come in person
</button>
<button
onClick={() => {
(setIsOrderMethodModalOpen(false),
setShowPaymentSuccess(true),
setOrderMethod(null));
}}
style={{
flex: 1,
padding: '12px 10px',
background: '#1a73e8',
color: 'white',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
fontWeight: 600,
}}
>
Home delivery
</button>
</div>
</div>
</DefaultModal>
{paymentUrl != null && (
<div className="payment-modal">
<div className="modal-header">
<h2>Complete Payment</h2>
<button
className="paymentclose-btn"
onClick={() => {
// setpaymentUrl(null);
setShowCancelConfirm(true);
2026-01-27 18:27:29 +05:30
}}
>
</button>
</div>
<iframe
src={paymentUrl}
title="Payment"
className="payment-frame"
></iframe>
</div>
)}
{showCancelConfirm && (
<Modal
open={showCancelConfirm}
title="Cancel Payment"
onOk={() => {
setShowCancelConfirm(false);
CancelPayment()
}}
onCancel={() => setShowCancelConfirm(false)}
okText="Yes"
cancelText="No"
>
Do you want to cancel the payment?
</Modal>
)}
2026-01-27 18:27:29 +05:30
</div>
);
};
export default selfKioskFooter;