Changeset 0c6b92a for imaps-frontend/src/components/SearchBar/SearchBar.jsx
Legend:
- Unmodified
- Added
- Removed
-
imaps-frontend/src/components/SearchBar/SearchBar.jsx
rd565449 r0c6b92a 1 import React, { useState } from "react"; 1 import React, { useState, useEffect, useRef } from "react"; 2 import ReactDOM from "react-dom"; 2 3 import searchIcon from "../../assets/search_icon.png"; 3 4 import routeIcon from "../../assets/route_icon.png"; … … 5 6 import styles from "./SearchBar.module.css"; 6 7 7 function SearchBar( props) {8 function SearchBar({ map, handleDirectionsSubmit, setIsPanelOpen, setSelectedRoom, availableShapes,handleFloorChange }) { 8 9 const [isExpanded, setIsExpanded] = useState(false); 9 10 const [from, setFrom] = useState(""); 10 11 const [to, setTo] = useState(""); 12 const [availableOptions, setAvailableOptions] = useState([]); 13 const [filteredOptions, setFilteredOptions] = useState([]); 14 const [dropdownVisible, setDropdownVisible] = useState(false); 15 const [inputFieldType, setInputFieldType] = useState(""); 16 const dropdownRef = useRef(null); 11 17 12 18 const toggleExpanded = () => { … … 14 20 }; 15 21 16 function searchRoom(){ 17 props.map.search(); 22 function searchRoom() { 23 let foundRoom = availableShapes.find(sh => sh.info.name === from) 24 console.log("map fnum",map.floorNum) 25 if(foundRoom.floorNum !== map.floorNum){ 26 handleFloorChange(foundRoom.floorNum); 27 } 18 28 29 30 console.log("FOUND ROOM: " + foundRoom) 31 map.highlightShape(from); 32 setSelectedRoom(foundRoom); 33 setIsPanelOpen(true); 19 34 } 20 35 21 const handleDirectionsSubmit = () => { 22 console.log(`From: ${from}, To: ${to}`); 23 const url = new URL('http://localhost:8080/api/public/navigate'); 24 url.searchParams.append('from', from); 25 url.searchParams.append('to', to); 36 const handleInputFocus = (field) => { 37 if (availableOptions.length === 0 && map) { 38 setAvailableOptions( 39 availableShapes 40 .filter((sh) => sh.className === "RenderedRoom") 41 .map((shape) => shape.info.name) 42 ); 43 } 44 setDropdownVisible(true); 45 setInputFieldType(field); 46 }; 26 47 27 fetch(url) 28 .then(response => { 29 if (!response.ok) { 30 throw new Error('Network response was not ok'); 31 } 32 return response.json(); 33 }) 34 .then(data => { 35 console.log('Success:', data); 36 const points = data.map(item => item.coordinates); 37 props.map.drawRoute(points); 38 }) 39 .catch(error => { 40 console.error('Error:', error); 41 }); 48 const handleInputChange = (setter) => (event) => { 49 const value = event.target.value; 50 setter(value); 51 setDropdownVisible(true); 52 53 const filtered = availableOptions.filter((option) => 54 option.toLowerCase().includes(value.toLowerCase()) 55 ); 56 setFilteredOptions(filtered); 57 }; 58 59 const handleOptionClick = (option) => { 60 if (inputFieldType === "from") { 61 setFrom(option); 62 } else if (inputFieldType === "to") { 63 setTo(option); 64 } 65 setDropdownVisible(false); 66 }; 67 68 const renderDropdown = () => { 69 if (!dropdownVisible || filteredOptions.length === 0) return null; 70 71 const position = dropdownRef.current?.getBoundingClientRect() || { top: 0, left: 0, width: 0 }; 72 73 return ReactDOM.createPortal( 74 <ul 75 className={styles.dropdown} 76 style={{ 77 position: "absolute", 78 top: position.top + position.height, 79 left: position.left, 80 width: position.width, 81 }} 82 > 83 {filteredOptions.map((option, index) => ( 84 <li 85 key={index} 86 className={styles.dropdownItem} 87 onClick={() => handleOptionClick(option)} 88 > 89 {option} 90 </li> 91 ))} 92 </ul>, 93 document.body // Portal renders outside the parent hierarchy 94 ); 42 95 }; 43 96 44 97 return ( 45 <div className={styles.wrapper}> 46 {/* Regular search bar */} 47 {!isExpanded ? ( 48 <div className={styles.searchBar}> 49 <input 50 type="search" 51 className={styles.inputField} 52 placeholder="Search location" 53 aria-label="Search" 54 /> 55 <div className={styles.buttons}> 56 <button type="button" className={styles.iconButton} onClick={searchRoom}> 57 <img src={searchIcon} alt="Search Icon" /> 58 </button> 59 <button type="button" className={styles.iconButton} onClick={toggleExpanded}> 60 <img src={routeIcon} alt="Route Icon" /> 61 </button> 62 </div> 63 </div> 64 ) : ( 65 /* Expanded view for directions */ 66 <div className={styles.directionsContainer}> 67 <div className={styles.directionsInputs}> 68 <input 69 type="text" 70 placeholder="From" 71 aria-label="From" 72 value={from} 73 onChange={(e) => setFrom(e.target.value)} 74 className={styles.inputField} 75 /> 76 <input 77 type="text" 78 placeholder="To" 79 aria-label="To" 80 value={to} 81 onChange={(e) => setTo(e.target.value)} 82 className={styles.inputField} 83 /> 84 </div> 85 <div className={styles.buttons}> 86 <button type="button" className={styles.iconButton} onClick={handleDirectionsSubmit}> 87 <img src={searchIcon} alt="Submit Directions" /> 88 </button> 89 <button type="button" className={styles.iconButton} onClick={toggleExpanded}> 90 <img src={closeIcon} alt="Close Icon" /> 91 </button> 92 </div> 93 </div> 94 )} 95 </div> 98 <div className={styles.wrapper}> 99 {!isExpanded ? ( 100 <div className={styles.searchBar}> 101 <input 102 type="search" 103 className={styles.inputField} 104 placeholder="Search location" 105 aria-label="Search" 106 ref={dropdownRef} // Attach the input to calculate dropdown position 107 onFocus={() => handleInputFocus("from")} 108 onChange={handleInputChange(setFrom)} 109 value={from} 110 /> 111 {renderDropdown()} 112 <div className={styles.buttons}> 113 <button type="button" className={styles.iconButton} onClick={searchRoom}> 114 <img src={searchIcon} alt="Search Icon" /> 115 </button> 116 <button type="button" className={styles.iconButton} onClick={toggleExpanded}> 117 <img src={routeIcon} alt="Route Icon" /> 118 </button> 119 </div> 120 </div> 121 ) : ( 122 <div className={styles.directionsContainer}> 123 <div className={styles.directionsInputs}> 124 <input 125 type="text" 126 placeholder="From" 127 aria-label="From" 128 value={from} 129 onFocus={() => handleInputFocus("from")} 130 onChange={handleInputChange(setFrom)} 131 className={styles.inputField} 132 ref={inputFieldType === "from" ? dropdownRef : null} 133 /> 134 <input 135 type="text" 136 placeholder="To" 137 aria-label="To" 138 value={to} 139 onFocus={() => handleInputFocus("to")} 140 onChange={handleInputChange(setTo)} 141 className={styles.inputField} 142 ref={inputFieldType === "to" ? dropdownRef : null} 143 /> 144 {renderDropdown()} 145 </div> 146 <div className={styles.buttons}> 147 <button 148 type="button" 149 className={styles.iconButton} 150 onClick={() => handleDirectionsSubmit(from, to)} 151 > 152 <img src={searchIcon} alt="Submit Directions" /> 153 </button> 154 <button type="button" className={styles.iconButton} onClick={toggleExpanded}> 155 <img src={closeIcon} alt="Close Icon" /> 156 </button> 157 </div> 158 </div> 159 )} 160 </div> 96 161 ); 97 162 }
Note:
See TracChangeset
for help on using the changeset viewer.