2026-01-27 18:27:29 +05:30
|
|
|
import { useDispatch, useSelector } from "react-redux";
|
|
|
|
|
import { useEffect, useRef, useState, useCallback } from "react";
|
|
|
|
|
import {
|
|
|
|
|
changeSearchedData,
|
|
|
|
|
getCardDataWithoutSub,
|
|
|
|
|
getCardDataWithoutSubmodule,
|
|
|
|
|
getLayoutproductCard,
|
|
|
|
|
getLayoutsearch,
|
|
|
|
|
getSelectedFavItems,
|
|
|
|
|
GlobalProductCategorie,
|
|
|
|
|
GlobalProductSubCategorie,
|
|
|
|
|
GlobalSearchData,
|
|
|
|
|
PreferenceData,
|
|
|
|
|
} from "../../../../Features/BookingScreen/BookingData/BookingData";
|
|
|
|
|
import { getTemplateData } from "../../../../Features/ThemeChange/ThemeChange";
|
|
|
|
|
import { getSession } from "../../../../Services/Others";
|
|
|
|
|
import axios from "axios";
|
|
|
|
|
import Search from "../../../../Components/Forms/Search";
|
|
|
|
|
import VoiceToTextItemCard from "../../../VoiceToText/VoiceToTextItemCard";
|
|
|
|
|
import { ApplicationPreferences } from "../../../../Features/BrachLogin/BranchLogin";
|
|
|
|
|
import { useDateStore } from "../../../../Features/BookingScreen/BookingData/DateStore";
|
|
|
|
|
|
|
|
|
|
const BSNavbarSearchStandard = ({ inputRef }) => {
|
|
|
|
|
const dispatch = useDispatch();
|
|
|
|
|
const { selectedDate } = useDateStore();
|
|
|
|
|
|
|
|
|
|
const CompId = getSession("CompId");
|
|
|
|
|
const BranchId = getSession("BranchId");
|
|
|
|
|
const AppId = getSession("AppId");
|
|
|
|
|
|
|
|
|
|
const preferences = useSelector(PreferenceData);
|
|
|
|
|
const preferenceSettings = preferences?.[0]?.SettingDtlDetails || [];
|
|
|
|
|
const ProdSubCat = useSelector(GlobalProductSubCategorie);
|
|
|
|
|
const ProdCat = useSelector(GlobalProductCategorie);
|
|
|
|
|
const ProdName = useSelector(GlobalSearchData);
|
|
|
|
|
const templateData = useSelector(getTemplateData);
|
|
|
|
|
const appPreferences = useSelector(ApplicationPreferences);
|
2026-02-04 18:10:12 +05:30
|
|
|
console.log(ProdName, "ProdName")
|
2026-01-27 18:27:29 +05:30
|
|
|
const [preFocus, setPreFocus] = useState(false);
|
|
|
|
|
const [screenWidth, setScreenWidth] = useState(window.innerWidth);
|
|
|
|
|
const [check, setCheck] = useState(false);
|
|
|
|
|
|
|
|
|
|
const debounceTimeoutRef = useRef(null);
|
|
|
|
|
const cancelTokenRef = useRef(null);
|
|
|
|
|
const [voiceSearch, setVoiceSearch] = useState(false);
|
|
|
|
|
|
|
|
|
|
const salespagefields = appPreferences?.find(
|
|
|
|
|
(pref) => pref?.PreferredCatName === 'Sales Page Fields'
|
|
|
|
|
)?.PreferenceCatDetails;
|
|
|
|
|
|
|
|
|
|
const AvailableDate = salespagefields?.find(
|
|
|
|
|
(type) =>
|
|
|
|
|
type?.PreferredSubCatName?.toLowerCase() === 'available date' &&
|
|
|
|
|
type?.PreferredStatus === 'Y'
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// --- Auto Focus Preference
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const shouldFocus = preferenceSettings.some(
|
|
|
|
|
(item) => item.SettingIdName === "SearchFocus" && item.SettingValue === "Y"
|
|
|
|
|
);
|
|
|
|
|
setPreFocus(shouldFocus || preferenceSettings.length === 0);
|
|
|
|
|
}, [preferenceSettings]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (preFocus && screenWidth > 768) {
|
|
|
|
|
inputRef?.current?.focus();
|
|
|
|
|
}
|
|
|
|
|
}, [preFocus, screenWidth, inputRef]);
|
|
|
|
|
|
|
|
|
|
// --- Screen Width Resize Listener
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const handleResize = () => setScreenWidth(window.innerWidth);
|
|
|
|
|
window.addEventListener("resize", handleResize);
|
|
|
|
|
return () => window.removeEventListener("resize", handleResize);
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
// --- Keyboard Shortcut Listener
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const handleKeyPress = (e) => {
|
|
|
|
|
if (e.shiftKey && e.code === "KeyS" && !["INPUT", "TEXTAREA"].includes(document.activeElement.tagName)) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
inputRef?.current?.focus();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
window.addEventListener("keydown", handleKeyPress);
|
|
|
|
|
return () => window.removeEventListener("keydown", handleKeyPress);
|
|
|
|
|
}, [inputRef]);
|
|
|
|
|
|
|
|
|
|
// --- Debounced Search Logic
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (debounceTimeoutRef.current) clearTimeout(debounceTimeoutRef.current);
|
|
|
|
|
|
|
|
|
|
debounceTimeoutRef.current = setTimeout(async () => {
|
2026-02-04 18:10:12 +05:30
|
|
|
|
2026-01-27 18:27:29 +05:30
|
|
|
const hasSearch = (Array?.isArray(ProdName) && ProdName?.length === 0 ? "" : ProdName)?.trim()?.length > 0;
|
|
|
|
|
|
|
|
|
|
if (hasSearch) {
|
|
|
|
|
if (cancelTokenRef.current) cancelTokenRef.current.cancel();
|
|
|
|
|
cancelTokenRef.current = axios.CancelToken.source();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await dispatch(
|
|
|
|
|
getLayoutsearch({
|
|
|
|
|
CompId,
|
|
|
|
|
BranchId,
|
|
|
|
|
AppId,
|
|
|
|
|
ProdName,
|
|
|
|
|
cancelToken: cancelTokenRef.current.token,
|
|
|
|
|
...(AvailableDate && selectedDate
|
|
|
|
|
? {
|
|
|
|
|
fromDate: selectedDate?.[0],
|
|
|
|
|
toDate: selectedDate?.[1],
|
|
|
|
|
}
|
|
|
|
|
: {})
|
|
|
|
|
})
|
|
|
|
|
)?.unwrap();
|
|
|
|
|
setCheck(true);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
if (!axios.isCancel(err)) console.error("Search error:", err.message);
|
|
|
|
|
}
|
|
|
|
|
} else if (check) {
|
|
|
|
|
loadDefaultCards();
|
|
|
|
|
}
|
|
|
|
|
}, 400);
|
|
|
|
|
|
|
|
|
|
return () => clearTimeout(debounceTimeoutRef.current);
|
|
|
|
|
}, [ProdName]);
|
|
|
|
|
|
|
|
|
|
// --- Default Card Loader
|
|
|
|
|
const loadDefaultCards = useCallback(async () => {
|
|
|
|
|
await dispatch(getSelectedFavItems({ CompId, BranchId, AppId }));
|
|
|
|
|
|
|
|
|
|
const hasSubCat = templateData?.BookingLayout?.[1]?.some((i) => i?.OptionName === "SubCategory");
|
|
|
|
|
const payload = { compId: CompId, branchId: BranchId, appId: AppId, prodCat: ProdCat };
|
|
|
|
|
|
|
|
|
|
if (hasSubCat && ProdSubCat) {
|
|
|
|
|
await dispatch(getLayoutproductCard({ ...payload, ProdSubCat }));
|
|
|
|
|
} else if (!hasSubCat) {
|
|
|
|
|
await dispatch(getCardDataWithoutSubmodule(payload));
|
|
|
|
|
} else {
|
|
|
|
|
await dispatch(getCardDataWithoutSub(payload));
|
|
|
|
|
}
|
|
|
|
|
}, [dispatch, CompId, BranchId, AppId, ProdCat, ProdSubCat, templateData]);
|
|
|
|
|
|
|
|
|
|
// --- Search Handler
|
|
|
|
|
const handleSearch = (e) => {
|
|
|
|
|
dispatch(changeSearchedData(e?.target?.value));
|
|
|
|
|
};
|
|
|
|
|
const HandleVoiceSearch = () => {
|
|
|
|
|
setVoiceSearch(!voiceSearch);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<Search
|
|
|
|
|
placeholder="Search Product (SHIFT + S)"
|
|
|
|
|
onSearchChange={handleSearch}
|
|
|
|
|
ref={inputRef}
|
|
|
|
|
value={ProdName}
|
|
|
|
|
/>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default BSNavbarSearchStandard;
|