Dispatch Router-Struktur; AddPenalty Layout gefixed
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import { Connection } from "./_components/Connection";
|
||||
/* import { ThemeSwap } from "./_components/ThemeSwap"; */
|
||||
import { Audio } from "../../../../_components/Audio/Audio";
|
||||
/* import { useState } from "react"; */
|
||||
import { ExitIcon, ExternalLinkIcon } from "@radix-ui/react-icons";
|
||||
import Link from "next/link";
|
||||
import { Settings } from "_components/navbar/Settings";
|
||||
import ModeSwitchDropdown from "_components/navbar/ModeSwitchDropdown";
|
||||
import AdminPanel from "_components/navbar/AdminPanel";
|
||||
import { getServerSession } from "api/auth/[...nextauth]/auth";
|
||||
|
||||
export default async function Navbar() {
|
||||
const session = await getServerSession();
|
||||
|
||||
return (
|
||||
<div className="navbar bg-base-100 shadow-sm flex gap-5 justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<ModeSwitchDropdown />
|
||||
{session?.user.permissions.includes("ADMIN_KICK") && <AdminPanel />}
|
||||
</div>
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex items-center gap-2">
|
||||
<Audio />
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<Connection />
|
||||
</div>
|
||||
{/* <ThemeSwap isDark={isDark} toggleTheme={toggleTheme} /> */}
|
||||
<div className="flex items-center">
|
||||
<Settings />
|
||||
<Link
|
||||
href={process.env.NEXT_PUBLIC_HUB_URL || "#!"}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<button className="btn btn-ghost">
|
||||
<ExternalLinkIcon className="w-4 h-4" /> HUB
|
||||
</button>
|
||||
</Link>
|
||||
<Link href={"/logout"}>
|
||||
<button className="btn btn-ghost">
|
||||
<ExitIcon className="w-4 h-4" />
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
"use client";
|
||||
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";
|
||||
|
||||
export const ConnectionBtn = () => {
|
||||
const modalRef = useRef<HTMLDialogElement>(null);
|
||||
const connection = useDispatchConnectionStore((state) => state);
|
||||
const [form, setForm] = useState({
|
||||
logoffTime: "",
|
||||
selectedZone: "LST_01",
|
||||
});
|
||||
const changeDispatcherMutation = useMutation({
|
||||
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;
|
||||
if (!uid) return null;
|
||||
|
||||
// useEffect für die Logoff-Zeit
|
||||
useEffect(() => {
|
||||
if (logoffDebounce) clearTimeout(logoffDebounce);
|
||||
|
||||
const timeout = setTimeout(async () => {
|
||||
if (!form.logoffTime || !connection.connectedDispatcher) return;
|
||||
await changeDispatcherMutation.mutateAsync({
|
||||
id: connection.connectedDispatcher?.id,
|
||||
data: {
|
||||
esimatedLogoutTime: new Date(
|
||||
new Date().toDateString() + " " + form.logoffTime,
|
||||
).toISOString(),
|
||||
},
|
||||
});
|
||||
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]);
|
||||
|
||||
return (
|
||||
<div className="rounded-box bg-base-200 flex justify-center items-center gap-2 p-1">
|
||||
{connection.message.length > 0 && (
|
||||
<span className="mx-2 text-error">{connection.message}</span>
|
||||
)}
|
||||
|
||||
{connection.status == "connected" ? (
|
||||
<button
|
||||
className="btn btn-sm btn-soft btn-success"
|
||||
type="submit"
|
||||
onSubmit={() => false}
|
||||
onClick={() => {
|
||||
modalRef.current?.showModal();
|
||||
}}
|
||||
>
|
||||
Verbunden
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
type="submit"
|
||||
onSubmit={() => false}
|
||||
onClick={() => {
|
||||
modalRef.current?.showModal();
|
||||
}}
|
||||
className="btn btn-sm btn-soft btn-info"
|
||||
>
|
||||
{connection.status == "disconnected" ? "Verbinden" : connection.status}
|
||||
</button>
|
||||
)}
|
||||
|
||||
<dialog ref={modalRef} className="modal">
|
||||
<div className="modal-box flex flex-col items-center justify-center">
|
||||
{connection.status == "connected" ? (
|
||||
<h3 className="text-lg font-bold mb-5">
|
||||
Verbunden als <span className="text-info"><{connection.selectedZone}></span>
|
||||
</h3>
|
||||
) : (
|
||||
<h3 className="text-lg font-bold mb-5">Als Disponent anmelden</h3>
|
||||
)}
|
||||
<fieldset className="fieldset w-full">
|
||||
<label className="floating-label w-full text-base">
|
||||
<span>Logoff Zeit (UTC+1)</span>
|
||||
<input
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
setForm({
|
||||
...form,
|
||||
logoffTime: value,
|
||||
});
|
||||
}}
|
||||
value={form.logoffTime}
|
||||
type="time"
|
||||
className="input w-full"
|
||||
/>
|
||||
</label>
|
||||
{connection.status == "disconnected" && (
|
||||
<p className="fieldset-label">Du kannst diese Zeit später noch anpassen.</p>
|
||||
)}
|
||||
</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
|
||||
type="submit"
|
||||
onSubmit={() => false}
|
||||
onClick={() => {
|
||||
connection.connect(uid, form.selectedZone, form.logoffTime);
|
||||
}}
|
||||
className="btn btn-soft btn-info"
|
||||
>
|
||||
{connection.status == "disconnected" ||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(connection.status as any) === ""
|
||||
? "Verbinden"
|
||||
: connection.status}
|
||||
</button>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Connection = () => {
|
||||
return (
|
||||
<div>
|
||||
<ConnectionBtn />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
"use client";
|
||||
|
||||
import { MoonIcon, SunIcon } from "@radix-ui/react-icons";
|
||||
|
||||
interface ThemeSwapProps {
|
||||
isDark: boolean;
|
||||
toggleTheme: () => void;
|
||||
}
|
||||
|
||||
export const ThemeSwap: React.FC<ThemeSwapProps> = ({
|
||||
isDark,
|
||||
toggleTheme,
|
||||
}) => {
|
||||
return (
|
||||
<label className="swap swap-rotate">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="theme-controller"
|
||||
checked={isDark}
|
||||
onChange={toggleTheme}
|
||||
/>
|
||||
<MoonIcon className="swap-off h-5 w-5 fill-current" />
|
||||
<SunIcon className="swap-on h-5 w-5 fill-current" />
|
||||
</label>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user