diff --git a/apps/dispatch-server/routes/aircraft.ts b/apps/dispatch-server/routes/aircraft.ts index e3e97c21..576d3e5f 100644 --- a/apps/dispatch-server/routes/aircraft.ts +++ b/apps/dispatch-server/routes/aircraft.ts @@ -91,12 +91,14 @@ router.patch("/:id", async (req, res) => { }); } + res.json(updatedConnectedAircraft); + // When change is only the estimated logout time, we don't need to emit an event + if (Object.keys(aircraftUpdate).length === 1 && aircraftUpdate.esimatedLogoutTime) return; io.to("dispatchers").emit("update-connectedAircraft", updatedConnectedAircraft); io.to(`user:${updatedConnectedAircraft.userId}`).emit( "aircraft-update", updatedConnectedAircraft, ); - res.json(updatedConnectedAircraft); } catch (error) { console.error(error); res.status(500).json({ error: "Failed to update connectedAircraft" }); diff --git a/apps/dispatch-server/routes/dispatcher.ts b/apps/dispatch-server/routes/dispatcher.ts index ab38ab3a..a3c79915 100644 --- a/apps/dispatch-server/routes/dispatcher.ts +++ b/apps/dispatch-server/routes/dispatcher.ts @@ -1,4 +1,4 @@ -import { prisma } from "@repo/db"; +import { Prisma, prisma } from "@repo/db"; import { Router } from "express"; import { pubClient } from "modules/redis"; @@ -14,4 +14,18 @@ router.get("/", async (req, res) => { res.json(user); }); +router.patch("/:id", async (req, res) => { + const { id } = req.params; + const disaptcherUpdate = req.body as Prisma.ConnectedDispatcherUpdateInput; + + const newDispatcher = await prisma.connectedDispatcher.update({ + where: { id: Number(id) }, + data: { + ...disaptcherUpdate, + }, + }); + + res.json(newDispatcher); +}); + export default router; diff --git a/apps/dispatch-server/socket-events/connect-dispatch.ts b/apps/dispatch-server/socket-events/connect-dispatch.ts index ace95790..e4f0a9b0 100644 --- a/apps/dispatch-server/socket-events/connect-dispatch.ts +++ b/apps/dispatch-server/socket-events/connect-dispatch.ts @@ -70,6 +70,7 @@ export const handleConnectDispatch = socket.join("dispatchers"); // Dem Dispatcher-Raum beitreten socket.join(`user:${user.id}`); // Dem User-Raum beitreten + io.to(`user:${user.id}`).emit("dispatchers-update", connectedDispatcherEntry); io.to("dispatchers").emit("dispatchers-update"); io.to("pilots").emit("dispatchers-update"); diff --git a/apps/dispatch-server/socket-events/connect-pilot.ts b/apps/dispatch-server/socket-events/connect-pilot.ts index 44e98d77..c5e743f0 100644 --- a/apps/dispatch-server/socket-events/connect-pilot.ts +++ b/apps/dispatch-server/socket-events/connect-pilot.ts @@ -6,6 +6,7 @@ export const handleConnectPilot = (socket: Socket, io: Server) => async ({ logoffTime, stationId }: { logoffTime: string; stationId: string }) => { try { + if (!stationId) return Error("Station ID is required"); const user: User = socket.data.user; // User ID aus dem JWT-Token const userId = socket.data.user.id; // User ID aus dem JWT-Token diff --git a/apps/dispatch/app/_querys/connected-user.ts b/apps/dispatch/app/_querys/connected-user.ts index e96de52d..b3d86ab7 100644 --- a/apps/dispatch/app/_querys/connected-user.ts +++ b/apps/dispatch/app/_querys/connected-user.ts @@ -1,4 +1,5 @@ import { ConnectedAircraft, ConnectedDispatcher, Prisma } from "@repo/db"; +import { serverApi } from "_helpers/axios"; import axios from "axios"; export const getConnectedUserAPI = async () => { @@ -12,6 +13,17 @@ export const getConnectedUserAPI = async () => { return res.data; }; +export const changeDispatcherAPI = async ( + id: number, + data: Prisma.ConnectedDispatcherUpdateInput, +) => { + const res = await serverApi.patch(`/dispatcher/${id}`, data); + if (res.status !== 200) { + throw new Error("Failed to update Connected Dispatcher"); + } + return res.data; +}; + export const getConnectedDispatcherAPI = async (filter?: Prisma.ConnectedDispatcherWhereInput) => { const res = await axios.get("/api/dispatcher", { params: { diff --git a/apps/dispatch/app/_store/dispatch/connectionStore.ts b/apps/dispatch/app/_store/dispatch/connectionStore.ts index 6dbc3ab5..1fdfae26 100644 --- a/apps/dispatch/app/_store/dispatch/connectionStore.ts +++ b/apps/dispatch/app/_store/dispatch/connectionStore.ts @@ -1,9 +1,11 @@ import { create } from "zustand"; import { dispatchSocket } from "../../dispatch/socket"; import { useAudioStore } from "_store/audioStore"; +import { ConnectedDispatcher } from "@repo/db"; interface ConnectionStore { status: "connected" | "disconnected" | "connecting" | "error"; + connectedDispatcher: ConnectedDispatcher | null; message: string; selectedZone: string; logoffTime: string; @@ -13,6 +15,7 @@ interface ConnectionStore { export const useDispatchConnectionStore = create((set) => ({ status: "disconnected", + connectedDispatcher: null, message: "", selectedZone: "LST_01", logoffTime: "", @@ -51,6 +54,7 @@ dispatchSocket.on("connect_error", (err) => { dispatchSocket.on("disconnect", () => { useDispatchConnectionStore.setState({ status: "disconnected", message: "" }); + useAudioStore.getState().disconnect(); }); dispatchSocket.on("force-disconnect", (reason: string) => { @@ -60,5 +64,10 @@ dispatchSocket.on("force-disconnect", (reason: string) => { message: reason, }); }); +dispatchSocket.on("dispatchers-update", (dispatch: ConnectedDispatcher) => { + useDispatchConnectionStore.setState({ + connectedDispatcher: dispatch, + }); +}); dispatchSocket.on("reconnect", () => {}); diff --git a/apps/dispatch/app/_store/pilot/connectionStore.ts b/apps/dispatch/app/_store/pilot/connectionStore.ts index 2efffb14..1c3044d3 100644 --- a/apps/dispatch/app/_store/pilot/connectionStore.ts +++ b/apps/dispatch/app/_store/pilot/connectionStore.ts @@ -81,6 +81,7 @@ pilotSocket.on("connect_error", (err) => { pilotSocket.on("disconnect", () => { usePilotConnectionStore.setState({ status: "disconnected", message: "" }); + useAudioStore.getState().disconnect(); }); pilotSocket.on("force-disconnect", (reason: string) => { @@ -95,7 +96,6 @@ pilotSocket.on("aircraft-update", (data) => { usePilotConnectionStore.setState({ connectedAircraft: data, }); - /* useMrtStore.getState().setLines(getNew); */ }); pilotSocket.on("mission-alert", (data: Mission & { Stations: Station[] }) => { diff --git a/apps/dispatch/app/dispatch/_components/navbar/_components/Connection.tsx b/apps/dispatch/app/dispatch/_components/navbar/_components/Connection.tsx index c25f4581..f7639e21 100644 --- a/apps/dispatch/app/dispatch/_components/navbar/_components/Connection.tsx +++ b/apps/dispatch/app/dispatch/_components/navbar/_components/Connection.tsx @@ -1,8 +1,11 @@ "use client"; import { useSession } from "next-auth/react"; import { useDispatchConnectionStore } from "../../../../_store/dispatch/connectionStore"; -import { useRef, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { toast } from "react-hot-toast"; +import { useMutation } from "@tanstack/react-query"; +import { Prisma } from "@repo/db"; +import { changeDispatcherAPI } from "_querys/connected-user"; export const ConnectionBtn = () => { const modalRef = useRef(null); @@ -11,11 +14,22 @@ export const ConnectionBtn = () => { logoffTime: "", selectedZone: "LST_01", }); + const changeDispatcherMutation = useMutation({ + mutationFn: ({ id, data }: { id: number; data: Prisma.ConnectedDispatcherUpdateInput }) => + changeDispatcherAPI(id, data), + }); const [logoffDebounce, setLogoffDebounce] = useState(null); const session = useSession(); const uid = session.data?.user?.id; if (!uid) return null; + useEffect(() => { + // Disconnect the socket when the component unmounts + return () => { + connection.disconnect(); + }; + }, [connection.disconnect]); + return (
{connection.message.length > 0 && ( @@ -66,7 +80,14 @@ export const ConnectionBtn = () => { logoffTime: value, }); if (logoffDebounce) clearTimeout(logoffDebounce); - const timeout = setTimeout(() => { + const timeout = setTimeout(async () => { + if (!connection.connectedDispatcher) return; + await changeDispatcherMutation.mutateAsync({ + id: connection.connectedDispatcher?.id, + data: { + esimatedLogoutTime: value, + }, + }); toast.success("Änderung gespeichert!"); }, 2000); setLogoffDebounce(timeout); diff --git a/apps/dispatch/app/pilot/_components/navbar/_components/Connection.tsx b/apps/dispatch/app/pilot/_components/navbar/_components/Connection.tsx index 896fd326..ec456bea 100644 --- a/apps/dispatch/app/pilot/_components/navbar/_components/Connection.tsx +++ b/apps/dispatch/app/pilot/_components/navbar/_components/Connection.tsx @@ -43,6 +43,13 @@ export const ConnectionBtn = () => { } }, [stations, form.selectedStationId]); + useEffect(() => { + // Disconnect the socket when the component unmounts + return () => { + connection.disconnect(); + }; + }, [connection.disconnect]); + const session = useSession(); const uid = session.data?.user?.id; if (!uid) return null;