187 lines
5.5 KiB
TypeScript
187 lines
5.5 KiB
TypeScript
import { getPublicUser, MissionSdsStatusLog, StationStatus } from "@repo/db";
|
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
import { BaseNotification } from "_components/customToasts/BaseNotification";
|
|
import { FMS_STATUS_COLORS } from "_helpers/fmsStatusColors";
|
|
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
|
|
import { getLivekitRooms } from "_querys/livekit";
|
|
import { sendSdsStatusMessageAPI } from "_querys/missions";
|
|
import { getStationsAPI } from "_querys/stations";
|
|
import { useAudioStore } from "_store/audioStore";
|
|
import { useMapStore } from "_store/mapStore";
|
|
import { X } from "lucide-react";
|
|
import { useSession } from "next-auth/react";
|
|
import { useEffect, useRef } from "react";
|
|
import { Toast, toast } from "react-hot-toast";
|
|
|
|
export const QUICK_RESPONSE: Record<string, string[]> = {
|
|
"5": ["J", "o"],
|
|
"9": ["u", "o"],
|
|
"0": ["J"],
|
|
};
|
|
|
|
export const StatusToast = ({ event, t }: { event: StationStatus; t: Toast }) => {
|
|
const status0Sounds = useRef<HTMLAudioElement | null>(null);
|
|
const status5Sounds = useRef<HTMLAudioElement | null>(null);
|
|
const status9Sounds = useRef<HTMLAudioElement | null>(null);
|
|
|
|
const session = useSession();
|
|
|
|
const { data: livekitRooms } = useQuery({
|
|
queryKey: ["livekit-rooms"],
|
|
queryFn: () => getLivekitRooms(),
|
|
refetchInterval: 5000,
|
|
});
|
|
const audioRoom = useAudioStore((s) => s.room?.name);
|
|
|
|
const participants =
|
|
livekitRooms?.flatMap((room) =>
|
|
room.participants.map((p) => ({
|
|
...p,
|
|
roomName: room.room.name,
|
|
})),
|
|
) || [];
|
|
|
|
const livekitUser = participants.find((p) => p.attributes.userId === event.data?.userId);
|
|
|
|
useEffect(() => {
|
|
if (typeof window !== "undefined") {
|
|
status0Sounds.current = new Audio("/sounds/status-0.mp3");
|
|
status5Sounds.current = new Audio("/sounds/status-5.mp3");
|
|
status9Sounds.current = new Audio("/sounds/status-9.mp3");
|
|
}
|
|
}, []);
|
|
|
|
//const mapStore = useMapStore((s) => s);
|
|
const { setOpenAircraftMarker, setMap } = useMapStore((store) => store);
|
|
|
|
const { data: connectedAircrafts } = useQuery({
|
|
queryKey: ["aircrafts"],
|
|
queryFn: () => getConnectedAircraftsAPI(),
|
|
refetchInterval: 10000,
|
|
initialData: [],
|
|
});
|
|
const { data: stations } = useQuery({
|
|
queryKey: ["stations"],
|
|
queryFn: () => getStationsAPI(),
|
|
});
|
|
|
|
const connectedAircraft = connectedAircrafts?.find((a) => a.id === event.data?.aircraftId);
|
|
const station = stations?.find((s) => s.id === event.data?.stationId);
|
|
|
|
const queryClient = useQueryClient();
|
|
const sendSdsStatusMutation = useMutation({
|
|
mutationFn: async ({ sdsMessage }: { sdsMessage: MissionSdsStatusLog }) => {
|
|
if (!connectedAircraft?.id) throw new Error("No connected aircraft");
|
|
await sendSdsStatusMessageAPI({ sdsMessage, aircraftId: connectedAircraft?.id });
|
|
queryClient.invalidateQueries({
|
|
queryKey: ["missions"],
|
|
});
|
|
},
|
|
});
|
|
|
|
useEffect(() => {
|
|
let soundRef: React.RefObject<HTMLAudioElement | null> | null = null;
|
|
switch (event.status) {
|
|
case "0":
|
|
soundRef = status0Sounds;
|
|
break;
|
|
case "5":
|
|
soundRef = status5Sounds;
|
|
break;
|
|
case "9":
|
|
soundRef = status9Sounds;
|
|
break;
|
|
default:
|
|
soundRef = null;
|
|
}
|
|
|
|
if (audioRoom && livekitUser?.roomName && audioRoom !== livekitUser?.roomName) {
|
|
toast.remove(t.id);
|
|
return;
|
|
}
|
|
|
|
if (soundRef?.current) {
|
|
soundRef.current.currentTime = 0;
|
|
soundRef.current.volume = 0.7;
|
|
soundRef.current.play().catch(() => {});
|
|
}
|
|
return () => {
|
|
if (soundRef?.current) {
|
|
soundRef.current.pause();
|
|
soundRef.current.currentTime = 0;
|
|
}
|
|
};
|
|
}, [event.status, livekitUser?.roomName, audioRoom, t.id]);
|
|
|
|
console.log(connectedAircraft, station);
|
|
if (!connectedAircraft || !station || !session.data) return null;
|
|
return (
|
|
<BaseNotification>
|
|
<div className="flex flex-row items-center gap-14">
|
|
<p>
|
|
<span
|
|
className="mr-1 cursor-pointer font-bold underline"
|
|
onClick={() => {
|
|
if (!connectedAircraft.posLat || !connectedAircraft.posLng) return;
|
|
|
|
setOpenAircraftMarker({
|
|
open: [{ id: connectedAircraft.id, tab: "fms" }],
|
|
close: [],
|
|
});
|
|
setMap({
|
|
center: [connectedAircraft.posLat, connectedAircraft.posLng],
|
|
zoom: 14,
|
|
});
|
|
}}
|
|
>
|
|
{station.bosCallsign}
|
|
</span>
|
|
sendet Status {event.status}
|
|
</p>
|
|
<div className="flex items-center gap-2">
|
|
{QUICK_RESPONSE[String(event.status)]?.map((status) => (
|
|
<button
|
|
key={status}
|
|
className={
|
|
"flex min-h-10 min-w-10 cursor-pointer items-center justify-center text-lg font-bold"
|
|
}
|
|
style={{
|
|
backgroundColor: FMS_STATUS_COLORS[status],
|
|
color: "white",
|
|
}}
|
|
onClick={async () => {
|
|
if (!event.data?.aircraftId) {
|
|
toast.remove(t.id);
|
|
toast.error("Keine Flugzeug-ID gefunden");
|
|
return;
|
|
}
|
|
await sendSdsStatusMutation.mutateAsync({
|
|
sdsMessage: {
|
|
type: "sds-status-log",
|
|
auto: false,
|
|
data: {
|
|
direction: "to-aircraft",
|
|
stationId: event.data.stationId!,
|
|
station: station,
|
|
user: getPublicUser(session.data?.user),
|
|
status,
|
|
},
|
|
timeStamp: new Date().toISOString(),
|
|
},
|
|
});
|
|
toast.remove(t.id);
|
|
toast.success(`Status auf ${status} geändert`);
|
|
}}
|
|
>
|
|
{status}
|
|
</button>
|
|
))}
|
|
<button className="btn btn-ghost btn-sm" onClick={() => toast.remove(t.id)}>
|
|
<X size={16} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</BaseNotification>
|
|
);
|
|
};
|