added grafana, map react-leaflet
This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
"use client";
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
import L from "leaflet";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import ToastCard from "./toast/ToastCard";
|
||||
import { Toast, ToastBar, Toaster, toast } from "react-hot-toast";
|
||||
|
||||
export default () => {
|
||||
const mapRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!mapRef.current) return;
|
||||
|
||||
// Initialisiere die Leaflet-Karte
|
||||
const map = L.map(mapRef.current).setView([51.1657, 10.4515], 6); // Deutschland
|
||||
|
||||
// OpenStreetMap Tile Layer hinzufügen
|
||||
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||
attribution:
|
||||
'© <a href="https://www.openstreetmap.org/copyright">OSM</a> contributors',
|
||||
}).addTo(map);
|
||||
|
||||
return () => {
|
||||
map.remove(); // Karte beim Unmounten bereinigen
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="relative w-full h-full">
|
||||
<div>
|
||||
<Toaster
|
||||
containerStyle={{
|
||||
top: 150,
|
||||
left: 20,
|
||||
right: 20,
|
||||
}}
|
||||
toastOptions={{
|
||||
style: {
|
||||
background: "var(--color-base-100)",
|
||||
color: "var(--color-base-content)",
|
||||
},
|
||||
}}
|
||||
position="top-left"
|
||||
reverseOrder={false}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
ref={mapRef}
|
||||
className="w-full h-full rounded-lg shadow-lg"
|
||||
style={{
|
||||
filter:
|
||||
"invert(100%) hue-rotate(180deg) brightness(95%) contrast(90%)",
|
||||
background: "#000 !important",
|
||||
}}
|
||||
/>
|
||||
<ToastCard />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
13
apps/dispatch/app/(dispatch)/_components/map/BaseMaps.tsx
Normal file
13
apps/dispatch/app/(dispatch)/_components/map/BaseMaps.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
"use client";
|
||||
import { TileLayer } from "react-leaflet";
|
||||
|
||||
export const BaseMaps = () => {
|
||||
return (
|
||||
<>
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
24
apps/dispatch/app/(dispatch)/_components/map/ContextMenu.tsx
Normal file
24
apps/dispatch/app/(dispatch)/_components/map/ContextMenu.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { useMapStore } from "_store/mapStore";
|
||||
import { useEffect } from "react";
|
||||
import { Popup, useMap } from "react-leaflet";
|
||||
|
||||
export const ContextMenu = () => {
|
||||
const map = useMap();
|
||||
const { popup, map: mapStore, setPopup } = useMapStore();
|
||||
|
||||
useEffect(() => {
|
||||
map.on("contextmenu", (e) => {
|
||||
setPopup({ isOpen: true, lat: e.latlng.lat, lng: e.latlng.lng });
|
||||
});
|
||||
}, [popup]);
|
||||
|
||||
if (!popup) return null;
|
||||
|
||||
return (
|
||||
<Popup position={[popup.lat, popup.lng]}>
|
||||
<div className="w-60">
|
||||
<h1>Context Menu</h1>
|
||||
</div>
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
27
apps/dispatch/app/(dispatch)/_components/map/Map.tsx
Normal file
27
apps/dispatch/app/(dispatch)/_components/map/Map.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
"use client";
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
import L from "leaflet";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import ToastCard from "../toast/ToastCard";
|
||||
import { Toast, ToastBar, Toaster, toast } from "react-hot-toast";
|
||||
import { useMapStore } from "_store/mapStore";
|
||||
import { MapContainer } from "react-leaflet";
|
||||
import { BaseMaps } from "(dispatch)/_components/map/BaseMaps";
|
||||
import { ContextMenu } from "(dispatch)/_components/map/ContextMenu";
|
||||
|
||||
export default () => {
|
||||
const { map } = useMapStore();
|
||||
|
||||
return (
|
||||
<MapContainer
|
||||
className="h-full w-full"
|
||||
center={map.center}
|
||||
zoom={map.zoom}
|
||||
scrollWheelZoom={true}
|
||||
>
|
||||
<BaseMaps />
|
||||
<ContextMenu />
|
||||
</MapContainer>
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import dynamic from "next/dynamic";
|
||||
const Map = dynamic(() => import("./_components/Map"), { ssr: false });
|
||||
const Map = dynamic(() => import("./_components/map/Map"), { ssr: false });
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
|
||||
27
apps/dispatch/app/_store/mapStore.ts
Normal file
27
apps/dispatch/app/_store/mapStore.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { popup } from "leaflet";
|
||||
import { create } from "zustand";
|
||||
|
||||
interface MapStore {
|
||||
popup: {
|
||||
isOpen: boolean;
|
||||
lat: number;
|
||||
lng: number;
|
||||
} | null;
|
||||
map: {
|
||||
center: L.LatLngExpression;
|
||||
zoom: number;
|
||||
};
|
||||
setPopup: (popup: MapStore["popup"]) => void;
|
||||
}
|
||||
|
||||
export const useMapStore = create<MapStore>((set, get) => ({
|
||||
map: {
|
||||
center: [51.5, 10.5],
|
||||
zoom: 6,
|
||||
},
|
||||
popup: null,
|
||||
setPopup: (popup) =>
|
||||
set((state) => ({
|
||||
popup: popup,
|
||||
})),
|
||||
}));
|
||||
@@ -28,6 +28,7 @@
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-hook-form": "^7.54.2",
|
||||
"react-leaflet": "^5.0.0-rc.2",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"tailwindcss": "^4.0.14",
|
||||
"zustand": "^5.0.3"
|
||||
|
||||
Reference in New Issue
Block a user