1 | import styles from "./Maps.module.css";
|
---|
2 | import "react-tiles-dnd/esm/index.css";
|
---|
3 | import {TilesContainer} from "react-tiles-dnd";
|
---|
4 | import {Link} from "react-router-dom";
|
---|
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
|
---|
8 | import {useEffect, useState} from "react";
|
---|
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";
|
---|
13 | import {useAppContext} from "../../components/AppContext/AppContext.jsx";
|
---|
14 | import FilterMaps from "../../components/FilterMaps/FilterMaps.jsx";
|
---|
15 |
|
---|
16 | let loadedTiles = [];
|
---|
17 |
|
---|
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}>
|
---|
21 | <div
|
---|
22 | className={`${styles.tile} ${isDragging ? styles.dragging : ""}`}
|
---|
23 | style={{width: "100%", height: "100%"}}
|
---|
24 | >
|
---|
25 | <img src={card} className={styles.imgStyle} alt="Map Thumbnail"/>
|
---|
26 | <div style={{fontFamily: "exo"}}>
|
---|
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"
|
---|
35 | style={{width: "20px", height: "20px"}}
|
---|
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([]);
|
---|
49 | const {username, isAuthenticated} = useAppContext();
|
---|
50 | const [filter, setFilter] = useState("all")
|
---|
51 | const [mapFilters, setMapFilters] = useState([])
|
---|
52 |
|
---|
53 | useEffect(() => {
|
---|
54 | const loadMaps = async () => {
|
---|
55 | const httpService = new HttpService();
|
---|
56 | let mapTiles = [];
|
---|
57 | let mapTypes = ['Hospital', 'Faculty', 'House', 'Other'];
|
---|
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,
|
---|
68 | type: elem.mapType,
|
---|
69 | }));
|
---|
70 |
|
---|
71 | console.log("TUKA")
|
---|
72 | // Load all maps
|
---|
73 | const allResp = await httpService.get(config.view_maps.display);
|
---|
74 | console.log("RESPONSE MAPS PUBLIC", allResp);
|
---|
75 |
|
---|
76 | // mapTypes = allResp.filter(elem => elem.mapType != null && elem.mapType !== "").map(elem => elem.mapType);
|
---|
77 |
|
---|
78 |
|
---|
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,
|
---|
86 | type: elem.mapType,
|
---|
87 | }));
|
---|
88 |
|
---|
89 |
|
---|
90 | mapTiles = [...favMapTiles, ...nonFavMapTiles];
|
---|
91 | } else {
|
---|
92 | const allResp = await httpService.get(config.view_maps.display);
|
---|
93 | console.log("RESPONSE MAPS PUBLIC", allResp);
|
---|
94 | // mapTypes = allResp.filter(elem => elem.mapType != null && elem.mapType !== "").map(elem => elem.mapType);
|
---|
95 |
|
---|
96 | mapTiles = allResp.map((elem) => ({
|
---|
97 | text: elem.mapName,
|
---|
98 | cols: 1,
|
---|
99 | rows: 1,
|
---|
100 | isFavorite: false,
|
---|
101 | type: elem.mapType,
|
---|
102 | }));
|
---|
103 | }
|
---|
104 |
|
---|
105 | console.log("TYPES:", mapTypes);
|
---|
106 | setMapFilters(mapTypes);
|
---|
107 |
|
---|
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) =>
|
---|
131 | tile.text === tileName ? {...tile, isFavorite: !tile.isFavorite} : tile
|
---|
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 |
|
---|
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 |
|
---|
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 |
|
---|
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>}
|
---|
189 | <TilesContainer
|
---|
190 | data={tiles}
|
---|
191 | renderTile={(props) => renderTile({...props, toggleFavorite})}
|
---|
192 | tileSize={tileSize}
|
---|
193 | forceTileWidth={170}
|
---|
194 | forceTileHeight={200}
|
---|
195 | />
|
---|
196 | </div>
|
---|
197 | );
|
---|
198 | }
|
---|