added MRT sds image

This commit is contained in:
PxlLoewe
2025-06-07 00:34:30 -07:00
parent 6be3f70371
commit dd53110500
16 changed files with 1853 additions and 136 deletions

View File

@@ -15,7 +15,6 @@ import { ConnectedAircraft, Station } from "@repo/db";
import { useQuery } from "@tanstack/react-query";
import { getConnectedAircraftPositionLogAPI, getConnectedAircraftsAPI } from "_querys/aircrafts";
import { getMissionsAPI } from "_querys/missions";
import { checkSimulatorConnected } from "_helpers/simulatorConnected";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
const AircraftPopupContent = ({
@@ -384,16 +383,14 @@ export const AircraftLayer = () => {
const { data: aircrafts } = useQuery({
queryKey: ["aircrafts"],
queryFn: getConnectedAircraftsAPI,
refetchInterval: 10000,
refetchInterval: 10_000,
});
return (
<>
{aircrafts
?.filter((a) => checkSimulatorConnected(a.lastHeartbeat))
?.map((aircraft) => {
return <AircraftMarker key={aircraft.id} aircraft={aircraft} />;
})}
{aircrafts?.map((aircraft) => {
return <AircraftMarker key={aircraft.id} aircraft={aircraft} />;
})}
</>
);
};

View File

@@ -1,5 +1,5 @@
"use client";
import React, { useState } from "react";
import React, { useEffect, useMemo, useState } from "react";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
import {
ConnectedAircraft,
@@ -13,7 +13,7 @@ import {
Station,
} from "@repo/db";
import { toast } from "react-hot-toast";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { editConnectedAircraftAPI } from "_querys/aircrafts";
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
import { cn } from "_helpers/cn";
@@ -39,7 +39,9 @@ import {
TextSearch,
} from "lucide-react";
import { useSession } from "next-auth/react";
import { editMissionAPI, sendSdsMessageAPI } from "_querys/missions";
import { sendSdsMessageAPI } from "_querys/missions";
import { getLivekitRooms } from "_querys/livekit";
import { findLeitstelleForPosition } from "_helpers/findLeitstelleinPoint";
const FMSStatusHistory = ({
aircraft,
@@ -216,14 +218,35 @@ const RettungsmittelTab = ({
aircraft: ConnectedAircraft & { Station: Station };
}) => {
const station = aircraft.Station;
const { data: livekitRooms } = useQuery({
queryKey: ["livekit-rooms"],
queryFn: () => getLivekitRooms(),
refetchInterval: 10000,
});
const participants =
livekitRooms?.flatMap((room) =>
room.participants.map((p) => ({
...p,
roomName: room.room.name,
})),
) || [];
const livekitUser = participants.find((p) => (p.attributes.userId = aircraft.userId));
const lstName = useMemo(() => {
if (!aircraft.posLng || !aircraft.posLat) return;
return findLeitstelleForPosition(aircraft.posLng, aircraft.posLat);
}, [aircraft]);
return (
<div className="p-4 text-base-content">
<ul className="text-base-content font-semibold">
<li className="flex items-center gap-2 mb-1">
<Component size={16} /> Aktuelle Rufgruppe: LST_01
<Component size={16} /> Aktuelle Rufgruppe: {livekitUser?.roomName || "Nicht verbunden"}
</li>
<li className="flex items-center gap-2 mb-1">
<RadioTower size={16} /> Leitstellenbereich: Florian Berlin
<RadioTower size={16} /> Leitstellenbereich: {lstName || station.bosRadioArea}
</li>
</ul>
<div className="divider mt-0 mb-0" />
@@ -348,7 +371,7 @@ const SDSTab = ({
onClick={() => setIsChatOpen(true)}
>
<span className="flex items-center gap-2">
<Plus size={18} /> Notiz hinzufügen
<Plus size={18} /> SDS senden
</span>
</button>
) : (
@@ -379,6 +402,7 @@ const SDSTab = ({
},
})
.then(() => {
toast.success("SDS-Nachricht gesendet");
setIsChatOpen(false);
setNote("");
});

View File

@@ -6,7 +6,6 @@ import { useMapStore } from "_store/mapStore";
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
import { MISSION_STATUS_COLORS, MISSION_STATUS_TEXT_COLORS } from "_components/map/MissionMarkers";
import { cn } from "_helpers/cn";
import { checkSimulatorConnected } from "_helpers/simulatorConnected";
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
import { getMissionsAPI } from "_querys/missions";
import { useEffect, useMemo, useState } from "react";
@@ -96,41 +95,39 @@ const PopupContent = ({
</div>
);
})}
{aircrafts
.filter((a) => checkSimulatorConnected(a.lastHeartbeat))
.map((aircraft) => (
<div
key={aircraft.id}
className="relative w-auto inline-flex items-center gap-2 text-nowrap cursor-pointer"
{aircrafts.map((aircraft) => (
<div
key={aircraft.id}
className="relative w-auto inline-flex items-center gap-2 text-nowrap cursor-pointer"
style={{
backgroundColor: FMS_STATUS_COLORS[aircraft.fmsStatus],
}}
onClick={() => {
setOpenAircraftMarker({
open: [
{
id: aircraft.id,
tab: "aircraft",
},
],
close: [],
});
map.setView([aircraft.posLat!, aircraft.posLng!], 12, {
animate: true,
});
}}
>
<span
className="mx-2 my-0.5 text-gt font-bold"
style={{
backgroundColor: FMS_STATUS_COLORS[aircraft.fmsStatus],
}}
onClick={() => {
setOpenAircraftMarker({
open: [
{
id: aircraft.id,
tab: "aircraft",
},
],
close: [],
});
map.setView([aircraft.posLat!, aircraft.posLng!], 12, {
animate: true,
});
color: FMS_STATUS_TEXT_COLORS[aircraft.fmsStatus],
}}
>
<span
className="mx-2 my-0.5 text-gt font-bold"
style={{
color: FMS_STATUS_TEXT_COLORS[aircraft.fmsStatus],
}}
>
{aircraft.fmsStatus}
</span>
<span>{aircraft.Station.bosCallsign}</span>
</div>
))}
{aircraft.fmsStatus}
</span>
<span>{aircraft.Station.bosCallsign}</span>
</div>
))}
</div>
</>
);
@@ -141,6 +138,7 @@ export const MarkerCluster = () => {
const { data: aircrafts } = useQuery({
queryKey: ["aircrafts"],
queryFn: getConnectedAircraftsAPI,
refetchInterval: 10_000,
});
const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected";
@@ -178,38 +176,36 @@ export const MarkerCluster = () => {
lat: number;
lng: number;
}[] = [];
aircrafts
?.filter((a) => checkSimulatorConnected(a.lastHeartbeat))
.forEach((aircraft) => {
const lat = aircraft.posLat!;
const lng = aircraft.posLng!;
aircrafts?.forEach((aircraft) => {
const lat = aircraft.posLat!;
const lng = aircraft.posLng!;
const existingClusterIndex = newCluster.findIndex(
(c) => Math.abs(c.lat - lat) < 1 && Math.abs(c.lng - lng) < 1,
);
const existingCluster = newCluster[existingClusterIndex];
if (existingCluster) {
newCluster = [...newCluster].map((c, i) => {
if (i === existingClusterIndex) {
return {
...c,
aircrafts: [...c.aircrafts, aircraft],
};
}
return c;
});
} else {
newCluster = [
...newCluster,
{
aircrafts: [aircraft],
missions: [],
lat,
lng,
},
];
}
});
const existingClusterIndex = newCluster.findIndex(
(c) => Math.abs(c.lat - lat) < 1 && Math.abs(c.lng - lng) < 1,
);
const existingCluster = newCluster[existingClusterIndex];
if (existingCluster) {
newCluster = [...newCluster].map((c, i) => {
if (i === existingClusterIndex) {
return {
...c,
aircrafts: [...c.aircrafts, aircraft],
};
}
return c;
});
} else {
newCluster = [
...newCluster,
{
aircrafts: [aircraft],
missions: [],
lat,
lng,
},
];
}
});
filteredMissions?.forEach((mission) => {
const lat = mission.addressLat;
const lng = mission.addressLng;

View File

@@ -35,14 +35,14 @@ export default function AdminPanel() {
refetchInterval: 10000,
});
const { data: livekitRooms } = useQuery({
queryKey: ["connected-audio-users"],
queryKey: ["livekit-rooms"],
queryFn: () => getLivekitRooms(),
refetchInterval: 10000,
});
const kickLivekitParticipantMutation = useMutation({
mutationFn: kickLivekitParticipant,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["connected-audio-users"] });
queryClient.invalidateQueries({ queryKey: ["livekit-rooms"] });
},
});
const editUSerMutation = useMutation({
@@ -95,8 +95,6 @@ export default function AdminPanel() {
return !pilot && !fDispatcher;
});
console.log("Livekit Rooms", livekitRooms);
const modalRef = useRef<HTMLDialogElement>(null);
return (