Ignore:
Timestamp:
12/12/24 17:06:06 (5 weeks ago)
Author:
stefan toskovski <stefantoska84@…>
Branches:
main
Parents:
d565449
Message:

Pred finalna verzija

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";
     1import { useContext, useEffect, useState } from "react";
    32import 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";
     3import RoomModal from "../../components/Modals/RoomModal/RoomModal.jsx";
     4import EntranceModal from "../../components/Modals/EntranceModal/EntranceModal.jsx";
    75import DrawGuide from "../../components/DrawGuide/DrawGuide.jsx";
    8 import RoomTypeModal from "../../components/RoomTypeModal/RoomTypeModal.jsx";
    9 import InfoPinModal from "../../components/InfoPinModal/InfoPinModal.jsx";
     6import RoomTypeModal from "../../components/Modals/RoomTypeModal/RoomTypeModal.jsx";
     7import InfoPinModal from "../../components/Modals/InfoPinModal/InfoPinModal.jsx";
     8import SaveMap from "../../components/SaveMap/SaveMap.jsx";
     9import Logo from "../../components/Logo/Logo.jsx";
     10import { Link, useNavigate, useParams, useSearchParams } from "react-router-dom";
     11import Profile from "../../components/Profile/Profile.jsx";
    1012import 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";
     13import StairsModal from "../../components/Modals/StairsModal/StairsModal.jsx";
     14import useMapLoader from "./Hooks/useMapLoader.js";
     15import {FloorSelector} from "./FloorSelector.jsx";
     16import {useRoomTypesLoader} from "./Hooks/useRoomTypesLoader.js";
     17import {useAppContext} from "../../components/AppContext/AppContext.jsx";
     18import config from "../../scripts/net/netconfig.js";
     19import ShapeRegistry from "../../scripts/util/ShapeRegistry.js";
    1620
    1721function Draw() {
    18   const [selectedFloor, setSelectedFloor] = useState(1);
    19   const [app, setApp] = useState(null);
     22  const { mapName } = useParams();
     23  const { username } = useAppContext();
     24
    2025  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
    2173  useEffect(() => {
    22     const app = new MapBuilder("container");
    23     setApp(app);
    24     // fpsCounterLoop();
     74    return () => {
     75      ShapeRegistry.clear();
     76    }
    2577  }, []);
    2678
    27   const handleFloorChange = (event) => {
    28     setSelectedFloor(event.target.value);
    29     console.log(`Floor changed to: ${event.target.value}`);
    30   };
    3179
    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    });
    3490
    35     setTimeout(() => {
    36       setIsPopupVisible(false);
    37     }, 3000);
    38   };
    3991
    40   const handleSaveClick = async (mapName) => {
    41     const resp = await app.saveMap(mapName);
    42   };
    43   const handleLoadMapClick = (data) => {
    44     app.deserializeMap(data);
    4592  };
    4693
    4794  return (
    4895    <div className={styles.wrapper} id="wrapper">
    49       <SideBar></SideBar>
     96      {/* <SideBar></SideBar> */}
     97      <Logo></Logo>
    5098      <div id="container" className={styles.cont}></div>
    5199      <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>
    54105        </Link>
    55         <h1 className={styles.title}>Map Builder</h1>
    56         {/* <div id="fpscont" className={styles.fpscounter}>
    57           <p id="fpsCounter"></p>
    58         </div> */}
    59106        <div className={styles.guideWrapper}>
    60           <DrawGuide />
     107          <DrawGuide/>
    61108        </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>} */}
    78112        <ul className={styles.shapeOptions} id="shapeOptions">
    79113          <li data-info="Entrance" className={`${styles.shapeOption} ${styles.entrance}`}></li>
    80114          <li data-info="Wall" className={`${styles.shapeOption} ${styles.wall}`} id="wall"></li>
    81115          <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>
    82117        </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>
    85127
    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>}
    96133        <div className={styles.templateCont}>
    97134          <SaveMap submitHandler={handleSaveClick}></SaveMap>
    98           <MapTemplateSelector loadHandler={handleLoadMapClick}></MapTemplateSelector>
    99135        </div>
    100136
    101137        <div className={styles.hide}>
    102           <RoomModal map={app}></RoomModal>
     138          <RoomModal map={app} roomTypes={roomTypes}></RoomModal>
    103139          <EntranceModal map={app}></EntranceModal>
    104140          <InfoPinModal map={app}></InfoPinModal>
     141          <StairsModal map={app}></StairsModal>
    105142        </div>
    106143      </div>
    107144
    108145      {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>
    113151          </div>
    114         </div>
    115152      )}
    116153    </div>
  • imaps-frontend/src/pages/Draw/Draw.module.css

    rd565449 r0c6b92a  
    44  padding: 0;
    55  height: 100%;
    6   overflow: hidden;
     6  overflow-x: hidden;
    77  background-color: #141414;
    88}
    99
     10.topPanelH {
     11  width: 100%;
     12  display: flex;
     13  justify-content: center;
     14  align-items: center;
     15  margin-bottom: 20px;
     16}
     17
    1018.logo {
    11   width: 100px;
    12   margin: 10px;
    13   align-self: center;
     19  width: 80px;
    1420}
    1521
    1622.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;
    2038}
    2139
     
    2341  color: #cccccc;
    2442}
     43
    2544.guideWrapper {
    2645  display: flex;
     
    2847  align-items: center;
    2948  margin: 0;
     49  width: 100%;
    3050}
    3151
     
    5171  display: flex;
    5272  flex-direction: column;
     73  align-items: center; /* Center elements horizontally */
    5374  padding: 20px;
    5475  background-color: #1c1c1c;
     
    5879  margin-right: 10px;
    5980  border-radius: 20px;
     81  overflow-x: hidden;
    6082}
    6183
    6284.buttonContainer {
    6385  display: flex;
    64   justify-content: space-between;
     86  justify-content: center;
    6587  align-items: center;
    6688  margin-top: 2rem;
    6789  gap: 10px;
    68 }
    69 
    70 /* .hide {
    71   visibility: hidden;
    72 } */
     90  width: 100%;
     91}
    7392
    7493.renderButton {
     
    104123  list-style: none;
    105124  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);
    109128  gap: 15px;
     129  justify-items: center;
    110130  align-items: center;
    111131}
     
    127147}
    128148
    129 .templateCont {
    130   display: flex;
    131   flex-direction: column;
    132 }
    133 
    134149.shapeOption:hover {
    135150  background-color: #94183b;
     
    137152}
    138153
     154.templateCont {
     155  display: flex;
     156  flex-direction: column;
     157  align-items: center; /* Center section horizontally */
     158  width: 100%;
     159}
     160
    139161.fpscounter {
    140162  border: 1px solid #00b822;
    141163  margin: 20px 0;
     164  text-align: center;
     165  width: 100%;
    142166}
    143167
     
    145169  color: #00740c;
    146170  font-weight: bold;
    147   text-align: center;
    148171  margin: 0;
    149172  padding: 5px 0;
    150173}
    151174
    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 }
    180175
    181176.popup {
     
    226221  background-image: url("./shapeImages/room_icon.png");
    227222}
     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.