diff --git a/apps/dispatch/app/_components/map/BaseMaps.tsx b/apps/dispatch/app/_components/map/BaseMaps.tsx index cebb083d..13b95956 100644 --- a/apps/dispatch/app/_components/map/BaseMaps.tsx +++ b/apps/dispatch/app/_components/map/BaseMaps.tsx @@ -1,7 +1,7 @@ "use client"; import { usePannelStore } from "_store/pannelStore"; import { Control, Icon, LatLngExpression } from "leaflet"; -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { LayerGroup, LayersControl, @@ -18,11 +18,13 @@ import { // @ts-ignore import type { FeatureCollection, Geometry } from "geojson"; import L from "leaflet"; -import LEITSTELLENBERECHE from "./_geojson/Leitstellen_VAR.json"; +import LEITSTELLENBERECHE from "./_geojson/Leitstellen.json"; +import WINDFARMS from "./_geojson/Windfarms.json"; import { createCustomMarker } from "_components/map/_components/createCustomMarker"; import { Station } from "@repo/db"; import { useQuery } from "@tanstack/react-query"; import { getStationsAPI } from "_querys/stations"; +import "./darkMapStyles.css"; const RadioAreaLayer = () => { const getColor = (randint: number) => { @@ -195,18 +197,12 @@ const StationsLayer = ({ attribution }: { attribution: Control.Attribution }) => }; const EsriSatellite = ({ attribution }: { attribution: Control.Attribution }) => { - const accessToken = process.env.NEXT_PUBLIC_ESRI_ACCESS_TOKEN || ""; - - const attributionText = "Sources: Esri, TomTom, Garmin, FAO, NOAA, USGS"; - + const accessToken = process.env.NEXT_PUBLIC_ESRI_ACCESS; return ( <> {/* Satellite Imagery Layer; API KEY PROVIDED BY VAR0002 */} attribution.addAttribution(attributionText), - remove: () => attribution.removeAttribution(attributionText), - }} + attribution="Sources: Esri, TomTom, Garmin, FAO, NOAA, USGS" url={`https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}?token=${accessToken}`} tileSize={256} /> @@ -226,39 +222,36 @@ const StrassentexteEsri = () => { const OpenAIP = ({ attribution }: { attribution: Control.Attribution }) => { const accessToken = process.env.NEXT_PUBLIC_OPENAIP_ACCESS; - const attributionText = '© OpenAIP'; + const ref = useRef(null); return ( attribution.addAttribution(attributionText), - remove: () => attribution.removeAttribution(attributionText), + add: () => { + if (ref.current) { + ref.current.bringToFront(); + } + }, }} - url={`https://api.tiles.openaip.net/api/data/openaip/{z}/{x}/{y}.png?apiKey=${accessToken}`} + ref={ref} + attribution='© OpenAIP' + url={`https://api.tiles.openaip.net/api/data/openaip/{z}/{x}/{y}.png?apiKey=${process.env.NEXT_PUBLIC_OPENAIP_ACCESS}`} /> ); }; const NiederschlagOverlay = ({ attribution }: { attribution: Control.Attribution }) => { - let tileLayer: L.TileLayer | null = null; - - useEffect(() => { - if (tileLayer) { - tileLayer.bringToFront(); - } - }, [tileLayer]); + const tileLayerRef = useRef(null); return ( { - if (layer) { - tileLayer = layer; - } - }} + ref={tileLayerRef} eventHandlers={{ - add: () => attribution.addAttribution("Quelle: Deutscher Wetterdienst"), - remove: () => attribution.removeAttribution("Quelle: Deutscher Wetterdienst"), + add: () => { + tileLayerRef.current?.bringToFront(); + }, }} + attribution="Quelle: Deutscher Wetterdienst" url="https://maps.dwd.de/geoserver/wms?" format="image/png" layers="dwd:Niederschlagsradar" @@ -268,6 +261,47 @@ const NiederschlagOverlay = ({ attribution }: { attribution: Control.Attribution ); }; +const WindfarmOutlineLayer = () => { + const map = useMap(); + const [isVisible, setIsVisible] = useState(false); + + useEffect(() => { + const handleZoom = () => { + setIsVisible(map.getZoom() < 13); + }; + + // Initial check and event listener + handleZoom(); + map.on("zoomend", handleZoom); + + // Cleanup on unmount + return () => { + map.off("zoomend", handleZoom); + }; + }, [map]); + + return isVisible ? ( + } + style={() => ({ + color: "#233EE5", + weight: 1.5, + dashArray: "7, 10", + className: "no-pointer", + })} + onEachFeature={(feature, layer) => { + layer.bindTooltip( + new L.Tooltip({ + content: feature.properties.Cluster_NR, + direction: "top", + sticky: true, + }), + ); + }} + /> + ) : null; +}; + export const BaseMaps = () => { const map = useMap(); const isPannelOpen = usePannelStore((state) => state.isOpen); @@ -287,23 +321,36 @@ export const BaseMaps = () => { + + + + - + + + + + - + diff --git a/apps/dispatch/app/_components/map/Map.tsx b/apps/dispatch/app/_components/map/Map.tsx index 331adcc8..70a64142 100644 --- a/apps/dispatch/app/_components/map/Map.tsx +++ b/apps/dispatch/app/_components/map/Map.tsx @@ -18,27 +18,6 @@ const Map = () => { // Sync map zoom and center with the map store if (ref.current) { ref.current.setView(map.center, map.zoom); - /* ref.current.on("moveend", () => { - const center = ref.current?.getCenter(); - const zoom = ref.current?.getZoom(); - if (center && zoom) { - setMap({ - center: [center.lat, center.lng], - zoom, - }); - } - }); - ref.current.on("zoomend", () => { - const zoom = ref.current?.getZoom(); - const center = ref.current?.getCenter(); - - if (zoom && center) { - setMap({ - center, - zoom, - }); - } - }); */ } }, [map, setMap]); diff --git a/apps/dispatch/app/_components/map/_geojson/Leitstellen_VAR.json b/apps/dispatch/app/_components/map/_geojson/Leitstellen.json similarity index 100% rename from apps/dispatch/app/_components/map/_geojson/Leitstellen_VAR.json rename to apps/dispatch/app/_components/map/_geojson/Leitstellen.json diff --git a/apps/dispatch/app/_components/map/_geojson/Windfarms.json b/apps/dispatch/app/_components/map/_geojson/Windfarms.json new file mode 100644 index 00000000..5b7c7146 --- /dev/null +++ b/apps/dispatch/app/_components/map/_geojson/Windfarms.json @@ -0,0 +1,280 @@ +{ + "type": "FeatureCollection", + "name": "Windwarm Outline", + "crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } }, + "features": [ + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Nordsee 2" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [6.408569171053162, 54.092894111774619], + [6.553274345023835, 54.096524568982488], + [6.567977009758822, 54.089263336836567], + [6.631237159342258, 54.044760552960362], + [6.633945544951335, 53.937622529733801], + [6.612278460078721, 53.925549400123892], + [6.485758160911852, 53.908230892125651], + [6.411857925007043, 53.964717399160051], + [6.405860785444085, 54.092837383359722], + [6.408569171053162, 54.092894111774619] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Nordsee 3" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [6.746150091613089, 53.999300372895689], + [6.803219645518634, 53.998959233810659], + [6.820243783632831, 53.997708366581392], + [6.901882264135003, 54.002939015860534], + [6.90362336916941, 53.991112263263219], + [6.906912123123289, 53.984742620210149], + [6.912909262686243, 53.977689378982305], + [6.851003305907347, 53.964717399160051], + [6.838815570666502, 53.968131469564277], + [6.81385973184001, 53.965627845278867], + [6.803993469978374, 53.967903873571053], + [6.775168508853198, 53.958912837641186], + [6.744602442693618, 53.957888419352699], + [6.743828618233882, 53.999300372895689], + [6.746150091613089, 53.999300372895689] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Nordsee 3" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [6.935156715903661, 54.096978353793709], + [7.115457815022199, 54.100948759136394], + [7.144863144492176, 54.006691033297585], + [6.945990258339969, 53.975982770232669], + [6.936704364823134, 53.991225998035624], + [6.935543628133531, 54.061908854497545], + [6.935156715903661, 54.096978353793709] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Nordsee 6" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [5.831683036319818, 54.351784560616196], + [6.02746062463308, 54.436483299742669], + [6.030169010242157, 54.300113717838755], + [5.933827865004999, 54.294468865715544], + [5.930732567166054, 54.267814715855764], + [5.802277706849843, 54.268040670933416], + [5.720639226347673, 54.308918141956461], + [5.831683036319818, 54.351784560616196] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Nordsee 8" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [6.196541269085445, 54.502588747611675], + [6.218982178417796, 54.505509312203003], + [6.237940877681333, 54.505509312203003], + [6.260768699243552, 54.50213941145477], + [6.295203887701812, 54.502813413837345], + [6.296751536621286, 54.549517146074706], + [6.437974500523144, 54.548843914226211], + [6.396961804157124, 54.454256822783051], + [6.401604750915541, 54.447058350528373], + [6.368330299146884, 54.379060417227556], + [6.192672146786764, 54.495623481951732], + [6.196541269085445, 54.502588747611675] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Nordsee 4" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [7.636435132539605, 54.542223209252747], + [7.782687955429749, 54.543569880350667], + [7.781914130970012, 54.504386042832451], + [7.756764836028584, 54.458305407267929], + [7.746124749707214, 54.447620776749311], + [7.750187328120828, 54.44233366528497], + [7.767018010120092, 54.435245615336498], + [7.776884271981728, 54.423654574157155], + [7.778045008671332, 54.382665786191204], + [7.712076473478818, 54.366101008484485], + [7.635080939735064, 54.33588407675699], + [7.632179098011054, 54.542110984655046], + [7.636435132539605, 54.542223209252747] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Nordsee 5" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [7.734517382811168, 55.047217966603846], + [7.750767696465628, 55.056969927710014], + [7.762375063361672, 55.062288178206174], + [7.787137446073229, 55.065611725974222], + [7.807256882026373, 55.066941067806432], + [7.809578355405578, 54.961342684172195], + [7.78288141154468, 54.957788326543074], + [7.730261348282617, 55.007076959508197], + [7.731422084972221, 55.036133309469704], + [7.734517382811168, 55.047217966603846] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Nordsee 5" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [6.784260946255096, 55.283254496126993], + [6.80399346997837, 55.296693824941102], + [6.851970586482014, 55.303081418102373], + [6.923162436777745, 55.114767971699848], + [6.876346056963706, 55.107686114070709], + [6.852357498711881, 55.115653115643283], + [6.784260946255096, 55.283254496126993] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Nordsee 5" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [7.161113458146631, 55.166294911164037], + [7.173494649502412, 55.166515913471592], + [7.158405072537557, 55.230334261433178], + [7.16382184375571, 55.240041580787846], + [7.17813759626083, 55.242247459290844], + [7.213346609178827, 55.233864469897796], + [7.223019414925529, 55.225038361225486], + [7.256293866694187, 55.067605722163997], + [7.242751938648803, 55.05896435444658], + [7.181232894099774, 55.056083483932724], + [7.168464790514125, 55.063396058127339], + [7.156857423618083, 55.165852902873965], + [7.161113458146631, 55.166294911164037] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Ostsee 3" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [13.147419478665986, 55.010183223462356], + [13.159800670021767, 55.012845543941353], + [13.238343852684991, 55.013954791975962], + [13.240278413834332, 54.997312849326931], + [13.22209353903053, 54.975556970624545], + [13.182628491583982, 54.959121247501052], + [13.126139306023241, 54.948901056787655], + [13.070810857152102, 54.945123371995351], + [13.147419478665986, 55.010183223462356] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Ostsee 2" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [13.905767449207476, 54.861701768020545], + [13.933238217528116, 54.783685583970481], + [13.917761728333391, 54.784354934615898], + [13.800527322683354, 54.808890142128121], + [13.794336727005462, 54.813349489091614], + [13.790467604706782, 54.83363330360168], + [13.790854516936651, 54.851902300845175], + [13.799753498223614, 54.859697525247405], + [13.817938373027419, 54.863483233529408], + [13.894160082311434, 54.866155284227013], + [13.905767449207476, 54.861701768020545] + ] + ] + } + }, + { + "type": "Feature", + "properties": { "Cluster_NR": "Cluster Ostsee 1" }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [14.104640335359685, 54.811565809371203], + [14.113926228876519, 54.820037586679021], + [14.125920508002428, 54.835861672920906], + [14.132884928140058, 54.841877655635969], + [14.088003109475354, 54.881070979779921], + [14.053181008787227, 54.875951288533805], + [14.029966274995141, 54.861924455513225], + [14.015263610260153, 54.84499670105194], + [14.007138453432921, 54.824941487790426], + [14.012555224651074, 54.801085100514676], + [14.024162591547121, 54.793724680462951], + [14.039639080741845, 54.791493985530259], + [14.041573641891183, 54.782793099210046], + [14.039639080741845, 54.776098835704246], + [14.038865256282104, 54.765162489223513], + [14.063240726763798, 54.75556285186056], + [14.099610476371401, 54.74707755632884], + [14.139849348277682, 54.745737610270567], + [14.159194959771089, 54.749757315444057], + [14.169254677747658, 54.757125738669906], + [14.190147938160536, 54.790155509491385], + [14.194403972689084, 54.807998213669585], + [14.174671448965812, 54.812457659075427], + [14.159968784230822, 54.818922980649404], + [14.110444018807705, 54.808890142128121], + [14.104640335359685, 54.811565809371203] + ] + ] + } + } + ] +} diff --git a/apps/dispatch/app/_components/map/darkMapStyles.css b/apps/dispatch/app/_components/map/darkMapStyles.css new file mode 100644 index 00000000..5587f399 --- /dev/null +++ b/apps/dispatch/app/_components/map/darkMapStyles.css @@ -0,0 +1,52 @@ +.leaflet-control-layers { + background-color: rgb(16, 22, 31); + color: white; + border-color: white; +} + +.leaflet-popup-content-wrapper { + background-color: rgb(16, 22, 31); + color: #fff; +} + +.leaflet-bar a, +.leaflet-bar a:hover { + color: #fff; + background-color: rgb(16, 22, 31); + border-color: white; +} + +.leaflet-control-attribution { + color: #fff; + background: rgb(16, 22, 31) !important; +} +.leaflet-control-attribution a, +.leaflet-control-attribution a:hover { + color: inherit; + text-decoration: underline; +} + +.leaflet-tooltip-aircraft { + padding: 0; + border: 0; + background-color: var(--dark-surface); + color: var(--dark-on-surface); +} + +.leaflet-tooltip-aircraft:before { + border-bottom-color: var(--surface) !important; +} + +.leaflet-tooltip-aircraft-light { + padding: 0 !important; + border: 0 !important; + background-color: var(--surface) !important; + color: var(--on-surface) !important; +} + +.leaflet-tooltip-aircraft-light:before { + border-bottom-color: var(--dark-surface) !important; +} +.leaflet-popup-tip { + background-color: var(--blue-600); +} diff --git a/apps/dispatch/app/_components/map/mapStyles.css b/apps/dispatch/app/_components/map/mapStyles.css new file mode 100644 index 00000000..0cc27180 --- /dev/null +++ b/apps/dispatch/app/_components/map/mapStyles.css @@ -0,0 +1,106 @@ +.no-pointer { + cursor: unset; +} +.pointer { + cursor: pointer; +} + +.leaflet-tooltip-aircraft { + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + color: rgb(254, 254, 254) !important; + left: 35px !important; + top: 40px !important; + border: none !important; + box-shadow: none !important; +} + +.leaflet-popup-content-wrapper { + background-color: var(--dark-background); +} + +@keyframes fade-in { + from { + right: -20%; + opacity: 0; + } + to { + right: 0; + opacity: 1; + } +} + +@keyframes fade-out { + from { + right: 0; + opacity: 1; + } + to { + right: -20%; + opacity: 0; + } +} + +.leaflet-tooltip-aircraft:before { + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + color: rgb(255, 255, 255) !important; + left: 0px !important; + top: 0px !important; + border: none !important; + box-shadow: none !important; +} + +.custom-tooltip-bg { + background: transparent !important; +} + +.custom-tooltip-bg:before { + background: transparent !important; +} + +.no-pointer { + cursor: unset; +} + +.pointer { + cursor: pointer; +} + +.leaflet-tooltip-aircraft { + padding: 0 !important; + border: 0 !important; + background-color: var(--surface) !important; + color: var(--on-surface) !important; +} + +.leaflet-tooltip-aircraft:before { + border-bottom-color: var(--dark-surface) !important; +} + +.modal-box { + position: fixed; + bottom: 50%; + right: 50px; + background-color: rgba(255, 255, 255, 0.75); + border: 5px solid #243671; + border-radius: 8px; + padding: 10px; + box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); + z-index: 1000; + max-width: 300px; + word-wrap: break-word; + overflow-wrap: break-word; + text-align: center; +} + +.modal-box-close { + position: absolute; + top: 5px; + right: 5px; + font-size: 18px; + cursor: pointer; + color: #243671; +} diff --git a/apps/dispatch/app/api/aircrafts/route.ts b/apps/dispatch/app/api/aircrafts/route.ts index 2bca80d9..39465c4b 100644 --- a/apps/dispatch/app/api/aircrafts/route.ts +++ b/apps/dispatch/app/api/aircrafts/route.ts @@ -3,11 +3,9 @@ import { Prisma, prisma } from "@repo/db"; export async function GET(request: Request): Promise { try { - console.log(new URL(request.url).searchParams.get("filter")); const filter = JSON.parse( new URL(request.url).searchParams.get("filter") || "{}", ) as Prisma.ConnectedAircraftWhereInput; - console.log("Filter:", filter); const connectedAircraft = await prisma.connectedAircraft.findMany({ where: {