Fix Pilot-conenction
This commit is contained in:
@@ -3,11 +3,10 @@
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useDispatchConnectionStore } from "../../../../../_store/dispatch/connectionStore";
|
||||
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/dispatcher";
|
||||
import { getNextDateWithTime } from "@repo/shared-components";
|
||||
import { Button, getNextDateWithTime } from "@repo/shared-components";
|
||||
|
||||
export const ConnectionBtn = () => {
|
||||
const modalRef = useRef<HTMLDialogElement>(null);
|
||||
@@ -20,44 +19,19 @@ export const ConnectionBtn = () => {
|
||||
mutationFn: ({ id, data }: { id: number; data: Prisma.ConnectedDispatcherUpdateInput }) =>
|
||||
changeDispatcherAPI(id, data),
|
||||
});
|
||||
const [logoffDebounce, setLogoffDebounce] = useState<NodeJS.Timeout | null>(null);
|
||||
const session = useSession();
|
||||
const uid = session.data?.user?.id;
|
||||
|
||||
// useEffect für die Logoff-Zeit
|
||||
const [logoffHours, logoffMinutes] = form.logoffTime?.split(":").map(Number) || [];
|
||||
|
||||
useEffect(() => {
|
||||
if (!logoffHours || !logoffMinutes) return;
|
||||
if (logoffDebounce) clearTimeout(logoffDebounce);
|
||||
|
||||
const timeout = setTimeout(async () => {
|
||||
if (!logoffHours || !logoffMinutes || !connection.connectedDispatcher) return;
|
||||
await changeDispatcherMutation.mutateAsync({
|
||||
id: connection.connectedDispatcher?.id,
|
||||
data: {
|
||||
esimatedLogoutTime:
|
||||
logoffHours && logoffMinutes ? getNextDateWithTime(logoffHours, logoffMinutes) : null,
|
||||
},
|
||||
});
|
||||
toast.success("Änderung gespeichert!");
|
||||
modalRef.current?.close();
|
||||
}, 2000);
|
||||
|
||||
setLogoffDebounce(timeout);
|
||||
|
||||
// Cleanup function
|
||||
return () => {
|
||||
if (logoffDebounce) clearTimeout(logoffDebounce);
|
||||
};
|
||||
}, [form.logoffTime, connection.connectedDispatcher]);
|
||||
|
||||
useEffect(() => {
|
||||
// Disconnect the socket when the component unmounts
|
||||
return () => {
|
||||
connection.disconnect();
|
||||
};
|
||||
}, [connection.disconnect]);
|
||||
|
||||
if (!uid) return null;
|
||||
return (
|
||||
<div className="rounded-box bg-base-200 flex justify-center items-center gap-2 p-1">
|
||||
@@ -122,16 +96,36 @@ export const ConnectionBtn = () => {
|
||||
<form method="dialog" className="w-full flex justify-between">
|
||||
<button className="btn btn-soft">Zurück</button>
|
||||
{connection.status == "connected" ? (
|
||||
<button
|
||||
className="btn btn-soft btn-error"
|
||||
type="submit"
|
||||
onSubmit={() => false}
|
||||
onClick={() => {
|
||||
connection.disconnect();
|
||||
}}
|
||||
>
|
||||
Verbindung Trennen
|
||||
</button>
|
||||
<>
|
||||
<Button
|
||||
className="btn"
|
||||
onClick={async () => {
|
||||
if (!connection.connectedDispatcher?.id) return;
|
||||
await changeDispatcherMutation.mutateAsync({
|
||||
id: connection.connectedDispatcher?.id,
|
||||
data: {
|
||||
esimatedLogoutTime:
|
||||
logoffHours && logoffMinutes
|
||||
? getNextDateWithTime(logoffHours, logoffMinutes)
|
||||
: null,
|
||||
},
|
||||
});
|
||||
modalRef.current?.close();
|
||||
}}
|
||||
>
|
||||
Logoff-Zeit speichern
|
||||
</Button>
|
||||
<button
|
||||
className="btn btn-soft btn-error"
|
||||
type="submit"
|
||||
onSubmit={() => false}
|
||||
onClick={() => {
|
||||
connection.disconnect();
|
||||
}}
|
||||
>
|
||||
Verbindung Trennen
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<button
|
||||
type="submit"
|
||||
|
||||
@@ -4,10 +4,9 @@ import { usePilotConnectionStore } from "_store/pilot/connectionStore";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { getStationsAPI } from "_querys/stations";
|
||||
import toast from "react-hot-toast";
|
||||
import { editConnectedAircraftAPI, getConnectedAircraftsAPI } from "_querys/aircrafts";
|
||||
import { Prisma } from "@repo/db";
|
||||
import { getNextDateWithTime } from "@repo/shared-components";
|
||||
import { Button, getNextDateWithTime } from "@repo/shared-components";
|
||||
import { Select } from "_components/Select";
|
||||
import { Radio } from "lucide-react";
|
||||
|
||||
@@ -23,7 +22,6 @@ export const ConnectionBtn = () => {
|
||||
selectedStationId: null,
|
||||
debugPosition: false,
|
||||
});
|
||||
const [logoffDebounce, setLogoffDebounce] = useState<NodeJS.Timeout | null>(null);
|
||||
|
||||
const { data: stations } = useQuery({
|
||||
queryKey: ["stations"],
|
||||
@@ -53,7 +51,8 @@ export const ConnectionBtn = () => {
|
||||
return () => {
|
||||
connection.disconnect();
|
||||
};
|
||||
}, [connection, connection.disconnect]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [connection.disconnect]);
|
||||
|
||||
const [logoffHours, logoffMinutes] = form.logoffTime?.split(":").map(Number) || [];
|
||||
|
||||
@@ -62,32 +61,6 @@ export const ConnectionBtn = () => {
|
||||
queryFn: () => getConnectedAircraftsAPI(),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!logoffHours || !logoffMinutes || !connection.connectedAircraft) return;
|
||||
|
||||
if (logoffDebounce) clearTimeout(logoffDebounce);
|
||||
|
||||
const timeout = setTimeout(async () => {
|
||||
if (!connection.connectedAircraft?.id) return;
|
||||
await aircraftMutation.mutateAsync({
|
||||
sessionId: connection.connectedAircraft.id,
|
||||
change: {
|
||||
esimatedLogoutTime:
|
||||
logoffHours && logoffMinutes ? getNextDateWithTime(logoffHours, logoffMinutes) : null,
|
||||
},
|
||||
});
|
||||
modalRef.current?.close();
|
||||
toast.success("Änderung gespeichert!");
|
||||
}, 2000);
|
||||
|
||||
setLogoffDebounce(timeout);
|
||||
|
||||
// Cleanup function to clear timeout
|
||||
return () => {
|
||||
if (logoffDebounce) clearTimeout(logoffDebounce);
|
||||
};
|
||||
}, [logoffHours, logoffMinutes, connection.connectedAircraft, aircraftMutation, logoffDebounce]);
|
||||
|
||||
const session = useSession();
|
||||
const uid = session.data?.user?.id;
|
||||
if (!uid) return null;
|
||||
@@ -185,45 +158,66 @@ export const ConnectionBtn = () => {
|
||||
)}
|
||||
</fieldset>
|
||||
|
||||
{session.data?.user.permissions.includes("ADMIN_STATION") && (
|
||||
<fieldset className="fieldset bg-base-100 border-base-300 rounded-box w-full border p-4">
|
||||
<legend className="fieldset-legend">Debug-optionen</legend>
|
||||
<label className="label">
|
||||
<input
|
||||
checked={form.debugPosition}
|
||||
onChange={(e) => setForm({ ...form, debugPosition: e.target.checked })}
|
||||
type="checkbox"
|
||||
className="checkbox"
|
||||
/>
|
||||
Zufalls Position für 2h anzeigen
|
||||
</label>
|
||||
</fieldset>
|
||||
)}
|
||||
{session.data?.user.permissions.includes("ADMIN_STATION") &&
|
||||
connection.status === "disconnected" && (
|
||||
<fieldset className="fieldset bg-base-100 border-base-300 rounded-box w-full border p-4">
|
||||
<legend className="fieldset-legend">Debug-optionen</legend>
|
||||
<label className="label">
|
||||
<input
|
||||
checked={form.debugPosition}
|
||||
onChange={(e) => setForm({ ...form, debugPosition: e.target.checked })}
|
||||
type="checkbox"
|
||||
className="checkbox"
|
||||
/>
|
||||
Zufalls Position für 2h anzeigen
|
||||
</label>
|
||||
</fieldset>
|
||||
)}
|
||||
<div className="modal-action flex justify-between w-full">
|
||||
<form method="dialog" className="w-full flex justify-between">
|
||||
<button className="btn btn-soft">Zurück</button>
|
||||
{connection.status == "connected" ? (
|
||||
<button
|
||||
className="btn btn-soft btn-error"
|
||||
type="submit"
|
||||
onSubmit={() => false}
|
||||
onClick={() => {
|
||||
connection.disconnect();
|
||||
}}
|
||||
>
|
||||
Verbindung Trennen
|
||||
</button>
|
||||
<>
|
||||
<Button
|
||||
className="btn"
|
||||
onClick={async () => {
|
||||
if (!connection.connectedAircraft) return;
|
||||
await aircraftMutation.mutateAsync({
|
||||
sessionId: connection.connectedAircraft.id,
|
||||
change: {
|
||||
esimatedLogoutTime:
|
||||
logoffHours && logoffMinutes
|
||||
? getNextDateWithTime(logoffHours, logoffMinutes)
|
||||
: null,
|
||||
},
|
||||
});
|
||||
modalRef.current?.close();
|
||||
}}
|
||||
>
|
||||
Logoff-Zeit speichern
|
||||
</Button>
|
||||
<button
|
||||
className="btn btn-soft btn-error"
|
||||
type="submit"
|
||||
onSubmit={() => false}
|
||||
onClick={() => {
|
||||
connection.disconnect();
|
||||
}}
|
||||
>
|
||||
Verbindung Trennen
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<button
|
||||
<Button
|
||||
type="submit"
|
||||
onSubmit={() => false}
|
||||
onClick={() => {
|
||||
onClick={async () => {
|
||||
const selectedStation = stations?.find(
|
||||
(station) =>
|
||||
station.id === parseInt(form.selectedStationId?.toString() || ""),
|
||||
);
|
||||
if (selectedStation) {
|
||||
connection.connect(
|
||||
await connection.connect(
|
||||
uid,
|
||||
form.selectedStationId?.toString() || "",
|
||||
form.logoffTime || "",
|
||||
@@ -232,11 +226,12 @@ export const ConnectionBtn = () => {
|
||||
form.debugPosition,
|
||||
);
|
||||
}
|
||||
modalRef.current?.close();
|
||||
}}
|
||||
className="btn btn-soft btn-info"
|
||||
>
|
||||
{connection.status == "disconnected" ? "Verbinden" : connection.status}
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
43
packages/shared-components/components/Button.tsx
Normal file
43
packages/shared-components/components/Button.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
"use client";
|
||||
import React, {
|
||||
ButtonHTMLAttributes,
|
||||
DetailedHTMLProps,
|
||||
useEffect,
|
||||
useState,
|
||||
forwardRef,
|
||||
} from "react";
|
||||
import { cn } from "@repo/shared-components";
|
||||
|
||||
export const Button = forwardRef<
|
||||
HTMLButtonElement,
|
||||
DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> & {
|
||||
isLoading?: boolean;
|
||||
}
|
||||
>(({ isLoading, ...props }, ref) => {
|
||||
const [isLoadingState, setIsLoadingState] = useState(isLoading);
|
||||
|
||||
useEffect(() => {
|
||||
setIsLoadingState(isLoading);
|
||||
}, [isLoading]);
|
||||
|
||||
return (
|
||||
<button
|
||||
{...props}
|
||||
ref={ref}
|
||||
className={cn("btn", props.className)}
|
||||
disabled={isLoadingState || props.disabled}
|
||||
onClick={async (e) => {
|
||||
if (props.onClick) {
|
||||
setIsLoadingState(true);
|
||||
await props.onClick(e);
|
||||
setIsLoadingState(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{isLoadingState && <span className="loading loading-spinner loading-sm"></span>}
|
||||
{props.children}
|
||||
</button>
|
||||
);
|
||||
});
|
||||
|
||||
Button.displayName = "Button";
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from "./Badge";
|
||||
export * from "./PenaltyDropdown";
|
||||
export * from "./Maintenance";
|
||||
export * from "./Button";
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"tailwind-merge": "^3.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^19.1.6",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.5",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0"
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -630,11 +630,11 @@ importers:
|
||||
version: 3.3.0
|
||||
devDependencies:
|
||||
'@types/react':
|
||||
specifier: ^19.1.6
|
||||
version: 19.1.6
|
||||
specifier: ^19.1.8
|
||||
version: 19.1.8
|
||||
'@types/react-dom':
|
||||
specifier: ^19.1.5
|
||||
version: 19.1.5(@types/react@19.1.6)
|
||||
version: 19.1.5(@types/react@19.1.8)
|
||||
react:
|
||||
specifier: ^19.1.0
|
||||
version: 19.1.0
|
||||
@@ -8668,9 +8668,9 @@ snapshots:
|
||||
|
||||
'@types/range-parser@1.2.7': {}
|
||||
|
||||
'@types/react-dom@19.1.5(@types/react@19.1.6)':
|
||||
'@types/react-dom@19.1.5(@types/react@19.1.8)':
|
||||
dependencies:
|
||||
'@types/react': 19.1.6
|
||||
'@types/react': 19.1.8
|
||||
|
||||
'@types/react-dom@19.1.6(@types/react@19.1.8)':
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user