[0c6b92a] | 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 |
|
---|
| 15 | let loadedTiles = [];
|
---|
| 16 |
|
---|
| 17 | const renderTile = ({ data, isDragging, toggleFavorite }) => (
|
---|
| 18 | <div style={{ padding: "1rem", width: "100%", position: "relative" }}>
|
---|
| 19 | <Link to={`/Maps/${data.text}/View`} className={styles.linkStyle}>
|
---|
| 20 | <div
|
---|
| 21 | className={`${styles.tile} ${isDragging ? styles.dragging : ""}`}
|
---|
| 22 | style={{ width: "100%", height: "100%" }}
|
---|
| 23 | >
|
---|
| 24 | <img src={card} className={styles.imgStyle} alt="Map Thumbnail" />
|
---|
| 25 | <div style={{ fontFamily: "exo" }}>
|
---|
| 26 | {data.text} {isDragging ? "DRAGGING" : null}
|
---|
| 27 | </div>
|
---|
| 28 | </div>
|
---|
| 29 | </Link>
|
---|
| 30 | <div className={styles.favorite} onClick={() => toggleFavorite(data.text, data.isFavorite)}>
|
---|
| 31 | <img
|
---|
| 32 | src={data.isFavorite ? star_filled_icon : star_icon}
|
---|
| 33 | alt="Favorite Icon"
|
---|
| 34 | style={{ width: "20px", height: "20px" }}
|
---|
| 35 | />
|
---|
| 36 | </div>
|
---|
| 37 | </div>
|
---|
| 38 | );
|
---|
| 39 |
|
---|
| 40 | const tileSize = (tile) => ({
|
---|
| 41 | colSpan: tile.cols,
|
---|
| 42 | rowSpan: tile.rows,
|
---|
| 43 | });
|
---|
| 44 |
|
---|
| 45 | export default function BrowseMaps() {
|
---|
| 46 | const [searchTerm, setSearchTerm] = useState("");
|
---|
| 47 | const [tiles, setTiles] = useState([]);
|
---|
| 48 | const { username, isAuthenticated } = useAppContext();
|
---|
| 49 |
|
---|
| 50 | useEffect(() => {
|
---|
| 51 | const loadMaps = async () => {
|
---|
| 52 | const httpService = new HttpService();
|
---|
| 53 | let mapTiles = [];
|
---|
| 54 |
|
---|
| 55 | if (isAuthenticated) {
|
---|
| 56 | // :D
|
---|
| 57 | const favResp = await httpService.get(`${config.favourites.display}?username=${username}`);
|
---|
| 58 | console.log("RESPONSE FAVORITE MAPS", favResp);
|
---|
| 59 |
|
---|
| 60 | const favMapTiles = favResp.map((elem) => ({
|
---|
| 61 | text: elem.mapName,
|
---|
| 62 | cols: 1,
|
---|
| 63 | rows: 1,
|
---|
| 64 | isFavorite: true,
|
---|
| 65 | }));
|
---|
| 66 |
|
---|
| 67 | // Load all maps
|
---|
| 68 | const allResp = await httpService.get(config.view_maps.display);
|
---|
| 69 | console.log("RESPONSE MAPS PUBLIC", allResp);
|
---|
| 70 |
|
---|
| 71 | const nonFavMapTiles = allResp
|
---|
| 72 | .filter((elem) => !favMapTiles.some((fav) => fav.text === elem.mapName))
|
---|
| 73 | .map((elem) => ({
|
---|
| 74 | text: elem.mapName,
|
---|
| 75 | cols: 1,
|
---|
| 76 | rows: 1,
|
---|
| 77 | isFavorite: false,
|
---|
| 78 | }));
|
---|
| 79 |
|
---|
| 80 | mapTiles = [...favMapTiles, ...nonFavMapTiles];
|
---|
| 81 | } else {
|
---|
| 82 | const allResp = await httpService.get(config.view_maps.display);
|
---|
| 83 | console.log("RESPONSE MAPS PUBLIC", allResp);
|
---|
| 84 |
|
---|
| 85 | mapTiles = allResp.map((elem) => ({
|
---|
| 86 | text: elem.mapName,
|
---|
| 87 | cols: 1,
|
---|
| 88 | rows: 1,
|
---|
| 89 | isFavorite: false,
|
---|
| 90 | }));
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | loadedTiles = [...mapTiles];
|
---|
| 94 | sortTiles(mapTiles);
|
---|
| 95 | setTiles(mapTiles);
|
---|
| 96 | };
|
---|
| 97 | loadMaps();
|
---|
| 98 | }, [isAuthenticated, username]);
|
---|
| 99 |
|
---|
| 100 | const toggleFavorite = async (tileName, isFavorite) => {
|
---|
| 101 | const httpService = new HttpService();
|
---|
| 102 | const url = isFavorite
|
---|
| 103 | ? `${config.favourites.delete}?username=${username}&mapName=${encodeURIComponent(tileName)}`
|
---|
| 104 | : `${config.favourites.add}?username=${username}&mapName=${encodeURIComponent(tileName)}`;
|
---|
| 105 |
|
---|
| 106 | console.log("Request URL:", url);
|
---|
| 107 | let response;
|
---|
| 108 | if (isFavorite) {
|
---|
| 109 | response = await httpService.delete(url);
|
---|
| 110 | } else {
|
---|
| 111 | response = await httpService.post(url);
|
---|
| 112 | }
|
---|
| 113 | console.log("Response received:", response);
|
---|
| 114 |
|
---|
| 115 | const updatedTiles = tiles.map((tile) =>
|
---|
| 116 | tile.text === tileName ? { ...tile, isFavorite: !tile.isFavorite } : tile
|
---|
| 117 | );
|
---|
| 118 |
|
---|
| 119 | loadedTiles = [...updatedTiles];
|
---|
| 120 | sortTiles(updatedTiles);
|
---|
| 121 | setTiles(updatedTiles);
|
---|
| 122 | };
|
---|
| 123 |
|
---|
| 124 | const handleSearchChange = (e) => {
|
---|
| 125 | const value = e.target.value.toLowerCase();
|
---|
| 126 | setSearchTerm(value);
|
---|
| 127 |
|
---|
| 128 | const filteredTiles = loadedTiles.filter((tile) =>
|
---|
| 129 | tile.text.toLowerCase().includes(value)
|
---|
| 130 | );
|
---|
| 131 | sortTiles(filteredTiles);
|
---|
| 132 | setTiles(filteredTiles);
|
---|
| 133 | };
|
---|
| 134 |
|
---|
| 135 | const sortTiles = (tilesToSort) => {
|
---|
| 136 | tilesToSort.sort((a, b) => {
|
---|
| 137 | if (a.isFavorite === b.isFavorite) return a.text.localeCompare(b.text);
|
---|
| 138 | return a.isFavorite ? -1 : 1;
|
---|
| 139 | });
|
---|
| 140 | };
|
---|
| 141 |
|
---|
| 142 | return (
|
---|
| 143 | <div className={styles.container}>
|
---|
| 144 | <h1>Explore Maps</h1>
|
---|
| 145 | <Logo></Logo>
|
---|
| 146 | <Profile></Profile>
|
---|
| 147 | <div className={styles.searchBar}>
|
---|
| 148 | <input
|
---|
| 149 | type="text"
|
---|
| 150 | placeholder="Search for maps..."
|
---|
| 151 | value={searchTerm}
|
---|
| 152 | onChange={handleSearchChange}
|
---|
| 153 | />
|
---|
| 154 | </div>
|
---|
| 155 |
|
---|
| 156 | <TilesContainer
|
---|
| 157 | data={tiles}
|
---|
| 158 | renderTile={(props) => renderTile({ ...props, toggleFavorite })}
|
---|
| 159 | tileSize={tileSize}
|
---|
| 160 | forceTileWidth={150}
|
---|
| 161 | forceTileHeight={170}
|
---|
| 162 | />
|
---|
| 163 | </div>
|
---|
| 164 | );
|
---|
| 165 | }
|
---|