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
+
+ );
+};