[0c6b92a] | 1 | import styles from "./Maps.module.css";
|
---|
| 2 | import "react-tiles-dnd/esm/index.css";
|
---|
[79a0317] | 3 | import {TilesContainer} from "react-tiles-dnd";
|
---|
| 4 | import {Link} from "react-router-dom";
|
---|
[0c6b92a] | 5 | import card from "../../assets/card-map.png";
|
---|
| 6 | import star_icon from "../../assets/star_icon.png"; // Unfilled star icon
|
---|
| 7 | import star_filled_icon from "../../assets/star_filled_icon.png"; // Filled star icon
|
---|
[79a0317] | 8 | import {useEffect, useState} from "react";
|
---|
[0c6b92a] | 9 | import HttpService from "../../scripts/net/HttpService.js";
|
---|
| 10 | import Logo from "../../components/Logo/Logo.jsx";
|
---|
| 11 | import Profile from "../../components/Profile/Profile.jsx";
|
---|
| 12 | import config from "../../scripts/net/netconfig.js";
|
---|
[79a0317] | 13 | import {useAppContext} from "../../components/AppContext/AppContext.jsx";
|
---|
| 14 | import FilterMaps from "../../components/FilterMaps/FilterMaps.jsx";
|
---|
[0c6b92a] | 15 |
|
---|
| 16 | let loadedTiles = [];
|
---|
| 17 |
|
---|
[79a0317] | 18 | const renderTile = ({data, isDragging, toggleFavorite}) => (
|
---|
| 19 | <div style={{padding: "1rem", width: "100%", position: "relative"}}>
|
---|
| 20 | <Link to={`/Maps/View/${data.text}`} className={styles.linkStyle}>
|
---|
[0c6b92a] | 21 | <div
|
---|
| 22 | className={`${styles.tile} ${isDragging ? styles.dragging : ""}`}
|
---|
[79a0317] | 23 | style={{width: "100%", height: "100%"}}
|
---|
[0c6b92a] | 24 | >
|
---|
[79a0317] | 25 | <img src={card} className={styles.imgStyle} alt="Map Thumbnail"/>
|
---|
| 26 | <div style={{fontFamily: "exo"}}>
|
---|
[0c6b92a] | 27 | {data.text} {isDragging ? "DRAGGING" : null}
|
---|
| 28 | </div>
|
---|
| 29 | </div>
|
---|
| 30 | </Link>
|
---|
| 31 | <div className={styles.favorite} onClick={() => toggleFavorite(data.text, data.isFavorite)}>
|
---|
| 32 | <img
|
---|
| 33 | src={data.isFavorite ? star_filled_icon : star_icon}
|
---|
| 34 | alt="Favorite Icon"
|
---|
[79a0317] | 35 | style={{width: "20px", height: "20px"}}
|
---|
[0c6b92a] | 36 | />
|
---|
| 37 | </div>
|
---|
| 38 | </div>
|
---|
| 39 | );
|
---|
| 40 |
|
---|
| 41 | const tileSize = (tile) => ({
|
---|
| 42 | colSpan: tile.cols,
|
---|
| 43 | rowSpan: tile.rows,
|
---|
| 44 | });
|
---|
| 45 |
|
---|
| 46 | export default function BrowseMaps() {
|
---|
| 47 | const [searchTerm, setSearchTerm] = useState("");
|
---|
| 48 | const [tiles, setTiles] = useState([]);
|
---|
[79a0317] | 49 | const {username, isAuthenticated} = useAppContext();
|
---|
| 50 | const [filter, setFilter] = useState("all")
|
---|
| 51 | const [mapFilters, setMapFilters] = useState([])
|
---|
[0c6b92a] | 52 |
|
---|
| 53 | useEffect(() => {
|
---|
| 54 | const loadMaps = async () => {
|
---|
| 55 | const httpService = new HttpService();
|
---|
| 56 | let mapTiles = [];
|
---|
[79a0317] | 57 | let mapTypes = ['Hospital', 'Faculty', 'House', 'Other'];
|
---|
[0c6b92a] | 58 | if (isAuthenticated) {
|
---|
| 59 | // :D
|
---|
| 60 | const favResp = await httpService.get(`${config.favourites.display}?username=${username}`);
|
---|
| 61 | console.log("RESPONSE FAVORITE MAPS", favResp);
|
---|
| 62 |
|
---|
| 63 | const favMapTiles = favResp.map((elem) => ({
|
---|
| 64 | text: elem.mapName,
|
---|
| 65 | cols: 1,
|
---|
| 66 | rows: 1,
|
---|
| 67 | isFavorite: true,
|
---|
[79a0317] | 68 | type: elem.mapType,
|
---|
[0c6b92a] | 69 | }));
|
---|
| 70 |
|
---|
[79a0317] | 71 | console.log("TUKA")
|
---|
[0c6b92a] | 72 | // Load all maps
|
---|
| 73 | const allResp = await httpService.get(config.view_maps.display);
|
---|
| 74 | console.log("RESPONSE MAPS PUBLIC", allResp);
|
---|
| 75 |
|
---|
[79a0317] | 76 | // mapTypes = allResp.filter(elem => elem.mapType != null && elem.mapType !== "").map(elem => elem.mapType);
|
---|
| 77 |
|
---|
| 78 |
|
---|
[0c6b92a] | 79 | const nonFavMapTiles = allResp
|
---|
| 80 | .filter((elem) => !favMapTiles.some((fav) => fav.text === elem.mapName))
|
---|
| 81 | .map((elem) => ({
|
---|
| 82 | text: elem.mapName,
|
---|
| 83 | cols: 1,
|
---|
| 84 | rows: 1,
|
---|
| 85 | isFavorite: false,
|
---|
[79a0317] | 86 | type: elem.mapType,
|
---|
[0c6b92a] | 87 | }));
|
---|
| 88 |
|
---|
[79a0317] | 89 |
|
---|
[0c6b92a] | 90 | mapTiles = [...favMapTiles, ...nonFavMapTiles];
|
---|
| 91 | } else {
|
---|
| 92 | const allResp = await httpService.get(config.view_maps.display);
|
---|
| 93 | console.log("RESPONSE MAPS PUBLIC", allResp);
|
---|
[79a0317] | 94 | // mapTypes = allResp.filter(elem => elem.mapType != null && elem.mapType !== "").map(elem => elem.mapType);
|
---|
[0c6b92a] | 95 |
|
---|
| 96 | mapTiles = allResp.map((elem) => ({
|
---|
| 97 | text: elem.mapName,
|
---|
| 98 | cols: 1,
|
---|
| 99 | rows: 1,
|
---|
| 100 | isFavorite: false,
|
---|
[79a0317] | 101 | type: elem.mapType,
|
---|
[0c6b92a] | 102 | }));
|
---|
| 103 | }
|
---|
| 104 |
|
---|
[79a0317] | 105 | console.log("TYPES:", mapTypes);
|
---|
| 106 | setMapFilters(mapTypes);
|
---|
| 107 |
|
---|
[0c6b92a] | 108 | loadedTiles = [...mapTiles];
|
---|
| 109 | sortTiles(mapTiles);
|
---|
| 110 | setTiles(mapTiles);
|
---|
| 111 | };
|
---|
| 112 | loadMaps();
|
---|
| 113 | }, [isAuthenticated, username]);
|
---|
| 114 |
|
---|
| 115 | const toggleFavorite = async (tileName, isFavorite) => {
|
---|
| 116 | const httpService = new HttpService();
|
---|
| 117 | const url = isFavorite
|
---|
| 118 | ? `${config.favourites.delete}?username=${username}&mapName=${encodeURIComponent(tileName)}`
|
---|
| 119 | : `${config.favourites.add}?username=${username}&mapName=${encodeURIComponent(tileName)}`;
|
---|
| 120 |
|
---|
| 121 | console.log("Request URL:", url);
|
---|
| 122 | let response;
|
---|
| 123 | if (isFavorite) {
|
---|
| 124 | response = await httpService.delete(url);
|
---|
| 125 | } else {
|
---|
| 126 | response = await httpService.post(url);
|
---|
| 127 | }
|
---|
| 128 | console.log("Response received:", response);
|
---|
| 129 |
|
---|
| 130 | const updatedTiles = tiles.map((tile) =>
|
---|
[79a0317] | 131 | tile.text === tileName ? {...tile, isFavorite: !tile.isFavorite} : tile
|
---|
[0c6b92a] | 132 | );
|
---|
| 133 |
|
---|
| 134 | loadedTiles = [...updatedTiles];
|
---|
| 135 | sortTiles(updatedTiles);
|
---|
| 136 | setTiles(updatedTiles);
|
---|
| 137 | };
|
---|
| 138 |
|
---|
| 139 | const handleSearchChange = (e) => {
|
---|
| 140 | const value = e.target.value.toLowerCase();
|
---|
| 141 | setSearchTerm(value);
|
---|
| 142 |
|
---|
| 143 | const filteredTiles = loadedTiles.filter((tile) =>
|
---|
| 144 | tile.text.toLowerCase().includes(value)
|
---|
| 145 | );
|
---|
| 146 | sortTiles(filteredTiles);
|
---|
| 147 | setTiles(filteredTiles);
|
---|
| 148 | };
|
---|
| 149 |
|
---|
| 150 | const sortTiles = (tilesToSort) => {
|
---|
| 151 | tilesToSort.sort((a, b) => {
|
---|
| 152 | if (a.isFavorite === b.isFavorite) return a.text.localeCompare(b.text);
|
---|
| 153 | return a.isFavorite ? -1 : 1;
|
---|
| 154 | });
|
---|
| 155 | };
|
---|
| 156 |
|
---|
[79a0317] | 157 | const onFilter = (selectedFilter) => {
|
---|
| 158 | setFilter(selectedFilter);
|
---|
| 159 |
|
---|
| 160 | if (selectedFilter === "all") {
|
---|
| 161 | // Show all tiles
|
---|
| 162 | setTiles(loadedTiles);
|
---|
| 163 | } else {
|
---|
| 164 | // Filter tiles by selected type
|
---|
| 165 | const filteredTiles = loadedTiles.filter((tile) => tile.type === selectedFilter);
|
---|
| 166 | setTiles(filteredTiles);
|
---|
| 167 | }
|
---|
| 168 | };
|
---|
| 169 |
|
---|
| 170 |
|
---|
[0c6b92a] | 171 | return (
|
---|
| 172 | <div className={styles.container}>
|
---|
| 173 | <h1>Explore Maps</h1>
|
---|
| 174 | <Logo></Logo>
|
---|
| 175 | <Profile></Profile>
|
---|
| 176 | <div className={styles.searchBar}>
|
---|
| 177 | <input
|
---|
| 178 | type="text"
|
---|
| 179 | placeholder="Search for maps..."
|
---|
| 180 | value={searchTerm}
|
---|
| 181 | onChange={handleSearchChange}
|
---|
| 182 | />
|
---|
| 183 |
|
---|
[79a0317] | 184 | </div>
|
---|
| 185 | <div className={styles.filterBar}>
|
---|
| 186 | <FilterMaps mapTypes={mapFilters} setFilter={onFilter}></FilterMaps>
|
---|
| 187 | </div>
|
---|
| 188 | {filter !== "all" && tiles.length === 0 && <p>No maps of type {filter} found</p>}
|
---|
[0c6b92a] | 189 | <TilesContainer
|
---|
| 190 | data={tiles}
|
---|
[79a0317] | 191 | renderTile={(props) => renderTile({...props, toggleFavorite})}
|
---|
[0c6b92a] | 192 | tileSize={tileSize}
|
---|
[79a0317] | 193 | forceTileWidth={170}
|
---|
| 194 | forceTileHeight={200}
|
---|
[0c6b92a] | 195 | />
|
---|
| 196 | </div>
|
---|
| 197 | );
|
---|
| 198 | }
|
---|