Changeset 0c6b92a for imaps-frontend/src/pages/Draw
- Timestamp:
- 12/12/24 17:06:06 (5 weeks ago)
- Branches:
- main
- Parents:
- d565449
- Location:
- imaps-frontend/src/pages/Draw
- Files:
-
- 4 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
imaps-frontend/src/pages/Draw/Draw.jsx
rd565449 r0c6b92a 1 import { useEffect, useState } from "react"; 2 import { MapBuilder } from "../../scripts/main/MapBuilder.js"; 1 import { useContext, useEffect, useState } from "react"; 3 2 import styles from "./Draw.module.css"; 4 import RoomModal from "../../components/RoomModal/RoomModal.jsx"; 5 import SideBar from "../../components/SideBar/SideBar.jsx"; 6 import EntranceModal from "../../components/EntranceModal/EntranceModal.jsx"; 3 import RoomModal from "../../components/Modals/RoomModal/RoomModal.jsx"; 4 import EntranceModal from "../../components/Modals/EntranceModal/EntranceModal.jsx"; 7 5 import DrawGuide from "../../components/DrawGuide/DrawGuide.jsx"; 8 import RoomTypeModal from "../../components/RoomTypeModal/RoomTypeModal.jsx"; 9 import InfoPinModal from "../../components/InfoPinModal/InfoPinModal.jsx"; 6 import RoomTypeModal from "../../components/Modals/RoomTypeModal/RoomTypeModal.jsx"; 7 import InfoPinModal from "../../components/Modals/InfoPinModal/InfoPinModal.jsx"; 8 import SaveMap from "../../components/SaveMap/SaveMap.jsx"; 9 import Logo from "../../components/Logo/Logo.jsx"; 10 import { Link, useNavigate, useParams, useSearchParams } from "react-router-dom"; 11 import Profile from "../../components/Profile/Profile.jsx"; 10 12 import HttpService from "../../scripts/net/HttpService.js"; 11 import SaveMap from "../../components/SaveMap/SaveMap.jsx"; 12 import logo from "../../assets/logo_icon.png"; 13 import MapTemplateSelector from "../../components/MapTemplateSelector/LoadMap.jsx"; 14 import KeymapPanel from "../../components/KeyMappingsGuidePanel/KeymapPanel.jsx"; 15 import { Link } from "react-router-dom"; 13 import StairsModal from "../../components/Modals/StairsModal/StairsModal.jsx"; 14 import useMapLoader from "./Hooks/useMapLoader.js"; 15 import {FloorSelector} from "./FloorSelector.jsx"; 16 import {useRoomTypesLoader} from "./Hooks/useRoomTypesLoader.js"; 17 import {useAppContext} from "../../components/AppContext/AppContext.jsx"; 18 import config from "../../scripts/net/netconfig.js"; 19 import ShapeRegistry from "../../scripts/util/ShapeRegistry.js"; 16 20 17 21 function Draw() { 18 const [selectedFloor, setSelectedFloor] = useState(1); 19 const [app, setApp] = useState(null); 22 const { mapName } = useParams(); 23 const { username } = useAppContext(); 24 20 25 const [isPopupVisible, setIsPopupVisible] = useState(false); 26 const [errorMessage, setErrorMessage] = useState("Error"); 27 const [hasError, setHasError] = useState(false); 28 const [searchParams, setSearchParams] = useSearchParams(); 29 30 const[roomTypes,setRoomTypes] = useState([]); 31 32 const {app,floors,saveFloor,setFloors} = useMapLoader(mapName,username,searchParams,setSearchParams) 33 const {addRoomType} = useRoomTypesLoader(setRoomTypes,mapName,username); 34 35 const addFloorHandler = async (newFloorNum) => { 36 const httpService = new HttpService(); 37 httpService.setAuthenticated(); 38 39 const payload = { 40 num: newFloorNum, 41 mapName: mapName, 42 }; 43 44 try { 45 await httpService.put(`${config.floors.add}`, payload); 46 console.log(`Added floor ${newFloorNum}`); 47 setFloors((prevFloors) => [...prevFloors, { num: newFloorNum }]); 48 } catch (error) { 49 console.error("Error adding floor:", error); 50 } 51 }; 52 53 const deleteFloorHandler = async (floorNum) => { 54 if(floorNum === 0) return 55 56 const httpService = new HttpService(); 57 httpService.setAuthenticated(); 58 59 try { 60 await httpService.delete(`${config.floors.delete}?floorNum=${floorNum}&mapName=${mapName}`); 61 setFloors((prevFloors) => prevFloors.filter(f => f.num !== floorNum)) 62 63 const currFloor = searchParams.get("floor"); 64 if(currFloor == floorNum){ 65 setSearchParams({floor:"0"},{replace:true}) 66 } 67 console.log(`Deleted floor ${floorNum}`); 68 } catch (error) { 69 console.error("Error deleting floor:", error); 70 } 71 }; 72 21 73 useEffect(() => { 22 const app = new MapBuilder("container");23 setApp(app);24 // fpsCounterLoop();74 return () => { 75 ShapeRegistry.clear(); 76 } 25 77 }, []); 26 78 27 const handleFloorChange = (event) => {28 setSelectedFloor(event.target.value);29 console.log(`Floor changed to: ${event.target.value}`);30 };31 79 32 const handleRenderClick = () => { 33 setIsPopupVisible(true); 80 const handleSaveClick = async () => { 81 saveFloor().then(r => { 82 floors.forEach(flr => { 83 setIsPopupVisible(true); 84 setTimeout(() => { 85 setIsPopupVisible(false);}, 86 3000); 87 console.log("floor after save: " + JSON.stringify(flr)) 88 }) 89 }); 34 90 35 setTimeout(() => {36 setIsPopupVisible(false);37 }, 3000);38 };39 91 40 const handleSaveClick = async (mapName) => {41 const resp = await app.saveMap(mapName);42 };43 const handleLoadMapClick = (data) => {44 app.deserializeMap(data);45 92 }; 46 93 47 94 return ( 48 95 <div className={styles.wrapper} id="wrapper"> 49 <SideBar></SideBar> 96 {/* <SideBar></SideBar> */} 97 <Logo></Logo> 50 98 <div id="container" className={styles.cont}></div> 51 99 <div className={styles.panel}> 52 <Link to="/"> 53 <img src={logo} alt="Finki Logo" className={styles.logo} /> 100 <div className={styles.topPanelH}> 101 <Profile position="inline"></Profile> 102 </div> 103 <Link to={`/myMaps/${mapName}/View`} className={styles.titleLink}> 104 <h1 className={styles.title}>{mapName}</h1> 54 105 </Link> 55 <h1 className={styles.title}>Map Builder</h1>56 {/* <div id="fpscont" className={styles.fpscounter}>57 <p id="fpsCounter"></p>58 </div> */}59 106 <div className={styles.guideWrapper}> 60 <DrawGuide 107 <DrawGuide/> 61 108 </div> 62 63 {/* <div className={styles.floorSelector}> 64 <label htmlFor="floorSelect">Select Floor:</label> 65 <select 66 id="floorSelect" 67 value={selectedFloor} 68 onChange={handleFloorChange} 69 className={styles.floorDropdown} 70 > 71 <option value={1}>1st Floor</option> 72 <option value={2}>2nd Floor</option> 73 <option value={3}>3rd Floor</option> 74 <option value={4}>4th Floor</option> 75 </select> 76 </div> */} 77 {/* <h2 className={styles.paragraph}>Objects:</h2> */} 109 <hr/> 110 <br/> 111 {/* {<h2 className={styles.paragraph}>Objects:</h2>} */} 78 112 <ul className={styles.shapeOptions} id="shapeOptions"> 79 113 <li data-info="Entrance" className={`${styles.shapeOption} ${styles.entrance}`}></li> 80 114 <li data-info="Wall" className={`${styles.shapeOption} ${styles.wall}`} id="wall"></li> 81 115 <li data-info="Room" className={`${styles.shapeOption} ${styles.room}`} id="room"></li> 116 <li data-info="Stairs" className={`${styles.shapeOption} ${styles.stairs}`} id="stairs"></li> 82 117 </ul> 83 <br /> 84 <RoomTypeModal map={app}></RoomTypeModal> 118 <RoomTypeModal map={app} roomTypes={roomTypes} addRoomTypeDB={addRoomType}></RoomTypeModal> 119 <br/> 120 <hr/> 121 <br/> 122 <FloorSelector floorConfig={{ 123 floors,searchParams, 124 setSearchParams,addFloorHandler, 125 deleteFloorHandler 126 }}></FloorSelector> 85 127 86 <div id="render" className={styles.buttonContainer}> 87 <button 88 id="render-button" 89 type="button" 90 className={styles.renderButton} 91 onClick={handleRenderClick} 92 > 93 Render 94 </button> 95 </div> 128 <br/> 129 130 <hr/> 131 <br/> 132 {hasError && <p style={{color: "red", textAlign: "center"}}>{errorMessage}</p>} 96 133 <div className={styles.templateCont}> 97 134 <SaveMap submitHandler={handleSaveClick}></SaveMap> 98 <MapTemplateSelector loadHandler={handleLoadMapClick}></MapTemplateSelector>99 135 </div> 100 136 101 137 <div className={styles.hide}> 102 <RoomModal map={app} ></RoomModal>138 <RoomModal map={app} roomTypes={roomTypes}></RoomModal> 103 139 <EntranceModal map={app}></EntranceModal> 104 140 <InfoPinModal map={app}></InfoPinModal> 141 <StairsModal map={app}></StairsModal> 105 142 </div> 106 143 </div> 107 144 108 145 {isPopupVisible && ( 109 <div className={styles.popup}> 110 <div className={styles.popupContent}> 111 <h2>Map Rendered!</h2> 112 <p>Your map has been successfully rendered.</p> 146 <div className={styles.popup}> 147 <div className={styles.popupContent}> 148 <h2>Map Saved!</h2> 149 <p>Your map has been successfully saved.</p> 150 </div> 113 151 </div> 114 </div>115 152 )} 116 153 </div> -
imaps-frontend/src/pages/Draw/Draw.module.css
rd565449 r0c6b92a 4 4 padding: 0; 5 5 height: 100%; 6 overflow : hidden;6 overflow-x: hidden; 7 7 background-color: #141414; 8 8 } 9 9 10 .topPanelH { 11 width: 100%; 12 display: flex; 13 justify-content: center; 14 align-items: center; 15 margin-bottom: 20px; 16 } 17 10 18 .logo { 11 width: 100px; 12 margin: 10px; 13 align-self: center; 19 width: 80px; 14 20 } 15 21 16 22 .title { 17 margin-top: 20px; 18 color: #804047; 19 font-size: 120%; 23 text-align: center; 24 font-size: 2.5em; 25 font-weight: 700; 26 text-transform: uppercase; 27 color: #333333; 28 font-family: "Oswald", sans-serif; 29 margin-bottom: 0; 30 text-decoration: none; 31 } 32 33 .titleLink { 34 text-decoration: none; 35 } 36 .titleLink:hover{ 37 text-decoration: none; 20 38 } 21 39 … … 23 41 color: #cccccc; 24 42 } 43 25 44 .guideWrapper { 26 45 display: flex; … … 28 47 align-items: center; 29 48 margin: 0; 49 width: 100%; 30 50 } 31 51 … … 51 71 display: flex; 52 72 flex-direction: column; 73 align-items: center; /* Center elements horizontally */ 53 74 padding: 20px; 54 75 background-color: #1c1c1c; … … 58 79 margin-right: 10px; 59 80 border-radius: 20px; 81 overflow-x: hidden; 60 82 } 61 83 62 84 .buttonContainer { 63 85 display: flex; 64 justify-content: space-between;86 justify-content: center; 65 87 align-items: center; 66 88 margin-top: 2rem; 67 89 gap: 10px; 68 } 69 70 /* .hide { 71 visibility: hidden; 72 } */ 90 width: 100%; 91 } 73 92 74 93 .renderButton { … … 104 123 list-style: none; 105 124 padding: 0; 106 margin: 0 0;107 display: flex;108 flex-direction: column;125 margin: 0; 126 display: grid; 127 grid-template-columns: repeat(2, 1fr); 109 128 gap: 15px; 129 justify-items: center; 110 130 align-items: center; 111 131 } … … 127 147 } 128 148 129 .templateCont {130 display: flex;131 flex-direction: column;132 }133 134 149 .shapeOption:hover { 135 150 background-color: #94183b; … … 137 152 } 138 153 154 .templateCont { 155 display: flex; 156 flex-direction: column; 157 align-items: center; /* Center section horizontally */ 158 width: 100%; 159 } 160 139 161 .fpscounter { 140 162 border: 1px solid #00b822; 141 163 margin: 20px 0; 164 text-align: center; 165 width: 100%; 142 166 } 143 167 … … 145 169 color: #00740c; 146 170 font-weight: bold; 147 text-align: center;148 171 margin: 0; 149 172 padding: 5px 0; 150 173 } 151 174 152 .floorSelector {153 margin-bottom: 20px;154 display: flex;155 flex-direction: column;156 gap: 8px;157 color: #ffffff;158 }159 160 .floorSelector label {161 font-size: 14px;162 }163 164 .floorDropdown {165 padding: 8px;166 font-size: 14px;167 border-radius: 5px;168 border: 1px solid #ccc;169 background-color: #3a3a3a;170 color: #ffffff;171 cursor: pointer;172 width: 100%;173 transition: border-color 0.3s;174 }175 176 .floorDropdown:focus {177 outline: none;178 border-color: #1e90ff;179 }180 175 181 176 .popup { … … 226 221 background-image: url("./shapeImages/room_icon.png"); 227 222 } 223 .stairs { 224 background-image: url("./shapeImages/stairs_icon.png"); 225 } 226 .floorSection { 227 display: flex; 228 flex-direction: column; 229 align-items: center; 230 gap: 20px; 231 background-color: #2d2d2d; 232 padding: 20px; 233 border-radius: 8px; 234 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); 235 width: 100%; 236 } 237 238 .floorLabel { 239 font-size: 16px; 240 font-weight: bold; 241 color: #ffffff; 242 margin-bottom: 10px; 243 text-align: center; 244 } 245 246 .floorList { 247 display: flex; 248 flex-direction: column; 249 align-items: center; 250 gap: 15px; 251 width: 100%; 252 } 253 254 .floorItems { 255 display: flex; 256 flex-direction: column; 257 align-items: center; 258 gap: 10px; 259 width: 100%; 260 } 261 262 .addFloorButton { 263 background-color: #e67e22; 264 border: none; 265 border-radius: 50%; 266 width: 40px; 267 height: 40px; 268 display: flex; 269 justify-content: center; 270 align-items: center; 271 cursor: pointer; 272 transition: background-color 0.3s, transform 0.2s; 273 } 274 275 .addFloorButton:hover { 276 background-color: #d2691e; 277 transform: scale(1.1); 278 } 279 280 .addFloorButton:active { 281 background-color: #b35418; 282 transform: scale(0.95); 283 } 284 285 .icon { 286 width: 20px; 287 height: 20px; 288 filter: invert(1); 289 } 290 291 .floorButton { 292 padding: 10px 15px; 293 font-size: 14px; 294 color: #ffffff; 295 background-color: #3a3a3a; 296 border: 1px solid #555555; 297 border-radius: 8px; 298 width: 100%; 299 text-align: center; 300 cursor: pointer; 301 transition: background-color 0.3s, transform 0.2s; 302 } 303 304 .floorButton:hover { 305 background-color: #4a4a4a; 306 } 307 308 .floorButton.active { 309 background-color: #1e90ff; 310 color: #ffffff; 311 font-weight: bold; 312 } 313 314 .floorInput { 315 width: 60%; 316 padding: 8px; 317 font-size: 14px; 318 border: 1px solid #ccc; 319 border-radius: 5px; 320 background-color: #3a3a3a; 321 color: #ffffff; 322 text-align: center; 323 transition: border-color 0.3s; 324 } 325 326 .floorInput:focus { 327 outline: none; 328 border-color: #1e90ff; 329 } 330 331 .floorActions { 332 display: flex; 333 gap: 10px; 334 justify-content: center; 335 align-items: center; 336 margin-top: 10px; 337 } 338 339 .errorMessage { 340 color: red; 341 font-size: 12px; 342 margin-top: 10px; 343 text-align: center; 344 } 345 .floorItemWrapper { 346 display: flex; 347 align-items: center; 348 gap: 10px; 349 width: 100%; 350 } 351 352 .floorItem { 353 padding: 10px 15px; 354 font-size: 14px; 355 color: #ffffff; 356 background-color: #3a3a3a; 357 border: 1px solid #555555; 358 border-radius: 8px; 359 text-align: center; 360 cursor: pointer; 361 flex-grow: 1; 362 transition: background-color 0.3s; 363 } 364 365 .floorItem:hover { 366 background-color: #4a4a4a; 367 } 368 369 .activeFloor { 370 background-color: #1e90ff; 371 color: #ffffff; 372 font-weight: bold; 373 } 374 375 .deleteFloorButton { 376 background-color: #ff4d4d; 377 border: none; 378 border-radius: 8px; 379 padding: 10px; 380 color: white; 381 cursor: pointer; 382 transition: background-color 0.3s, transform 0.2s; 383 } 384 385 .deleteFloorButton:hover { 386 background-color: #e60000; 387 transform: scale(1.1); 388 } 389 390 .deleteFloorButton:active { 391 background-color: #cc0000; 392 transform: scale(0.95); 393 }
Note:
See TracChangeset
for help on using the changeset viewer.