374 lines
12 KiB
JavaScript
374 lines
12 KiB
JavaScript
import '../../../../Styles/BookingScreen/Components/UtillComponents/BSNavBarComponents.scss';
|
|
import { useRef, useState, useEffect, useCallback } from 'react';
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
import { IoCloseOutline, IoSearchOutline } from 'react-icons/io5';
|
|
import { BiBarcodeReader } from 'react-icons/bi';
|
|
import { isMobile } from 'react-device-detect';
|
|
import { debounce } from 'lodash';
|
|
|
|
import {
|
|
changeKisokSearchedData,
|
|
GlobalfocusStatusBalrec,
|
|
GlobalfocusStatusCustMouse,
|
|
ChangeSearchFocusPreOrder,
|
|
GlobalKisoksearchedData,
|
|
} from '../../../../Features/BookingScreen/BookingData/BookingData.js';
|
|
import { ArrowRightOutlined } from '@ant-design/icons';
|
|
import { DefaultModal } from '../../../../Components/Modal/DefaultModal.jsx';
|
|
import BarcodeScanner from './BarcodeScanner';
|
|
import { CiBarcode } from 'react-icons/ci';
|
|
import {
|
|
changeCardlistDate,
|
|
getCardlistDate,
|
|
globalCurrentKioskPageName,
|
|
} from '../../../../Features/Kiosk/kiosk.js';
|
|
import dayjs from 'dayjs';
|
|
import moment from 'moment';
|
|
import { DatePicker } from 'antd';
|
|
import {
|
|
changeSelfBookingCustomerDtls,
|
|
GlobalMembershipDetail,
|
|
GlobalSelfBookingCustomerDtls,
|
|
PostSelfBookingCustomer,
|
|
} from '../../../../Features/BookingScreen/BookingData/KioskBookingData.js';
|
|
import { Crown } from 'lucide-react';
|
|
import MemberShipCard from '../../../MemberShipSelfBooking/MemberShipCard.jsx';
|
|
import BSMembership from './BSMembership.jsx';
|
|
import { getSession } from '../../../../Services/Others.js';
|
|
import Buttons from '../../../../Components/Forms/Buttons.jsx';
|
|
import { Messages } from '../../../../../ownLib/my-ui-lib.js';
|
|
const BSKioskSearch = (props) => {
|
|
const selfBookingOption = sessionStorage.getItem('selfBookingOption');
|
|
const dispatch = useDispatch();
|
|
const searchInputRef = useRef(null);
|
|
const scannerRef = useRef();
|
|
const searchFocuStatus = useSelector(GlobalfocusStatusBalrec);
|
|
const mouseCustFocus = useSelector(GlobalfocusStatusCustMouse);
|
|
const CurrentPageName = useSelector(globalCurrentKioskPageName);
|
|
const selectedDate = useSelector(getCardlistDate);
|
|
const AppName = sessionStorage.getItem('AppName');
|
|
const AppId = getSession('AppId');
|
|
const CompId = getSession('CompId');
|
|
const BranchId = getSession('BranchId');
|
|
const MembershipDetail = useSelector(
|
|
GlobalMembershipDetail
|
|
)?.MembershipDetail;
|
|
const KisoksearchedData = useSelector(GlobalKisoksearchedData);
|
|
|
|
// Local States
|
|
const [messageType, setMessageType] = useState(null);
|
|
const [messageData, setMessageData] = useState(null);
|
|
const [memberShip, setSetmemberShip] = useState(false);
|
|
const [focused, setFocused] = useState(true);
|
|
const [screenWidth, setScreenWidth] = useState(window.innerWidth);
|
|
const [preFocus, setPreFocus] = useState(true);
|
|
const [openScanner, setOpenScanner] = useState(false);
|
|
const [searchInput, setSearchInput] = useState(null);
|
|
const [showSearch, setShowSearch] = useState(false);
|
|
const [showUserModal, setShowUserModal] = useState(false);
|
|
const [userNumber, setUserNumber] = useState('');
|
|
|
|
// Debounced dispatch
|
|
const debouncedDispatch = useCallback(
|
|
debounce((value) => {
|
|
dispatch(changeKisokSearchedData(value));
|
|
}, 400),
|
|
[]
|
|
);
|
|
|
|
const handleChange = (e) => {
|
|
setSearchInput(e?.target?.value);
|
|
debouncedDispatch(e.target.value);
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (KisoksearchedData == null) {
|
|
setSearchInput('');
|
|
}
|
|
}, [KisoksearchedData]);
|
|
|
|
// Manage focus & blur states
|
|
useEffect(() => {
|
|
if (mouseCustFocus || searchFocuStatus || screenWidth < 768 || !preFocus) {
|
|
setFocused(false);
|
|
searchInputRef.current?.blur();
|
|
dispatch(ChangeSearchFocusPreOrder(false));
|
|
} else if (preFocus && screenWidth > 768) {
|
|
setFocused(true);
|
|
searchInputRef.current?.focus();
|
|
}
|
|
}, [mouseCustFocus, searchFocuStatus, screenWidth, preFocus]);
|
|
|
|
// Screen resize listener
|
|
useEffect(() => {
|
|
const handleResize = () => setScreenWidth(window.innerWidth);
|
|
window.addEventListener('resize', handleResize);
|
|
return () => window.removeEventListener('resize', handleResize);
|
|
}, []);
|
|
|
|
// Outside click handling
|
|
useEffect(() => {
|
|
const handleClickOutside = (event) => {
|
|
if (
|
|
searchInputRef.current &&
|
|
!searchInputRef.current.contains(event.target)
|
|
) {
|
|
setFocused(false);
|
|
}
|
|
};
|
|
document.addEventListener('mousedown', handleClickOutside);
|
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
}, []);
|
|
|
|
const handleBlur = () => {
|
|
if (preFocus && screenWidth > 768) setFocused(true);
|
|
};
|
|
|
|
// Scanner Handling
|
|
const stopScannerFromParent = () => {
|
|
scannerRef.current?.stopScanner();
|
|
};
|
|
|
|
const handleQrcode = () => {
|
|
setOpenScanner((prev) => !prev);
|
|
if (!openScanner) scannerRef.current?.reinitializeCamera();
|
|
};
|
|
|
|
const handleQrData = async (value, err) => {
|
|
if (err && err?.error) {
|
|
setMessageData(err?.error);
|
|
setMessageType('error');
|
|
}
|
|
dispatch(changeKisokSearchedData(value));
|
|
setOpenScanner(false);
|
|
stopScannerFromParent();
|
|
};
|
|
|
|
const handleToggleSearch = () => {
|
|
setShowSearch((prev) => !prev);
|
|
|
|
// Optional: focus input when opened
|
|
setTimeout(() => {
|
|
if (!showSearch && searchInputRef.current) {
|
|
searchInputRef.current.focus();
|
|
}
|
|
}, 0);
|
|
};
|
|
const disablePastDates = (current) => {
|
|
return current && current < moment().startOf('day');
|
|
};
|
|
const changeDateFunction = (date) => {
|
|
if (date) {
|
|
dispatch(changeCardlistDate(date));
|
|
console.log('Selected Date:', date.format('DD-MM-YYYY'));
|
|
} else {
|
|
dispatch(changeCardlistDate(null));
|
|
}
|
|
};
|
|
const handlePostCustnumber = async () => {
|
|
try {
|
|
let response = await dispatch(
|
|
PostSelfBookingCustomer({
|
|
CompId: CompId,
|
|
BranchId: BranchId,
|
|
AppId: AppId,
|
|
CustMobile: userNumber,
|
|
})
|
|
).unwrap();
|
|
if (response?.data?.statusCode == 1 || response?.data?.statusCode == 2) {
|
|
dispatch(
|
|
changeSelfBookingCustomerDtls(response?.data?.CustomerDetails?.[0])
|
|
);
|
|
setShowUserModal(false);
|
|
} else {
|
|
dispatch(changeSelfBookingCustomerDtls(null));
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
};
|
|
const onComplete = useCallback(() => {
|
|
setMessageData(null);
|
|
setMessageType(null);
|
|
}, []);
|
|
return (
|
|
<>
|
|
<Messages
|
|
messageType={messageType}
|
|
messageData={messageData}
|
|
onComplete={onComplete}
|
|
/>
|
|
<div>
|
|
{AppName?.toLowerCase() !== 'sports' && (
|
|
<>
|
|
{selfBookingOption === 'Search Only' ? (
|
|
<div className="Prdinput-container1">
|
|
<div className="search-container-code">
|
|
{showSearch && (
|
|
<div
|
|
className={`search-input ${props.nosearch ? 'no-search' : ''}`}
|
|
>
|
|
<input
|
|
// type="number"
|
|
value={searchInput}
|
|
// ref={searchInputRef}
|
|
className="custom-input1"
|
|
placeholder="Search..."
|
|
onChange={handleChange}
|
|
onBlur={handleBlur}
|
|
/>
|
|
</div>
|
|
)}
|
|
<button
|
|
onClick={handleToggleSearch}
|
|
className="search-button-code"
|
|
>
|
|
{showSearch ? <IoCloseOutline /> : <IoSearchOutline />}
|
|
</button>
|
|
</div>
|
|
|
|
<div className="barcode-container" onClick={handleQrcode}>
|
|
<CiBarcode className="barcode-icon1" />
|
|
<h2>Barcode</h2>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="Prdinput-container">
|
|
<div className="search-input" style={props.nosearch ? {} : {}}>
|
|
<input
|
|
// type="number"
|
|
value={searchInput}
|
|
// ref={searchInputRef}
|
|
className="custom-input"
|
|
placeholder="Search"
|
|
onChange={handleChange}
|
|
onBlur={handleBlur}
|
|
/>
|
|
{isMobile && screenWidth <= 768 ? (
|
|
<BiBarcodeReader
|
|
className="search-icon"
|
|
onClick={handleQrcode}
|
|
/>
|
|
) : (
|
|
<IoSearchOutline className="search-icon" />
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
{/* Scanner Modal */}
|
|
{isMobile && screenWidth <= 768 && (
|
|
<DefaultModal
|
|
title="Barcode Reader"
|
|
width={800}
|
|
open={openScanner}
|
|
footer={false}
|
|
handleCancel={handleQrData}
|
|
>
|
|
{openScanner && (
|
|
<BarcodeScanner
|
|
ref={scannerRef}
|
|
openScanner={openScanner}
|
|
setOpenScanner={setOpenScanner}
|
|
handleQrData={handleQrData}
|
|
type="Search"
|
|
/>
|
|
)}
|
|
</DefaultModal>
|
|
)}
|
|
|
|
<DefaultModal
|
|
open={memberShip}
|
|
title="Membership"
|
|
handleCancel={() => {
|
|
setSetmemberShip(false);
|
|
}}
|
|
footer={false}
|
|
className={'ProddtlModalTable'}
|
|
width={400}
|
|
children={
|
|
<div>
|
|
<MemberShipCard data={MembershipDetail?.[0]} />
|
|
</div>
|
|
}
|
|
/>
|
|
|
|
<DefaultModal
|
|
open={showUserModal}
|
|
title="Enter Your Number"
|
|
handleCancel={() => {
|
|
setShowUserModal(false);
|
|
setUserNumber('');
|
|
}}
|
|
footer={false}
|
|
handleSubmit={handlePostCustnumber}
|
|
okText="Save"
|
|
width={400}
|
|
children={
|
|
<div style={{ padding: '20px' }}>
|
|
<input
|
|
type="text"
|
|
value={userNumber}
|
|
onChange={(e) => {
|
|
const value = e.target.value;
|
|
// Allow only numbers and max 10 digits
|
|
if (/^\d{0,10}$/.test(value)) {
|
|
setUserNumber(value);
|
|
}
|
|
}}
|
|
placeholder="Enter user number"
|
|
style={{
|
|
width: '100%',
|
|
padding: '8px',
|
|
borderRadius: '4px',
|
|
border: '1px solid #d9d9d9',
|
|
}}
|
|
maxLength={10}
|
|
/>
|
|
{userNumber.length > 0 && userNumber.length < 10 && (
|
|
<p style={{ color: 'red', marginTop: '8px', fontSize: '12px' }}>
|
|
Number must be 10 digits
|
|
</p>
|
|
)}
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
flexDirection: 'row-reverse',
|
|
paddingTop: '10px',
|
|
}}
|
|
>
|
|
<button
|
|
onClick={handlePostCustnumber}
|
|
disabled={userNumber.length !== 10}
|
|
style={{
|
|
backgroundColor:
|
|
userNumber.length === 10 ? '#901D77' : '#ccc',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '6px',
|
|
padding: '10px 16px',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
gap: '8px',
|
|
cursor:
|
|
userNumber.length === 10 ? 'pointer' : 'not-allowed',
|
|
transition: 'all 0.2s ease-in-out',
|
|
textTransform: 'uppercase',
|
|
}}
|
|
>
|
|
Submit <ArrowRightOutlined />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
}
|
|
/>
|
|
</div>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default BSKioskSearch;
|