From 9e4a46c59571996e631d78f9c276408d92189281 Mon Sep 17 00:00:00 2001 From: PxlLoewe <72106766+PxlLoewe@users.noreply.github.com> Date: Mon, 7 Jul 2025 01:55:45 -0700 Subject: [PATCH] =?UTF-8?q?StationStatus=20Toast=20hinzugef=C3=BCgt=20#45?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/dispatch-server/routes/aircraft.ts | 26 ++- .../socket-events/connect-dispatch.ts | 1 - .../socket-events/connect-pilot.ts | 2 +- apps/dispatch/app/(app)/pilot/page.tsx | 2 +- .../app/_components/QueryProvider.tsx | 10 +- .../customToasts/StationStatusToast.tsx | 213 ++++++++---------- .../map/_components/AircraftMarkerTabs.tsx | 3 +- apps/dispatch/app/_querys/aircrafts.ts | 2 +- apps/dispatch/app/layout.tsx | 32 +-- packages/database/prisma/json/SocketEvents.ts | 16 +- .../components/PenaltyDropdown.tsx | 2 +- packages/shared-components/helper/index.ts | 1 + .../helper}/simulatorConnected.ts | 0 13 files changed, 170 insertions(+), 140 deletions(-) rename {apps/dispatch/app/_helpers => packages/shared-components/helper}/simulatorConnected.ts (100%) diff --git a/apps/dispatch-server/routes/aircraft.ts b/apps/dispatch-server/routes/aircraft.ts index 032a7bf3..ba5c8f7d 100644 --- a/apps/dispatch-server/routes/aircraft.ts +++ b/apps/dispatch-server/routes/aircraft.ts @@ -1,4 +1,11 @@ -import { AdminMessage, getPublicUser, MissionLog, Prisma, prisma } from "@repo/db"; +import { + AdminMessage, + getPublicUser, + MissionLog, + NotificationPayload, + Prisma, + prisma, +} from "@repo/db"; import { Router } from "express"; import { io } from "../index"; @@ -63,6 +70,23 @@ router.patch("/:id", async (req, res) => { }, }, }); + + if ( + oldConnectedAircraft && + updatedConnectedAircraft && + oldConnectedAircraft.fmsStatus !== updatedConnectedAircraft.fmsStatus + ) { + io.to("dispatchers").emit("notification", { + type: "station-status", + status: updatedConnectedAircraft.fmsStatus, + message: "FMS status changed", + data: { + stationId: updatedConnectedAircraft.stationId, + aircraftId: updatedConnectedAircraft.id, + }, + } as NotificationPayload); + } + if ( mission && aircraftUpdate.fmsStatus && diff --git a/apps/dispatch-server/socket-events/connect-dispatch.ts b/apps/dispatch-server/socket-events/connect-dispatch.ts index 5bc654f1..cadd1284 100644 --- a/apps/dispatch-server/socket-events/connect-dispatch.ts +++ b/apps/dispatch-server/socket-events/connect-dispatch.ts @@ -45,7 +45,6 @@ export const handleConnectDispatch = }); } - let parsedLogoffDate = null; const [logoffHours, logoffMinutes] = logoffTime.split(":").map(Number); const connectedDispatcherEntry = await prisma.connectedDispatcher.create({ diff --git a/apps/dispatch-server/socket-events/connect-pilot.ts b/apps/dispatch-server/socket-events/connect-pilot.ts index f55c774c..efe7582b 100644 --- a/apps/dispatch-server/socket-events/connect-pilot.ts +++ b/apps/dispatch-server/socket-events/connect-pilot.ts @@ -101,7 +101,7 @@ export const handleConnectPilot = await addRolesToMember(discordAccount.discordId.toString(), [DISCORD_ROLES.ONLINE_PILOT]); } - socket.join("dispatchers"); // Join the dispatchers room + socket.join("pilots"); // Join the pilots room socket.join(`user:${userId}`); // Join the user-specific room socket.join(`station:${stationId}`); // Join the station-specific room diff --git a/apps/dispatch/app/(app)/pilot/page.tsx b/apps/dispatch/app/(app)/pilot/page.tsx index f83c31d3..664b0b8e 100644 --- a/apps/dispatch/app/(app)/pilot/page.tsx +++ b/apps/dispatch/app/(app)/pilot/page.tsx @@ -9,7 +9,7 @@ import { ConnectedDispatcher } from "tracker/_components/ConnectedDispatcher"; import { useQuery } from "@tanstack/react-query"; import { usePilotConnectionStore } from "_store/pilot/connectionStore"; import { getAircraftsAPI, getConnectedAircraftsAPI } from "_querys/aircrafts"; -import { checkSimulatorConnected } from "_helpers/simulatorConnected"; +import { checkSimulatorConnected } from "@repo/shared-components"; import { SimConnectionAlert } from "(app)/pilot/_components/SimConnectionAlert"; const Map = dynamic(() => import("_components/map/Map"), { diff --git a/apps/dispatch/app/_components/QueryProvider.tsx b/apps/dispatch/app/_components/QueryProvider.tsx index d2dc6f84..cd415a27 100644 --- a/apps/dispatch/app/_components/QueryProvider.tsx +++ b/apps/dispatch/app/_components/QueryProvider.tsx @@ -2,7 +2,7 @@ "use client"; import { toast } from "react-hot-toast"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { QueryClient, QueryClientProvider, useQuery } from "@tanstack/react-query"; import { ReactNode, useEffect, useState } from "react"; import { dispatchSocket } from "(app)/dispatch/socket"; import { Mission, NotificationPayload } from "@repo/db"; @@ -10,9 +10,11 @@ import { HPGnotificationToast } from "_components/customToasts/HPGnotification"; import { useMapStore } from "_store/mapStore"; import { AdminMessageToast } from "_components/customToasts/AdminMessage"; import { pilotSocket } from "(app)/pilot/socket"; +import { StatusToast } from "_components/customToasts/StationStatusToast"; export function QueryProvider({ children }: { children: ReactNode }) { const mapStore = useMapStore((s) => s); + const [queryClient] = useState( () => new QueryClient({ @@ -73,6 +75,12 @@ export function QueryProvider({ children }: { children: ReactNode }) { duration: 999999, }); break; + case "station-status": + if (notification.status !== "5") return; + toast.custom((e) => , { + duration: 99999999 /* 30000 */, + }); + break; default: toast("unbekanntes Notification-Event"); break; diff --git a/apps/dispatch/app/_components/customToasts/StationStatusToast.tsx b/apps/dispatch/app/_components/customToasts/StationStatusToast.tsx index f60d725c..80ae3fe6 100644 --- a/apps/dispatch/app/_components/customToasts/StationStatusToast.tsx +++ b/apps/dispatch/app/_components/customToasts/StationStatusToast.tsx @@ -1,117 +1,102 @@ -import { useState } from "react"; -import { toast } from "react-hot-toast"; +import { Prisma, 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 { editConnectedAircraftAPI, getConnectedAircraftsAPI } from "_querys/aircrafts"; +import { getStationsAPI } from "_querys/stations"; +import { useMapStore } from "_store/mapStore"; +import { X } from "lucide-react"; +import { Toast, toast } from "react-hot-toast"; -interface ToastCard { - id: number; - title: string; - content: string; -} - -const MapToastCard2 = () => { - const [cards, setCards] = useState([]); - const [openCardId, setOpenCardId] = useState(null); - - const addCard = () => { - const newCard: ToastCard = { - id: Date.now(), - title: `Einsatz #${cards.length + 1}`, - content: `Inhalt von Einsatz #${cards.length + 1}.`, - }; - setCards([...cards, newCard]); - // DEBUG - /* toast("😖 Christoph 31 sendet Status 4", { - duration: 10000, - }); */ - // DEBUG - const toastId = toast.custom( -
-
- 😖 Christoph 31 sendet Status 5{" "} - -
-
, - { - duration: 999999999, - }, - ); - // DEBUG - }; - - const removeCard = (id: number) => { - setCards(cards.filter((card) => card.id !== id)); - }; - - const toggleCard = (id: number) => { - setOpenCardId(openCardId === id ? null : id); - }; - - return ( -
- {/* DEBUG */} - - {/* DEBUG */} - {cards.map((card) => ( -
- toggleCard(card.id)} - /> -
- {card.title} - -
-
{card.content}
-
- ))} -
- ); +const QUICK_RESPONSE: Record = { + "5": ["J", "c"], }; -export default MapToastCard2; +export const StatusToast = ({ event, t }: { event: StationStatus; t: Toast }) => { + const mapStore = useMapStore((s) => s); + + const { data: connectedAircrafts } = useQuery({ + queryKey: ["aircrafts"], + queryFn: () => getConnectedAircraftsAPI(), + refetchInterval: 10000, + }); + const { data: stations } = useQuery({ + queryKey: ["stations"], + queryFn: () => getStationsAPI(), + }); + + const queryClient = useQueryClient(); + const changeAircraftMutation = useMutation({ + mutationFn: async ({ + id, + update, + }: { + id: number; + update: Prisma.ConnectedAircraftUpdateInput; + }) => { + await editConnectedAircraftAPI(id, update); + queryClient.invalidateQueries({ + queryKey: ["aircrafts"], + }); + }, + }); + + const connectedAircraft = connectedAircrafts?.find((a) => a.id === event.data?.aircraftId); + const station = stations?.find((s) => s.id === event.data?.stationId); + + if (!connectedAircraft || !station) return null; + return ( + +
+

+ { + if (!connectedAircraft.posLat || !connectedAircraft.posLng) return; + mapStore.setOpenAircraftMarker({ + open: [{ id: connectedAircraft.id, tab: "fms" }], + close: [], + }); + mapStore.setMap({ + center: [connectedAircraft.posLat, connectedAircraft.posLng], + zoom: 14, + }); + }} + > + {station.bosCallsign} + + sendet Status {connectedAircraft.fmsStatus} +

+
+ {QUICK_RESPONSE[String(connectedAircraft.fmsStatus)]?.map((status) => ( + + ))} + +
+
+
+ ); +}; diff --git a/apps/dispatch/app/_components/map/_components/AircraftMarkerTabs.tsx b/apps/dispatch/app/_components/map/_components/AircraftMarkerTabs.tsx index 1206f900..edc6e7f2 100644 --- a/apps/dispatch/app/_components/map/_components/AircraftMarkerTabs.tsx +++ b/apps/dispatch/app/_components/map/_components/AircraftMarkerTabs.tsx @@ -180,7 +180,7 @@ const FMSStatusSelector = ({ fmsStatus: status, }, }); - toast.success(`Status changed to ${status}`); + toast.success(`Status auf ${status} geändert`); }} > {status} @@ -219,7 +219,6 @@ const FMSStatusSelector = ({ fmsStatus: status, }, }); - toast.success(`Status changed to ${status}`); }} > {status} diff --git a/apps/dispatch/app/_querys/aircrafts.ts b/apps/dispatch/app/_querys/aircrafts.ts index 81549720..b0978f0d 100644 --- a/apps/dispatch/app/_querys/aircrafts.ts +++ b/apps/dispatch/app/_querys/aircrafts.ts @@ -1,7 +1,7 @@ import { ConnectedAircraft, PositionLog, Prisma, PublicUser, Station } from "@repo/db"; import axios from "axios"; import { serverApi } from "_helpers/axios"; -import { checkSimulatorConnected } from "_helpers/simulatorConnected"; +import { checkSimulatorConnected } from "@repo/shared-components"; export const getConnectedAircraftsAPI = async () => { const res = await axios.get<(ConnectedAircraft & { Station: Station })[]>("/api/aircrafts"); // return only connected aircrafts diff --git a/apps/dispatch/app/layout.tsx b/apps/dispatch/app/layout.tsx index 7d20354f..6fa6b099 100644 --- a/apps/dispatch/app/layout.tsx +++ b/apps/dispatch/app/layout.tsx @@ -39,24 +39,24 @@ export default async function RootLayout({ - + {session?.user.isBanned && ( )} diff --git a/packages/database/prisma/json/SocketEvents.ts b/packages/database/prisma/json/SocketEvents.ts index de5c1fdb..99e29e69 100644 --- a/packages/database/prisma/json/SocketEvents.ts +++ b/packages/database/prisma/json/SocketEvents.ts @@ -29,4 +29,18 @@ export interface AdminMessage { }; } -export type NotificationPayload = ValidationFailed | ValidationSuccess | AdminMessage; +export interface StationStatus { + type: "station-status"; + status: "5"; + message: string; + data?: { + stationId: number; + aircraftId: number; + }; +} + +export type NotificationPayload = + | ValidationFailed + | ValidationSuccess + | AdminMessage + | StationStatus; diff --git a/packages/shared-components/components/PenaltyDropdown.tsx b/packages/shared-components/components/PenaltyDropdown.tsx index 648013f5..0b415867 100644 --- a/packages/shared-components/components/PenaltyDropdown.tsx +++ b/packages/shared-components/components/PenaltyDropdown.tsx @@ -17,7 +17,7 @@ export const PenaltyDropdown = ({ btnTip?: string; Icon: ReactNode; }) => { - const [open, setOpen] = useState(true); + const [open, setOpen] = useState(false); const [reason, setReason] = useState(""); const [until, setUntil] = useState("default"); return ( diff --git a/packages/shared-components/helper/index.ts b/packages/shared-components/helper/index.ts index 9d6d8ebc..6b04f846 100644 --- a/packages/shared-components/helper/index.ts +++ b/packages/shared-components/helper/index.ts @@ -1,3 +1,4 @@ export * from "./cn"; export * from "./event"; export * from "./dates"; +export * from "./simulatorConnected"; diff --git a/apps/dispatch/app/_helpers/simulatorConnected.ts b/packages/shared-components/helper/simulatorConnected.ts similarity index 100% rename from apps/dispatch/app/_helpers/simulatorConnected.ts rename to packages/shared-components/helper/simulatorConnected.ts