diff --git a/apps/dispatch-server/index.ts b/apps/dispatch-server/index.ts index c54f6119..21597f3f 100644 --- a/apps/dispatch-server/index.ts +++ b/apps/dispatch-server/index.ts @@ -5,6 +5,7 @@ import { Server } from "socket.io"; import { createAdapter } from "@socket.io/redis-adapter"; import { jwtMiddleware } from "modules/socketJWTmiddleware"; import { pubClient, subClient } from "modules/redis"; +import { handle } from "socket-events/connect-dispatch"; const app = express(); const server = createServer(app); @@ -17,7 +18,7 @@ const io = new Server(server, { io.use(jwtMiddleware); io.on("connection", (socket) => { - socket.on("connect-dispatch", () => {}); + socket.on("connect-dispatch", handle(socket, io)); }); server.listen(process.env.PORT, () => { console.log(`Server running on port ${process.env.PORT}`); diff --git a/apps/dispatch-server/package.json b/apps/dispatch-server/package.json index 74e07cf1..2eaacc9e 100644 --- a/apps/dispatch-server/package.json +++ b/apps/dispatch-server/package.json @@ -13,12 +13,12 @@ "@types/express": "^5.0.0", "@types/node": "^22.13.5", "@types/nodemailer": "^6.4.17", - "@types/socket.io-redis": "^3.0.0", "concurrently": "^9.1.2", "typescript": "latest" }, "dependencies": { "@react-email/components": "^0.0.33", + "@redis/json": "^1.0.7", "@socket.io/redis-adapter": "^8.3.0", "axios": "^1.7.9", "cron": "^4.1.0", @@ -28,7 +28,6 @@ "nodemailer": "^6.10.0", "react": "^19.0.0", "redis": "^4.7.0", - "socket.io": "^4.8.1", - "socket.io-redis": "^6.1.1" + "socket.io": "^4.8.1" } } diff --git a/apps/dispatch-server/socket-events/connect-dispatch.ts b/apps/dispatch-server/socket-events/connect-dispatch.ts index 47048cb3..8d1876c7 100644 --- a/apps/dispatch-server/socket-events/connect-dispatch.ts +++ b/apps/dispatch-server/socket-events/connect-dispatch.ts @@ -1,14 +1,34 @@ import { pubClient } from "modules/redis"; import { Server, Socket } from "socket.io"; -export const handle = (socket: Socket, io: Server) => async (jwt: string) => { - const userId = socket.data.user.id; // User ID aus dem JWT-Token - await pubClient.set(`dispatchers:${socket.id}`, userId); +export const handle = + (socket: Socket, io: Server) => + async ({ + logoffTime, + selectedZone, + }: { + logoffTime: string; + selectedZone: string; + }) => { + const userId = socket.data.user.id; // User ID aus dem JWT-Token + await pubClient.json.set(`dispatchers:${socket.id}`, "$", { + logoffTime, + selectedZone, + userId, + }); - socket.join("dispatchers"); // Dem Dispatcher-Raum beitreten + socket.join("dispatchers"); // Dem Dispatcher-Raum beitreten - socket.on("disconnect", async () => { - console.log("Disconnected from dispatch server"); - await pubClient.del(`dispatchers:${socket.id}`); - }); -}; + const keys = await pubClient.keys("dispatchers:*"); + const dispatchers = await Promise.all( + keys.map(async (key) => { + return await pubClient.json.get(key); + }), + ); + console.log(dispatchers); + + socket.on("disconnect", async () => { + console.log("Disconnected from dispatch server"); + await pubClient.json.del(`dispatchers:${socket.id}`); + }); + }; diff --git a/apps/dispatch/app/(dispatch)/_components/Connection.tsx b/apps/dispatch/app/(dispatch)/_components/Connection.tsx index 58dc3856..6862e894 100644 --- a/apps/dispatch/app/(dispatch)/_components/Connection.tsx +++ b/apps/dispatch/app/(dispatch)/_components/Connection.tsx @@ -1,79 +1,96 @@ "use client"; import { useSession } from "next-auth/react"; import { connectionStore } from "../../_store/connectionStore"; -import { useEffect } from "react"; -import { CheckCircledIcon } from "@radix-ui/react-icons"; +import { useEffect, useRef, useState } from "react"; +import { useForm } from "react-hook-form"; -export const ConnectBtn = () => { +export const ConnectionBtn = () => { + const modalRef = useRef(null); + const connection = connectionStore((state) => state); + const [form, setForm] = useState({ + logoffTime: "", + selectedZone: "LST_01", + }); + const session = useSession(); + const uid = session.data?.user?.id; + if (!uid) return null; return ( <> - - + {!connection.isConnected ? ( + + ) : ( + + )} + +
-

Als Disponent anmelden

+ {connection.isConnected ? ( +

+ Verbunden als{" "} + + <{connection.selectedZone}> + +

+ ) : ( +

Als Disponent anmelden

+ )}
-

- Du kannst diese Zeit später noch anpassen. -

+ {!connection.isConnected && ( +

+ Du kannst diese Zeit später noch anpassen. +

+ )}
- -
-
-
-
- - ); -}; - -export const ConnectedBtn = () => { - return ( - <> - - -
-

- Verbunden als <LST_01> -

-
- -
-
-
- - + {connection.isConnected ? ( + + ) : ( + + )}
@@ -83,15 +100,9 @@ export const ConnectedBtn = () => { }; export const Connection = () => { - const session = useSession(); - const cStore = connectionStore((state) => state); - const uid = session.data?.user?.id; - - useEffect(() => { - if (uid) { - cStore.connect(uid); - } - }, [uid]); - - return
{cStore.isConnected ? : }
; + return ( +
+ +
+ ); }; diff --git a/apps/dispatch/app/_store/connectionStore.ts b/apps/dispatch/app/_store/connectionStore.ts index 1ba1764a..22719f1b 100644 --- a/apps/dispatch/app/_store/connectionStore.ts +++ b/apps/dispatch/app/_store/connectionStore.ts @@ -3,17 +3,39 @@ import { socket } from "../(dispatch)/socket"; interface ConnectionStore { isConnected: boolean; - connect: (uid: string) => Promise; + selectedZone: string; + connect: ( + uid: string, + selectedZone: string, + logoffTime: string, + ) => Promise; + disconnect: () => void; } export const connectionStore = create((set) => ({ isConnected: false, - connect: async (uid: string) => { - socket.auth = { uid }; - socket.connect(); + selectedZone: "LST_01", + connect: async (uid, selectedZone, logoffTime) => + new Promise((resolve) => { + socket.auth = { uid }; + set({ selectedZone }); + socket.connect(); + socket.once("connect", () => { + socket.emit("connect-dispatch", { + logoffTime, + selectedZone, + }); + resolve(); + }); + }), + disconnect: () => { + socket.disconnect(); }, })); socket.on("connect", () => { connectionStore.setState({ isConnected: true }); }); +socket.on("disconnect", () => { + connectionStore.setState({ isConnected: false }); +}); diff --git a/apps/dispatch/package.json b/apps/dispatch/package.json index 90643a3b..cdcc38e5 100644 --- a/apps/dispatch/package.json +++ b/apps/dispatch/package.json @@ -20,6 +20,7 @@ "postcss": "^8.5.1", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-hook-form": "^7.54.2", "socket.io-client": "^4.8.1", "tailwindcss": "^4.0.14", "zustand": "^5.0.3" diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 81cd18b2..ea7338d3 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -23,15 +23,11 @@ services: - postgres redis: container_name: redis - image: docker.io/bitnami/redis:7.4 - environment: - # ALLOW_EMPTY_PASSWORD is recommended only for development. - - ALLOW_EMPTY_PASSWORD=yes - - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL + image: redis/redis-stack:latest ports: - "6379:6379" volumes: - - "redis_data:/bitnami/redis/data" + - "redis_data:/data" moodle_database: container_name: moodle_database diff --git a/package-lock.json b/package-lock.json index 339dded6..ac4479a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "postcss": "^8.5.1", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-hook-form": "^7.54.2", "socket.io-client": "^4.8.1", "tailwindcss": "^4.0.14", "zustand": "^5.0.3" @@ -48,6 +49,7 @@ "apps/dispatch-server": { "dependencies": { "@react-email/components": "^0.0.33", + "@redis/json": "^1.0.7", "@socket.io/redis-adapter": "^8.3.0", "axios": "^1.7.9", "cron": "^4.1.0",