getNextHourTime zu shared library hinzugefügt
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
"devDependencies": {
|
||||
"@repo/db": "workspace:*",
|
||||
"@repo/typescript-config": "workspace:*",
|
||||
"@repo/shared-components": "workspace:*",
|
||||
"@types/cookie-parser": "^1.4.8",
|
||||
"@types/cors": "^2.8.18",
|
||||
"@types/express": "^5.0.2",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getPublicUser, prisma, User } from "@repo/db";
|
||||
import { addRolesToMember, removeRolesFromMember, renameMember } from "modules/discord";
|
||||
import { getNextDateWithTime } from "@repo/shared-components";
|
||||
import { DISCORD_ROLES } from "@repo/db";
|
||||
import { Server, Socket } from "socket.io";
|
||||
|
||||
@@ -45,30 +46,13 @@ export const handleConnectDispatch =
|
||||
}
|
||||
|
||||
let parsedLogoffDate = null;
|
||||
if (logoffTime.length > 0) {
|
||||
const now = new Date();
|
||||
const [hours, minutes] = logoffTime.split(":").map(Number);
|
||||
if (!hours || !minutes) {
|
||||
throw new Error("Invalid logoffTime format");
|
||||
}
|
||||
parsedLogoffDate = new Date(now);
|
||||
parsedLogoffDate.setHours(hours, minutes, 0, 0);
|
||||
|
||||
// If the calculated time is earlier than now, add one day to make it tomorrow
|
||||
if (parsedLogoffDate <= now) {
|
||||
parsedLogoffDate.setDate(parsedLogoffDate.getDate() + 1);
|
||||
}
|
||||
|
||||
// If the calculated time is in the past, add one day to make it in the future
|
||||
if (parsedLogoffDate <= now) {
|
||||
parsedLogoffDate.setDate(parsedLogoffDate.getDate() + 1);
|
||||
}
|
||||
}
|
||||
const [logoffHours, logoffMinutes] = logoffTime.split(":").map(Number);
|
||||
|
||||
const connectedDispatcherEntry = await prisma.connectedDispatcher.create({
|
||||
data: {
|
||||
publicUser: getPublicUser(user) as any,
|
||||
esimatedLogoutTime: parsedLogoffDate?.toISOString() || null,
|
||||
esimatedLogoutTime:
|
||||
logoffHours && logoffMinutes ? getNextDateWithTime(logoffHours, logoffMinutes) : null,
|
||||
lastHeartbeat: new Date().toISOString(),
|
||||
userId: user.id,
|
||||
zone: selectedZone,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getPublicUser, prisma, User } from "@repo/db";
|
||||
import { addRolesToMember, removeRolesFromMember, renameMember } from "modules/discord";
|
||||
import { getNextDateWithTime } from "@repo/shared-components";
|
||||
import { DISCORD_ROLES } from "@repo/db";
|
||||
import { Server, Socket } from "socket.io";
|
||||
|
||||
@@ -55,22 +56,6 @@ export const handleConnectPilot =
|
||||
});
|
||||
}
|
||||
|
||||
let parsedLogoffDate = null;
|
||||
if (logoffTime.length > 0) {
|
||||
const now = new Date();
|
||||
const [hours, minutes] = logoffTime.split(":").map(Number);
|
||||
if (!hours || !minutes) {
|
||||
throw new Error("Invalid logoffTime format");
|
||||
}
|
||||
parsedLogoffDate = new Date(now);
|
||||
parsedLogoffDate.setHours(hours, minutes, 0, 0);
|
||||
|
||||
// If the calculated time is earlier than now, add one day to make it tomorrow
|
||||
if (parsedLogoffDate <= now) {
|
||||
parsedLogoffDate.setDate(parsedLogoffDate.getDate() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Set "now" to 2 hours in the future
|
||||
const nowPlus2h = new Date();
|
||||
nowPlus2h.setHours(nowPlus2h.getHours() + 2);
|
||||
@@ -87,11 +72,13 @@ export const handleConnectPilot =
|
||||
}
|
||||
|
||||
const randomPos = debug ? getRandomGermanPosition() : undefined;
|
||||
const [logoffHours, logoffMinutes] = logoffTime.split(":").map(Number);
|
||||
|
||||
const connectedAircraftEntry = await prisma.connectedAircraft.create({
|
||||
data: {
|
||||
publicUser: getPublicUser(user) as any,
|
||||
esimatedLogoutTime: parsedLogoffDate?.toISOString() || null,
|
||||
esimatedLogoutTime:
|
||||
logoffHours && logoffMinutes ? getNextDateWithTime(logoffHours, logoffMinutes) : null,
|
||||
userId: userId,
|
||||
stationId: parseInt(stationId),
|
||||
lastHeartbeat: debug ? nowPlus2h.toISOString() : undefined,
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
"extends": "@repo/typescript-config/base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"allowImportingTsExtensions": false,
|
||||
"baseUrl": ".",
|
||||
"jsx": "react"
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"noEmit": true,
|
||||
"baseUrl": "."
|
||||
},
|
||||
"include": ["**/*.ts", "./index.ts", "**/*.d.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
|
||||
@@ -6,6 +6,7 @@ import { toast } from "react-hot-toast";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { Prisma } from "@repo/db";
|
||||
import { changeDispatcherAPI } from "_querys/dispatcher";
|
||||
import { getNextDateWithTime } from "@repo/shared-components";
|
||||
|
||||
export const ConnectionBtn = () => {
|
||||
const modalRef = useRef<HTMLDialogElement>(null);
|
||||
@@ -24,17 +25,19 @@ export const ConnectionBtn = () => {
|
||||
if (!uid) return null;
|
||||
|
||||
// useEffect für die Logoff-Zeit
|
||||
const [logoffHours, logoffMinutes] = form.logoffTime?.split(":").map(Number) || [];
|
||||
|
||||
useEffect(() => {
|
||||
if (!logoffHours || !logoffMinutes) return;
|
||||
if (logoffDebounce) clearTimeout(logoffDebounce);
|
||||
|
||||
const timeout = setTimeout(async () => {
|
||||
if (!form.logoffTime || !connection.connectedDispatcher) return;
|
||||
if (!logoffHours || !logoffMinutes || !connection.connectedDispatcher) return;
|
||||
await changeDispatcherMutation.mutateAsync({
|
||||
id: connection.connectedDispatcher?.id,
|
||||
data: {
|
||||
esimatedLogoutTime: new Date(
|
||||
new Date().toDateString() + " " + form.logoffTime,
|
||||
).toISOString(),
|
||||
esimatedLogoutTime:
|
||||
logoffHours && logoffMinutes ? getNextDateWithTime(logoffHours, logoffMinutes) : null,
|
||||
},
|
||||
});
|
||||
toast.success("Änderung gespeichert!");
|
||||
|
||||
@@ -8,6 +8,7 @@ import toast from "react-hot-toast";
|
||||
import { editConnectedAircraftAPI } from "_querys/aircrafts";
|
||||
import { Prisma } from "@repo/db";
|
||||
import { debug } from "console";
|
||||
import { getNextDateWithTime } from "@repo/shared-components";
|
||||
|
||||
export const ConnectionBtn = () => {
|
||||
const modalRef = useRef<HTMLDialogElement>(null);
|
||||
@@ -53,10 +54,10 @@ export const ConnectionBtn = () => {
|
||||
};
|
||||
}, [connection.disconnect]);
|
||||
|
||||
const logoffTime = form.logoffTime;
|
||||
const [logoffHours, logoffMinutes] = form.logoffTime?.split(":").map(Number) || [];
|
||||
|
||||
useEffect(() => {
|
||||
if (!logoffTime || !connection.connectedAircraft) return;
|
||||
if (!logoffHours || !logoffMinutes || !connection.connectedAircraft) return;
|
||||
|
||||
if (logoffDebounce) clearTimeout(logoffDebounce);
|
||||
|
||||
@@ -65,9 +66,8 @@ export const ConnectionBtn = () => {
|
||||
await aircraftMutation.mutateAsync({
|
||||
sessionId: connection.connectedAircraft.id,
|
||||
change: {
|
||||
esimatedLogoutTime: logoffTime
|
||||
? new Date(new Date().toDateString() + " " + logoffTime).toISOString()
|
||||
: null,
|
||||
esimatedLogoutTime:
|
||||
logoffHours && logoffMinutes ? getNextDateWithTime(logoffHours, logoffMinutes) : null,
|
||||
},
|
||||
});
|
||||
modalRef.current?.close();
|
||||
@@ -80,7 +80,7 @@ export const ConnectionBtn = () => {
|
||||
return () => {
|
||||
if (logoffDebounce) clearTimeout(logoffDebounce);
|
||||
};
|
||||
}, [logoffTime, connection.connectedAircraft]);
|
||||
}, [logoffHours, logoffMinutes, connection.connectedAircraft]);
|
||||
|
||||
const session = useSession();
|
||||
const uid = session.data?.user?.id;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
"use client";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { FMS_STATUS_COLORS, FMS_STATUS_TEXT_COLORS } from "_helpers/fmsStatusColors";
|
||||
import { Badge, cn } from "@repo/shared-components";
|
||||
import {
|
||||
BADGES,
|
||||
ConnectedAircraft,
|
||||
getPublicUser,
|
||||
Mission,
|
||||
@@ -16,7 +18,6 @@ import { toast } from "react-hot-toast";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { editConnectedAircraftAPI } from "_querys/aircrafts";
|
||||
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
|
||||
import { cn } from "@repo/shared-components";
|
||||
import { PersonIcon } from "@radix-ui/react-icons";
|
||||
import {
|
||||
Ban,
|
||||
@@ -42,6 +43,8 @@ import { useSession } from "next-auth/react";
|
||||
import { sendSdsMessageAPI } from "_querys/missions";
|
||||
import { getLivekitRooms } from "_querys/livekit";
|
||||
import { findLeitstelleForPosition } from "_helpers/findLeitstelleinPoint";
|
||||
import { formatDistance } from "date-fns";
|
||||
import { de } from "date-fns/locale";
|
||||
|
||||
const FMSStatusHistory = ({
|
||||
aircraft,
|
||||
@@ -63,9 +66,22 @@ const FMSStatusHistory = ({
|
||||
<ul className="text-base-content font-semibold">
|
||||
<li className="flex items-center gap-2 mb-1">
|
||||
<p className="flex items-center gap-2 flex-1">
|
||||
<PersonIcon className="w-5 h-5" /> {aircraftUser.fullName} ({aircraftUser.publicId})
|
||||
<PersonIcon className="w-5 h-5" /> {aircraftUser.fullName} ({aircraftUser.publicId}){" "}
|
||||
{(() => {
|
||||
const badges = aircraftUser.badges
|
||||
.filter((b) => b.startsWith("P") && b.length == 2)
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
const lastBadge = badges[badges.length - 1];
|
||||
return lastBadge ? <Badge badge={lastBadge as BADGES} className="h-8 w-12" /> : null;
|
||||
})()}
|
||||
</p>
|
||||
<p className="text-sm font-thin text-gray-500">
|
||||
<p
|
||||
className={cn(
|
||||
"text-sm font-thin text-gray-500",
|
||||
aircraft.esimatedLogoutTime && "tooltip tooltip-left",
|
||||
)}
|
||||
data-tip={`in ${aircraft.esimatedLogoutTime && formatDistance(new Date(aircraft.esimatedLogoutTime), new Date(), { locale: de })}`}
|
||||
>
|
||||
{aircraft.esimatedLogoutTime
|
||||
? `Geplante Abmeldung: ${new Date(aircraft.esimatedLogoutTime).toLocaleTimeString(
|
||||
[],
|
||||
|
||||
@@ -16,8 +16,6 @@ export async function GET(request: NextRequest): Promise<NextResponse> {
|
||||
Station: true,
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Filter applied:", filter, connectedAircraft);
|
||||
return NextResponse.json(connectedAircraft, {
|
||||
status: 200,
|
||||
});
|
||||
|
||||
@@ -3,6 +3,8 @@ import { useQuery } from "@tanstack/react-query";
|
||||
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
|
||||
import { getConnectedDispatcherAPI } from "_querys/dispatcher";
|
||||
import { Plane, Workflow } from "lucide-react";
|
||||
import { formatDistance } from "date-fns";
|
||||
import { de } from "date-fns/locale";
|
||||
import { Badge } from "@repo/shared-components";
|
||||
|
||||
export const ConnectedDispatcher = () => {
|
||||
@@ -59,7 +61,10 @@ export const ConnectedDispatcher = () => {
|
||||
</p>
|
||||
</div>
|
||||
{d.esimatedLogoutTime && (
|
||||
<div className="tooltip tooltip-right" data-tip="Vorrausichtliche Abmeldung">
|
||||
<div
|
||||
className="tooltip tooltip-right"
|
||||
data-tip={`vorraussichtliche Abmeldung in ${formatDistance(new Date(), new Date(d.esimatedLogoutTime), { locale: de })}`}
|
||||
>
|
||||
<p className="text-gray-500 font-thin ">
|
||||
{new Date(d.esimatedLogoutTime).toLocaleTimeString([], {
|
||||
hour: "2-digit",
|
||||
@@ -74,11 +79,15 @@ export const ConnectedDispatcher = () => {
|
||||
<div className="text-xs uppercase font-semibold opacity-60">{d.zone}</div>
|
||||
</div>
|
||||
<div>
|
||||
{(d.publicUser as unknown as PublicUser).badges
|
||||
.filter((b) => b.startsWith("D"))
|
||||
.map((b) => (
|
||||
<Badge badge={b as BADGES} className="h-8 w-12" />
|
||||
))}
|
||||
{(() => {
|
||||
const badges = (d.publicUser as unknown as PublicUser).badges
|
||||
.filter((b) => b.startsWith("D") && b.length == 2)
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
const lastBadge = badges[badges.length - 1];
|
||||
return lastBadge ? (
|
||||
<Badge badge={lastBadge as BADGES} className="h-8 w-12" />
|
||||
) : null;
|
||||
})()}
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
"@next-auth/prisma-adapter": "^1.0.7",
|
||||
"@radix-ui/react-icons": "^1.3.2",
|
||||
"@repo/db": "workspace:*",
|
||||
"@repo/shared-components": "workspace:*",
|
||||
"@repo/eslint-config": "workspace:*",
|
||||
"@repo/shared-components": "workspace:*",
|
||||
"@repo/typescript-config": "workspace:*",
|
||||
"@tailwindcss/postcss": "^4.1.8",
|
||||
"@tanstack/react-query": "^5.79.0",
|
||||
@@ -33,6 +33,7 @@
|
||||
"axios": "^1.9.0",
|
||||
"clsx": "^2.1.1",
|
||||
"daisyui": "^5.0.43",
|
||||
"date-fns": "^4.1.0",
|
||||
"geojson": "^0.5.0",
|
||||
"i": "^0.3.7",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
|
||||
Reference in New Issue
Block a user