import classNames from "classnames";
import { SearchIcon } from "./icons";
import { useState, useEffect, useRef, useCallback } from "@wordpress/element";
import useSearch from "../../hooks/useSearch";
import { Excerpt } from "../shared/templates/templates-parts/templates-parts";
import { findDataFromArray } from "../../controls/controls";
import useMetaData from "../../hooks/useMetaData";
const Render = ({ attributes }) => {
const { displayType, searchResultDisplayType } = attributes;
const [isPopupOpen, setIsPopupOpen] = useState(false);
return (
<>
{"popup" === displayType && (
)}
{displayType === "popup" && (
setIsPopupOpen(false)}
>
)}
>
);
};
const SmartSearchBody = ({ attributes, isPopupOpen, setIsPopupOpen }) => {
const { displayType, popupHeadingText, enablePopupHeading, popupHeadingGlobalTypography, enablePopupCloseButton } =
attributes;
const { posts, remaining_posts, fetchPosts } = useSearch(attributes);
const [isLoading, setIsLoading] = useState(false);
const [searchText, setSearchText] = useState("");
const [isShow, setIsShow] = useState(!!searchText && !isLoading);
const [popupClass, setPopupClass] = useState("");
const searchRef = useRef(null);
useEffect(() => {
if (!!searchText && !isLoading) {
setIsShow(true);
}
}, [searchText, isLoading]);
useEffect(() => {
if (!searchRef.current) {
return;
}
const updatePosition = () => {
const rect = searchRef.current.getBoundingClientRect();
const viewportWidth = document.documentElement.clientWidth;
if (rect.right > viewportWidth) {
setPopupClass("sp-popup-position-right");
} else {
setPopupClass("sp-popup-position-left");
}
};
updatePosition();
window.addEventListener("resize", updatePosition);
return () => {
window.removeEventListener("resize", updatePosition);
};
}, []);
return (
{
// If focus left the entire search wrapper → close dropdown
if (!searchRef.current.contains(e.relatedTarget)) {
setIsShow(false);
}
}}
className={classNames(
"sp-smart-post-search-wrapper",
displayType === "popup" && "sp-smart-post-search-popup",
isPopupOpen && displayType === "popup" && "sp-smart-post-search-popup--active",
popupClass
)}
>
{displayType === "popup" && enablePopupHeading && (
{popupHeadingText}
)}
{displayType === "popup" && enablePopupCloseButton && (
setIsPopupOpen(false)}>
)}
{/*
*/}
);
};
const SearchForm = ({ attributes, setSearchText, setIsLoading, searchText, isLoading, fetchPosts }) => {
const {
searchFormPreset,
placeholder,
placeholderEnable,
searchBtnLabel,
searchIcon,
inputPlaceHolderGlobalTypography,
selectedTaxonomy,
selectedTerms,
postType,
filterLabelText,
taxonomyFilterEnable,
searchBtnLabelText,
} = attributes;
const { allTaxonomies } = useMetaData(attributes, "editSite");
const selectedTaxonomyData = findDataFromArray(allTaxonomies, "name", selectedTaxonomy);
const _terms = selectedTaxonomyData?.terms_items.map((item) => ({
...item,
id: item.value,
}));
const terms = selectedTerms?.length > 0 ? selectedTerms : _terms;
const [selectedTerm, setSelectedTerm] = useState("");
const debounceTimer = useRef(null);
const inputRef = useRef(null);
const handleSearch = useCallback(
async (query, term) => {
try {
setIsLoading(true);
await fetchPosts(query, term);
} catch (error) {
console.log("Error fetching posts:", error.message);
} finally {
setIsLoading(false);
}
},
[searchText, selectedTerm, postType]
);
useEffect(() => {
if (debounceTimer.current) {
clearTimeout(debounceTimer.current);
}
if (searchText) {
debounceTimer.current = setTimeout(() => {
handleSearch(searchText, selectedTerm);
}, 500);
}
return () => clearTimeout(debounceTimer.current);
}, [searchText, handleSearch, postType]);
useEffect(() => {
if (selectedTerm) {
handleSearch(searchText, selectedTerm);
}
}, [selectedTerm]);
const onSubmit = (e) => {
e.preventDefault();
handleSearch(searchText, selectedTerm);
};
const handleTermChange = (e) => {
e.stopPropagation();
const value = e.target.value;
if (value) {
setSelectedTerm(value);
}
};
const formHandler = (e) => {
e.stopPropagation();
inputRef.current.focus();
};
return (
);
};
const SearchResult = ({ attributes, posts, remaining_posts, isShow }) => {
const {
searchResultDisplayType,
searchResultNotFoundText,
moreResultLabelText,
moreResultsEnable,
showResultsCount,
} = attributes;
return (
{posts?.length > 0 ? (
posts.map((post, index) => {
return
;
})
) : (
{searchResultNotFoundText}
)}
{/* TODO: Need to manage loading state if needed in future */}
{/* {isLoading ? (
) : (
<>
>
)} */}
{moreResultsEnable && remaining_posts > 0 && (
)}
);
};
const SearchItem = ({ post, attributes }) => {
const { categories, author, image_alt, post_thumbnail_url, date, excerpt, postTitle } = post;
const {
searchResultDisplayType,
searchResultTitleGlobalTypography,
searchResultMetaGlobalTypography,
searchResultShowImage,
searchResultShowExcerpt,
searchResultShowTaxonomy,
searchResultExcerptLimit,
searchResultShowDate,
searchResultShowAuthor,
} = attributes;
return (
{searchResultDisplayType !== "smart-search-result-layout-two" && searchResultShowImage && (
)}
{searchResultShowTaxonomy && categories?.length > 0 && (
{categories?.map((category, index) => {
return (
{category}
);
})}
)}
{post?.title}
{searchResultShowExcerpt && excerpt && (
)}
{(searchResultShowDate || searchResultShowAuthor) && (
{author && searchResultShowAuthor && {author}, }
{date && searchResultShowDate && {date}}
)}
);
};
export default Render;