Merge branch 'main' of https://github.com/VAR-Virtual-Air-Rescue/var-monorepo
This commit is contained in:
@@ -314,7 +314,7 @@ export const BaseMaps = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<LayersControl position="topleft">
|
<LayersControl position="topleft">
|
||||||
<LayersControl.Overlay name={"Funknetzbereiche"}>
|
<LayersControl.Overlay name={"Leitstellenbereiche"}>
|
||||||
<RadioAreaLayer />
|
<RadioAreaLayer />
|
||||||
</LayersControl.Overlay>
|
</LayersControl.Overlay>
|
||||||
<LayersControl.Overlay name={"Niederschlag"}>
|
<LayersControl.Overlay name={"Niederschlag"}>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import { useDispatchConnectionStore } from "../../../../_store/dispatch/connectionStore";
|
import { useDispatchConnectionStore } from "../../../../_store/dispatch/connectionStore";
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
|
import { toast } from "react-hot-toast";
|
||||||
|
|
||||||
export const ConnectionBtn = () => {
|
export const ConnectionBtn = () => {
|
||||||
const modalRef = useRef<HTMLDialogElement>(null);
|
const modalRef = useRef<HTMLDialogElement>(null);
|
||||||
@@ -10,6 +11,7 @@ export const ConnectionBtn = () => {
|
|||||||
logoffTime: "",
|
logoffTime: "",
|
||||||
selectedZone: "LST_01",
|
selectedZone: "LST_01",
|
||||||
});
|
});
|
||||||
|
const [logoffDebounce, setLogoffDebounce] = useState<NodeJS.Timeout | null>(null);
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
const uid = session.data?.user?.id;
|
const uid = session.data?.user?.id;
|
||||||
if (!uid) return null;
|
if (!uid) return null;
|
||||||
@@ -22,14 +24,14 @@ export const ConnectionBtn = () => {
|
|||||||
|
|
||||||
{connection.status == "connected" ? (
|
{connection.status == "connected" ? (
|
||||||
<button
|
<button
|
||||||
className="btn btn-soft btn-error"
|
className="btn btn-sm btn-soft btn-success"
|
||||||
type="submit"
|
type="submit"
|
||||||
onSubmit={() => false}
|
onSubmit={() => false}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
connection.disconnect();
|
modalRef.current?.showModal();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Trennen
|
Verbunden
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
@@ -40,9 +42,7 @@ export const ConnectionBtn = () => {
|
|||||||
}}
|
}}
|
||||||
className="btn btn-sm btn-soft btn-info"
|
className="btn btn-sm btn-soft btn-info"
|
||||||
>
|
>
|
||||||
{connection.status == "disconnected"
|
{connection.status == "disconnected" ? "Verbinden" : connection.status}
|
||||||
? "Verbinden"
|
|
||||||
: connection.status}
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -50,10 +50,7 @@ export const ConnectionBtn = () => {
|
|||||||
<div className="modal-box flex flex-col items-center justify-center">
|
<div className="modal-box flex flex-col items-center justify-center">
|
||||||
{connection.status == "connected" ? (
|
{connection.status == "connected" ? (
|
||||||
<h3 className="text-lg font-bold mb-5">
|
<h3 className="text-lg font-bold mb-5">
|
||||||
Verbunden als{" "}
|
Verbunden als <span className="text-info"><{connection.selectedZone}></span>
|
||||||
<span className="text-info">
|
|
||||||
<{connection.selectedZone}>
|
|
||||||
</span>
|
|
||||||
</h3>
|
</h3>
|
||||||
) : (
|
) : (
|
||||||
<h3 className="text-lg font-bold mb-5">Als Disponent anmelden</h3>
|
<h3 className="text-lg font-bold mb-5">Als Disponent anmelden</h3>
|
||||||
@@ -62,26 +59,30 @@ export const ConnectionBtn = () => {
|
|||||||
<label className="floating-label w-full text-base">
|
<label className="floating-label w-full text-base">
|
||||||
<span>Logoff Zeit (UTC+1)</span>
|
<span>Logoff Zeit (UTC+1)</span>
|
||||||
<input
|
<input
|
||||||
onChange={(e) =>
|
onChange={(e) => {
|
||||||
|
const value = e.target.value;
|
||||||
setForm({
|
setForm({
|
||||||
...form,
|
...form,
|
||||||
logoffTime: e.target.value,
|
logoffTime: value,
|
||||||
})
|
});
|
||||||
}
|
if (logoffDebounce) clearTimeout(logoffDebounce);
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
toast.success("Änderung gespeichert!");
|
||||||
|
}, 2000);
|
||||||
|
setLogoffDebounce(timeout);
|
||||||
|
}}
|
||||||
value={form.logoffTime}
|
value={form.logoffTime}
|
||||||
type="time"
|
type="time"
|
||||||
className="input w-full"
|
className="input w-full"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
{connection.status == "disconnected" && (
|
{connection.status == "disconnected" && (
|
||||||
<p className="fieldset-label">
|
<p className="fieldset-label">Du kannst diese Zeit später noch anpassen.</p>
|
||||||
Du kannst diese Zeit später noch anpassen.
|
|
||||||
</p>
|
|
||||||
)}
|
)}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<div className="modal-action flex justify-between w-full">
|
<div className="modal-action flex justify-between w-full">
|
||||||
<form method="dialog" className="w-full flex justify-between">
|
<form method="dialog" className="w-full flex justify-between">
|
||||||
<button className="btn btn-soft">Abbrechen</button>
|
<button className="btn btn-soft">Zurück</button>
|
||||||
{connection.status == "connected" ? (
|
{connection.status == "connected" ? (
|
||||||
<button
|
<button
|
||||||
className="btn btn-soft btn-error"
|
className="btn btn-soft btn-error"
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export default async function RootLayout({
|
|||||||
>
|
>
|
||||||
<Toaster
|
<Toaster
|
||||||
containerStyle={{
|
containerStyle={{
|
||||||
top: 150,
|
top: 200,
|
||||||
left: 20,
|
left: 20,
|
||||||
right: 20,
|
right: 20,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1,26 +1,25 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const session = useSession();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Replace this with actual permission-checking logic
|
if (session.status === "authenticated" && session.data?.user) {
|
||||||
const hasDispoPermission = checkUserPermission("DISPO");
|
const hasDispoPermission = session.data.user.permissions?.includes("DISPO");
|
||||||
|
|
||||||
if (hasDispoPermission) {
|
if (hasDispoPermission) {
|
||||||
router.replace("/dispatch");
|
router.replace("/dispatch");
|
||||||
|
} else {
|
||||||
|
router.replace("/pilot");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
router.replace("/pilot");
|
router.replace("/tracker");
|
||||||
}
|
}
|
||||||
}, [router]);
|
}, [router, session]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Mock function for permission checking
|
|
||||||
function checkUserPermission(permission: string): boolean {
|
|
||||||
// Replace with real permission logic
|
|
||||||
return permission === "DISPO";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,14 +41,14 @@ export const ConnectionBtn = () => {
|
|||||||
|
|
||||||
{connection.status == "connected" ? (
|
{connection.status == "connected" ? (
|
||||||
<button
|
<button
|
||||||
className="btn btn-soft btn-error"
|
className="btn btn-sm btn-soft btn-success"
|
||||||
type="submit"
|
type="submit"
|
||||||
onSubmit={() => false}
|
onSubmit={() => false}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
connection.disconnect();
|
modalRef.current?.showModal();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Trennen
|
Verbunden
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
@@ -115,7 +115,7 @@ export const ConnectionBtn = () => {
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
<div className="modal-action flex justify-between w-full">
|
<div className="modal-action flex justify-between w-full">
|
||||||
<form method="dialog" className="w-full flex justify-between">
|
<form method="dialog" className="w-full flex justify-between">
|
||||||
<button className="btn btn-soft">Abbrechen</button>
|
<button className="btn btn-soft">Zurück</button>
|
||||||
{connection.status == "connected" ? (
|
{connection.status == "connected" ? (
|
||||||
<button
|
<button
|
||||||
className="btn btn-soft btn-error"
|
className="btn btn-soft btn-error"
|
||||||
@@ -125,7 +125,7 @@ export const ConnectionBtn = () => {
|
|||||||
connection.disconnect();
|
connection.disconnect();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Trennen
|
Verbindung Trennen
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useQuery } from "@tanstack/react-query";
|
|||||||
import { Badge } from "_components/Badge/Badge";
|
import { Badge } from "_components/Badge/Badge";
|
||||||
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
|
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
|
||||||
import { getConnectedDispatcherAPI } from "_querys/connected-user";
|
import { getConnectedDispatcherAPI } from "_querys/connected-user";
|
||||||
|
import { Plane, Workflow } from "lucide-react";
|
||||||
|
|
||||||
export const ConnectedDispatcher = () => {
|
export const ConnectedDispatcher = () => {
|
||||||
const { data: dispatcher } = useQuery({
|
const { data: dispatcher } = useQuery({
|
||||||
@@ -16,23 +17,32 @@ export const ConnectedDispatcher = () => {
|
|||||||
refetchInterval: 10000,
|
refetchInterval: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const connections = (aircrafts?.length || 0) + (dispatcher?.length || 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="absolute top-5 right-10 min-w-120 z-99999">
|
<div className="absolute top-5 right-10 min-w-120 z-99999">
|
||||||
<div className="collapse collapse-arrow bg-base-100 border-base-300 border">
|
<div className="collapse collapse-arrow bg-base-100 border-base-300 border">
|
||||||
<input type="checkbox" />
|
<input type="checkbox" />
|
||||||
{/* <div className="collapse-title font-semibold">Kein Disponent Online</div> */}
|
{/* <div className="collapse-title font-semibold">Kein Disponent Online</div> */}
|
||||||
<div className="collapse-title font-semibold">
|
<div className="collapse-title font-semibold flex items-center justify-between">
|
||||||
{(aircrafts?.length || 0) + (dispatcher?.length || 0)} Verbundene Mitglieder
|
<span>
|
||||||
|
{connections} {connections > 1 ? "Verbundene Mitglieder" : "Verbundenes Mitglied"}
|
||||||
|
</span>
|
||||||
|
<div className="gap-2 flex items-center">
|
||||||
|
<div
|
||||||
|
className={`badge badge-outline ${
|
||||||
|
(dispatcher?.length || 0) > 0 ? "badge-success" : "badge-error"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<Workflow size={14} /> {dispatcher?.length || 0}
|
||||||
|
</div>
|
||||||
|
<div className="badge badge-outline badge-primary">
|
||||||
|
<Plane size={14} /> {aircrafts?.length || 0}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="collapse-content">
|
<div className="collapse-content">
|
||||||
<ul className="list bg-base-100 rounded-box shadow-md">
|
<ul className="list bg-base-100 rounded-box shadow-md">
|
||||||
<li className="text-xs opacity-60 tracking-wide">
|
|
||||||
Disponenten: {dispatcher?.length || 0}
|
|
||||||
</li>
|
|
||||||
<li className="pb-2 text-xs opacity-60 tracking-wide">
|
|
||||||
Piloten: {aircrafts?.length || 0}
|
|
||||||
</li>
|
|
||||||
|
|
||||||
{dispatcher?.map((d) => {
|
{dispatcher?.map((d) => {
|
||||||
return (
|
return (
|
||||||
<li className="list-row" key={d.id}>
|
<li className="list-row" key={d.id}>
|
||||||
|
|||||||
Reference in New Issue
Block a user