Android_Retail/src/Pages/BookingScreen/Components/UtillComponents/BSSelfBookingSearch.jsx

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;