implemented #76

This commit is contained in:
PxlLoewe
2025-07-23 19:06:35 -07:00
parent 115296d7f7
commit 0b0f4fac2f
6 changed files with 45 additions and 6 deletions

View File

@@ -6,7 +6,15 @@ import { Server, Socket } from "socket.io";
export const handleConnectDispatch = export const handleConnectDispatch =
(socket: Socket, io: Server) => (socket: Socket, io: Server) =>
async ({ logoffTime, selectedZone }: { logoffTime: string; selectedZone: string }) => { async ({
logoffTime,
selectedZone,
ghostMode,
}: {
logoffTime: string;
selectedZone: string;
ghostMode: boolean;
}) => {
try { try {
const user: User = socket.data.user; // User ID aus dem JWT-Token const user: User = socket.data.user; // User ID aus dem JWT-Token
@@ -53,6 +61,7 @@ export const handleConnectDispatch =
userId: user.id, userId: user.id,
zone: selectedZone, zone: selectedZone,
loginTime: new Date().toISOString(), loginTime: new Date().toISOString(),
ghostMode,
}, },
}); });

View File

@@ -7,6 +7,7 @@ import { useMutation } from "@tanstack/react-query";
import { Prisma } from "@repo/db"; import { Prisma } from "@repo/db";
import { changeDispatcherAPI } from "_querys/dispatcher"; import { changeDispatcherAPI } from "_querys/dispatcher";
import { Button, getNextDateWithTime } from "@repo/shared-components"; import { Button, getNextDateWithTime } from "@repo/shared-components";
import { Ghost } from "lucide-react";
export const ConnectionBtn = () => { export const ConnectionBtn = () => {
const modalRef = useRef<HTMLDialogElement>(null); const modalRef = useRef<HTMLDialogElement>(null);
@@ -14,6 +15,7 @@ export const ConnectionBtn = () => {
const [form, setForm] = useState({ const [form, setForm] = useState({
logoffTime: "", logoffTime: "",
selectedZone: "LST_01", selectedZone: "LST_01",
ghostMode: false,
}); });
const changeDispatcherMutation = useMutation({ const changeDispatcherMutation = useMutation({
mutationFn: ({ id, data }: { id: number; data: Prisma.ConnectedDispatcherUpdateInput }) => mutationFn: ({ id, data }: { id: number; data: Prisma.ConnectedDispatcherUpdateInput }) =>
@@ -45,7 +47,7 @@ export const ConnectionBtn = () => {
modalRef.current?.showModal(); modalRef.current?.showModal();
}} }}
> >
Verbunden Verbunden {connection.ghostMode && <Ghost />}
</button> </button>
) : ( ) : (
<button <button
@@ -89,6 +91,21 @@ export const ConnectionBtn = () => {
<p className="fieldset-label">Du kannst diese Zeit später noch anpassen.</p> <p className="fieldset-label">Du kannst diese Zeit später noch anpassen.</p>
)} )}
</fieldset> </fieldset>
{session.data?.user.permissions.includes("ADMIN_KICK") &&
connection.status === "disconnected" && (
<fieldset className="fieldset bg-base-100 border-base-300 rounded-box w-full border p-4">
<legend className="fieldset-legend">Ghost-Mode</legend>
<label className="label">
<input
checked={form.ghostMode}
onChange={(e) => setForm({ ...form, ghostMode: e.target.checked })}
type="checkbox"
className="checkbox"
/>
Vesteckt deine Verbindung auf dem Tracker
</label>
</fieldset>
)}
<div className="modal-action flex w-full justify-between"> <div className="modal-action flex w-full justify-between">
<form method="dialog" className="flex w-full justify-between"> <form method="dialog" className="flex w-full justify-between">
<button className="btn btn-soft">Zurück</button> <button className="btn btn-soft">Zurück</button>
@@ -138,6 +155,7 @@ export const ConnectionBtn = () => {
form.logoffTime && logoffHours !== undefined && logoffMinutes !== undefined form.logoffTime && logoffHours !== undefined && logoffMinutes !== undefined
? getNextDateWithTime(logoffHours, logoffMinutes).toISOString() ? getNextDateWithTime(logoffHours, logoffMinutes).toISOString()
: "", : "",
form.ghostMode,
); );
}} }}
className="btn btn-soft btn-info" className="btn btn-soft btn-info"

View File

@@ -11,7 +11,13 @@ interface ConnectionStore {
message: string; message: string;
selectedZone: string; selectedZone: string;
logoffTime: string; logoffTime: string;
connect: (uid: string, selectedZone: string, logoffTime: string) => Promise<void>; ghostMode: boolean;
connect: (
uid: string,
selectedZone: string,
logoffTime: string,
ghostMode: boolean,
) => Promise<void>;
disconnect: () => void; disconnect: () => void;
} }
@@ -23,11 +29,12 @@ export const useDispatchConnectionStore = create<ConnectionStore>((set) => ({
message: "", message: "",
selectedZone: "LST_01", selectedZone: "LST_01",
logoffTime: "", logoffTime: "",
connect: async (uid, selectedZone, logoffTime) => ghostMode: false,
connect: async (uid, selectedZone, logoffTime, ghostMode) =>
new Promise((resolve) => { new Promise((resolve) => {
set({ status: "connecting", message: "" }); set({ status: "connecting", message: "" });
dispatchSocket.auth = { uid }; dispatchSocket.auth = { uid };
set({ selectedZone, logoffTime }); set({ selectedZone, logoffTime, ghostMode });
dispatchSocket.connect(); dispatchSocket.connect();
dispatchSocket.once("connect", () => { dispatchSocket.once("connect", () => {
@@ -40,11 +47,12 @@ export const useDispatchConnectionStore = create<ConnectionStore>((set) => ({
})); }));
dispatchSocket.on("connect", () => { dispatchSocket.on("connect", () => {
const { logoffTime, selectedZone } = useDispatchConnectionStore.getState(); const { logoffTime, selectedZone, ghostMode } = useDispatchConnectionStore.getState();
useAudioStore.getState().connect("LST_01", selectedZone || "Leitstelle"); useAudioStore.getState().connect("LST_01", selectedZone || "Leitstelle");
dispatchSocket.emit("connect-dispatch", { dispatchSocket.emit("connect-dispatch", {
logoffTime, logoffTime,
selectedZone, selectedZone,
ghostMode,
}); });
useDispatchConnectionStore.setState({ status: "connected", message: "" }); useDispatchConnectionStore.setState({ status: "connected", message: "" });
}); });

View File

@@ -10,6 +10,7 @@ export async function GET(request: Request): Promise<NextResponse> {
const connectedDispatcher = await prisma.connectedDispatcher.findMany({ const connectedDispatcher = await prisma.connectedDispatcher.findMany({
where: { where: {
logoutTime: null, logoutTime: null,
ghostMode: false, // Ensure we only get non-ghost mode connections
...filter, // Ensure filter is parsed correctly ...filter, // Ensure filter is parsed correctly
}, },
include: { include: {

View File

@@ -7,6 +7,7 @@ model ConnectedDispatcher {
zone String @default("LST_1") zone String @default("LST_1")
esimatedLogoutTime DateTime? esimatedLogoutTime DateTime?
logoutTime DateTime? logoutTime DateTime?
ghostMode Boolean @default(false)
// relations: // relations:
user User @relation(fields: [userId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade)

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "ConnectedDispatcher" ADD COLUMN "ghostMode" BOOLEAN NOT NULL DEFAULT false;