diff --git a/prediction-polls/frontend/src/Components/SearchBar/index.jsx b/prediction-polls/frontend/src/Components/SearchBar/index.jsx index cb9a9626..725defea 100644 --- a/prediction-polls/frontend/src/Components/SearchBar/index.jsx +++ b/prediction-polls/frontend/src/Components/SearchBar/index.jsx @@ -6,9 +6,12 @@ import styles from "./SearchBar.module.css"; function SearchBar({ onSearch }) { const [searchText, setSearchText] = useState(''); - const handleSearch = value => { - setSearchText(value); - onSearch(value); + const handleInputChange = (e) => { + setSearchText(e.target.value); + }; + + const handleSearchTrigger = () => { + onSearch(searchText); }; return ( @@ -17,8 +20,13 @@ function SearchBar({ onSearch }) { style={{ padding: '10px' }} placeholder="Search with question, tag, and creator name" value={searchText} - onChange={e => handleSearch(e.target.value)} - prefix={} + onChange={handleInputChange} + onPressEnter={handleSearchTrigger} + suffix={ + + + + } allowClear /> diff --git a/prediction-polls/frontend/src/Pages/Feed/index.jsx b/prediction-polls/frontend/src/Pages/Feed/index.jsx index f686359e..f12a7afd 100644 --- a/prediction-polls/frontend/src/Pages/Feed/index.jsx +++ b/prediction-polls/frontend/src/Pages/Feed/index.jsx @@ -7,11 +7,13 @@ import pointData from "../../MockData/PointList.json"; import SearchBar from "../../Components/SearchBar"; import getProfileMe from "../../api/requests/profileMe.jsx"; import { useNavigate } from "react-router-dom"; +import { Spin } from 'antd'; function Feed() { const [pollData, setPollData] = useState({ pollList: [] }); const [filteredPolls, setFilteredPolls] = useState(pollData.pollList); const [userData, setUserData] = useState({}); + const [spinning, setSpinning] = useState(false); React.useEffect(() => { const data = getProfileMe(); @@ -24,6 +26,7 @@ function Feed() { useEffect(() => { const fetchData = async () => { + setSpinning(true); try { const response = await fetch(url + "/polls", { method: "GET", @@ -58,6 +61,7 @@ function Feed() { } catch (error) { console.error("Error fetching polls:", error); } + setSpinning(false); }; fetchData(); @@ -66,32 +70,70 @@ function Feed() { const handleSearch = (searchText) => { - if (!searchText.trim()) { - setFilteredPolls(pollData.pollList); - return; - } + setSpinning(true); + if (!searchText.trim()) { + setFilteredPolls(pollData.pollList); + setSpinning(false); + return; + } + + const lowerCaseSearchText = searchText.toLowerCase(); + + // Filter local polls + const localFiltered = pollData.pollList.filter((poll) => { + const questionMatch = poll.question + .toLowerCase() + .includes(lowerCaseSearchText); + const tagsMatch = + poll.tags && + poll.tags.some((tag) => + tag.toLowerCase().includes(lowerCaseSearchText) + ); + const creatorNameMatch = + poll.creatorName && + poll.creatorName.toLowerCase().includes(lowerCaseSearchText); + + return questionMatch || tagsMatch || creatorNameMatch; + }); + + // Make a GET request to the semantic search endpoint + const fetchSemanticSearch = async () => { + try { + const response = await fetch(`${url}/semantic/pollsearch?keyword=${encodeURIComponent(lowerCaseSearchText)}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${localStorage.getItem("accessToken")}`, + } + }); - const lowerCaseSearchText = searchText.toLowerCase(); - - const filtered = pollData.pollList.filter((poll) => { - const questionMatch = poll.question - .toLowerCase() - .includes(lowerCaseSearchText); - const tagsMatch = - poll.tags && - poll.tags.some((tag) => - tag.toLowerCase().includes(lowerCaseSearchText) - ); - const creatorNameMatch = - poll.creatorName && - poll.creatorName.toLowerCase().includes(lowerCaseSearchText); - - return questionMatch || tagsMatch || creatorNameMatch; - }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const semanticData = await response.json(); - setFilteredPolls(filtered); + // Combine local filtered polls with semantic search results + const combinedPolls = [...localFiltered]; + + // Add polls from semanticData if they don't already exist in combinedPolls + semanticData.forEach((semanticPoll) => { + const exists = combinedPolls.some(poll => poll.id === semanticPoll.id); + if (!exists) { + combinedPolls.push(semanticPoll); + } + }); + setFilteredPolls(combinedPolls); + } catch (error) { + // Fallback to local filtered results if semantic search fails + setFilteredPolls(localFiltered); + } + setSpinning(false); }; + fetchSemanticSearch(); +}; + return (
@@ -108,6 +150,7 @@ function Feed() {
+
); }