import { Paper, Flex, ScrollArea, Autocomplete, Title } from "@mantine/core"; import { ArticleCardVertical } from "./ArticleCard"; import Map, { Source, Layer, ScaleControl, GeolocateControl, } from "react-map-gl/maplibre"; import 'maplibre-gl/dist/maplibre-gl.css'; import { useState, useEffect, useRef } from "react"; import Fuse from "fuse.js"; // import mapstyle from './assets/basemap.json'; import mapstyle from "./assets/basemap-mapbox.json"; import plus from "./assets/plus.png"; import minus from "./assets/minus.png"; import pin from "./assets/pin.png"; import prishvin from "./assets/prishvin.png"; import ostrovskiy from "./assets/ostrovskiy.png"; import brusov from "./assets/brusov.png"; export function KartaPage() { const mapRef = useRef(null); const [initial, setInitial] = useState(null); const [articles, setArticles] = useState(null); const [search, setSearch] = useState(""); const [selected, setSelected] = useState(-1); const [cursor, setCursor] = useState("grab"); const host = "https://strapi.litmusmap.ru"; // Load icons const handleMapLoad = (e) => { const icons = ["pin", "prishvin", "ostrovskiy", "brusov"]; const pinImage = new Image(); pinImage.src = pin; pinImage.onload = () => mapRef.current.addImage("pin-marker", pinImage); const prishvinImage = new Image(); prishvinImage.src = prishvin; prishvinImage.onload = () => mapRef.current.addImage("prishvin-marker", prishvinImage); const ostrovskiyImage = new Image(); ostrovskiyImage.src = ostrovskiy; ostrovskiyImage.onload = () => mapRef.current.addImage("ostrovskiy-marker", ostrovskiyImage); const brusovImage = new Image(); brusovImage.src = brusov; brusovImage.onload = () => mapRef.current.addImage("brusov-marker", brusovImage); }; // Load articles useEffect(() => { fetch(`${host}/api/articles?populate=*`) .then((r) => r.json()) .then((d) => { setInitial(d.data); setArticles(d.data); }); }, []); // Search const fuse = initial !== null && new Fuse(initial, { keys: ["attributes.tags.value"], }); useEffect(() => { const foundArticles = fuse && fuse.search(search).map((e) => e.item); const updatedArticles = search.length > 0 ? foundArticles : initial; setArticles(updatedArticles); }, [search]); // Select article interaction useEffect(() => { if (selected > 0) { const selectedArticleIndex = articles.findIndex((a) => a.id == selected); const selectedArticle = articles[selectedArticleIndex]; const reorderedArticles = [ selectedArticle, ...articles.filter((a) => a.id !== selected), ]; setArticles(reorderedArticles); mapRef.current?.flyTo({ center: [ selectedArticle.attributes.longitude, selectedArticle.attributes.latitude, ], zoom: 10, }); } else { mapRef.current?.flyTo({ center: [35, 57], zoom: 5, }); } }, [selected]); const handleAddressClick = (id) => { setSelected(id); }; // Zoom const ZoomControl = (props) => { const zoomIn = () => { mapRef.current.zoomTo(mapRef.current.getZoom() + 1); }; const zoomOut = () => { mapRef.current.zoomTo(mapRef.current.getZoom() - 1); }; return ( ); }; return (
{ // console.log(e.features); e.features[0] ? (setSelected(e.features[0].properties.id), mapRef.current.flyTo({ center: e.features[0].geometry.coordinates, zoom: mapRef.current.getZoom() + 6, })) : setSelected(-1); }} onMouseEnter={() => setCursor("pointer")} onMouseLeave={() => setCursor("grab")} onLoad={handleMapLoad} > a.id)] } paint={{ "circle-color": [ "match", ["get", "id"], selected, "#e66a5a", "#F2994A", ], "circle-radius": 8, "circle-opacity": ["step", ["zoom"], 0.8, 7, 0], }} /> a.id)] } layout={{ "icon-image": "pin-marker", "icon-size": ['interpolate', ['linear'], ['zoom'], 7, 0.5, 12, 1], }} minzoom={7} maxzoom={12} /> a.id)] } layout={{ "icon-image": [ "match", ["get", "id"], 6, "ostrovskiy-marker", 7, "brusov-marker", 1, "prishvin-marker", "pin-marker", ], "icon-size": ['interpolate', ['linear'], ['zoom'], 12, 0.05, 14, 0.1], }} minzoom={12} /> Статьи {articles !== null && articles.length > 0 && articles.map((article) => ( ))}
); }