diff --git a/apps/dispatch-server/routes/aircraft.ts b/apps/dispatch-server/routes/aircraft.ts index 4f37b90a..725d66d6 100644 --- a/apps/dispatch-server/routes/aircraft.ts +++ b/apps/dispatch-server/routes/aircraft.ts @@ -171,7 +171,7 @@ router.delete("/:id", async (req, res) => { data: { userId: aircraft.userId, type: bann ? (until ? "TIME_BAN" : "BAN") : "KICK", - until: until ? new Date(until) : null, + until: until ? new Date(until) : new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 50), reason: reason, createdUserId: req.user.id, }, diff --git a/apps/dispatch-server/routes/dispatcher.ts b/apps/dispatch-server/routes/dispatcher.ts index 15a1a897..a49942a3 100644 --- a/apps/dispatch-server/routes/dispatcher.ts +++ b/apps/dispatch-server/routes/dispatcher.ts @@ -88,7 +88,7 @@ router.delete("/:id", async (req, res) => { data: { userId: dispatcher.userId, type: bann ? (until ? "TIME_BAN" : "BAN") : "KICK", - until: until ? new Date(until) : null, + until: until ? new Date(until) : new Date(Date.now() + 1000 * 60 * 60 * 24 * 365 * 50), reason: reason, createdUserId: req.user.id, }, diff --git a/apps/dispatch/app/dispatch/layout.tsx b/apps/dispatch/app/dispatch/layout.tsx index 46a26aed..30f3cb62 100644 --- a/apps/dispatch/app/dispatch/layout.tsx +++ b/apps/dispatch/app/dispatch/layout.tsx @@ -22,7 +22,7 @@ export default async function RootLayout({ until: { gte: new Date(), }, - type: "TIME_BAN", + type: { in: ["TIME_BAN", "BAN"] }, }, }); @@ -30,13 +30,16 @@ export default async function RootLayout({ redirect("/login"); } - if (!session.user.emailVerified) - return ; - - if (!session.user.permissions.includes("DISPO")) - return ; - if (openPenaltys[0]) { + if (openPenaltys[0].type === "BAN") { + return ( + + ); + } return ( ; + + if (!session.user.permissions.includes("DISPO")) + return ; + return ( <> diff --git a/apps/dispatch/app/pilot/layout.tsx b/apps/dispatch/app/pilot/layout.tsx index 7d40ab63..c28893eb 100644 --- a/apps/dispatch/app/pilot/layout.tsx +++ b/apps/dispatch/app/pilot/layout.tsx @@ -22,21 +22,24 @@ export default async function RootLayout({ until: { gte: new Date(), }, - type: "TIME_BAN", + type: { in: ["TIME_BAN", "BAN"] }, }, }); if (!session || !session.user.firstname) { redirect("/login"); } - if (!session.user.emailVerified) { - return ; - } - - if (!session.user.permissions.includes("PILOT")) - return ; if (openPenaltys[0]) { + if (openPenaltys[0].type === "BAN") { + return ( + + ); + } return ( ; + } + + if (!session.user.permissions.includes("PILOT")) + return ; + return ( <> diff --git a/apps/hub/app/(app)/_components/Penalty.tsx b/apps/hub/app/(app)/_components/Penalty.tsx index 5c0a4ded..d66119b7 100644 --- a/apps/hub/app/(app)/_components/Penalty.tsx +++ b/apps/hub/app/(app)/_components/Penalty.tsx @@ -1,6 +1,7 @@ import { prisma } from "@repo/db"; import { TriangleAlert } from "lucide-react"; import { getServerSession } from "next-auth"; +import { PenaltyCountdown } from "./PenaltyCountdown"; export const Penalty = async () => { const session = await getServerSession(); @@ -10,7 +11,7 @@ export const Penalty = async () => { until: { gte: new Date(), }, - type: "TIME_BAN", + type: { in: ["TIME_BAN", "BAN"] }, }, }); if (!openPenaltys[0]) { @@ -18,18 +19,33 @@ export const Penalty = async () => { } return ( -
-
-

- - Aktive Strafe -

-

Du hast eine aktive Strafe, die dich daran hindert, an Flügen teilzunehmen.

-

Strafe: {openPenaltys[0].reason}

- {openPenaltys[0].until && ( -

Bis: {new Date(openPenaltys[0].until).toLocaleDateString()}

- )} -
+
+ {openPenaltys[0].type === "TIME_BAN" && ( +
+

+ + Aktive Strafe - {" "} + verbleibend +

+

+ Du hast eine aktive Strafe und kannst dich deshalb nicht mit dem Netzwerk verbinden. +

+

Grund: {openPenaltys[0].reason}

+
+ )} + {openPenaltys[0].type === "BAN" && ( +
+

+ + Du wurdest permanent von VirtualAirRescue ausgeschlossen. +

+

+ Dein Fehlverhalten war so schwerwiegend, dass du dauerhaft von VirtualAirRescue + ausgeschlossen wurdest. Du kannst dich nicht mehr mit dem Netzwerk verbinden. +

+

Grund: {openPenaltys[0].reason}

+
+ )}
); }; diff --git a/apps/hub/app/(app)/_components/PenaltyCountdown.tsx b/apps/hub/app/(app)/_components/PenaltyCountdown.tsx new file mode 100644 index 00000000..1dc4d65b --- /dev/null +++ b/apps/hub/app/(app)/_components/PenaltyCountdown.tsx @@ -0,0 +1,46 @@ +"use client"; +import React, { useEffect, useState } from "react"; + +interface PenaltyCountdownProps { + until: string | Date; +} + +function getTimeLeft(until: string | Date) { + const untilDate = new Date(until).getTime(); + const now = Date.now(); + let diff = Math.max(0, untilDate - now); + const hours = Math.floor(diff / (1000 * 60 * 60)); + diff -= hours * 1000 * 60 * 60; + const minutes = Math.floor(diff / (1000 * 60)); + diff -= minutes * 1000 * 60; + const seconds = Math.floor(diff / 1000); + return { hours, minutes, seconds }; +} + +export const PenaltyCountdown: React.FC = ({ until }) => { + const [timeLeft, setTimeLeft] = useState(() => getTimeLeft(until)); + + useEffect(() => { + const interval = setInterval(() => { + setTimeLeft(getTimeLeft(until)); + }, 1000); + return () => clearInterval(interval); + }, [until]); + + return ( + + + {timeLeft.hours} + + h + + {timeLeft.minutes} + + m + + {timeLeft.seconds} + + s + + ); +};