From d74181c78ffa33962e2e86dd4c31c6ebcb021a61 Mon Sep 17 00:00:00 2001 From: PxlLoewe <72106766+PxlLoewe@users.noreply.github.com> Date: Tue, 15 Apr 2025 23:24:07 -0700 Subject: [PATCH] copied aircraft marker to mission marker --- apps/dispatch/app/_store/missionsStore.ts | 1 + .../app/dispatch/_components/map/Map.tsx | 4 +- .../_components/map/MissionMarkers.tsx | 274 ++++++++++++++---- grafana/grafana.db | Bin 1122304 -> 1122304 bytes .../database/prisma/schema/mission.prisma | 19 +- 5 files changed, 227 insertions(+), 71 deletions(-) diff --git a/apps/dispatch/app/_store/missionsStore.ts b/apps/dispatch/app/_store/missionsStore.ts index 9e186a5c..95f50c25 100644 --- a/apps/dispatch/app/_store/missionsStore.ts +++ b/apps/dispatch/app/_store/missionsStore.ts @@ -9,6 +9,7 @@ interface MissionStore { export const useMissionsStore = create((set) => ({ missions: [ { + state: "draft", id: "01250325", addressLat: 52.520008, addressLng: 13.404954, diff --git a/apps/dispatch/app/dispatch/_components/map/Map.tsx b/apps/dispatch/app/dispatch/_components/map/Map.tsx index 176cc4f6..56166236 100644 --- a/apps/dispatch/app/dispatch/_components/map/Map.tsx +++ b/apps/dispatch/app/dispatch/_components/map/Map.tsx @@ -4,7 +4,7 @@ import { useMapStore } from "_store/mapStore"; import { MapContainer } from "react-leaflet"; import { BaseMaps } from "dispatch/_components/map/BaseMaps"; import { ContextMenu } from "dispatch/_components/map/ContextMenu"; -import { MissionMarkers } from "dispatch/_components/map/MissionMarkers"; +import { MissionLayer } from "dispatch/_components/map/MissionMarkers"; import { SearchElements } from "dispatch/_components/map/SearchElements"; import { AircraftLayer } from "dispatch/_components/map/AircraftMarker"; @@ -16,7 +16,7 @@ export default ({}) => { - + ); diff --git a/apps/dispatch/app/dispatch/_components/map/MissionMarkers.tsx b/apps/dispatch/app/dispatch/_components/map/MissionMarkers.tsx index 893317c4..fa8aeec6 100644 --- a/apps/dispatch/app/dispatch/_components/map/MissionMarkers.tsx +++ b/apps/dispatch/app/dispatch/_components/map/MissionMarkers.tsx @@ -1,104 +1,252 @@ -import { MissionOptionalDefaults } from "@repo/db/zod"; -import { useMapStore } from "_store/mapStore"; import { useMissionsStore } from "_store/missionsStore"; -import { Icon, Marker as LMarker } from "leaflet"; -import { House, Route } from "lucide-react"; -import { RefObject, useEffect, useRef, useState } from "react"; import { Marker, Popup, useMap } from "react-leaflet"; +import { DivIcon, Marker as LMarker, Popup as LPopup } from "leaflet"; +import { useMapStore } from "_store/mapStore"; +import { Fragment, useCallback, useEffect, useRef, useState } from "react"; +import { cn } from "helpers/cn"; +import { Cross, House, Minimize2, Route } from "lucide-react"; +import { SmartPopup, useConflict, useSmartPopup } from "_components/SmartPopup"; +import { Mission } from "@repo/db"; -export const MissionMarker = ({ - mission, -}: { - mission: MissionOptionalDefaults; -}) => { - const { openMissionMarker, setOpenMissionMarker } = useMapStore(); - const [zoom, setZoom] = useState(0); +export const MISSION_STATUS_COLORS: { [key: string]: string } = { + draft: "0092b8", + running: "#155dfc", +}; + +export const MISSION_STATUS_TEXT_COLORS: { [key: string]: string } = { + draft: "00d3f2", + running: "#50a2ff", +}; + +const MissionPopupContent = ({ mission }: { mission: Mission }) => { + const setOpenMissionMarker = useMapStore( + (state) => state.setOpenMissionMarker, + ); + const { anchor } = useSmartPopup(); + return ( + <> +
{ + setOpenMissionMarker({ + open: [], + close: [mission.id], + }); + }} + > + +
+ +
+
+
+
+ +
+
+ +
+
+ {mission.state} +
+
+ Einsatz 250411 +
+
+
+ + ); +}; + +const MissionMarker = ({ mission }: { mission: Mission }) => { + const missions = useMissionsStore((state) => state.missions); const map = useMap(); - const markerRef = useRef>(null); + const markerRef = useRef(null); + const popupRef = useRef(null); - useEffect(() => { - // markerRef.current?.openPopup(); - - const handleZoom = () => { - setZoom(map.getZoom()); - }; - map.on("zoom", handleZoom); - return () => { - map.off("zoom", handleZoom); - }; - }, [map]); + const { openMissionMarker, setOpenMissionMarker } = useMapStore( + (store) => store, + ); useEffect(() => { const handleClick = () => { - if (!mission.id) return; - if (!openMissionMarker.includes(mission.id)) { - setOpenMissionMarker({ - open: [mission.id], - close: [], - }); - // setSearchPopup(null); - } else { - console.log("close", mission.id); + const open = openMissionMarker.includes(mission.id); + if (open) { setOpenMissionMarker({ open: [], close: [mission.id], }); - // setSearchPopup(null); + } else { + setOpenMissionMarker({ + open: [mission.id], + close: [], + }); } }; markerRef.current?.on("click", handleClick); return () => { markerRef.current?.off("click", handleClick); }; - }, [markerRef.current, mission.id, setOpenMissionMarker, openMissionMarker]); + }, [markerRef.current, mission.id, openMissionMarker]); + + const [anchor, setAnchor] = useState< + "topleft" | "topright" | "bottomleft" | "bottomright" + >("topleft"); + + const handleConflict = () => { + const newAnchor = useConflict(mission.id, "marker"); + setAnchor(newAnchor); + }; + + useEffect(() => { + handleConflict(); + }, [missions, openMissionMarker]); + + useEffect(() => {}); + + useEffect(() => { + setTimeout(() => { + handleConflict(); + }, 100); + + map.on("zoom", handleConflict); + return () => { + map.off("zoom", handleConflict); + }; + }, [map, openMissionMarker]); + + const getMarkerHTML = ( + mission: Mission, + anchor: "topleft" | "topright" | "bottomleft" | "bottomright", + ) => { + return `
+ +
+ + ${mission.state} + + + ${mission.missionSummary} + +
+
`; + }; return ( - <> + - {mission.id && openMissionMarker.includes(mission.id) && ( - + {openMissionMarker.includes(mission.id) && ( + -
-
-
- -
-
- -
-
- {mission.missionCategory} -
-
-
-
+ + )} - +
); }; -export const MissionMarkers = () => { - const { missions } = useMissionsStore(); +export const MissionLayer = () => { + const missions = useMissionsStore((state) => state.missions); + // IDEA: Add Marker to Map Layer / LayerGroup return ( <> - {missions.map((mission) => ( - - ))} + {missions.map((mission) => { + return ; + })} ); }; diff --git a/grafana/grafana.db b/grafana/grafana.db index b0fd56e4a09ea5dd7913ef1b9c0868e44eb2ea65..98cd062b4f2009916d13292ef1693d85933d1b50 100644 GIT binary patch delta 87 zcmZoT;L>owWr8%L%S0JxMwiBf)&$1Z1g6#m=GFw3)&$np1h&=$_N@sVrTVO{>Hodu g+HdJ|05K;Ja{)0o5c2>rFA(zqG5_{k`T}Yn07aM}3IG5A delta 87 zcmZoT;L>owWr8%L<3t%}M#sj4)&$1Z1g6#m=GFw3)&$np1h&=$_N@sVrTVN+>Hl5C g+HdJ|05K;Ja{)0o5c2>rFA(zqG5_{k`T}Yn06_vD@&Et; diff --git a/packages/database/prisma/schema/mission.prisma b/packages/database/prisma/schema/mission.prisma index 88b18ee9..1acb0fc8 100644 --- a/packages/database/prisma/schema/mission.prisma +++ b/packages/database/prisma/schema/mission.prisma @@ -1,5 +1,6 @@ model Mission { - id String @id @default(uuid()) + id String @id @default(uuid()) + state MissionState @default(draft) addressLat Float addressLng Float addressStreet String @@ -10,11 +11,17 @@ model Mission { missionSummary String missionPatientInfo String missionAdditionalInfo String - hpgAmbulanceState HpgState? @default(ready) - hpgFireEngineState HpgState? @default(ready) - hpgPoliceState HpgState? @default(ready) - hpgLocationLat Float? @default(0) - hpgLocationLng Float? @default(0) + hpgAmbulanceState HpgState? @default(ready) + hpgFireEngineState HpgState? @default(ready) + hpgPoliceState HpgState? @default(ready) + hpgLocationLat Float? @default(0) + hpgLocationLng Float? @default(0) +} + +enum MissionState { + running + finished + draft } enum HpgState {