diff --git a/apps/dispatch/app/_components/navbar/PageAlert.tsx b/apps/dispatch/app/_components/navbar/PageAlert.tsx index d2f12840..df8927b9 100644 --- a/apps/dispatch/app/_components/navbar/PageAlert.tsx +++ b/apps/dispatch/app/_components/navbar/PageAlert.tsx @@ -1,22 +1,13 @@ import { prisma } from "@repo/db"; import { MessageCircleWarning } from "lucide-react"; -const fetchMainMessage = async () => { - return await prisma.notam.findFirst({ - where: { - active: true, - }, - }); -}; export const WarningAlert = async () => { - const mainMessage = await fetchMainMessage(); - - if (mainMessage?.showUntilActive && new Date(mainMessage.showUntil) < new Date()) { - return <>; - } + const config = await prisma.notam.findFirst({ + orderBy: [{ createdAt: "desc" }], + }); let msgColor; - switch (mainMessage?.color) { + switch (config?.color) { case "WARNING": msgColor = "alert alert-soft alert-warning ml-3 py-2 flex items-center gap-2"; break; @@ -33,15 +24,11 @@ export const WarningAlert = async () => { msgColor = "alert alert-soft ml-3 py-2 flex items-center gap-2"; } - if ((mainMessage?.message == "" && !mainMessage?.wartungsmodus) || !mainMessage) { - return <>; - } else { + if (config?.message || config?.maintenanceEnabled) { return ( -
- - - {mainMessage?.wartungsmodus ? "Wartungsmodus aktiv!" : mainMessage?.message} - +
+ + {config?.message}
); } diff --git a/apps/dispatch/app/layout.tsx b/apps/dispatch/app/layout.tsx index 38bdc89c..d53bcdd0 100644 --- a/apps/dispatch/app/layout.tsx +++ b/apps/dispatch/app/layout.tsx @@ -7,6 +7,7 @@ import { Toaster } from "react-hot-toast"; import { QueryProvider } from "_components/QueryProvider"; import { prisma } from "@repo/db"; import { Error as ErrorComp } from "_components/Error"; +import { Maintenance } from "@repo/shared-components"; const geistSans = localFont({ src: "./fonts/GeistVF.woff", @@ -29,21 +30,10 @@ export default async function RootLayout({ }>) { const session = await getServerSession(); - const latestNotam = await prisma.notam.findFirst({ - orderBy: { createdAt: "desc" }, + const config = await prisma.notam.findFirst({ + orderBy: [{ createdAt: "desc" }], }); - let wartungsarbeiten = false; - if ( - latestNotam && - latestNotam.wartungsmodus && - latestNotam.active && - ((latestNotam.showUntilActive && new Date(latestNotam.showUntil) > new Date()) || - !latestNotam.showUntilActive) - ) { - wartungsarbeiten = true; - } - return ( )} + {config?.maintenanceEnabled && !session?.user.permissions.includes("ADMIN_MESSAGE") && ( + + )} {!session?.user.isBanned && - wartungsarbeiten && - !session?.user.permissions.includes("ADMIN_MESSAGE") && ( - - )} - {!session?.user.isBanned && - (!wartungsarbeiten || session?.user.permissions.includes("ADMIN_MESSAGE")) && + (!config?.maintenanceEnabled || + session?.user.permissions.includes("ADMIN_MESSAGE")) && children} diff --git a/apps/hub/app/(app)/admin/message/_components/messageForm.tsx b/apps/hub/app/(app)/admin/config/_components/MessageForm.tsx similarity index 65% rename from apps/hub/app/(app)/admin/message/_components/messageForm.tsx rename to apps/hub/app/(app)/admin/config/_components/MessageForm.tsx index 4ddac1bb..fa491b89 100644 --- a/apps/hub/app/(app)/admin/message/_components/messageForm.tsx +++ b/apps/hub/app/(app)/admin/config/_components/MessageForm.tsx @@ -5,54 +5,39 @@ import { Notam } from "@repo/db"; import { NotamOptionalDefaults, NotamOptionalDefaultsSchema } from "@repo/db/zod"; import { useForm } from "react-hook-form"; import { addMessage, disableMessage } from "../action"; -import { useState } from "react"; -import { DateInput } from "_components/ui/DateInput"; import "react-datepicker/dist/react-datepicker.css"; // <-- Add this line at the top if using react-datepicker +import { Button } from "_components/ui/Button"; +import { PaginatedTableRef } from "_components/PaginatedTable"; +import { RefObject } from "react"; -export const MessageForm = ({ message }: { message?: Notam }) => { - const [isSubmitting, setIsSubmitting] = useState(false); - - const getDefaultShowUntilDate = () => { - const date = new Date(); - return date; - }; - +export const MessageForm = ({ tableRef }: { tableRef: RefObject }) => { const disableMessageClient = async () => { await disableMessage(); - window.location.reload(); + tableRef?.current?.refresh(); }; const form = useForm({ resolver: zodResolver(NotamOptionalDefaultsSchema), - defaultValues: { - message: message?.message, - color: message?.color, - active: true, - wartungsmodus: message?.wartungsmodus, - disableHPG: message?.disableHPG, - showUntil: getDefaultShowUntilDate(), - }, }); return (
{ - setIsSubmitting(true); try { await addMessage(values); - window.location.reload(); + tableRef?.current?.refresh(); + form.reset(); } catch (error) { - setIsSubmitting(false); console.error("Failed to add message", error); } })} className="grid grid-cols-6 gap-3" > @@ -107,26 +92,24 @@ export const MessageForm = ({ message }: { message?: Notam }) => { HPG Alarmierung deaktivieren
-
- - -
- - + +
diff --git a/apps/hub/app/(app)/admin/config/action.tsx b/apps/hub/app/(app)/admin/config/action.tsx new file mode 100644 index 00000000..29eb80e8 --- /dev/null +++ b/apps/hub/app/(app)/admin/config/action.tsx @@ -0,0 +1,22 @@ +"use server"; +import { prisma, Prisma } from "@repo/db"; + +export const addMessage = async (notam: Prisma.NotamCreateInput) => { + try { + await prisma.notam.create({ + data: notam, + }); + } catch (error) { + throw new Error("Failed to add message"); + } +}; + +export const disableMessage = async () => { + try { + await prisma.notam.create({ + data: {}, + }); + } catch (error) { + throw new Error("Failed to disable message"); + } +}; diff --git a/apps/hub/app/(app)/admin/message/page.tsx b/apps/hub/app/(app)/admin/config/page.tsx similarity index 63% rename from apps/hub/app/(app)/admin/message/page.tsx rename to apps/hub/app/(app)/admin/config/page.tsx index 4402c117..a832882c 100644 --- a/apps/hub/app/(app)/admin/message/page.tsx +++ b/apps/hub/app/(app)/admin/config/page.tsx @@ -1,27 +1,30 @@ "use client"; -import { Check, MessageSquareWarning } from "lucide-react"; -import { MessageForm } from "./_components/messageForm"; -import { PaginatedTable } from "_components/PaginatedTable"; +import { Check, MessageSquareWarning, Settings } from "lucide-react"; +import { MessageForm } from "./_components/MessageForm"; +import { PaginatedTable, PaginatedTableRef } from "_components/PaginatedTable"; import { ColumnDef } from "@tanstack/react-table"; import { Notam } from "@repo/db"; +import { useRef } from "react"; export default function MessagePage() { + const tableRef = useRef(null); return ( <>

- Service Nachrichten + Config

- +
{ - const wartungsmodus = row.getValue("wartungsmodus"); + const wartungsmodus = row.original.maintenanceEnabled; return wartungsmodus ? : ""; }, }, @@ -50,28 +53,11 @@ export default function MessagePage() { accessorKey: "disableHPG", header: "HPG deaktiviert", cell: ({ row }) => { - const disableHPG = row.getValue("disableHPG"); + const disableHPG = row.original.disableHPG; return disableHPG ? : ""; }, }, - { - accessorKey: "showUntil", - header: "Zeitlimit", - cell: ({ row, cell }) => { - const showUntil = new Date(cell.getValue() as string); - const createdAt = new Date(row.getValue("createdAt") as string); - if (showUntil > createdAt) { - return showUntil.toLocaleDateString("de-DE", { - year: "numeric", - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - }); - } - return ""; - }, - }, + { accessorKey: "createdAt", header: "Erstellt am", diff --git a/apps/hub/app/(app)/admin/message/action.tsx b/apps/hub/app/(app)/admin/message/action.tsx deleted file mode 100644 index 64d7b798..00000000 --- a/apps/hub/app/(app)/admin/message/action.tsx +++ /dev/null @@ -1,39 +0,0 @@ -"use server"; -import { prisma, Prisma } from "@repo/db"; - -export const addMessage = async (message: Prisma.NotamCreateInput) => { - try { - await prisma.notam.updateMany({ - where: { active: true }, - data: { active: false }, - }); - - const showUntil = new Date(message.showUntil); - const showUntilActive = showUntil > new Date(); - - await prisma.notam.create({ - data: { - message: message.message, - color: message.color, - active: true, - wartungsmodus: message.wartungsmodus, - disableHPG: message.disableHPG, - showUntilActive, - showUntil, - }, - }); - } catch (error) { - throw new Error("Failed to add message"); - } -}; - -export const disableMessage = async () => { - try { - await prisma.notam.updateMany({ - where: { active: true }, - data: { active: false }, - }); - } catch (error) { - throw new Error("Failed to disable message"); - } -}; diff --git a/apps/hub/app/_components/Nav.tsx b/apps/hub/app/_components/Nav.tsx index a7540cbe..3b1afb5f 100644 --- a/apps/hub/app/_components/Nav.tsx +++ b/apps/hub/app/_components/Nav.tsx @@ -80,7 +80,7 @@ export const VerticalNav = async () => { )} {session.user.permissions.includes("ADMIN_MESSAGE") && (
  • - Service Nachrichten + Config
  • )} {session.user.permissions.includes("ADMIN_USER") && ( diff --git a/apps/hub/app/_components/ui/PageAlert.tsx b/apps/hub/app/_components/ui/PageAlert.tsx index d2f12840..3744f625 100644 --- a/apps/hub/app/_components/ui/PageAlert.tsx +++ b/apps/hub/app/_components/ui/PageAlert.tsx @@ -1,19 +1,12 @@ import { prisma } from "@repo/db"; import { MessageCircleWarning } from "lucide-react"; -const fetchMainMessage = async () => { - return await prisma.notam.findFirst({ - where: { - active: true, - }, - }); -}; export const WarningAlert = async () => { - const mainMessage = await fetchMainMessage(); - - if (mainMessage?.showUntilActive && new Date(mainMessage.showUntil) < new Date()) { - return <>; - } + const mainMessage = await await prisma.notam.findFirst({ + orderBy: { + createdAt: "desc", + }, + }); let msgColor; switch (mainMessage?.color) { @@ -33,14 +26,14 @@ export const WarningAlert = async () => { msgColor = "alert alert-soft ml-3 py-2 flex items-center gap-2"; } - if ((mainMessage?.message == "" && !mainMessage?.wartungsmodus) || !mainMessage) { - return <>; + if ((mainMessage?.message == "" && !mainMessage?.maintenanceEnabled) || !mainMessage) { + return null; } else { return (
    - {mainMessage?.wartungsmodus ? "Wartungsmodus aktiv!" : mainMessage?.message} + {mainMessage?.maintenanceEnabled ? "Wartungsmodus aktiv!" : mainMessage?.message}
    ); diff --git a/apps/hub/app/layout.tsx b/apps/hub/app/layout.tsx index f1b4d4f1..028235d8 100644 --- a/apps/hub/app/layout.tsx +++ b/apps/hub/app/layout.tsx @@ -8,6 +8,7 @@ import { QueryProvider } from "_components/QueryClient"; import { prisma } from "@repo/db"; import React from "react"; import { Error as ErrorComp } from "_components/Error"; +import { Maintenance } from "@repo/shared-components"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -30,31 +31,16 @@ const RootLayout = async ({ orderBy: { createdAt: "desc" }, }); - let wartungsarbeiten = false; - if ( - latestNotam && - latestNotam.wartungsmodus && - latestNotam.active && - ((latestNotam.showUntilActive && new Date(latestNotam.showUntil) > new Date()) || - !latestNotam.showUntilActive) - ) { - wartungsarbeiten = true; - } - return ( - {wartungsarbeiten && !session?.user.permissions.includes("ADMIN_MESSAGE") && ( - - )} - {(!wartungsarbeiten || session?.user.permissions.includes("ADMIN_MESSAGE")) && ( + {latestNotam?.maintenanceEnabled && + !session?.user.permissions.includes("ADMIN_MESSAGE") && ( + + )} + {(!latestNotam?.maintenanceEnabled || + session?.user.permissions.includes("ADMIN_MESSAGE")) && ( <>
    { + const [rotationSpeed, setRotationSpeed] = useState(0); + const [rotationDeg, setRotationDeg] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setRotationDeg(rotationDeg + rotationSpeed); + }); + + return () => { + clearInterval(interval); + }; + }, [rotationDeg, rotationSpeed]); + + return ( +
    +

    Wartungsarbeiten

    +

    + {message || "Unsere Website wird derzeit gewartet. Bitte versuchen Sie es später erneut."} +

    +
    + logo { + setRotationSpeed(rotationSpeed + 0.1); + }} + onContextMenu={(e) => { + e.preventDefault(); + setRotationSpeed(Math.max(rotationSpeed - 0.1, 0)); + }} + /> +
    +
    + ); +}; diff --git a/packages/shared-components/components/index.ts b/packages/shared-components/components/index.ts index 52ce020f..8f59c043 100644 --- a/packages/shared-components/components/index.ts +++ b/packages/shared-components/components/index.ts @@ -1,2 +1,3 @@ export * from "./Badge"; export * from "./PenaltyDropdown"; +export * from "./Maintenance";